summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--bin/kdepim/WhatsNew.txt2
-rw-r--r--kabc/vcardparser/vcard.cpp2
-rw-r--r--kabc/vcardparser/vcardline.cpp14
-rw-r--r--kabc/vcardparser/vcardline.h7
-rw-r--r--kabc/vcardparser/vcardparser.cpp8
-rw-r--r--kabc/vcardparser/vcardtool.cpp86
-rw-r--r--kaddressbook/views/cardview.cpp9
7 files changed, 67 insertions, 61 deletions
diff --git a/bin/kdepim/WhatsNew.txt b/bin/kdepim/WhatsNew.txt
index bc0c62a..97c8154 100644
--- a/bin/kdepim/WhatsNew.txt
+++ b/bin/kdepim/WhatsNew.txt
@@ -1,254 +1,256 @@
1Info about the changes in new versions of KDE-Pim/Pi 1Info about the changes in new versions of KDE-Pim/Pi
2 2
3********** VERSION 2.0.26 ************ 3********** VERSION 2.0.26 ************
4 4
5And again fixed some bugs. 5And again fixed some bugs.
6Added two more fields to the KA/Pi view config: 6Added two more fields to the KA/Pi view config:
7A "Mobile (home)" and a "Mobile (work)" field. 7A "Mobile (home)" and a "Mobile (work)" field.
8Fixed utf8 import (e.g. for Japaneese text) in KA/Pi.
9
8 10
9********** VERSION 2.0.25 ************ 11********** VERSION 2.0.25 ************
10 12
11And again fixed some bugs. 13And again fixed some bugs.
12 14
13********** VERSION 2.0.24 ************ 15********** VERSION 2.0.24 ************
14 16
15Fixed again a lot of small bugs. 17Fixed again a lot of small bugs.
16Some performance optimizations in date navigator. 18Some performance optimizations in date navigator.
17Month view displays now multi days events on top of each cell, such that it is more likely that all multi days items of one event are in the same row. 19Month view displays now multi days events on top of each cell, such that it is more likely that all multi days items of one event are in the same row.
18 20
19********** VERSION 2.0.23 ************ 21********** VERSION 2.0.23 ************
20 22
21Fixed again a lot of small and strange bugs, e.g. the missing toolbar of KA/Pi after a new installation. 23Fixed again a lot of small and strange bugs, e.g. the missing toolbar of KA/Pi after a new installation.
22Fixed the (agenda) layout of KO/Pi on 5500er. 24Fixed the (agenda) layout of KO/Pi on 5500er.
23Some usebility enhancements (e.g. reselection the current item of the todo view after some changes). 25Some usebility enhancements (e.g. reselection the current item of the todo view after some changes).
24 26
25********** VERSION 2.0.22 ************ 27********** VERSION 2.0.22 ************
26 28
27KO/Pi: 29KO/Pi:
28Fix for creating events/todos via the abgenda context menu. 30Fix for creating events/todos via the abgenda context menu.
29Added option to split toolbar to 3 toolbars. 31Added option to split toolbar to 3 toolbars.
30(Toolbar moving s disabled for this option due to a bug in Qt somewhere). 32(Toolbar moving s disabled for this option due to a bug in Qt somewhere).
31Added option to show one small filter-view-toolbar. 33Added option to show one small filter-view-toolbar.
32Added a print option to the desktop version: 34Added a print option to the desktop version:
33Now you can print out the view of the "Event Viewer". 35Now you can print out the view of the "Event Viewer".
34That means you can print all data of one particular event/todo. 36That means you can print all data of one particular event/todo.
35Added scaling options to printout of Event Viewer and What'sNext View. 37Added scaling options to printout of Event Viewer and What'sNext View.
36Fixed some problems in the month view in "week start sunday" mode. 38Fixed some problems in the month view in "week start sunday" mode.
37KA/Pi: 39KA/Pi:
38Added two more config options. 40Added two more config options.
39Fixed resizing problem of address request dialog when orientation was switched. 41Fixed resizing problem of address request dialog when orientation was switched.
40Cleaned up the menu structure. 42Cleaned up the menu structure.
41Fixed some more problems. 43Fixed some more problems.
42 44
43Fixed the annoying problem that scrolling continued after the key was released in KO/Pi Monthview and the KA/Pi views. 45Fixed the annoying problem that scrolling continued after the key was released in KO/Pi Monthview and the KA/Pi views.
44 46
45And, this is a really cool option (Ben did suggest it): 47And, this is a really cool option (Ben did suggest it):
46Now KO/Pi and KA/Pi can be run from a USB stick: 48Now KO/Pi and KA/Pi can be run from a USB stick:
47All data is read from and written to the stick. 49All data is read from and written to the stick.
48You can enable this in the global configure option TAB with: 50You can enable this in the global configure option TAB with:
49Save using LOCAL storage. 51Save using LOCAL storage.
50Just put KDE-Pim/Pi on a memory stick and you can access all your PIM data on every computer with Windows XP. It will work with the ME and Linux versions as well. I will put a memory stick version for teh next stable release online. 52Just put KDE-Pim/Pi on a memory stick and you can access all your PIM data on every computer with Windows XP. It will work with the ME and Linux versions as well. I will put a memory stick version for teh next stable release online.
51 53
52********** VERSION 2.0.21 ************ 54********** VERSION 2.0.21 ************
53 55
54Fixed another SMTP problem in OM/Pi. 56Fixed another SMTP problem in OM/Pi.
55Some small changed in the new datenavigator in KO/Pi. 57Some small changed in the new datenavigator in KO/Pi.
56Changed default setting for new filter in KA/Pi to "exclude categories". 58Changed default setting for new filter in KA/Pi to "exclude categories".
57Changed the default font size for 640x480 display . 59Changed the default font size for 640x480 display .
58Changed popup menu behaviour in agenda and list view. 60Changed popup menu behaviour in agenda and list view.
59Fixed some layout problems of the date label size in the month view. 61Fixed some layout problems of the date label size in the month view.
60Made month view update faster. 62Made month view update faster.
61Made first datenavigator repainting faster. 63Made first datenavigator repainting faster.
62Changed the title of the event/todo edit dialogs. 64Changed the title of the event/todo edit dialogs.
63Timelabels in agenga changed from 22:00 to 22 oo. ( the oo higher, of course). 65Timelabels in agenga changed from 22:00 to 22 oo. ( the oo higher, of course).
64Many small usebility fixes in KO/Pi. 66Many small usebility fixes in KO/Pi.
65Pressing the "Calendar" button on the Z switches now to the next view in KO/Pi. 67Pressing the "Calendar" button on the Z switches now to the next view in KO/Pi.
66The set of possible "next views" are the views you have toolbar buttons for. 68The set of possible "next views" are the views you have toolbar buttons for.
67 69
68Made alarm sound working on Linux. 70Made alarm sound working on Linux.
69 71
70KO/Pi alarm applet changed: 72KO/Pi alarm applet changed:
71Made buttons in alarm dialog much bigger. 73Made buttons in alarm dialog much bigger.
72Made setting of timer more user friendly by showing the actual timer fire time and making the buttons in the timer settings much bigger. 74Made setting of timer more user friendly by showing the actual timer fire time and making the buttons in the timer settings much bigger.
73The goal was it to make it possible to use a finger tip ( and not the stylus ) on the touchscreen to adjust the settings. 75The goal was it to make it possible to use a finger tip ( and not the stylus ) on the touchscreen to adjust the settings.
74 76
75And because this version is realeased at Easter, I added an Easter-egg: 77And because this version is realeased at Easter, I added an Easter-egg:
76With a new undocumented command you can get a message box about the next alarm. 78With a new undocumented command you can get a message box about the next alarm.
77Good luck to find it! 79Good luck to find it!
78 80
79 81
80 82
81********** VERSION 2.0.20 ************ 83********** VERSION 2.0.20 ************
82 84
83Two small fixes in OM/Pi. 85Two small fixes in OM/Pi.
84 86
85Better resizing of the new datenavigator in KO/Pi. 87Better resizing of the new datenavigator in KO/Pi.
86 88
87********** VERSION 2.0.19 ************ 89********** VERSION 2.0.19 ************
88KO/Pi: 90KO/Pi:
89Enhancements and bugfixes in the new datenavigator. 91Enhancements and bugfixes in the new datenavigator.
90Bugfix in this changelog: 92Bugfix in this changelog:
91The datenavigator was changed in version 2.0.18, not the datepicker. 93The datenavigator was changed in version 2.0.18, not the datepicker.
92 94
93********** VERSION 2.0.18 ************ 95********** VERSION 2.0.18 ************
94KO/Pi: 96KO/Pi:
95Fixed some minor problems. 97Fixed some minor problems.
96Cleaned up the KO/Pi config dialog. 98Cleaned up the KO/Pi config dialog.
97Fixed problem moving events in aganda view. 99Fixed problem moving events in aganda view.
98Made datepicker scaleable, i.e. if the datenavigator shows now a 100Made datepicker scaleable, i.e. if the datenavigator shows now a
99datenavigator matrix depending on its size. 101datenavigator matrix depending on its size.
100Birthdays are now displayed green in the datenavigator. 102Birthdays are now displayed green in the datenavigator.
101What'sThis Help in datenavigator shows all events of the day. 103What'sThis Help in datenavigator shows all events of the day.
102 104
103OM/Pi: 105OM/Pi:
104Updated the backend mail library to the latest version. 106Updated the backend mail library to the latest version.
105Please backup your mail before using this version. 107Please backup your mail before using this version.
106 108
107********** VERSION 2.0.17 ************ 109********** VERSION 2.0.17 ************
108 110
109KO/Pi: 111KO/Pi:
110Tooltips in month view were not sorted. Fixed. 112Tooltips in month view were not sorted. Fixed.
111Daylabel in agenda view ( for display of one day ) was too short. Fixed. 113Daylabel in agenda view ( for display of one day ) was too short. Fixed.
112Conflict display dialog for syncing was not on top of other windows. Fixed. 114Conflict display dialog for syncing was not on top of other windows. Fixed.
113Fixed some minor problems. 115Fixed some minor problems.
114 116
115Fixed an endless loop when importing vcs file with RESOURCES entry. 117Fixed an endless loop when importing vcs file with RESOURCES entry.
116 118
117********** VERSION 2.0.16 ************ 119********** VERSION 2.0.16 ************
118OM/Pi: 120OM/Pi:
119Fixed the SMTP account setting the option. 121Fixed the SMTP account setting the option.
120Fixed something in mail sending. 122Fixed something in mail sending.
121 123
122KO/Pi: 124KO/Pi:
123Added possibility to export selected events/todos as vcal file. 125Added possibility to export selected events/todos as vcal file.
124 126
125********** VERSION 2.0.15 ************ 127********** VERSION 2.0.15 ************
126 128
127PwM/Pi: 129PwM/Pi:
128Added keyboard shorcuts for 130Added keyboard shorcuts for
129- toggling summary view (space bar) 131- toggling summary view (space bar)
130- delete item (delete + backspace key) 132- delete item (delete + backspace key)
131- add new item ( i + n key) 133- add new item ( i + n key)
132Fixed length of info in the title. 134Fixed length of info in the title.
133 135
134KO/Pi-KA/Pi: 136KO/Pi-KA/Pi:
135Changed "ME" menu bar entry to an icon. 137Changed "ME" menu bar entry to an icon.
136 138
137KO/Pi: 139KO/Pi:
138Fixed two minor bugs in displaying todos. 140Fixed two minor bugs in displaying todos.
139If in month view a cell is selected, the key shortcut "d" shows now that date. 141If in month view a cell is selected, the key shortcut "d" shows now that date.
140Added complete info for a todo in month view as an icon left of the text. 142Added complete info for a todo in month view as an icon left of the text.
141Fixed problems of displaying data when "<" or ">" are used in summary/location/description. 143Fixed problems of displaying data when "<" or ">" are used in summary/location/description.
142Fixed problem of search dialog size when switching displays. 144Fixed problem of search dialog size when switching displays.
143Cancel key now closes date picker. 145Cancel key now closes date picker.
144Rearranged KO/Pi file menu structure. 146Rearranged KO/Pi file menu structure.
145 147
146OM/Pi: 148OM/Pi:
147Added to the SMTP account setting the option 149Added to the SMTP account setting the option
148"No secure connection". 150"No secure connection".
149You have to configure your SMTP accounts again, sorry. 151You have to configure your SMTP accounts again, sorry.
150 152
151KA/Pi: 153KA/Pi:
152Added support for importing quoted-printable. 154Added support for importing quoted-printable.
153Support was added by Peter P.. Thanks, Peter! 155Support was added by Peter P.. Thanks, Peter!
154 156
155 157
156********** VERSION 2.0.14 ************ 158********** VERSION 2.0.14 ************
157 159
158Made Passwordmanager PwM/Pi more userfriendly: 160Made Passwordmanager PwM/Pi more userfriendly:
159Rearranged some toolbar icons, optimized setting of focus, fixed layout problems and more. 161Rearranged some toolbar icons, optimized setting of focus, fixed layout problems and more.
160Fixed bug in KO/Pi todo printing. 162Fixed bug in KO/Pi todo printing.
161Made Qtopia calendar import possible on desktop . 163Made Qtopia calendar import possible on desktop .
162 164
163********** VERSION 2.0.13 ************ 165********** VERSION 2.0.13 ************
164 166
165Fixed a problem in the addressee select dialog and made it more user friendly by adding a minimize splitter. 167Fixed a problem in the addressee select dialog and made it more user friendly by adding a minimize splitter.
166 168
167In the search dialog you can switch now the focus from search line edit to the list view by pressing key "arrow down". 169In the search dialog you can switch now the focus from search line edit to the list view by pressing key "arrow down".
168 170
169OM/Pi: 171OM/Pi:
170Fixed a refresh problem of outgoing/sent/sendfailed folders after sending mails. 172Fixed a refresh problem of outgoing/sent/sendfailed folders after sending mails.
171Added missing German translation. 173Added missing German translation.
172Added warning if path is specified in local folder settings of account config. 174Added warning if path is specified in local folder settings of account config.
173 175
174********** VERSION 2.0.12 ************ 176********** VERSION 2.0.12 ************
175 177
176KO/Pi: 178KO/Pi:
177Fixed a bug in todo start/due date handling for non recurring todos with a start and due date. 179Fixed a bug in todo start/due date handling for non recurring todos with a start and due date.
178Fixed some layout problems in the KO/Pi agenda view when there were many conflicting itmes. 180Fixed some layout problems in the KO/Pi agenda view when there were many conflicting itmes.
179Fixed several problems of the keyboard focus in the desktop versions when opening the search dialog/event viewer. 181Fixed several problems of the keyboard focus in the desktop versions when opening the search dialog/event viewer.
180 182
181Fixed problem in pi-sync mode when wrong password was sent. 183Fixed problem in pi-sync mode when wrong password was sent.
182 184
183OM/Pi: 185OM/Pi:
184Fixed a crash when displaying mails with "Show mail as html" was checked in the config. 186Fixed a crash when displaying mails with "Show mail as html" was checked in the config.
185Added a check before displaying the mail if the mail is in html format, if "Show mail as html" is enabled. 187Added a check before displaying the mail if the mail is in html format, if "Show mail as html" is enabled.
186 188
187********** VERSION 2.0.11 ************ 189********** VERSION 2.0.11 ************
188 190
189Fixed some problems in pi-sync mode 191Fixed some problems in pi-sync mode
190(e.g. details of events were not synced properly) 192(e.g. details of events were not synced properly)
191 193
192********** VERSION 2.0.10 ************ 194********** VERSION 2.0.10 ************
193 195
194KO/Pi: 196KO/Pi:
195In the desktop versions the context menu in the search dialog was broken after introducing the What'sThis info for the list view. 197In the desktop versions the context menu in the search dialog was broken after introducing the What'sThis info for the list view.
196This is fixed. 198This is fixed.
197Changed the search dialog a bit to make it more user friendly. 199Changed the search dialog a bit to make it more user friendly.
198(E.g.: Removed message box about "no items found" and set key focus to search line edit after search). 200(E.g.: Removed message box about "no items found" and set key focus to search line edit after search).
199 201
200Added config option to hide the week number in KO/Pi toolbar. 202Added config option to hide the week number in KO/Pi toolbar.
201 203
202********** VERSION 2.0.9 ************ 204********** VERSION 2.0.9 ************
203 205
204Made month view icons for multiday events a bit nicer. 206Made month view icons for multiday events a bit nicer.
205Some minor fixes in KO/Pi 207Some minor fixes in KO/Pi
206(e.g. go to today did not work for new week view properly). 208(e.g. go to today did not work for new week view properly).
207 209
208 210
209********** VERSION 2.0.8 ************ 211********** VERSION 2.0.8 ************
210 212
211Fixed a problem in dependency info in the ipk files for the Zaurus. 213Fixed a problem in dependency info in the ipk files for the Zaurus.
212 214
213Added icon for the stealth new week view and made navigation more user friendly in monthview by adding a prev/next week button to the navigator bar. 215Added icon for the stealth new week view and made navigation more user friendly in monthview by adding a prev/next week button to the navigator bar.
214 216
215Added a "go today" button to the datepicker. 217Added a "go today" button to the datepicker.
216 218
217Added "created" and "last modified" to event/todo viewer (and What'sThis viewer) 219Added "created" and "last modified" to event/todo viewer (and What'sThis viewer)
218and made it configureable to show these values. 220and made it configureable to show these values.
219 221
220Fixed a problem for events (from external iCal files) that do have a duration but no end date. 222Fixed a problem for events (from external iCal files) that do have a duration but no end date.
221 223
222 224
223********** VERSION 2.0.7 ************ 225********** VERSION 2.0.7 ************
224 226
225Added global application font settings 227Added global application font settings
226(for all KDE-Pim/Pi apps) to the general settings. 228(for all KDE-Pim/Pi apps) to the general settings.
227 229
228Fixed a problem in OM/Pi when trying to login to some IMAP servers 230Fixed a problem in OM/Pi when trying to login to some IMAP servers
229(like the IMAP server of Apple: mail.mac.com ) 231(like the IMAP server of Apple: mail.mac.com )
230 232
231Added recurring todos to KO/Pi. 233Added recurring todos to KO/Pi.
232 234
233 235
234********** VERSION 2.0.6 ************ 236********** VERSION 2.0.6 ************
235 237
236Stable release 2.0.6! 238Stable release 2.0.6!
237 239
238Some bugfixes in the pi-sync mode. 240Some bugfixes in the pi-sync mode.
239Added German translation for pi-sync mode. 241Added German translation for pi-sync mode.
240 242
241KO/Pi: 243KO/Pi:
242Made the todolist using alternate background. 244Made the todolist using alternate background.
243 245
244Other minor fixes in KO/Pi. 246Other minor fixes in KO/Pi.
245 247
246 248
247You can find the complete changelog 249You can find the complete changelog
248from version 1.7.7 to 2.0.5 250from version 1.7.7 to 2.0.5
249in the source package or on 251in the source package or on
250 252
251http://www.pi-sync.net/html/changelog.html 253http://www.pi-sync.net/html/changelog.html
252 254
253 255
254 256
diff --git a/kabc/vcardparser/vcard.cpp b/kabc/vcardparser/vcard.cpp
index 24fd498..bc9f208 100644
--- a/kabc/vcardparser/vcard.cpp
+++ b/kabc/vcardparser/vcard.cpp
@@ -1,118 +1,118 @@
1/* 1/*
2 This file is part of libkabc. 2 This file is part of libkabc.
3 Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> 3 Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
4 4
5 This library is free software; you can redistribute it and/or 5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public 6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either 7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version. 8 version 2 of the License, or (at your option) any later version.
9 9
10 This library is distributed in the hope that it will be useful, 10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details. 13 Library General Public License for more details.
14 14
15 You should have received a copy of the GNU Library General Public License 15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to 16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. 18 Boston, MA 02111-1307, USA.
19*/ 19*/
20 20
21#include "vcard.h" 21#include "vcard.h"
22 22
23using namespace KABC; 23using namespace KABC;
24 24
25VCard::VCard() 25VCard::VCard()
26{ 26{
27} 27}
28 28
29VCard::VCard( const VCard& vcard ) 29VCard::VCard( const VCard& vcard )
30{ 30{
31 mLineMap = vcard.mLineMap; 31 mLineMap = vcard.mLineMap;
32} 32}
33 33
34VCard::~VCard() 34VCard::~VCard()
35{ 35{
36} 36}
37 37
38VCard& VCard::operator=( const VCard& vcard ) 38VCard& VCard::operator=( const VCard& vcard )
39{ 39{
40 if ( &vcard == this ) 40 if ( &vcard == this )
41 return *this; 41 return *this;
42 42
43 mLineMap = vcard.mLineMap; 43 mLineMap = vcard.mLineMap;
44 44
45 return *this; 45 return *this;
46} 46}
47 47
48void VCard::clear() 48void VCard::clear()
49{ 49{
50 mLineMap.clear(); 50 mLineMap.clear();
51} 51}
52 52
53QStringList VCard::identifiers() const 53QStringList VCard::identifiers() const
54{ 54{
55 //return mLineMap.keys(); 55 //return mLineMap.keys();
56//PP re: US method QMap::keys() not available yet. SO collect the data manually 56//PP re: US method QMap::keys() not available yet. SO collect the data manually
57 57
58 QStringList result; 58 QStringList result;
59 59
60 QMap<QString, VCardLine::List>::ConstIterator it; 60 QMap<QString, VCardLine::List>::ConstIterator it;
61 for( it = mLineMap.begin(); it != mLineMap.end(); ++it ) { 61 for( it = mLineMap.begin(); it != mLineMap.end(); ++it ) {
62 result << it.key().latin1(); 62 result << it.key().latin1();
63 } 63 }
64 return result; 64 return result;
65} 65}
66 66
67void VCard::addLine( const VCardLine& line ) 67void VCard::addLine( const VCardLine& line )
68{ 68{
69 mLineMap[ line.identifier() ].append( line ); 69 mLineMap[ line.identifier() ].append( line );
70} 70}
71 71
72VCardLine::List VCard::lines( const QString& identifier ) const 72VCardLine::List VCard::lines( const QString& identifier ) const
73{ 73{
74 LineMap::ConstIterator it = mLineMap.find( identifier ); 74 LineMap::ConstIterator it = mLineMap.find( identifier );
75 if ( it == mLineMap.end() ) 75 if ( it == mLineMap.end() )
76 return VCardLine::List(); 76 return VCardLine::List();
77 77
78 return *it; 78 return *it;
79} 79}
80 80
81VCardLine VCard::line( const QString& identifier ) const 81VCardLine VCard::line( const QString& identifier ) const
82{ 82{
83 LineMap::ConstIterator it = mLineMap.find( identifier ); 83 LineMap::ConstIterator it = mLineMap.find( identifier );
84 if ( it == mLineMap.end() ) 84 if ( it == mLineMap.end() )
85 return VCardLine(); 85 return VCardLine();
86 86
87 if ( (*it).isEmpty() ) 87 if ( (*it).isEmpty() )
88 return VCardLine(); 88 return VCardLine();
89 else 89 else
90 return (*it).first(); 90 return (*it).first();
91} 91}
92 92
93void VCard::setVersion( Version version ) 93void VCard::setVersion( Version version )
94{ 94{
95 mLineMap.remove( "VERSION" ); 95 mLineMap.remove( "VERSION" );
96 96
97 VCardLine line; 97 VCardLine line;
98 line.setIdentifier( "VERSION" ); 98 line.setIdentifier( "VERSION" );
99 if ( version == v2_1 ) 99 if ( version == v2_1 )
100 line.setIdentifier( "2.1" ); 100 line.setIdentifier( "2.1" );
101 else if ( version == v3_0 ) 101 else if ( version == v3_0 )
102 line.setIdentifier( "3.0" ); 102 line.setIdentifier( "3.0" );
103 103
104 mLineMap[ "VERSION" ].append( line ); 104 mLineMap[ "VERSION" ].append( line );
105} 105}
106 106
107VCard::Version VCard::version() const 107VCard::Version VCard::version() const
108{ 108{
109 LineMap::ConstIterator versionEntry = mLineMap.find( "VERSION" ); 109 LineMap::ConstIterator versionEntry = mLineMap.find( "VERSION" );
110 if ( versionEntry == mLineMap.end() ) 110 if ( versionEntry == mLineMap.end() )
111 return v3_0; 111 return v3_0;
112 112
113 VCardLine line = ( *versionEntry )[ 0 ]; 113 VCardLine line = ( *versionEntry )[ 0 ];
114 if ( line.value() == "2.1" ) 114 if ( line.valueString() == "2.1" )
115 return v2_1; 115 return v2_1;
116 else 116 else
117 return v3_0; 117 return v3_0;
118} 118}
diff --git a/kabc/vcardparser/vcardline.cpp b/kabc/vcardparser/vcardline.cpp
index 0972a35..8df2d32 100644
--- a/kabc/vcardparser/vcardline.cpp
+++ b/kabc/vcardparser/vcardline.cpp
@@ -1,171 +1,175 @@
1/* 1/*
2 This file is part of libkabc. 2 This file is part of libkabc.
3 Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> 3 Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
4 4
5 This library is free software; you can redistribute it and/or 5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public 6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either 7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version. 8 version 2 of the License, or (at your option) any later version.
9 9
10 This library is distributed in the hope that it will be useful, 10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details. 13 Library General Public License for more details.
14 14
15 You should have received a copy of the GNU Library General Public License 15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to 16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. 18 Boston, MA 02111-1307, USA.
19*/ 19*/
20 20
21#include "vcardline.h" 21#include "vcardline.h"
22 22
23using namespace KABC; 23using namespace KABC;
24 24
25class VCardLine::VCardLinePrivate 25class VCardLine::VCardLinePrivate
26{ 26{
27 public: 27 public:
28 QString mGroup; 28 QString mGroup;
29}; 29};
30 30
31VCardLine::VCardLine() 31VCardLine::VCardLine()
32 : d( 0 ) 32 : d( 0 )
33{ 33{
34} 34}
35 35
36VCardLine::VCardLine( const QString &identifier ) 36VCardLine::VCardLine( const QString &identifier )
37 : d( 0 ) 37 : d( 0 )
38{ 38{
39 mIdentifier = identifier; 39 mIdentifier = identifier;
40} 40}
41 41
42VCardLine::VCardLine( const QString &identifier, const QString &value ) 42VCardLine::VCardLine( const QString &identifier, const QString &value )
43 : d( 0 ) 43 : d( 0 )
44{ 44{
45 mIdentifier = identifier; 45 mIdentifier = identifier;
46 mValue.assign( value.data(), value.length() ); 46 mValue.assign( value.data(), value.length() );
47} 47}
48 48
49VCardLine::VCardLine( const VCardLine& line ) 49VCardLine::VCardLine( const VCardLine& line )
50 : d( 0 ) 50 : d( 0 )
51{ 51{
52 mParamMap = line.mParamMap; 52 mParamMap = line.mParamMap;
53 mValue = line.mValue; 53 mValue = line.mValue;
54 mIdentifier = line.mIdentifier; 54 mIdentifier = line.mIdentifier;
55} 55}
56 56
57VCardLine::~VCardLine() 57VCardLine::~VCardLine()
58{ 58{
59 delete d; 59 delete d;
60 d = 0; 60 d = 0;
61} 61}
62 62
63VCardLine& VCardLine::operator=( const VCardLine& line ) 63VCardLine& VCardLine::operator=( const VCardLine& line )
64{ 64{
65 if ( &line == this ) 65 if ( &line == this )
66 return *this; 66 return *this;
67 67
68 mParamMap = line.mParamMap; 68 mParamMap = line.mParamMap;
69 mValue = line.mValue; 69 mValue = line.mValue;
70 mIdentifier = line.mIdentifier; 70 mIdentifier = line.mIdentifier;
71 71
72 return *this; 72 return *this;
73} 73}
74 74
75void VCardLine::setIdentifier( const QString& identifier ) 75void VCardLine::setIdentifier( const QString& identifier )
76{ 76{
77 mIdentifier = identifier; 77 mIdentifier = identifier;
78} 78}
79 79
80QString VCardLine::identifier() const 80QString VCardLine::identifier() const
81{ 81{
82 return mIdentifier; 82 return mIdentifier;
83} 83}
84 84
85void VCardLine::setValue( const QString& value ) 85void VCardLine::setValueString( const QString& value )
86{ 86{
87 mValue.duplicate( value.data(), value.length() ); 87 setValueCString( value.utf8() );
88}
89void VCardLine::setValueCString( const QCString& value )
90{
91 mValue.duplicate( value.data(), value.length() );
88} 92}
89 93
90void VCardLine::setValue( const QByteArray& value ) 94void VCardLine::setValueBytes( const QByteArray& value )
91{ 95{
92 mValue = value; 96 mValue = value;
93} 97}
94 98
95QVariant VCardLine::value() const 99QString VCardLine::valueString() const
96{ 100{
97 return QVariant( QCString( mValue.data(), mValue.size()+1 ) ); 101 return QString::fromUtf8( mValue.data(), mValue.size() );
98} 102}
99 103
100QByteArray VCardLine::valueBytes() const 104QByteArray VCardLine::valueBytes() const
101{ 105{
102 return mValue; 106 return mValue;
103} 107}
104 108
105void VCardLine::setGroup( const QString& group ) 109void VCardLine::setGroup( const QString& group )
106{ 110{
107 if ( !d ) 111 if ( !d )
108 d = new VCardLinePrivate(); 112 d = new VCardLinePrivate();
109 113
110 d->mGroup = group; 114 d->mGroup = group;
111} 115}
112 116
113QString VCardLine::group() const 117QString VCardLine::group() const
114{ 118{
115 if ( d ) 119 if ( d )
116 return d->mGroup; 120 return d->mGroup;
117 else 121 else
118 return QString(); 122 return QString();
119} 123}
120 124
121bool VCardLine::hasGroup() const 125bool VCardLine::hasGroup() const
122{ 126{
123 if ( !d ) 127 if ( !d )
124 return false; 128 return false;
125 else 129 else
126 return d->mGroup.isEmpty(); 130 return d->mGroup.isEmpty();
127} 131}
128 132
129QStringList VCardLine::parameterList() const 133QStringList VCardLine::parameterList() const
130{ 134{
131 //return mParamMap.keys(); 135 //return mParamMap.keys();
132//US method QMap::keys() not available yet. SO collect the data manually 136//US method QMap::keys() not available yet. SO collect the data manually
133//US return mParamMap->keys(); 137//US return mParamMap->keys();
134 138
135 QStringList result; 139 QStringList result;
136 140
137 QMap<QString, QStringList>::ConstIterator it; 141 QMap<QString, QStringList>::ConstIterator it;
138 for( it = mParamMap.begin(); it != mParamMap.end(); ++it ) { 142 for( it = mParamMap.begin(); it != mParamMap.end(); ++it ) {
139 result << it.key().latin1(); 143 result << it.key().latin1();
140 } 144 }
141 return result; 145 return result;
142} 146}
143 147
144void VCardLine::addParameter( const QString& param, const QString& value ) 148void VCardLine::addParameter( const QString& param, const QString& value )
145{ 149{
146 QStringList &list = mParamMap[ param ]; 150 QStringList &list = mParamMap[ param ];
147 if ( list.findIndex( value ) == -1 ) // not included yet 151 if ( list.findIndex( value ) == -1 ) // not included yet
148 list.append( value ); 152 list.append( value );
149} 153}
150 154
151QStringList VCardLine::parameters( const QString& param ) const 155QStringList VCardLine::parameters( const QString& param ) const
152{ 156{
153 ParamMap::ConstIterator it = mParamMap.find( param ); 157 ParamMap::ConstIterator it = mParamMap.find( param );
154 if ( it == mParamMap.end() ) 158 if ( it == mParamMap.end() )
155 return QStringList(); 159 return QStringList();
156 else 160 else
157 return *it; 161 return *it;
158} 162}
159 163
160QString VCardLine::parameter( const QString& param ) const 164QString VCardLine::parameter( const QString& param ) const
161{ 165{
162 ParamMap::ConstIterator it = mParamMap.find( param ); 166 ParamMap::ConstIterator it = mParamMap.find( param );
163 if ( it == mParamMap.end() ) 167 if ( it == mParamMap.end() )
164 return QString::null; 168 return QString::null;
165 else { 169 else {
166 if ( (*it).isEmpty() ) 170 if ( (*it).isEmpty() )
167 return QString::null; 171 return QString::null;
168 else 172 else
169 return (*it).first(); 173 return (*it).first();
170 } 174 }
171} 175}
diff --git a/kabc/vcardparser/vcardline.h b/kabc/vcardparser/vcardline.h
index 6e74b38..8dc9322 100644
--- a/kabc/vcardparser/vcardline.h
+++ b/kabc/vcardparser/vcardline.h
@@ -1,118 +1,119 @@
1/* 1/*
2 This file is part of libkabc. 2 This file is part of libkabc.
3 Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> 3 Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
4 4
5 This library is free software; you can redistribute it and/or 5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public 6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either 7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version. 8 version 2 of the License, or (at your option) any later version.
9 9
10 This library is distributed in the hope that it will be useful, 10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details. 13 Library General Public License for more details.
14 14
15 You should have received a copy of the GNU Library General Public License 15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to 16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. 18 Boston, MA 02111-1307, USA.
19*/ 19*/
20 20
21#ifndef VCARDLINE_H 21#ifndef VCARDLINE_H
22#define VCARDLINE_H 22#define VCARDLINE_H
23 23
24#include <qstringlist.h> 24#include <qstringlist.h>
25#include <qvaluelist.h> 25#include <qvaluelist.h>
26#include <qcstring.h> 26#include <qcstring.h>
27#include <qvariant.h> 27#include <qvariant.h>
28#include <qmap.h> 28#include <qmap.h>
29#include <qstring.h> 29#include <qstring.h>
30 30
31namespace KABC { 31namespace KABC {
32 32
33class VCardLine 33class VCardLine
34{ 34{
35 public: 35 public:
36 typedef QValueList<VCardLine> List; 36 typedef QValueList<VCardLine> List;
37 typedef QMap<QString, QStringList> ParamMap; 37 typedef QMap<QString, QStringList> ParamMap;
38 38
39 VCardLine(); 39 VCardLine();
40 VCardLine( const QString &identifier ); 40 VCardLine( const QString &identifier );
41 VCardLine( const QString &identifier, const QString &value ); 41 VCardLine( const QString &identifier, const QString &value );
42 VCardLine( const VCardLine& ); 42 VCardLine( const VCardLine& );
43 43
44 ~VCardLine(); 44 ~VCardLine();
45 45
46 VCardLine& operator=( const VCardLine& ); 46 VCardLine& operator=( const VCardLine& );
47 47
48 /** 48 /**
49 * Sets the identifier of this line e.g. UID, FN, CLASS 49 * Sets the identifier of this line e.g. UID, FN, CLASS
50 */ 50 */
51 void setIdentifier( const QString& identifier ); 51 void setIdentifier( const QString& identifier );
52 52
53 /** 53 /**
54 * Returns the identifier of this line. 54 * Returns the identifier of this line.
55 */ 55 */
56 QString identifier() const; 56 QString identifier() const;
57 57
58 /** 58 /**
59 * Sets the value of of this line. 59 * Sets the value of of this line.
60 */ 60 */
61 void setValue( const QString& value ); 61 void setValueString( const QString& value );
62 void setValue( const QByteArray& value ); 62 void setValueCString( const QCString& value );
63 void setValueBytes( const QByteArray& value );
63 64
64 /** 65 /**
65 * Returns the value of this line. 66 * Returns the value of this line.
66 */ 67 */
67 QVariant value() const; 68 QString valueString() const;
68 QByteArray valueBytes() const; 69 QByteArray valueBytes() const;
69 70
70 /** 71 /**
71 * Sets the group the line belongs to. 72 * Sets the group the line belongs to.
72 */ 73 */
73 void setGroup( const QString& group ); 74 void setGroup( const QString& group );
74 75
75 /** 76 /**
76 * Returns the group the line belongs to. 77 * Returns the group the line belongs to.
77 */ 78 */
78 QString group() const; 79 QString group() const;
79 80
80 /** 81 /**
81 * Returns whether the line belongs to a group. 82 * Returns whether the line belongs to a group.
82 */ 83 */
83 bool hasGroup() const; 84 bool hasGroup() const;
84 85
85 /** 86 /**
86 * Returns all parameters. 87 * Returns all parameters.
87 */ 88 */
88 QStringList parameterList() const; 89 QStringList parameterList() const;
89 90
90 /** 91 /**
91 * Add a new parameter to the line. 92 * Add a new parameter to the line.
92 */ 93 */
93 void addParameter( const QString& param, const QString& value ); 94 void addParameter( const QString& param, const QString& value );
94 95
95 /** 96 /**
96 * Returns the values of a special parameter. 97 * Returns the values of a special parameter.
97 * You can get a list of all parameters with paramList(). 98 * You can get a list of all parameters with paramList().
98 */ 99 */
99 QStringList parameters( const QString& param ) const; 100 QStringList parameters( const QString& param ) const;
100 101
101 /** 102 /**
102 * Returns only the first value of a special parameter. 103 * Returns only the first value of a special parameter.
103 * You can get a list of all parameters with paramList(). 104 * You can get a list of all parameters with paramList().
104 */ 105 */
105 QString parameter( const QString& param ) const; 106 QString parameter( const QString& param ) const;
106 107
107 private: 108 private:
108 ParamMap mParamMap; 109 ParamMap mParamMap;
109 QString mIdentifier; 110 QString mIdentifier;
110 QByteArray mValue; 111 QByteArray mValue;
111 112
112 class VCardLinePrivate; 113 class VCardLinePrivate;
113 VCardLinePrivate *d; 114 VCardLinePrivate *d;
114}; 115};
115 116
116} 117}
117 118
118#endif 119#endif
diff --git a/kabc/vcardparser/vcardparser.cpp b/kabc/vcardparser/vcardparser.cpp
index 7fae011..11622a0 100644
--- a/kabc/vcardparser/vcardparser.cpp
+++ b/kabc/vcardparser/vcardparser.cpp
@@ -1,240 +1,240 @@
1/* 1/*
2 This file is part of libkabc. 2 This file is part of libkabc.
3 Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> 3 Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
4 4
5 This library is free software; you can redistribute it and/or 5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public 6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either 7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version. 8 version 2 of the License, or (at your option) any later version.
9 9
10 This library is distributed in the hope that it will be useful, 10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details. 13 Library General Public License for more details.
14 14
15 You should have received a copy of the GNU Library General Public License 15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to 16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. 18 Boston, MA 02111-1307, USA.
19*/ 19*/
20 20
21#include <qregexp.h> 21#include <qregexp.h>
22 22
23#include <kmdcodec.h> 23#include <kmdcodec.h>
24 24
25#include "vcardparser.h" 25#include "vcardparser.h"
26 26
27#define FOLD_WIDTH 75 27#define FOLD_WIDTH 75
28 28
29using namespace KABC; 29using namespace KABC;
30 30
31VCardParser::VCardParser() 31VCardParser::VCardParser()
32{ 32{
33} 33}
34 34
35VCardParser::~VCardParser() 35VCardParser::~VCardParser()
36{ 36{
37} 37}
38 38
39VCard::List VCardParser::parseVCards( const QString& text ) 39VCard::List VCardParser::parseVCards( const QString& text )
40{ 40{
41 static QRegExp sep( "[\x0d\x0a]" ); 41 static QRegExp sep( "[\x0d\x0a]" );
42 42
43 VCard currentVCard; 43 VCard currentVCard;
44 VCard::List vCardList; 44 VCard::List vCardList;
45 QString currentLine; 45 QString currentLine;
46 46
47 const QStringList lines = QStringList::split( sep, text ); 47 const QStringList lines = QStringList::split( sep, text );
48 QStringList::ConstIterator it; 48 QStringList::ConstIterator it;
49 49
50 bool inVCard = false; 50 bool inVCard = false;
51 QStringList::ConstIterator linesEnd( lines.end() ); 51 QStringList::ConstIterator linesEnd( lines.end() );
52 for ( it = lines.begin(); it != linesEnd; ++it ) { 52 for ( it = lines.begin(); it != linesEnd; ++it ) {
53 53
54 if ( (*it).isEmpty() ) // empty line 54 if ( (*it).isEmpty() ) // empty line
55 continue; 55 continue;
56 56
57 if ( (*it)[ 0 ] == ' ' || (*it)[ 0 ] == '\t' ) { // folded line => append to previous 57 if ( (*it)[ 0 ] == ' ' || (*it)[ 0 ] == '\t' ) { // folded line => append to previous
58 currentLine += QString( *it ).remove( 0, 1 ); 58 currentLine += QString( *it ).remove( 0, 1 );
59 continue; 59 continue;
60 } else { 60 } else {
61 if ( inVCard && !currentLine.isEmpty() ) { // now parse the line 61 if ( inVCard && !currentLine.isEmpty() ) { // now parse the line
62 int colon = currentLine.find( ':' ); 62 int colon = currentLine.find( ':' );
63 if ( colon == -1 ) { // invalid line 63 if ( colon == -1 ) { // invalid line
64 currentLine = (*it); 64 currentLine = (*it);
65 continue; 65 continue;
66 } 66 }
67 67
68 VCardLine vCardLine; 68 VCardLine vCardLine;
69 const QString key = currentLine.left( colon ).stripWhiteSpace(); 69 const QString key = currentLine.left( colon ).stripWhiteSpace();
70 QString value = currentLine.mid( colon + 1 ); 70 QString value = currentLine.mid( colon + 1 );
71 71
72 QStringList params = QStringList::split( ';', key ); 72 QStringList params = QStringList::split( ';', key );
73 73
74 // check for group 74 // check for group
75 if ( params[0].find( '.' ) != -1 ) { 75 if ( params[0].find( '.' ) != -1 ) {
76 const QStringList groupList = QStringList::split( '.', params[0] ); 76 const QStringList groupList = QStringList::split( '.', params[0] );
77 vCardLine.setGroup( groupList[0] ); 77 vCardLine.setGroup( groupList[0] );
78 vCardLine.setIdentifier( groupList[1] ); 78 vCardLine.setIdentifier( groupList[1] );
79 } else 79 } else
80 vCardLine.setIdentifier( params[0] ); 80 vCardLine.setIdentifier( params[0] );
81 81
82 if ( params.count() > 1 ) { // find all parameters 82 if ( params.count() > 1 ) { // find all parameters
83 QStringList::ConstIterator paramIt = params.begin(); 83 QStringList::ConstIterator paramIt = params.begin();
84 for ( ++paramIt; paramIt != params.end(); ++paramIt ) { 84 for ( ++paramIt; paramIt != params.end(); ++paramIt ) {
85 QStringList pair = QStringList::split( '=', *paramIt ); 85 QStringList pair = QStringList::split( '=', *paramIt );
86 if ( pair.count() == 1 ) { 86 if ( pair.count() == 1 ) {
87 // correct the fucking 2.1 'standard' 87 // correct the fucking 2.1 'standard'
88 if ( pair[0].lower() == "quoted-printable" ) { 88 if ( pair[0].lower() == "quoted-printable" ) {
89 pair[0] = "encoding"; 89 pair[0] = "encoding";
90 pair[1] = "quoted-printable"; 90 pair[1] = "quoted-printable";
91 } else if ( pair[0].lower() == "base64" ) { 91 } else if ( pair[0].lower() == "base64" ) {
92 pair[0] = "encoding"; 92 pair[0] = "encoding";
93 pair[1] = "base64"; 93 pair[1] = "base64";
94 } else { 94 } else {
95 pair.prepend( "type" ); 95 pair.prepend( "type" );
96 } 96 }
97 } 97 }
98 // This is pretty much a faster pair[1].contains( ',' )... 98 // This is pretty much a faster pair[1].contains( ',' )...
99 if ( pair[1].find( ',' ) != -1 ) { // parameter in type=x,y,z format 99 if ( pair[1].find( ',' ) != -1 ) { // parameter in type=x,y,z format
100 const QStringList args = QStringList::split( ',', pair[ 1 ] ); 100 const QStringList args = QStringList::split( ',', pair[ 1 ] );
101 QStringList::ConstIterator argIt; 101 QStringList::ConstIterator argIt;
102 for ( argIt = args.begin(); argIt != args.end(); ++argIt ) 102 for ( argIt = args.begin(); argIt != args.end(); ++argIt )
103 vCardLine.addParameter( pair[0].lower(), *argIt ); 103 vCardLine.addParameter( pair[0].lower(), *argIt );
104 } else 104 } else
105 vCardLine.addParameter( pair[0].lower(), pair[1] ); 105 vCardLine.addParameter( pair[0].lower(), pair[1] );
106 } 106 }
107 } 107 }
108 108
109 params = vCardLine.parameterList(); 109 params = vCardLine.parameterList();
110 if ( params.findIndex( "encoding" ) != -1 ) { // have to decode the data 110 if ( params.findIndex( "encoding" ) != -1 ) { // have to decode the data
111 QByteArray input, output; 111 QByteArray input, output;
112 if ( vCardLine.parameter( "encoding" ).lower() == "b" || 112 if ( vCardLine.parameter( "encoding" ).lower() == "b" ||
113 vCardLine.parameter( "encoding" ).lower() == "base64" ) { 113 vCardLine.parameter( "encoding" ).lower() == "base64" ) {
114 input = value.local8Bit(); 114 input = value.local8Bit();
115 KCodecs::base64Decode( input, output ); 115 KCodecs::base64Decode( input, output );
116 } else if ( vCardLine.parameter( "encoding" ).lower() == "quoted-printable" ) { 116 } else if ( vCardLine.parameter( "encoding" ).lower() == "quoted-printable" ) {
117 // join any qp-folded lines 117 // join any qp-folded lines
118 while ( value.mid(value.length()-1,1) == "=" && it != linesEnd ) { 118 while ( value.mid(value.length()-1,1) == "=" && it != linesEnd ) {
119 value = value.remove( value.length()-1, 1 ) + (*it); 119 value = value.remove( value.length()-1, 1 ) + (*it);
120 ++it; 120 ++it;
121 } 121 }
122 input = value.local8Bit(); 122 input = value.local8Bit();
123 KCodecs::quotedPrintableDecode( input, output ); 123 KCodecs::quotedPrintableDecode( input, output );
124 } 124 }
125//PP our vcards are *supposed* to be in UTF-8 125//PP our vcards are *supposed* to be in UTF-8
126// if ( vCardLine.parameter( "charset" ).lower() == "utf-8" ) { 126// if ( vCardLine.parameter( "charset" ).lower() == "utf-8" ) {
127// vCardLine.setValue( QString::fromUtf8( output.data(), output.size() ) ); 127// vCardLine.setValue( QString::fromUtf8( output.data(), output.size() ) );
128// } else 128// } else
129 vCardLine.setValue( output ); 129 vCardLine.setValueBytes( output );
130//PP our vcards are *supposed* to be in UTF-8 130//PP our vcards are *supposed* to be in UTF-8
131// } else if ( vCardLine.parameter( "charset" ).lower() == "utf-8" ) { 131// } else if ( vCardLine.parameter( "charset" ).lower() == "utf-8" ) {
132// vCardLine.setValue( QString::fromUtf8( value.ascii() ) ); 132// vCardLine.setValue( QString::fromUtf8( value.ascii() ) );
133 } else 133 } else
134 vCardLine.setValue( value.replace( QRegExp("\\\\n"), "\n" ) ); 134 vCardLine.setValueString( value.replace( QRegExp("\\\\n"), "\n" ) );
135 135
136 currentVCard.addLine( vCardLine ); 136 currentVCard.addLine( vCardLine );
137 } 137 }
138 138
139 // we do not save the start and end tag as vcardline 139 // we do not save the start and end tag as vcardline
140 if ( (*it).lower().startsWith( "begin:vcard" ) ) { 140 if ( (*it).lower().startsWith( "begin:vcard" ) ) {
141 inVCard = true; 141 inVCard = true;
142 currentLine = ""; 142 currentLine = "";
143 currentVCard.clear(); // flush vcard 143 currentVCard.clear(); // flush vcard
144 continue; 144 continue;
145 } 145 }
146 146
147 if ( (*it).lower().startsWith( "end:vcard" ) ) { 147 if ( (*it).lower().startsWith( "end:vcard" ) ) {
148 inVCard = false; 148 inVCard = false;
149 vCardList.append( currentVCard ); 149 vCardList.append( currentVCard );
150 currentLine = ""; 150 currentLine = "";
151 currentVCard.clear(); // flush vcard 151 currentVCard.clear(); // flush vcard
152 continue; 152 continue;
153 } 153 }
154 154
155 currentLine = (*it); 155 currentLine = (*it);
156 } 156 }
157 } 157 }
158 158
159 return vCardList; 159 return vCardList;
160} 160}
161 161
162QString VCardParser::createVCards( const VCard::List& list ) 162QString VCardParser::createVCards( const VCard::List& list )
163{ 163{
164 QString text; 164 QString text;
165 QString textLine; 165 QString textLine;
166 QString encodingType; 166 QString encodingType;
167 QStringList idents; 167 QStringList idents;
168 QStringList params; 168 QStringList params;
169 QStringList values; 169 QStringList values;
170 QStringList::ConstIterator identIt; 170 QStringList::ConstIterator identIt;
171 QStringList::Iterator paramIt; 171 QStringList::Iterator paramIt;
172 QStringList::ConstIterator valueIt; 172 QStringList::ConstIterator valueIt;
173 173
174 VCardLine::List lines; 174 VCardLine::List lines;
175 VCardLine::List::ConstIterator lineIt; 175 VCardLine::List::ConstIterator lineIt;
176 VCard::List::ConstIterator cardIt; 176 VCard::List::ConstIterator cardIt;
177 177
178 bool hasEncoding; 178 bool hasEncoding;
179 179
180 // iterate over the cards 180 // iterate over the cards
181 VCard::List::ConstIterator listEnd( list.end() ); 181 VCard::List::ConstIterator listEnd( list.end() );
182 for ( cardIt = list.begin(); cardIt != listEnd; ++cardIt ) { 182 for ( cardIt = list.begin(); cardIt != listEnd; ++cardIt ) {
183 text.append( "BEGIN:VCARD\r\n" ); 183 text.append( "BEGIN:VCARD\r\n" );
184 184
185 idents = (*cardIt).identifiers(); 185 idents = (*cardIt).identifiers();
186 for ( identIt = idents.begin(); identIt != idents.end(); ++identIt ) { 186 for ( identIt = idents.begin(); identIt != idents.end(); ++identIt ) {
187 lines = (*cardIt).lines( (*identIt) ); 187 lines = (*cardIt).lines( (*identIt) );
188 188
189 // iterate over the lines 189 // iterate over the lines
190 for ( lineIt = lines.begin(); lineIt != lines.end(); ++lineIt ) { 190 for ( lineIt = lines.begin(); lineIt != lines.end(); ++lineIt ) {
191 if ( !(*lineIt).value().asString().isEmpty() ) { 191 if ( !(*lineIt).valueString().isEmpty() ) {
192 if ( (*lineIt).hasGroup() ) 192 if ( (*lineIt).hasGroup() )
193 textLine = (*lineIt).group() + "." + (*lineIt).identifier(); 193 textLine = (*lineIt).group() + "." + (*lineIt).identifier();
194 else 194 else
195 textLine = (*lineIt).identifier(); 195 textLine = (*lineIt).identifier();
196 196
197 params = (*lineIt).parameterList(); 197 params = (*lineIt).parameterList();
198 hasEncoding = false; 198 hasEncoding = false;
199 if ( params.count() > 0 ) { // we have parameters 199 if ( params.count() > 0 ) { // we have parameters
200 for ( paramIt = params.begin(); paramIt != params.end(); ++paramIt ) { 200 for ( paramIt = params.begin(); paramIt != params.end(); ++paramIt ) {
201 if ( (*paramIt) == "encoding" ) { 201 if ( (*paramIt) == "encoding" ) {
202 hasEncoding = true; 202 hasEncoding = true;
203 encodingType = (*lineIt).parameter( "encoding" ).lower(); 203 encodingType = (*lineIt).parameter( "encoding" ).lower();
204 } 204 }
205 205
206 values = (*lineIt).parameters( *paramIt ); 206 values = (*lineIt).parameters( *paramIt );
207 for ( valueIt = values.begin(); valueIt != values.end(); ++valueIt ) { 207 for ( valueIt = values.begin(); valueIt != values.end(); ++valueIt ) {
208 textLine.append( ";" + (*paramIt).upper() ); 208 textLine.append( ";" + (*paramIt).upper() );
209 if ( !(*valueIt).isEmpty() ) 209 if ( !(*valueIt).isEmpty() )
210 textLine.append( "=" + (*valueIt) ); 210 textLine.append( "=" + (*valueIt) );
211 } 211 }
212 } 212 }
213 } 213 }
214 214
215 if ( hasEncoding ) { // have to encode the data 215 if ( hasEncoding ) { // have to encode the data
216 QByteArray input, output; 216 QByteArray input, output;
217 input = (*lineIt).valueBytes(); 217 input = (*lineIt).valueBytes();
218 if ( encodingType == "b" ) 218 if ( encodingType == "b" )
219 KCodecs::base64Encode( input, output ); 219 KCodecs::base64Encode( input, output );
220 else if ( encodingType == "quoted-printable" ) 220 else if ( encodingType == "quoted-printable" )
221 KCodecs::quotedPrintableEncode( input, output ); 221 KCodecs::quotedPrintableEncode( input, output );
222 textLine.append( ":" + QString( output ) ); 222 textLine.append( ":" + QString( output ) );
223 } else 223 } else
224 textLine.append( ":" + (*lineIt).value().asString().replace( QRegExp("\n"), "\\n" ) ); 224 textLine.append( ":" + (*lineIt).valueString().replace( QRegExp("\n"), "\\n" ) );
225 225
226 if ( textLine.length() > FOLD_WIDTH ) { // we have to fold the line 226 if ( textLine.length() > FOLD_WIDTH ) { // we have to fold the line
227 for ( uint i = 0; i <= ( textLine.length() / FOLD_WIDTH ); ++i ) 227 for ( uint i = 0; i <= ( textLine.length() / FOLD_WIDTH ); ++i )
228 text.append( ( i == 0 ? "" : " " ) + textLine.mid( i * FOLD_WIDTH, FOLD_WIDTH ) + "\r\n" ); 228 text.append( ( i == 0 ? "" : " " ) + textLine.mid( i * FOLD_WIDTH, FOLD_WIDTH ) + "\r\n" );
229 } else 229 } else
230 text.append( textLine + "\r\n" ); 230 text.append( textLine + "\r\n" );
231 } 231 }
232 } 232 }
233 } 233 }
234 234
235 text.append( "END:VCARD\r\n" ); 235 text.append( "END:VCARD\r\n" );
236 text.append( "\r\n" ); 236 text.append( "\r\n" );
237 } 237 }
238 238
239 return text; 239 return text;
240} 240}
diff --git a/kabc/vcardparser/vcardtool.cpp b/kabc/vcardparser/vcardtool.cpp
index 0cf72c0..c3d92b6 100644
--- a/kabc/vcardparser/vcardtool.cpp
+++ b/kabc/vcardparser/vcardtool.cpp
@@ -1,869 +1,869 @@
1/* 1/*
2 This file is part of libkabc. 2 This file is part of libkabc.
3 Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> 3 Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
4 4
5 This library is free software; you can redistribute it and/or 5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public 6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either 7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version. 8 version 2 of the License, or (at your option) any later version.
9 9
10 This library is distributed in the hope that it will be useful, 10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details. 13 Library General Public License for more details.
14 14
15 You should have received a copy of the GNU Library General Public License 15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to 16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. 18 Boston, MA 02111-1307, USA.
19*/ 19*/
20 20
21#include <qdatastream.h> 21#include <qdatastream.h>
22#include <qstring.h> 22#include <qstring.h>
23#include <qregexp.h> 23#include <qregexp.h>
24 24
25#include "agent.h" 25#include "agent.h"
26#include "key.h" 26#include "key.h"
27#include "picture.h" 27#include "picture.h"
28#include "secrecy.h" 28#include "secrecy.h"
29#include "sound.h" 29#include "sound.h"
30 30
31#include "vcardtool.h" 31#include "vcardtool.h"
32 32
33using namespace KABC; 33using namespace KABC;
34 34
35VCardTool::VCardTool() 35VCardTool::VCardTool()
36{ 36{
37 mAddressTypeMap.insert( "dom", Address::Dom ); 37 mAddressTypeMap.insert( "dom", Address::Dom );
38 mAddressTypeMap.insert( "intl", Address::Intl ); 38 mAddressTypeMap.insert( "intl", Address::Intl );
39 mAddressTypeMap.insert( "postal", Address::Postal ); 39 mAddressTypeMap.insert( "postal", Address::Postal );
40 mAddressTypeMap.insert( "parcel", Address::Parcel ); 40 mAddressTypeMap.insert( "parcel", Address::Parcel );
41 mAddressTypeMap.insert( "home", Address::Home ); 41 mAddressTypeMap.insert( "home", Address::Home );
42 mAddressTypeMap.insert( "work", Address::Work ); 42 mAddressTypeMap.insert( "work", Address::Work );
43 mAddressTypeMap.insert( "pref", Address::Pref ); 43 mAddressTypeMap.insert( "pref", Address::Pref );
44 44
45 mPhoneTypeMap.insert( "HOME", PhoneNumber::Home ); 45 mPhoneTypeMap.insert( "HOME", PhoneNumber::Home );
46 mPhoneTypeMap.insert( "WORK", PhoneNumber::Work ); 46 mPhoneTypeMap.insert( "WORK", PhoneNumber::Work );
47 mPhoneTypeMap.insert( "MSG", PhoneNumber::Msg ); 47 mPhoneTypeMap.insert( "MSG", PhoneNumber::Msg );
48 mPhoneTypeMap.insert( "PREF", PhoneNumber::Pref ); 48 mPhoneTypeMap.insert( "PREF", PhoneNumber::Pref );
49 mPhoneTypeMap.insert( "VOICE", PhoneNumber::Voice ); 49 mPhoneTypeMap.insert( "VOICE", PhoneNumber::Voice );
50 mPhoneTypeMap.insert( "FAX", PhoneNumber::Fax ); 50 mPhoneTypeMap.insert( "FAX", PhoneNumber::Fax );
51 mPhoneTypeMap.insert( "CELL", PhoneNumber::Cell ); 51 mPhoneTypeMap.insert( "CELL", PhoneNumber::Cell );
52 mPhoneTypeMap.insert( "VIDEO", PhoneNumber::Video ); 52 mPhoneTypeMap.insert( "VIDEO", PhoneNumber::Video );
53 mPhoneTypeMap.insert( "BBS", PhoneNumber::Bbs ); 53 mPhoneTypeMap.insert( "BBS", PhoneNumber::Bbs );
54 mPhoneTypeMap.insert( "MODEM", PhoneNumber::Modem ); 54 mPhoneTypeMap.insert( "MODEM", PhoneNumber::Modem );
55 mPhoneTypeMap.insert( "CAR", PhoneNumber::Car ); 55 mPhoneTypeMap.insert( "CAR", PhoneNumber::Car );
56 mPhoneTypeMap.insert( "ISDN", PhoneNumber::Isdn ); 56 mPhoneTypeMap.insert( "ISDN", PhoneNumber::Isdn );
57 mPhoneTypeMap.insert( "PCS", PhoneNumber::Pcs ); 57 mPhoneTypeMap.insert( "PCS", PhoneNumber::Pcs );
58 mPhoneTypeMap.insert( "PAGER", PhoneNumber::Pager ); 58 mPhoneTypeMap.insert( "PAGER", PhoneNumber::Pager );
59} 59}
60 60
61VCardTool::~VCardTool() 61VCardTool::~VCardTool()
62{ 62{
63} 63}
64 64
65// TODO: make list a const& 65// TODO: make list a const&
66QString VCardTool::createVCards( Addressee::List list, VCard::Version version ) 66QString VCardTool::createVCards( Addressee::List list, VCard::Version version )
67{ 67{
68 VCard::List vCardList; 68 VCard::List vCardList;
69 static const QRegExp semiExp(";"); 69 static const QRegExp semiExp(";");
70 70
71 Addressee::List::ConstIterator addrIt; 71 Addressee::List::ConstIterator addrIt;
72 Addressee::List::ConstIterator listEnd( list.end() ); 72 Addressee::List::ConstIterator listEnd( list.end() );
73 for ( addrIt = list.begin(); addrIt != listEnd; ++addrIt ) { 73 for ( addrIt = list.begin(); addrIt != listEnd; ++addrIt ) {
74 VCard card; 74 VCard card;
75 QStringList::ConstIterator strIt; 75 QStringList::ConstIterator strIt;
76 76
77 // ADR + LABEL 77 // ADR + LABEL
78 const Address::List addresses = (*addrIt).addresses(); 78 const Address::List addresses = (*addrIt).addresses();
79 for ( Address::List::ConstIterator it = addresses.begin(); it != addresses.end(); ++it ) { 79 for ( Address::List::ConstIterator it = addresses.begin(); it != addresses.end(); ++it ) {
80 QStringList address; 80 QStringList address;
81 81
82 bool isEmpty = ( (*it).postOfficeBox().isEmpty() && 82 bool isEmpty = ( (*it).postOfficeBox().isEmpty() &&
83 (*it).extended().isEmpty() && 83 (*it).extended().isEmpty() &&
84 (*it).street().isEmpty() && 84 (*it).street().isEmpty() &&
85 (*it).locality().isEmpty() && 85 (*it).locality().isEmpty() &&
86 (*it).region().isEmpty() && 86 (*it).region().isEmpty() &&
87 (*it).postalCode().isEmpty() && 87 (*it).postalCode().isEmpty() &&
88 (*it).country().isEmpty() ); 88 (*it).country().isEmpty() );
89 89
90 address.append( (*it).postOfficeBox().replace( semiExp, "\\;" ) ); 90 address.append( (*it).postOfficeBox().replace( semiExp, "\\;" ) );
91 address.append( (*it).extended().replace( semiExp, "\\;" ) ); 91 address.append( (*it).extended().replace( semiExp, "\\;" ) );
92 address.append( (*it).street().replace( semiExp, "\\;" ) ); 92 address.append( (*it).street().replace( semiExp, "\\;" ) );
93 address.append( (*it).locality().replace( semiExp, "\\;" ) ); 93 address.append( (*it).locality().replace( semiExp, "\\;" ) );
94 address.append( (*it).region().replace( semiExp, "\\;" ) ); 94 address.append( (*it).region().replace( semiExp, "\\;" ) );
95 address.append( (*it).postalCode().replace( semiExp, "\\;" ) ); 95 address.append( (*it).postalCode().replace( semiExp, "\\;" ) );
96 address.append( (*it).country().replace( semiExp, "\\;" ) ); 96 address.append( (*it).country().replace( semiExp, "\\;" ) );
97 97
98 VCardLine adrLine( "ADR", address.join( ";" ) ); 98 VCardLine adrLine( "ADR", address.join( ";" ) );
99 if ( version == VCard::v2_1 ) { 99 if ( version == VCard::v2_1 ) {
100 adrLine.addParameter( "CHARSET", "UTF-8" ); 100 adrLine.addParameter( "CHARSET", "UTF-8" );
101 adrLine.addParameter( "ENCODING", "8BIT" ); 101 adrLine.addParameter( "ENCODING", "8BIT" );
102 } 102 }
103 103
104 VCardLine labelLine( "LABEL", (*it).label() ); 104 VCardLine labelLine( "LABEL", (*it).label() );
105 if ( version == VCard::v2_1 ) { 105 if ( version == VCard::v2_1 ) {
106 labelLine.addParameter( "CHARSET", "UTF-8" ); 106 labelLine.addParameter( "CHARSET", "UTF-8" );
107 labelLine.addParameter( "ENCODING", "8BIT" ); 107 labelLine.addParameter( "ENCODING", "8BIT" );
108 } 108 }
109 109
110 bool hasLabel = !(*it).label().isEmpty(); 110 bool hasLabel = !(*it).label().isEmpty();
111 QMap<QString, int>::ConstIterator typeIt; 111 QMap<QString, int>::ConstIterator typeIt;
112 for ( typeIt = mAddressTypeMap.begin(); typeIt != mAddressTypeMap.end(); ++typeIt ) { 112 for ( typeIt = mAddressTypeMap.begin(); typeIt != mAddressTypeMap.end(); ++typeIt ) {
113 if ( typeIt.data() & (*it).type() ) { 113 if ( typeIt.data() & (*it).type() ) {
114 adrLine.addParameter( "TYPE", typeIt.key() ); 114 adrLine.addParameter( "TYPE", typeIt.key() );
115 if ( hasLabel ) 115 if ( hasLabel )
116 labelLine.addParameter( "TYPE", typeIt.key() ); 116 labelLine.addParameter( "TYPE", typeIt.key() );
117 } 117 }
118 } 118 }
119 119
120 if ( !isEmpty ) 120 if ( !isEmpty )
121 card.addLine( adrLine ); 121 card.addLine( adrLine );
122 if ( hasLabel ) 122 if ( hasLabel )
123 card.addLine( labelLine ); 123 card.addLine( labelLine );
124 } 124 }
125 125
126 // AGENT 126 // AGENT
127 card.addLine( createAgent( version, (*addrIt).agent() ) ); 127 card.addLine( createAgent( version, (*addrIt).agent() ) );
128 128
129 // BDAY 129 // BDAY
130 card.addLine( VCardLine( "BDAY", createDateTime( (*addrIt).birthday() ) ) ); 130 card.addLine( VCardLine( "BDAY", createDateTime( (*addrIt).birthday() ) ) );
131 131
132 // CATEGORIES 132 // CATEGORIES
133 if ( version == VCard::v3_0 ) { 133 if ( version == VCard::v3_0 ) {
134 QStringList categories = (*addrIt).categories(); 134 QStringList categories = (*addrIt).categories();
135 QStringList::Iterator catIt; 135 QStringList::Iterator catIt;
136 for ( catIt = categories.begin(); catIt != categories.end(); ++catIt ) 136 for ( catIt = categories.begin(); catIt != categories.end(); ++catIt )
137 (*catIt).replace( QRegExp(","), "\\," ); 137 (*catIt).replace( QRegExp(","), "\\," );
138 138
139 VCardLine catLine( "CATEGORIES", categories.join( "," ) ); 139 VCardLine catLine( "CATEGORIES", categories.join( "," ) );
140 if ( version == VCard::v2_1 ) { 140 if ( version == VCard::v2_1 ) {
141 catLine.addParameter( "CHARSET", "UTF-8" ); 141 catLine.addParameter( "CHARSET", "UTF-8" );
142 catLine.addParameter( "ENCODING", "8BIT" ); 142 catLine.addParameter( "ENCODING", "8BIT" );
143 } 143 }
144 144
145 card.addLine( catLine ); 145 card.addLine( catLine );
146 } 146 }
147 147
148 // CLASS 148 // CLASS
149 if ( version == VCard::v3_0 ) { 149 if ( version == VCard::v3_0 ) {
150 card.addLine( createSecrecy( (*addrIt).secrecy() ) ); 150 card.addLine( createSecrecy( (*addrIt).secrecy() ) );
151 } 151 }
152 152
153 // EMAIL 153 // EMAIL
154 const QStringList emails = (*addrIt).emails(); 154 const QStringList emails = (*addrIt).emails();
155 bool pref = true; 155 bool pref = true;
156 for ( strIt = emails.begin(); strIt != emails.end(); ++strIt ) { 156 for ( strIt = emails.begin(); strIt != emails.end(); ++strIt ) {
157 VCardLine line( "EMAIL", *strIt ); 157 VCardLine line( "EMAIL", *strIt );
158 if ( version == VCard::v2_1 ) { 158 if ( version == VCard::v2_1 ) {
159 line.addParameter( "CHARSET", "UTF-8" ); 159 line.addParameter( "CHARSET", "UTF-8" );
160 line.addParameter( "ENCODING", "8BIT" ); 160 line.addParameter( "ENCODING", "8BIT" );
161 } 161 }
162 if ( pref == true && emails.count() > 1 ) { 162 if ( pref == true && emails.count() > 1 ) {
163 line.addParameter( "TYPE", "PREF" ); 163 line.addParameter( "TYPE", "PREF" );
164 pref = false; 164 pref = false;
165 } 165 }
166 card.addLine( line ); 166 card.addLine( line );
167 } 167 }
168 168
169 // FN 169 // FN
170 VCardLine fnLine( "FN", (*addrIt).formattedName() ); 170 VCardLine fnLine( "FN", (*addrIt).formattedName() );
171 if ( version == VCard::v2_1 ) { 171 if ( version == VCard::v2_1 ) {
172 fnLine.addParameter( "CHARSET", "UTF-8" ); 172 fnLine.addParameter( "CHARSET", "UTF-8" );
173 fnLine.addParameter( "ENCODING", "8BIT" ); 173 fnLine.addParameter( "ENCODING", "8BIT" );
174 } 174 }
175 card.addLine( fnLine ); 175 card.addLine( fnLine );
176 176
177 // GEO 177 // GEO
178 Geo geo = (*addrIt).geo(); 178 Geo geo = (*addrIt).geo();
179 if ( geo.isValid() ) { 179 if ( geo.isValid() ) {
180 QString str; 180 QString str;
181 str.sprintf( "%.6f;%.6f", geo.latitude(), geo.longitude() ); 181 str.sprintf( "%.6f;%.6f", geo.latitude(), geo.longitude() );
182 card.addLine( VCardLine( "GEO", str ) ); 182 card.addLine( VCardLine( "GEO", str ) );
183 } 183 }
184 184
185 // KEY 185 // KEY
186 const Key::List keys = (*addrIt).keys(); 186 const Key::List keys = (*addrIt).keys();
187 Key::List::ConstIterator keyIt; 187 Key::List::ConstIterator keyIt;
188 for ( keyIt = keys.begin(); keyIt != keys.end(); ++keyIt ) 188 for ( keyIt = keys.begin(); keyIt != keys.end(); ++keyIt )
189 card.addLine( createKey( *keyIt ) ); 189 card.addLine( createKey( *keyIt ) );
190 190
191 // LOGO 191 // LOGO
192 card.addLine( createPicture( "LOGO", (*addrIt).logo() ) ); 192 card.addLine( createPicture( "LOGO", (*addrIt).logo() ) );
193 193
194 // MAILER 194 // MAILER
195 VCardLine mailerLine( "MAILER", (*addrIt).mailer() ); 195 VCardLine mailerLine( "MAILER", (*addrIt).mailer() );
196 if ( version == VCard::v2_1 ) { 196 if ( version == VCard::v2_1 ) {
197 mailerLine.addParameter( "CHARSET", "UTF-8" ); 197 mailerLine.addParameter( "CHARSET", "UTF-8" );
198 mailerLine.addParameter( "ENCODING", "8BIT" ); 198 mailerLine.addParameter( "ENCODING", "8BIT" );
199 } 199 }
200 card.addLine( mailerLine ); 200 card.addLine( mailerLine );
201 201
202 // N 202 // N
203 QStringList name; 203 QStringList name;
204 name.append( (*addrIt).familyName().replace( semiExp, "\\;" ) ); 204 name.append( (*addrIt).familyName().replace( semiExp, "\\;" ) );
205 name.append( (*addrIt).givenName().replace( semiExp, "\\;" ) ); 205 name.append( (*addrIt).givenName().replace( semiExp, "\\;" ) );
206 name.append( (*addrIt).additionalName().replace( semiExp, "\\;" ) ); 206 name.append( (*addrIt).additionalName().replace( semiExp, "\\;" ) );
207 name.append( (*addrIt).prefix().replace( semiExp, "\\;" ) ); 207 name.append( (*addrIt).prefix().replace( semiExp, "\\;" ) );
208 name.append( (*addrIt).suffix().replace( semiExp, "\\;" ) ); 208 name.append( (*addrIt).suffix().replace( semiExp, "\\;" ) );
209 209
210 VCardLine nLine( "N", name.join( ";" ) ); 210 VCardLine nLine( "N", name.join( ";" ) );
211 if ( version == VCard::v2_1 ) { 211 if ( version == VCard::v2_1 ) {
212 nLine.addParameter( "CHARSET", "UTF-8" ); 212 nLine.addParameter( "CHARSET", "UTF-8" );
213 nLine.addParameter( "ENCODING", "8BIT" ); 213 nLine.addParameter( "ENCODING", "8BIT" );
214 } 214 }
215 card.addLine( nLine ); 215 card.addLine( nLine );
216 216
217 // NAME 217 // NAME
218 VCardLine nameLine( "NAME", (*addrIt).name() ); 218 VCardLine nameLine( "NAME", (*addrIt).name() );
219 if ( version == VCard::v2_1 ) { 219 if ( version == VCard::v2_1 ) {
220 nameLine.addParameter( "CHARSET", "UTF-8" ); 220 nameLine.addParameter( "CHARSET", "UTF-8" );
221 nameLine.addParameter( "ENCODING", "8BIT" ); 221 nameLine.addParameter( "ENCODING", "8BIT" );
222 } 222 }
223 card.addLine( nameLine ); 223 card.addLine( nameLine );
224 224
225 // NICKNAME 225 // NICKNAME
226 if ( version == VCard::v3_0 ) 226 if ( version == VCard::v3_0 )
227 card.addLine( VCardLine( "NICKNAME", (*addrIt).nickName() ) ); 227 card.addLine( VCardLine( "NICKNAME", (*addrIt).nickName() ) );
228 228
229 // NOTE 229 // NOTE
230 VCardLine noteLine( "NOTE", (*addrIt).note() ); 230 VCardLine noteLine( "NOTE", (*addrIt).note() );
231 if ( version == VCard::v2_1 ) { 231 if ( version == VCard::v2_1 ) {
232 noteLine.addParameter( "CHARSET", "UTF-8" ); 232 noteLine.addParameter( "CHARSET", "UTF-8" );
233 noteLine.addParameter( "ENCODING", "8BIT" ); 233 noteLine.addParameter( "ENCODING", "8BIT" );
234 } 234 }
235 card.addLine( noteLine ); 235 card.addLine( noteLine );
236 236
237 // ORG 237 // ORG
238 VCardLine orgLine( "ORG", (*addrIt).organization() ); 238 VCardLine orgLine( "ORG", (*addrIt).organization() );
239 if ( version == VCard::v2_1 ) { 239 if ( version == VCard::v2_1 ) {
240 orgLine.addParameter( "CHARSET", "UTF-8" ); 240 orgLine.addParameter( "CHARSET", "UTF-8" );
241 orgLine.addParameter( "ENCODING", "8BIT" ); 241 orgLine.addParameter( "ENCODING", "8BIT" );
242 } 242 }
243 card.addLine( orgLine ); 243 card.addLine( orgLine );
244 244
245 // PHOTO 245 // PHOTO
246 card.addLine( createPicture( "PHOTO", (*addrIt).photo() ) ); 246 card.addLine( createPicture( "PHOTO", (*addrIt).photo() ) );
247 247
248 // PROID 248 // PROID
249 if ( version == VCard::v3_0 ) 249 if ( version == VCard::v3_0 )
250 card.addLine( VCardLine( "PRODID", (*addrIt).productId() ) ); 250 card.addLine( VCardLine( "PRODID", (*addrIt).productId() ) );
251 251
252 // REV 252 // REV
253 card.addLine( VCardLine( "REV", createDateTime( (*addrIt).revision() ) ) ); 253 card.addLine( VCardLine( "REV", createDateTime( (*addrIt).revision() ) ) );
254 254
255 // ROLE 255 // ROLE
256 VCardLine roleLine( "ROLE", (*addrIt).role() ); 256 VCardLine roleLine( "ROLE", (*addrIt).role() );
257 if ( version == VCard::v2_1 ) { 257 if ( version == VCard::v2_1 ) {
258 roleLine.addParameter( "CHARSET", "UTF-8" ); 258 roleLine.addParameter( "CHARSET", "UTF-8" );
259 roleLine.addParameter( "ENCODING", "8BIT" ); 259 roleLine.addParameter( "ENCODING", "8BIT" );
260 } 260 }
261 card.addLine( roleLine ); 261 card.addLine( roleLine );
262 262
263 // SORT-STRING 263 // SORT-STRING
264 if ( version == VCard::v3_0 ) 264 if ( version == VCard::v3_0 )
265 card.addLine( VCardLine( "SORT-STRING", (*addrIt).sortString() ) ); 265 card.addLine( VCardLine( "SORT-STRING", (*addrIt).sortString() ) );
266 266
267 // SOUND 267 // SOUND
268 card.addLine( createSound( (*addrIt).sound() ) ); 268 card.addLine( createSound( (*addrIt).sound() ) );
269 269
270 // TEL 270 // TEL
271 const PhoneNumber::List phoneNumbers = (*addrIt).phoneNumbers(); 271 const PhoneNumber::List phoneNumbers = (*addrIt).phoneNumbers();
272 PhoneNumber::List::ConstIterator phoneIt; 272 PhoneNumber::List::ConstIterator phoneIt;
273 for ( phoneIt = phoneNumbers.begin(); phoneIt != phoneNumbers.end(); ++phoneIt ) { 273 for ( phoneIt = phoneNumbers.begin(); phoneIt != phoneNumbers.end(); ++phoneIt ) {
274 VCardLine line( "TEL", (*phoneIt).number() ); 274 VCardLine line( "TEL", (*phoneIt).number() );
275 275
276 QMap<QString, int>::ConstIterator typeIt; 276 QMap<QString, int>::ConstIterator typeIt;
277 for ( typeIt = mPhoneTypeMap.begin(); typeIt != mPhoneTypeMap.end(); ++typeIt ) { 277 for ( typeIt = mPhoneTypeMap.begin(); typeIt != mPhoneTypeMap.end(); ++typeIt ) {
278 if ( typeIt.data() & (*phoneIt).type() ) 278 if ( typeIt.data() & (*phoneIt).type() )
279 line.addParameter( "TYPE", typeIt.key() ); 279 line.addParameter( "TYPE", typeIt.key() );
280 } 280 }
281 281
282 card.addLine( line ); 282 card.addLine( line );
283 } 283 }
284 284
285 // TITLE 285 // TITLE
286 VCardLine titleLine( "TITLE", (*addrIt).title() ); 286 VCardLine titleLine( "TITLE", (*addrIt).title() );
287 if ( version == VCard::v2_1 ) { 287 if ( version == VCard::v2_1 ) {
288 titleLine.addParameter( "CHARSET", "UTF-8" ); 288 titleLine.addParameter( "CHARSET", "UTF-8" );
289 titleLine.addParameter( "ENCODING", "8BIT" ); 289 titleLine.addParameter( "ENCODING", "8BIT" );
290 } 290 }
291 card.addLine( titleLine ); 291 card.addLine( titleLine );
292 292
293 // TZ 293 // TZ
294 TimeZone timeZone = (*addrIt).timeZone(); 294 TimeZone timeZone = (*addrIt).timeZone();
295 if ( timeZone.isValid() ) { 295 if ( timeZone.isValid() ) {
296 QString str; 296 QString str;
297 297
298 int neg = 1; 298 int neg = 1;
299 if ( timeZone.offset() < 0 ) 299 if ( timeZone.offset() < 0 )
300 neg = -1; 300 neg = -1;
301 301
302 str.sprintf( "%c%02d:%02d", ( timeZone.offset() >= 0 ? '+' : '-' ), 302 str.sprintf( "%c%02d:%02d", ( timeZone.offset() >= 0 ? '+' : '-' ),
303 ( timeZone.offset() / 60 ) * neg, 303 ( timeZone.offset() / 60 ) * neg,
304 ( timeZone.offset() % 60 ) * neg ); 304 ( timeZone.offset() % 60 ) * neg );
305 305
306 card.addLine( VCardLine( "TZ", str ) ); 306 card.addLine( VCardLine( "TZ", str ) );
307 } 307 }
308 308
309 // UID 309 // UID
310 card.addLine( VCardLine( "UID", (*addrIt).uid() ) ); 310 card.addLine( VCardLine( "UID", (*addrIt).uid() ) );
311 311
312 // URL 312 // URL
313 card.addLine( VCardLine( "URL", (*addrIt).url().url() ) ); 313 card.addLine( VCardLine( "URL", (*addrIt).url().url() ) );
314 314
315 // VERSION 315 // VERSION
316 if ( version == VCard::v2_1 ) 316 if ( version == VCard::v2_1 )
317 card.addLine( VCardLine( "VERSION", "2.1" ) ); 317 card.addLine( VCardLine( "VERSION", "2.1" ) );
318 if ( version == VCard::v3_0 ) 318 if ( version == VCard::v3_0 )
319 card.addLine( VCardLine( "VERSION", "3.0" ) ); 319 card.addLine( VCardLine( "VERSION", "3.0" ) );
320 320
321 // X- 321 // X-
322 const QStringList customs = (*addrIt).customs(); 322 const QStringList customs = (*addrIt).customs();
323 for ( strIt = customs.begin(); strIt != customs.end(); ++strIt ) { 323 for ( strIt = customs.begin(); strIt != customs.end(); ++strIt ) {
324 QString identifier = "X-" + (*strIt).left( (*strIt).find( ":" ) ); 324 QString identifier = "X-" + (*strIt).left( (*strIt).find( ":" ) );
325 QString value = (*strIt).mid( (*strIt).find( ":" ) + 1 ); 325 QString value = (*strIt).mid( (*strIt).find( ":" ) + 1 );
326 if ( value.isEmpty() ) 326 if ( value.isEmpty() )
327 continue; 327 continue;
328 328
329 VCardLine line( identifier, value ); 329 VCardLine line( identifier, value );
330 if ( version == VCard::v2_1 ) { 330 if ( version == VCard::v2_1 ) {
331 line.addParameter( "CHARSET", "UTF-8" ); 331 line.addParameter( "CHARSET", "UTF-8" );
332 line.addParameter( "ENCODING", "8BIT" ); 332 line.addParameter( "ENCODING", "8BIT" );
333 } 333 }
334 card.addLine( line ); 334 card.addLine( line );
335 } 335 }
336 336
337 vCardList.append( card ); 337 vCardList.append( card );
338 } 338 }
339 339
340 return VCardParser::createVCards( vCardList ); 340 return VCardParser::createVCards( vCardList );
341} 341}
342 342
343Addressee::List VCardTool::parseVCards( const QString& vcard ) 343Addressee::List VCardTool::parseVCards( const QString& vcard )
344{ 344{
345 static const QChar semicolonSep( ';' ); 345 static const QChar semicolonSep( ';' );
346 static const QChar commaSep( ',' ); 346 static const QChar commaSep( ',' );
347 QString identifier; 347 QString identifier;
348 348
349 Addressee::List addrList; 349 Addressee::List addrList;
350 const VCard::List vCardList = VCardParser::parseVCards( vcard ); 350 const VCard::List vCardList = VCardParser::parseVCards( vcard );
351 351
352 VCard::List::ConstIterator cardIt; 352 VCard::List::ConstIterator cardIt;
353 VCard::List::ConstIterator listEnd( vCardList.end() ); 353 VCard::List::ConstIterator listEnd( vCardList.end() );
354 for ( cardIt = vCardList.begin(); cardIt != listEnd; ++cardIt ) { 354 for ( cardIt = vCardList.begin(); cardIt != listEnd; ++cardIt ) {
355 Addressee addr; 355 Addressee addr;
356 356
357 const QStringList idents = (*cardIt).identifiers(); 357 const QStringList idents = (*cardIt).identifiers();
358 QStringList::ConstIterator identIt; 358 QStringList::ConstIterator identIt;
359 QStringList::ConstIterator identEnd( idents.end() ); 359 QStringList::ConstIterator identEnd( idents.end() );
360 for ( identIt = idents.begin(); identIt != identEnd; ++identIt ) { 360 for ( identIt = idents.begin(); identIt != identEnd; ++identIt ) {
361 const VCardLine::List lines = (*cardIt).lines( (*identIt) ); 361 const VCardLine::List lines = (*cardIt).lines( (*identIt) );
362 VCardLine::List::ConstIterator lineIt; 362 VCardLine::List::ConstIterator lineIt;
363 363
364 // iterate over the lines 364 // iterate over the lines
365 for ( lineIt = lines.begin(); lineIt != lines.end(); ++lineIt ) { 365 for ( lineIt = lines.begin(); lineIt != lines.end(); ++lineIt ) {
366 identifier = (*lineIt).identifier().lower(); 366 identifier = (*lineIt).identifier().lower();
367 // ADR 367 // ADR
368 if ( identifier == "adr" ) { 368 if ( identifier == "adr" ) {
369 Address address; 369 Address address;
370 const QStringList addrParts = splitString( semicolonSep, (*lineIt).value().asString() ); 370 const QStringList addrParts = splitString( semicolonSep, (*lineIt).valueString() );
371 if ( addrParts.count() > 0 ) 371 if ( addrParts.count() > 0 )
372 address.setPostOfficeBox( addrParts[ 0 ] ); 372 address.setPostOfficeBox( addrParts[ 0 ] );
373 if ( addrParts.count() > 1 ) 373 if ( addrParts.count() > 1 )
374 address.setExtended( addrParts[ 1 ] ); 374 address.setExtended( addrParts[ 1 ] );
375 if ( addrParts.count() > 2 ) 375 if ( addrParts.count() > 2 )
376 address.setStreet( addrParts[ 2 ] ); 376 address.setStreet( addrParts[ 2 ] );
377 if ( addrParts.count() > 3 ) 377 if ( addrParts.count() > 3 )
378 address.setLocality( addrParts[ 3 ] ); 378 address.setLocality( addrParts[ 3 ] );
379 if ( addrParts.count() > 4 ) 379 if ( addrParts.count() > 4 )
380 address.setRegion( addrParts[ 4 ] ); 380 address.setRegion( addrParts[ 4 ] );
381 if ( addrParts.count() > 5 ) 381 if ( addrParts.count() > 5 )
382 address.setPostalCode( addrParts[ 5 ] ); 382 address.setPostalCode( addrParts[ 5 ] );
383 if ( addrParts.count() > 6 ) 383 if ( addrParts.count() > 6 )
384 address.setCountry( addrParts[ 6 ] ); 384 address.setCountry( addrParts[ 6 ] );
385 385
386 int type = 0; 386 int type = 0;
387 387
388 const QStringList types = (*lineIt).parameters( "type" ); 388 const QStringList types = (*lineIt).parameters( "type" );
389 for ( QStringList::ConstIterator it = types.begin(); it != types.end(); ++it ) 389 for ( QStringList::ConstIterator it = types.begin(); it != types.end(); ++it )
390 type += mAddressTypeMap[ (*it).lower() ]; 390 type += mAddressTypeMap[ (*it).lower() ];
391 391
392 address.setType( type ); 392 address.setType( type );
393 addr.insertAddress( address ); 393 addr.insertAddress( address );
394 } 394 }
395 395
396 // AGENT 396 // AGENT
397 else if ( identifier == "agent" ) 397 else if ( identifier == "agent" )
398 addr.setAgent( parseAgent( *lineIt ) ); 398 addr.setAgent( parseAgent( *lineIt ) );
399 399
400 // BDAY 400 // BDAY
401 else if ( identifier == "bday" ) 401 else if ( identifier == "bday" )
402 addr.setBirthday( parseDateTime( (*lineIt).value().asString() ) ); 402 addr.setBirthday( parseDateTime( (*lineIt).valueString() ) );
403 403
404 // CATEGORIES 404 // CATEGORIES
405 else if ( identifier == "categories" ) { 405 else if ( identifier == "categories" ) {
406 const QStringList categories = splitString( commaSep, (*lineIt).value().asString() ); 406 const QStringList categories = splitString( commaSep, (*lineIt).valueString() );
407 addr.setCategories( categories ); 407 addr.setCategories( categories );
408 } 408 }
409 409
410 // CLASS 410 // CLASS
411 else if ( identifier == "class" ) 411 else if ( identifier == "class" )
412 addr.setSecrecy( parseSecrecy( *lineIt ) ); 412 addr.setSecrecy( parseSecrecy( *lineIt ) );
413 413
414 // EMAIL 414 // EMAIL
415 else if ( identifier == "email" ) { 415 else if ( identifier == "email" ) {
416 const QStringList types = (*lineIt).parameters( "type" ); 416 const QStringList types = (*lineIt).parameters( "type" );
417 addr.insertEmail( (*lineIt).value().asString(), types.findIndex( "PREF" ) != -1 ); 417 addr.insertEmail( (*lineIt).valueString(), types.findIndex( "PREF" ) != -1 );
418 } 418 }
419 419
420 // FN 420 // FN
421 else if ( identifier == "fn" ) 421 else if ( identifier == "fn" )
422 addr.setFormattedName( (*lineIt).value().asString() ); 422 addr.setFormattedName( (*lineIt).valueString() );
423 423
424 // GEO 424 // GEO
425 else if ( identifier == "geo" ) { 425 else if ( identifier == "geo" ) {
426 Geo geo; 426 Geo geo;
427 427
428 const QStringList geoParts = QStringList::split( ';', (*lineIt).value().asString(), true ); 428 const QStringList geoParts = QStringList::split( ';', (*lineIt).valueString(), true );
429 geo.setLatitude( geoParts[ 0 ].toFloat() ); 429 geo.setLatitude( geoParts[ 0 ].toFloat() );
430 geo.setLongitude( geoParts[ 1 ].toFloat() ); 430 geo.setLongitude( geoParts[ 1 ].toFloat() );
431 431
432 addr.setGeo( geo ); 432 addr.setGeo( geo );
433 } 433 }
434 434
435 // KEY 435 // KEY
436 else if ( identifier == "key" ) 436 else if ( identifier == "key" )
437 addr.insertKey( parseKey( *lineIt ) ); 437 addr.insertKey( parseKey( *lineIt ) );
438 438
439 // LABEL 439 // LABEL
440 else if ( identifier == "label" ) { 440 else if ( identifier == "label" ) {
441 int type = 0; 441 int type = 0;
442 442
443 const QStringList types = (*lineIt).parameters( "type" ); 443 const QStringList types = (*lineIt).parameters( "type" );
444 for ( QStringList::ConstIterator it = types.begin(); it != types.end(); ++it ) 444 for ( QStringList::ConstIterator it = types.begin(); it != types.end(); ++it )
445 type += mAddressTypeMap[ (*it).lower() ]; 445 type += mAddressTypeMap[ (*it).lower() ];
446 446
447 bool available = false; 447 bool available = false;
448 KABC::Address::List addressList = addr.addresses(); 448 KABC::Address::List addressList = addr.addresses();
449 KABC::Address::List::Iterator it; 449 KABC::Address::List::Iterator it;
450 for ( it = addressList.begin(); it != addressList.end(); ++it ) { 450 for ( it = addressList.begin(); it != addressList.end(); ++it ) {
451 if ( (*it).type() == type ) { 451 if ( (*it).type() == type ) {
452 (*it).setLabel( (*lineIt).value().asString() ); 452 (*it).setLabel( (*lineIt).valueString() );
453 addr.insertAddress( *it ); 453 addr.insertAddress( *it );
454 available = true; 454 available = true;
455 break; 455 break;
456 } 456 }
457 } 457 }
458 458
459 if ( !available ) { // a standalone LABEL tag 459 if ( !available ) { // a standalone LABEL tag
460 KABC::Address address( type ); 460 KABC::Address address( type );
461 address.setLabel( (*lineIt).value().asString() ); 461 address.setLabel( (*lineIt).valueString() );
462 addr.insertAddress( address ); 462 addr.insertAddress( address );
463 } 463 }
464 } 464 }
465 465
466 // LOGO 466 // LOGO
467 else if ( identifier == "logo" ) 467 else if ( identifier == "logo" )
468 addr.setLogo( parsePicture( *lineIt ) ); 468 addr.setLogo( parsePicture( *lineIt ) );
469 469
470 // MAILER 470 // MAILER
471 else if ( identifier == "mailer" ) 471 else if ( identifier == "mailer" )
472 addr.setMailer( (*lineIt).value().asString() ); 472 addr.setMailer( (*lineIt).valueString() );
473 473
474 // N 474 // N
475 else if ( identifier == "n" ) { 475 else if ( identifier == "n" ) {
476 const QStringList nameParts = splitString( semicolonSep, (*lineIt).value().asString() ); 476 const QStringList nameParts = splitString( semicolonSep, (*lineIt).valueString() );
477 if ( nameParts.count() > 0 ) 477 if ( nameParts.count() > 0 )
478 addr.setFamilyName( nameParts[ 0 ] ); 478 addr.setFamilyName( nameParts[ 0 ] );
479 if ( nameParts.count() > 1 ) 479 if ( nameParts.count() > 1 )
480 addr.setGivenName( nameParts[ 1 ] ); 480 addr.setGivenName( nameParts[ 1 ] );
481 if ( nameParts.count() > 2 ) 481 if ( nameParts.count() > 2 )
482 addr.setAdditionalName( nameParts[ 2 ] ); 482 addr.setAdditionalName( nameParts[ 2 ] );
483 if ( nameParts.count() > 3 ) 483 if ( nameParts.count() > 3 )
484 addr.setPrefix( nameParts[ 3 ] ); 484 addr.setPrefix( nameParts[ 3 ] );
485 if ( nameParts.count() > 4 ) 485 if ( nameParts.count() > 4 )
486 addr.setSuffix( nameParts[ 4 ] ); 486 addr.setSuffix( nameParts[ 4 ] );
487 } 487 }
488 488
489 // NAME 489 // NAME
490 else if ( identifier == "name" ) 490 else if ( identifier == "name" )
491 addr.setName( (*lineIt).value().asString() ); 491 addr.setName( (*lineIt).valueString() );
492 492
493 // NICKNAME 493 // NICKNAME
494 else if ( identifier == "nickname" ) 494 else if ( identifier == "nickname" )
495 addr.setNickName( (*lineIt).value().asString() ); 495 addr.setNickName( (*lineIt).valueString() );
496 496
497 // NOTE 497 // NOTE
498 else if ( identifier == "note" ) 498 else if ( identifier == "note" )
499 addr.setNote( (*lineIt).value().asString() ); 499 addr.setNote( (*lineIt).valueString() );
500 500
501 // ORGANIZATION 501 // ORGANIZATION
502 else if ( identifier == "org" ) 502 else if ( identifier == "org" )
503 addr.setOrganization( (*lineIt).value().asString() ); 503 addr.setOrganization( (*lineIt).valueString() );
504 504
505 // PHOTO 505 // PHOTO
506 else if ( identifier == "photo" ) 506 else if ( identifier == "photo" )
507 addr.setPhoto( parsePicture( *lineIt ) ); 507 addr.setPhoto( parsePicture( *lineIt ) );
508 508
509 // PROID 509 // PROID
510 else if ( identifier == "prodid" ) 510 else if ( identifier == "prodid" )
511 addr.setProductId( (*lineIt).value().asString() ); 511 addr.setProductId( (*lineIt).valueString() );
512 512
513 // REV 513 // REV
514 else if ( identifier == "rev" ) 514 else if ( identifier == "rev" )
515 addr.setRevision( parseDateTime( (*lineIt).value().asString() ) ); 515 addr.setRevision( parseDateTime( (*lineIt).valueString() ) );
516 516
517 // ROLE 517 // ROLE
518 else if ( identifier == "role" ) 518 else if ( identifier == "role" )
519 addr.setRole( (*lineIt).value().asString() ); 519 addr.setRole( (*lineIt).valueString() );
520 520
521 // SORT-STRING 521 // SORT-STRING
522 else if ( identifier == "sort-string" ) 522 else if ( identifier == "sort-string" )
523 addr.setSortString( (*lineIt).value().asString() ); 523 addr.setSortString( (*lineIt).valueString() );
524 524
525 // SOUND 525 // SOUND
526 else if ( identifier == "sound" ) 526 else if ( identifier == "sound" )
527 addr.setSound( parseSound( *lineIt ) ); 527 addr.setSound( parseSound( *lineIt ) );
528 528
529 // TEL 529 // TEL
530 else if ( identifier == "tel" ) { 530 else if ( identifier == "tel" ) {
531 PhoneNumber phone; 531 PhoneNumber phone;
532 phone.setNumber( (*lineIt).value().asString() ); 532 phone.setNumber( (*lineIt).valueString() );
533 533
534 int type = 0; 534 int type = 0;
535 535
536 const QStringList types = (*lineIt).parameters( "type" ); 536 const QStringList types = (*lineIt).parameters( "type" );
537 for ( QStringList::ConstIterator it = types.begin(); it != types.end(); ++it ) 537 for ( QStringList::ConstIterator it = types.begin(); it != types.end(); ++it )
538 type += mPhoneTypeMap[(*it).upper()]; 538 type += mPhoneTypeMap[(*it).upper()];
539 539
540 phone.setType( type ); 540 phone.setType( type );
541 541
542 addr.insertPhoneNumber( phone ); 542 addr.insertPhoneNumber( phone );
543 } 543 }
544 544
545 // TITLE 545 // TITLE
546 else if ( identifier == "title" ) 546 else if ( identifier == "title" )
547 addr.setTitle( (*lineIt).value().asString() ); 547 addr.setTitle( (*lineIt).valueString() );
548 548
549 // TZ 549 // TZ
550 else if ( identifier == "tz" ) { 550 else if ( identifier == "tz" ) {
551 TimeZone tz; 551 TimeZone tz;
552 const QString date = (*lineIt).value().asString(); 552 const QString date = (*lineIt).valueString();
553 553
554 int hours = date.mid( 1, 2).toInt(); 554 int hours = date.mid( 1, 2).toInt();
555 int minutes = date.mid( 4, 2 ).toInt(); 555 int minutes = date.mid( 4, 2 ).toInt();
556 int offset = ( hours * 60 ) + minutes; 556 int offset = ( hours * 60 ) + minutes;
557 offset = offset * ( date[ 0 ] == '+' ? 1 : -1 ); 557 offset = offset * ( date[ 0 ] == '+' ? 1 : -1 );
558 558
559 tz.setOffset( offset ); 559 tz.setOffset( offset );
560 addr.setTimeZone( tz ); 560 addr.setTimeZone( tz );
561 } 561 }
562 562
563 // UID 563 // UID
564 else if ( identifier == "uid" ) 564 else if ( identifier == "uid" )
565 addr.setUid( (*lineIt).value().asString() ); 565 addr.setUid( (*lineIt).valueString() );
566 566
567 // URL 567 // URL
568 else if ( identifier == "url" ) 568 else if ( identifier == "url" )
569 addr.setUrl( KURL( (*lineIt).value().asString() ) ); 569 addr.setUrl( KURL( (*lineIt).valueString() ) );
570 570
571 // X- 571 // X-
572 else if ( identifier.startsWith( "x-" ) ) { 572 else if ( identifier.startsWith( "x-" ) ) {
573 const QString key = (*lineIt).identifier().mid( 2 ); 573 const QString key = (*lineIt).identifier().mid( 2 );
574 int dash = key.find( "-" ); 574 int dash = key.find( "-" );
575 addr.insertCustom( key.left( dash ), key.mid( dash + 1 ), (*lineIt).value().asString() ); 575 addr.insertCustom( key.left( dash ), key.mid( dash + 1 ), (*lineIt).valueString() );
576 } 576 }
577 } 577 }
578 } 578 }
579 579
580 addrList.append( addr ); 580 addrList.append( addr );
581 } 581 }
582 582
583 return addrList; 583 return addrList;
584} 584}
585 585
586QDateTime VCardTool::parseDateTime( const QString &str ) 586QDateTime VCardTool::parseDateTime( const QString &str )
587{ 587{
588 QDateTime dateTime; 588 QDateTime dateTime;
589 589
590 if ( str.find( '-' ) == -1 ) { // is base format (yyyymmdd) 590 if ( str.find( '-' ) == -1 ) { // is base format (yyyymmdd)
591 dateTime.setDate( QDate( str.left( 4 ).toInt(), str.mid( 4, 2 ).toInt(), 591 dateTime.setDate( QDate( str.left( 4 ).toInt(), str.mid( 4, 2 ).toInt(),
592 str.mid( 6, 2 ).toInt() ) ); 592 str.mid( 6, 2 ).toInt() ) );
593 593
594 if ( str.find( 'T' ) ) // has time information yyyymmddThh:mm:ss 594 if ( str.find( 'T' ) ) // has time information yyyymmddThh:mm:ss
595 dateTime.setTime( QTime( str.mid( 11, 2 ).toInt(), str.mid( 14, 2 ).toInt(), 595 dateTime.setTime( QTime( str.mid( 11, 2 ).toInt(), str.mid( 14, 2 ).toInt(),
596 str.mid( 17, 2 ).toInt() ) ); 596 str.mid( 17, 2 ).toInt() ) );
597 597
598 } else { // is extended format yyyy-mm-dd 598 } else { // is extended format yyyy-mm-dd
599 dateTime.setDate( QDate( str.left( 4 ).toInt(), str.mid( 5, 2 ).toInt(), 599 dateTime.setDate( QDate( str.left( 4 ).toInt(), str.mid( 5, 2 ).toInt(),
600 str.mid( 8, 2 ).toInt() ) ); 600 str.mid( 8, 2 ).toInt() ) );
601 601
602 if ( str.find( 'T' ) ) // has time information yyyy-mm-ddThh:mm:ss 602 if ( str.find( 'T' ) ) // has time information yyyy-mm-ddThh:mm:ss
603 dateTime.setTime( QTime( str.mid( 11, 2 ).toInt(), str.mid( 14, 2 ).toInt(), 603 dateTime.setTime( QTime( str.mid( 11, 2 ).toInt(), str.mid( 14, 2 ).toInt(),
604 str.mid( 17, 2 ).toInt() ) ); 604 str.mid( 17, 2 ).toInt() ) );
605 } 605 }
606 606
607 return dateTime; 607 return dateTime;
608} 608}
609 609
610QString VCardTool::createDateTime( const QDateTime &dateTime ) 610QString VCardTool::createDateTime( const QDateTime &dateTime )
611{ 611{
612 QString str; 612 QString str;
613 613
614 if ( dateTime.date().isValid() ) { 614 if ( dateTime.date().isValid() ) {
615 str.sprintf( "%4d-%02d-%02d", dateTime.date().year(), dateTime.date().month(), 615 str.sprintf( "%4d-%02d-%02d", dateTime.date().year(), dateTime.date().month(),
616 dateTime.date().day() ); 616 dateTime.date().day() );
617 if ( dateTime.time().isValid() ) { 617 if ( dateTime.time().isValid() ) {
618 QString tmp; 618 QString tmp;
619 tmp.sprintf( "T%02d:%02d:%02dZ", dateTime.time().hour(), dateTime.time().minute(), 619 tmp.sprintf( "T%02d:%02d:%02dZ", dateTime.time().hour(), dateTime.time().minute(),
620 dateTime.time().second() ); 620 dateTime.time().second() );
621 str += tmp; 621 str += tmp;
622 } 622 }
623 } 623 }
624 624
625 return str; 625 return str;
626} 626}
627 627
628Picture VCardTool::parsePicture( const VCardLine &line ) 628Picture VCardTool::parsePicture( const VCardLine &line )
629{ 629{
630 Picture pic; 630 Picture pic;
631 631
632 const QStringList params = line.parameterList(); 632 const QStringList params = line.parameterList();
633 if ( params.findIndex( "encoding" ) != -1 ) { 633 if ( params.findIndex( "encoding" ) != -1 ) {
634 QImage img; 634 QImage img;
635 img.loadFromData( line.valueBytes() ); 635 img.loadFromData( line.valueBytes() );
636 pic.setData( img ); 636 pic.setData( img );
637 } else if ( params.findIndex( "value" ) != -1 ) { 637 } else if ( params.findIndex( "value" ) != -1 ) {
638 if ( line.parameter( "value" ).lower() == "uri" ) 638 if ( line.parameter( "value" ).lower() == "uri" )
639 pic.setUrl( line.value().asString() ); 639 pic.setUrl( line.valueString() );
640 } 640 }
641 641
642 if ( params.findIndex( "type" ) != -1 ) 642 if ( params.findIndex( "type" ) != -1 )
643 pic.setType( line.parameter( "type" ) ); 643 pic.setType( line.parameter( "type" ) );
644 644
645 return pic; 645 return pic;
646} 646}
647 647
648VCardLine VCardTool::createPicture( const QString &identifier, const Picture &pic ) 648VCardLine VCardTool::createPicture( const QString &identifier, const Picture &pic )
649{ 649{
650 VCardLine line( identifier ); 650 VCardLine line( identifier );
651 651
652 if ( pic.isIntern() ) { 652 if ( pic.isIntern() ) {
653 if ( !pic.data().isNull() ) { 653 if ( !pic.data().isNull() ) {
654 QByteArray input; 654 QByteArray input;
655 QDataStream s( input, IO_WriteOnly ); 655 QDataStream s( input, IO_WriteOnly );
656 s.setVersion( 4 ); 656 s.setVersion( 4 );
657 s << pic.data(); 657 s << pic.data();
658 line.setValue( input ); 658 line.setValueBytes( input );
659 line.addParameter( "encoding", "b" ); 659 line.addParameter( "encoding", "b" );
660 line.addParameter( "type", "image/png" ); 660 line.addParameter( "type", "image/png" );
661 } 661 }
662 } else if ( !pic.url().isEmpty() ) { 662 } else if ( !pic.url().isEmpty() ) {
663 QByteArray ba; 663 QByteArray ba;
664 line.setValue( pic.url() ); 664 line.setValueString( pic.url() );
665 line.addParameter( "value", "URI" ); 665 line.addParameter( "value", "URI" );
666 } 666 }
667 667
668 return line; 668 return line;
669} 669}
670 670
671Sound VCardTool::parseSound( const VCardLine &line ) 671Sound VCardTool::parseSound( const VCardLine &line )
672{ 672{
673 Sound snd; 673 Sound snd;
674 674
675 const QStringList params = line.parameterList(); 675 const QStringList params = line.parameterList();
676 if ( params.findIndex( "encoding" ) != -1 ) 676 if ( params.findIndex( "encoding" ) != -1 )
677 snd.setData( line.valueBytes() ); 677 snd.setData( line.valueBytes() );
678 else if ( params.findIndex( "value" ) != -1 ) { 678 else if ( params.findIndex( "value" ) != -1 ) {
679 if ( line.parameter( "value" ).lower() == "uri" ) 679 if ( line.parameter( "value" ).lower() == "uri" )
680 snd.setUrl( line.value().asString() ); 680 snd.setUrl( line.valueString() );
681 } 681 }
682 682
683/* TODO: support sound types 683/* TODO: support sound types
684 if ( params.contains( "type" ) ) 684 if ( params.contains( "type" ) )
685 snd.setType( line.parameter( "type" ) ); 685 snd.setType( line.parameter( "type" ) );
686*/ 686*/
687 687
688 return snd; 688 return snd;
689} 689}
690 690
691VCardLine VCardTool::createSound( const Sound &snd ) 691VCardLine VCardTool::createSound( const Sound &snd )
692{ 692{
693 VCardLine line( "SOUND" ); 693 VCardLine line( "SOUND" );
694 694
695 if ( snd.isIntern() ) { 695 if ( snd.isIntern() ) {
696 if ( !snd.data().isEmpty() ) { 696 if ( !snd.data().isEmpty() ) {
697 line.setValue( snd.data() ); 697 line.setValueBytes( snd.data() );
698 line.addParameter( "encoding", "b" ); 698 line.addParameter( "encoding", "b" );
699 // TODO: need to store sound type!!! 699 // TODO: need to store sound type!!!
700 } 700 }
701 } else if ( !snd.url().isEmpty() ) { 701 } else if ( !snd.url().isEmpty() ) {
702 line.setValue( snd.url() ); 702 line.setValueString( snd.url() );
703 line.addParameter( "value", "URI" ); 703 line.addParameter( "value", "URI" );
704 } 704 }
705 705
706 return line; 706 return line;
707} 707}
708 708
709Key VCardTool::parseKey( const VCardLine &line ) 709Key VCardTool::parseKey( const VCardLine &line )
710{ 710{
711 Key key; 711 Key key;
712 712
713 const QStringList params = line.parameterList(); 713 const QStringList params = line.parameterList();
714 if ( params.findIndex( "encoding" ) != -1 ) 714 if ( params.findIndex( "encoding" ) != -1 )
715 key.setBinaryData( line.valueBytes() ); 715 key.setBinaryData( line.valueBytes() );
716 else 716 else
717 key.setTextData( line.value().asString() ); 717 key.setTextData( line.valueString() );
718 718
719 if ( params.findIndex( "type" ) != -1 ) { 719 if ( params.findIndex( "type" ) != -1 ) {
720 if ( line.parameter( "type" ).lower() == "x509" ) 720 if ( line.parameter( "type" ).lower() == "x509" )
721 key.setType( Key::X509 ); 721 key.setType( Key::X509 );
722 else if ( line.parameter( "type" ).lower() == "pgp" ) 722 else if ( line.parameter( "type" ).lower() == "pgp" )
723 key.setType( Key::PGP ); 723 key.setType( Key::PGP );
724 else { 724 else {
725 key.setType( Key::Custom ); 725 key.setType( Key::Custom );
726 key.setCustomTypeString( line.parameter( "type" ) ); 726 key.setCustomTypeString( line.parameter( "type" ) );
727 } 727 }
728 } 728 }
729 729
730 return key; 730 return key;
731} 731}
732 732
733VCardLine VCardTool::createKey( const Key &key ) 733VCardLine VCardTool::createKey( const Key &key )
734{ 734{
735 VCardLine line( "KEY" ); 735 VCardLine line( "KEY" );
736 736
737 if ( key.isBinary() ) { 737 if ( key.isBinary() ) {
738 if ( !key.binaryData().isEmpty() ) { 738 if ( !key.binaryData().isEmpty() ) {
739 line.setValue( key.binaryData() ); 739 line.setValueBytes( key.binaryData() );
740 line.addParameter( "encoding", "b" ); 740 line.addParameter( "encoding", "b" );
741 } 741 }
742 } else if ( !key.textData().isEmpty() ) 742 } else if ( !key.textData().isEmpty() )
743 line.setValue( key.textData() ); 743 line.setValueString( key.textData() );
744 744
745 if ( key.type() == Key::X509 ) 745 if ( key.type() == Key::X509 )
746 line.addParameter( "type", "X509" ); 746 line.addParameter( "type", "X509" );
747 else if ( key.type() == Key::PGP ) 747 else if ( key.type() == Key::PGP )
748 line.addParameter( "type", "PGP" ); 748 line.addParameter( "type", "PGP" );
749 else if ( key.type() == Key::Custom ) 749 else if ( key.type() == Key::Custom )
750 line.addParameter( "type", key.customTypeString() ); 750 line.addParameter( "type", key.customTypeString() );
751 751
752 return line; 752 return line;
753} 753}
754 754
755Secrecy VCardTool::parseSecrecy( const VCardLine &line ) 755Secrecy VCardTool::parseSecrecy( const VCardLine &line )
756{ 756{
757 Secrecy secrecy; 757 Secrecy secrecy;
758 758
759 if ( line.value().asString().lower() == "public" ) 759 if ( line.valueString().lower() == "public" )
760 secrecy.setType( Secrecy::Public ); 760 secrecy.setType( Secrecy::Public );
761 if ( line.value().asString().lower() == "private" ) 761 if ( line.valueString().lower() == "private" )
762 secrecy.setType( Secrecy::Private ); 762 secrecy.setType( Secrecy::Private );
763 if ( line.value().asString().lower() == "confidential" ) 763 if ( line.valueString().lower() == "confidential" )
764 secrecy.setType( Secrecy::Confidential ); 764 secrecy.setType( Secrecy::Confidential );
765 765
766 return secrecy; 766 return secrecy;
767} 767}
768 768
769VCardLine VCardTool::createSecrecy( const Secrecy &secrecy ) 769VCardLine VCardTool::createSecrecy( const Secrecy &secrecy )
770{ 770{
771 VCardLine line( "CLASS" ); 771 VCardLine line( "CLASS" );
772 772
773 int type = secrecy.type(); 773 int type = secrecy.type();
774 774
775 if ( type == Secrecy::Public ) 775 if ( type == Secrecy::Public )
776 line.setValue( "PUBLIC" ); 776 line.setValueString( "PUBLIC" );
777 else if ( type == Secrecy::Private ) 777 else if ( type == Secrecy::Private )
778 line.setValue( "PRIVATE" ); 778 line.setValueString( "PRIVATE" );
779 else if ( type == Secrecy::Confidential ) 779 else if ( type == Secrecy::Confidential )
780 line.setValue( "CONFIDENTIAL" ); 780 line.setValueString( "CONFIDENTIAL" );
781 781
782 return line; 782 return line;
783} 783}
784 784
785Agent VCardTool::parseAgent( const VCardLine &line ) 785Agent VCardTool::parseAgent( const VCardLine &line )
786{ 786{
787 Agent agent; 787 Agent agent;
788 788
789 const QStringList params = line.parameterList(); 789 const QStringList params = line.parameterList();
790 if ( params.findIndex( "value" ) != -1 ) { 790 if ( params.findIndex( "value" ) != -1 ) {
791 if ( line.parameter( "value" ).lower() == "uri" ) 791 if ( line.parameter( "value" ).lower() == "uri" )
792 agent.setUrl( line.value().asString() ); 792 agent.setUrl( line.valueString() );
793 } else { 793 } else {
794 QString str = line.value().asString(); 794 QString str = line.valueString();
795 str.replace( QRegExp("\\\\n"), "\r\n" ); 795 str.replace( QRegExp("\\\\n"), "\r\n" );
796 str.replace( QRegExp("\\\\N"), "\r\n" ); 796 str.replace( QRegExp("\\\\N"), "\r\n" );
797 str.replace( QRegExp("\\\\;"), ";" ); 797 str.replace( QRegExp("\\\\;"), ";" );
798 str.replace( QRegExp("\\\\:"), ":" ); 798 str.replace( QRegExp("\\\\:"), ":" );
799 str.replace( QRegExp("\\\\,"), "," ); 799 str.replace( QRegExp("\\\\,"), "," );
800 800
801 const Addressee::List list = parseVCards( str ); 801 const Addressee::List list = parseVCards( str );
802 if ( list.count() > 0 ) { 802 if ( list.count() > 0 ) {
803 Addressee *addr = new Addressee; 803 Addressee *addr = new Addressee;
804 *addr = list[ 0 ]; 804 *addr = list[ 0 ];
805 agent.setAddressee( addr ); 805 agent.setAddressee( addr );
806 } 806 }
807 } 807 }
808 808
809 return agent; 809 return agent;
810} 810}
811 811
812VCardLine VCardTool::createAgent( VCard::Version version, const Agent &agent ) 812VCardLine VCardTool::createAgent( VCard::Version version, const Agent &agent )
813{ 813{
814 VCardLine line( "AGENT" ); 814 VCardLine line( "AGENT" );
815 815
816 if ( agent.isIntern() ) { 816 if ( agent.isIntern() ) {
817 if ( agent.addressee() != 0 ) { 817 if ( agent.addressee() != 0 ) {
818 Addressee::List list; 818 Addressee::List list;
819 list.append( *agent.addressee() ); 819 list.append( *agent.addressee() );
820 820
821 QString str = createVCards( list, version ); 821 QString str = createVCards( list, version );
822 str.replace( QRegExp("\\r\\n"), "\\n" ); 822 str.replace( QRegExp("\\r\\n"), "\\n" );
823 str.replace( QRegExp(";"), "\\;" ); 823 str.replace( QRegExp(";"), "\\;" );
824 str.replace( QRegExp(":"), "\\:" ); 824 str.replace( QRegExp(":"), "\\:" );
825 str.replace( QRegExp(","), "\\," ); 825 str.replace( QRegExp(","), "\\," );
826 line.setValue( str ); 826 line.setValueString( str );
827 } 827 }
828 } else if ( !agent.url().isEmpty() ) { 828 } else if ( !agent.url().isEmpty() ) {
829 line.setValue( agent.url() ); 829 line.setValueString( agent.url() );
830 line.addParameter( "value", "URI" ); 830 line.addParameter( "value", "URI" );
831 } 831 }
832 832
833 return line; 833 return line;
834} 834}
835 835
836QStringList VCardTool::splitString( const QChar &sep, const QString &str ) 836QStringList VCardTool::splitString( const QChar &sep, const QString &str )
837{ 837{
838 QStringList list; 838 QStringList list;
839 QString value( str ); 839 QString value( str );
840 840
841 int start = 0; 841 int start = 0;
842 int pos = value.find( sep, start ); 842 int pos = value.find( sep, start );
843 843
844 while ( pos != -1 ) { 844 while ( pos != -1 ) {
845 if ( value[ pos - 1 ] != '\\' ) { 845 if ( value[ pos - 1 ] != '\\' ) {
846 if ( pos > start && pos <= (int)value.length() ) 846 if ( pos > start && pos <= (int)value.length() )
847 list << value.mid( start, pos - start ); 847 list << value.mid( start, pos - start );
848 else 848 else
849 list << QString::null; 849 list << QString::null;
850 850
851 start = pos + 1; 851 start = pos + 1;
852 pos = value.find( sep, start ); 852 pos = value.find( sep, start );
853 } else { 853 } else {
854 if ( pos != 0 ) { 854 if ( pos != 0 ) {
855 value.replace( pos - 1, 2, sep ); 855 value.replace( pos - 1, 2, sep );
856 pos = value.find( sep, pos ); 856 pos = value.find( sep, pos );
857 } else 857 } else
858 pos = value.find( sep, pos + 1 ); 858 pos = value.find( sep, pos + 1 );
859 } 859 }
860 } 860 }
861 861
862 int l = value.length() - 1; 862 int l = value.length() - 1;
863 if ( value.mid( start, l - start + 1 ).length() > 0 ) 863 if ( value.mid( start, l - start + 1 ).length() > 0 )
864 list << value.mid( start, l - start + 1 ); 864 list << value.mid( start, l - start + 1 );
865 else 865 else
866 list << QString::null; 866 list << QString::null;
867 867
868 return list; 868 return list;
869} 869}
diff --git a/kaddressbook/views/cardview.cpp b/kaddressbook/views/cardview.cpp
index 84d3116..b6e053f 100644
--- a/kaddressbook/views/cardview.cpp
+++ b/kaddressbook/views/cardview.cpp
@@ -427,1042 +427,1041 @@ bool CardViewItem::isSelected() const
427{ 427{
428 return d->mSelected; 428 return d->mSelected;
429} 429}
430 430
431void CardViewItem::setSelected(bool selected) 431void CardViewItem::setSelected(bool selected)
432{ 432{
433 d->mSelected = selected; 433 d->mSelected = selected;
434} 434}
435 435
436void CardViewItem::insertField(const QString &label, const QString &value) 436void CardViewItem::insertField(const QString &label, const QString &value)
437{ 437{
438 CardViewItem::Field *f = new CardViewItem::Field(label, value); 438 CardViewItem::Field *f = new CardViewItem::Field(label, value);
439 d->mFieldList.append(f); 439 d->mFieldList.append(f);
440 d->hcache=0; 440 d->hcache=0;
441 441
442 if (mView) 442 if (mView)
443 { 443 {
444 mView->setLayoutDirty(true); 444 mView->setLayoutDirty(true);
445 d->maxLabelWidth = QMAX( mView->d->mFm->width( label ), d->maxLabelWidth ); 445 d->maxLabelWidth = QMAX( mView->d->mFm->width( label ), d->maxLabelWidth );
446 } 446 }
447} 447}
448 448
449void CardViewItem::removeField(const QString &label) 449void CardViewItem::removeField(const QString &label)
450{ 450{
451 CardViewItem::Field *f; 451 CardViewItem::Field *f;
452 452
453 QPtrListIterator< CardViewItem::Field > iter(d->mFieldList); 453 QPtrListIterator< CardViewItem::Field > iter(d->mFieldList);
454 for (iter.toFirst(); iter.current(); ++iter) 454 for (iter.toFirst(); iter.current(); ++iter)
455 { 455 {
456 f = *iter; 456 f = *iter;
457 if (f->first == label) 457 if (f->first == label)
458 break; 458 break;
459 } 459 }
460 460
461 if (*iter) 461 if (*iter)
462 d->mFieldList.remove(*iter); 462 d->mFieldList.remove(*iter);
463 d->hcache = 0; 463 d->hcache = 0;
464 464
465 if (mView) 465 if (mView)
466 mView->setLayoutDirty(true); 466 mView->setLayoutDirty(true);
467} 467}
468 468
469void CardViewItem::clearFields() 469void CardViewItem::clearFields()
470{ 470{
471 d->mFieldList.clear(); 471 d->mFieldList.clear();
472 d->hcache = 0; 472 d->hcache = 0;
473 473
474 if (mView) 474 if (mView)
475 mView->setLayoutDirty(true); 475 mView->setLayoutDirty(true);
476} 476}
477 477
478QString CardViewItem::trimString(const QString &text, int width, 478QString CardViewItem::trimString(const QString &text, int width,
479 QFontMetrics &fm) 479 QFontMetrics &fm)
480{ 480{
481 if (fm.width(text) <= width) 481 if (fm.width(text) <= width)
482 return text; 482 return text;
483 483
484 QString dots = "..."; 484 QString dots = "...";
485 int dotWidth = fm.width(dots); 485 int dotWidth = fm.width(dots);
486 QString trimmed; 486 QString trimmed;
487 int charNum = 0; 487 int charNum = 0;
488 488
489 while (fm.width(trimmed) + dotWidth < width) 489 while (fm.width(trimmed) + dotWidth < width)
490 { 490 {
491 trimmed += text[charNum]; 491 trimmed += text[charNum];
492 charNum++; 492 charNum++;
493 } 493 }
494 494
495 // Now trim the last char, since it put the width over the top 495 // Now trim the last char, since it put the width over the top
496 trimmed = trimmed.left(trimmed.length()-1); 496 trimmed = trimmed.left(trimmed.length()-1);
497 trimmed += dots; 497 trimmed += dots;
498 498
499 return trimmed; 499 return trimmed;
500} 500}
501 501
502CardViewItem *CardViewItem::nextItem() 502CardViewItem *CardViewItem::nextItem()
503{ 503{
504 CardViewItem *item = 0; 504 CardViewItem *item = 0;
505 505
506 if (mView) 506 if (mView)
507 item = mView->itemAfter(this); 507 item = mView->itemAfter(this);
508 508
509 return item; 509 return item;
510} 510}
511 511
512void CardViewItem::repaintCard() 512void CardViewItem::repaintCard()
513{ 513{
514 if (mView) 514 if (mView)
515 mView->repaintItem(this); 515 mView->repaintItem(this);
516} 516}
517 517
518void CardViewItem::setCaption(const QString &caption) 518void CardViewItem::setCaption(const QString &caption)
519{ 519{
520 d->mCaption = caption; 520 d->mCaption = caption;
521 repaintCard(); 521 repaintCard();
522} 522}
523 523
524QString CardViewItem::fieldValue(const QString &label) 524QString CardViewItem::fieldValue(const QString &label)
525{ 525{
526 QPtrListIterator< CardViewItem::Field > iter(d->mFieldList); 526 QPtrListIterator< CardViewItem::Field > iter(d->mFieldList);
527 for (iter.toFirst(); iter.current(); ++iter) 527 for (iter.toFirst(); iter.current(); ++iter)
528 if ((*iter)->first == label) 528 if ((*iter)->first == label)
529 return (*iter)->second; 529 return (*iter)->second;
530 530
531 return QString(); 531 return QString();
532} 532}
533 533
534 534
535void CardViewItem::showFullString( const QPoint &itempos, CardViewTip *tip ) 535void CardViewItem::showFullString( const QPoint &itempos, CardViewTip *tip )
536{ 536{
537 bool trimmed( false ); 537 bool trimmed( false );
538 QString s; 538 QString s;
539 int mrg = mView->itemMargin(); 539 int mrg = mView->itemMargin();
540 int y = mView->d->mBFm->height() + 6 + mrg; 540 int y = mView->d->mBFm->height() + 6 + mrg;
541 int w = mView->itemWidth() - (2*mrg); 541 int w = mView->itemWidth() - (2*mrg);
542 int lw; 542 int lw;
543 bool drawLabels = mView->drawFieldLabels(); 543 bool drawLabels = mView->drawFieldLabels();
544 bool isLabel = drawLabels && itempos.x() < w/2 ? true : false; 544 bool isLabel = drawLabels && itempos.x() < w/2 ? true : false;
545 545
546 if ( itempos.y() < y ) 546 if ( itempos.y() < y )
547 { 547 {
548 if ( itempos.y() < 8 + mrg || itempos.y() > y - 4 ) 548 if ( itempos.y() < 8 + mrg || itempos.y() > y - 4 )
549 return; 549 return;
550 // this is the caption 550 // this is the caption
551 s = caption(); 551 s = caption();
552 trimmed = mView->d->mBFm->width( s ) > w - 4; 552 trimmed = mView->d->mBFm->width( s ) > w - 4;
553 y = 2 + mrg; 553 y = 2 + mrg;
554 lw = 0; 554 lw = 0;
555 isLabel=true; 555 isLabel=true;
556 } else { 556 } else {
557 // find the field 557 // find the field
558 Field *f = fieldAt( itempos ); 558 Field *f = fieldAt( itempos );
559 if ( !f || ( !mView->showEmptyFields() && f->second.isEmpty() ) ) 559 if ( !f || ( !mView->showEmptyFields() && f->second.isEmpty() ) )
560 return; 560 return;
561 561
562 // y position: 562 // y position:
563 // header font height + 4px hader margin + 2px leading + item margin 563 // header font height + 4px hader margin + 2px leading + item margin
564 // + actual field index * (fontheight + 2px leading) 564 // + actual field index * (fontheight + 2px leading)
565 int maxLines = mView->maxFieldLines(); 565 int maxLines = mView->maxFieldLines();
566 bool se = mView->showEmptyFields(); 566 bool se = mView->showEmptyFields();
567 int fh = mView->d->mFm->height(); 567 int fh = mView->d->mFm->height();
568// { 568// {
569 Field *_f; 569 Field *_f;
570 for (_f = d->mFieldList.first(); _f != f; _f = d->mFieldList.next()) 570 for (_f = d->mFieldList.first(); _f != f; _f = d->mFieldList.next())
571 if ( se || ! _f->second.isEmpty() ) 571 if ( se || ! _f->second.isEmpty() )
572 y += ( QMIN(_f->second.contains('\n')+1, maxLines) * fh ) + 2; 572 y += ( QMIN(_f->second.contains('\n')+1, maxLines) * fh ) + 2;
573// } 573// }
574 if ( isLabel && itempos.y() > y + fh ) 574 if ( isLabel && itempos.y() > y + fh )
575 return; 575 return;
576 // label or data? 576 // label or data?
577 s = isLabel ? f->first : f->second; 577 s = isLabel ? f->first : f->second;
578 // trimmed? 578 // trimmed?
579 int colonWidth = mView->d->mFm->width(":"); 579 int colonWidth = mView->d->mFm->width(":");
580 lw = drawLabels ? // label width 580 lw = drawLabels ? // label width
581 QMIN( w/2 - 4 - mrg, d->maxLabelWidth + colonWidth + 4 ) : 581 QMIN( w/2 - 4 - mrg, d->maxLabelWidth + colonWidth + 4 ) :
582 0; 582 0;
583 int mw = isLabel ? lw - colonWidth : w - lw - (mrg*2); // max width for string 583 int mw = isLabel ? lw - colonWidth : w - lw - (mrg*2); // max width for string
584 if ( isLabel ) 584 if ( isLabel )
585 { 585 {
586 trimmed = mView->d->mFm->width( s ) > mw - colonWidth; 586 trimmed = mView->d->mFm->width( s ) > mw - colonWidth;
587 } else { 587 } else {
588 QRect r( mView->d->mFm->boundingRect( 0, 0, INT_MAX, INT_MAX, Qt::AlignTop|Qt::AlignLeft, s ) ); 588 QRect r( mView->d->mFm->boundingRect( 0, 0, INT_MAX, INT_MAX, Qt::AlignTop|Qt::AlignLeft, s ) );
589 trimmed = r.width() > mw || r.height()/fh > QMIN(s.contains('\n') + 1, maxLines); 589 trimmed = r.width() > mw || r.height()/fh > QMIN(s.contains('\n') + 1, maxLines);
590 } 590 }
591 } 591 }
592 if ( trimmed ) 592 if ( trimmed )
593 { 593 {
594 tip->setFont( (isLabel && !lw) ? mView->headerFont() : mView->font() ); // if condition is true, a header 594 tip->setFont( (isLabel && !lw) ? mView->headerFont() : mView->font() ); // if condition is true, a header
595 tip->setText( s ); 595 tip->setText( s );
596 tip->adjustSize(); 596 tip->adjustSize();
597 // find a proper position 597 // find a proper position
598 int lx; 598 int lx;
599 lx = isLabel || !drawLabels ? mrg : lw + mrg + 2 /*-1*/; 599 lx = isLabel || !drawLabels ? mrg : lw + mrg + 2 /*-1*/;
600 QPoint pnt(mView->contentsToViewport( QPoint(d->x, d->y) )); 600 QPoint pnt(mView->contentsToViewport( QPoint(d->x, d->y) ));
601 pnt += QPoint(lx, y); 601 pnt += QPoint(lx, y);
602 if ( pnt.x() < 0 ) 602 if ( pnt.x() < 0 )
603 pnt.setX( 0 ); 603 pnt.setX( 0 );
604 if ( pnt.x() + tip->width() > mView->visibleWidth() ) 604 if ( pnt.x() + tip->width() > mView->visibleWidth() )
605 pnt.setX( mView->visibleWidth() - tip->width() ); 605 pnt.setX( mView->visibleWidth() - tip->width() );
606 if ( pnt.y() + tip->height() > mView->visibleHeight() ) 606 if ( pnt.y() + tip->height() > mView->visibleHeight() )
607 pnt.setY( QMAX( 0, mView->visibleHeight() - tip->height() ) ); 607 pnt.setY( QMAX( 0, mView->visibleHeight() - tip->height() ) );
608 // show 608 // show
609 tip->move( pnt ); 609 tip->move( pnt );
610 tip->show(); 610 tip->show();
611 } 611 }
612} 612}
613 613
614CardViewItem::Field *CardViewItem::fieldAt( const QPoint & itempos ) const 614CardViewItem::Field *CardViewItem::fieldAt( const QPoint & itempos ) const
615{ 615{
616 int ypos = mView->d->mBFm->height() + 7 + mView->d->mItemMargin; 616 int ypos = mView->d->mBFm->height() + 7 + mView->d->mItemMargin;
617 int iy = itempos.y(); 617 int iy = itempos.y();
618 // skip below caption 618 // skip below caption
619 if ( iy <= ypos ) 619 if ( iy <= ypos )
620 return 0; 620 return 0;
621 // try find a field 621 // try find a field
622 bool showEmpty = mView->showEmptyFields(); 622 bool showEmpty = mView->showEmptyFields();
623 int fh = mView->d->mFm->height(); 623 int fh = mView->d->mFm->height();
624 int maxLines = mView->maxFieldLines(); 624 int maxLines = mView->maxFieldLines();
625 Field *f; 625 Field *f;
626 for ( f = d->mFieldList.first(); f; f = d->mFieldList.next() ) 626 for ( f = d->mFieldList.first(); f; f = d->mFieldList.next() )
627 { 627 {
628 if ( showEmpty || !f->second.isEmpty() ) 628 if ( showEmpty || !f->second.isEmpty() )
629 ypos += ( QMIN( f->second.contains('\n')+1, maxLines ) *fh)+2; 629 ypos += ( QMIN( f->second.contains('\n')+1, maxLines ) *fh)+2;
630 if ( iy <= ypos ) 630 if ( iy <= ypos )
631 break; 631 break;
632 } 632 }
633 return f ? f : 0; 633 return f ? f : 0;
634} 634}
635//END CardViewItem 635//END CardViewItem
636 636
637//BEGIN CardView 637//BEGIN CardView
638 638
639CardView::CardView(QWidget *parent, const char *name) 639CardView::CardView(QWidget *parent, const char *name)
640 : QScrollView(parent, name), 640 : QScrollView(parent, name),
641 d(new CardViewPrivate()) 641 d(new CardViewPrivate())
642{ 642{
643 mFlagKeyPressed = false; 643 mFlagKeyPressed = false;
644 mFlagBlockKeyPressed = false; 644 mFlagBlockKeyPressed = false;
645 d->mItemList.setAutoDelete(true); 645 d->mItemList.setAutoDelete(true);
646 d->mSeparatorList.setAutoDelete(true); 646 d->mSeparatorList.setAutoDelete(true);
647 647
648 QFont f = font(); 648 QFont f = font();
649 d->mFm = new QFontMetrics(f); 649 d->mFm = new QFontMetrics(f);
650 f.setBold(true); 650 f.setBold(true);
651 d->mHeaderFont = f; 651 d->mHeaderFont = f;
652 d->mBFm = new QFontMetrics(f); 652 d->mBFm = new QFontMetrics(f);
653 d->mTip = ( new CardViewTip( viewport() ) ), 653 d->mTip = ( new CardViewTip( viewport() ) ),
654 d->mTip->hide(); 654 d->mTip->hide();
655 d->mTimer = ( new QTimer(this, "mouseTimer") ), 655 d->mTimer = ( new QTimer(this, "mouseTimer") ),
656 656
657 viewport()->setMouseTracking( true ); 657 viewport()->setMouseTracking( true );
658 viewport()->setFocusProxy(this); 658 viewport()->setFocusProxy(this);
659 viewport()->setFocusPolicy(WheelFocus); 659 viewport()->setFocusPolicy(WheelFocus);
660 viewport()->setBackgroundMode(PaletteBase); 660 viewport()->setBackgroundMode(PaletteBase);
661 661
662 connect( d->mTimer, SIGNAL(timeout()), this, SLOT(tryShowFullText()) ); 662 connect( d->mTimer, SIGNAL(timeout()), this, SLOT(tryShowFullText()) );
663 663
664//US setBackgroundMode(PaletteBackground, PaletteBase); 664//US setBackgroundMode(PaletteBackground, PaletteBase);
665 setBackgroundMode(PaletteBackground); 665 setBackgroundMode(PaletteBackground);
666 666
667 // no reason for a vertical scrollbar 667 // no reason for a vertical scrollbar
668 setVScrollBarMode(AlwaysOff); 668 setVScrollBarMode(AlwaysOff);
669} 669}
670 670
671CardView::~CardView() 671CardView::~CardView()
672{ 672{
673 delete d->mFm; 673 delete d->mFm;
674 delete d->mBFm; 674 delete d->mBFm;
675 delete d; 675 delete d;
676 d = 0; 676 d = 0;
677} 677}
678 678
679void CardView::insertItem(CardViewItem *item) 679void CardView::insertItem(CardViewItem *item)
680{ 680{
681 d->mItemList.inSort(item); 681 d->mItemList.inSort(item);
682 setLayoutDirty(true); 682 setLayoutDirty(true);
683} 683}
684 684
685void CardView::takeItem(CardViewItem *item) 685void CardView::takeItem(CardViewItem *item)
686{ 686{
687 if ( d->mCurrentItem == item ) 687 if ( d->mCurrentItem == item )
688 d->mCurrentItem = item->nextItem(); 688 d->mCurrentItem = item->nextItem();
689 d->mItemList.take(d->mItemList.findRef(item)); 689 d->mItemList.take(d->mItemList.findRef(item));
690 690
691 setLayoutDirty(true); 691 setLayoutDirty(true);
692} 692}
693 693
694void CardView::clear() 694void CardView::clear()
695{ 695{
696 d->mItemList.clear(); 696 d->mItemList.clear();
697 697
698 setLayoutDirty(true); 698 setLayoutDirty(true);
699} 699}
700 700
701CardViewItem *CardView::currentItem() 701CardViewItem *CardView::currentItem()
702{ 702{
703 if ( ! d->mCurrentItem && d->mItemList.count() ) 703 if ( ! d->mCurrentItem && d->mItemList.count() )
704 d->mCurrentItem = d->mItemList.first(); 704 d->mCurrentItem = d->mItemList.first();
705 return d->mCurrentItem; 705 return d->mCurrentItem;
706} 706}
707 707
708void CardView::setCurrentItem( CardViewItem *item ) 708void CardView::setCurrentItem( CardViewItem *item )
709{ 709{
710 if ( !item ) 710 if ( !item )
711 return; 711 return;
712 else if ( item->cardView() != this ) 712 else if ( item->cardView() != this )
713 { 713 {
714 kdDebug(5720)<<"CardView::setCurrentItem: Item ("<<item<<") not owned! Backing out.."<<endl; 714 kdDebug(5720)<<"CardView::setCurrentItem: Item ("<<item<<") not owned! Backing out.."<<endl;
715 return; 715 return;
716 } 716 }
717 else if ( item == currentItem() ) 717 else if ( item == currentItem() )
718 { 718 {
719 return; 719 return;
720 } 720 }
721 721
722 if ( d->mSelectionMode == Single ) 722 if ( d->mSelectionMode == Single )
723 { 723 {
724 setSelected( item, true ); 724 setSelected( item, true );
725 } 725 }
726 else 726 else
727 { 727 {
728 CardViewItem *it = d->mCurrentItem; 728 CardViewItem *it = d->mCurrentItem;
729 d->mCurrentItem = item; 729 d->mCurrentItem = item;
730 if ( it ) 730 if ( it )
731 it->repaintCard(); 731 it->repaintCard();
732 item->repaintCard(); 732 item->repaintCard();
733 } 733 }
734 if ( ! d->mOnSeparator ) 734 if ( ! d->mOnSeparator )
735 ensureItemVisible( item ); 735 ensureItemVisible( item );
736 emit currentChanged( item ); 736 emit currentChanged( item );
737} 737}
738 738
739CardViewItem *CardView::itemAt(const QPoint &viewPos) 739CardViewItem *CardView::itemAt(const QPoint &viewPos)
740{ 740{
741 CardViewItem *item = 0; 741 CardViewItem *item = 0;
742 QPtrListIterator<CardViewItem> iter(d->mItemList); 742 QPtrListIterator<CardViewItem> iter(d->mItemList);
743 bool found = false; 743 bool found = false;
744 for (iter.toFirst(); iter.current() && !found; ++iter) 744 for (iter.toFirst(); iter.current() && !found; ++iter)
745 { 745 {
746 item = *iter; 746 item = *iter;
747 //if (item->d->mRect.contains(viewPos)) 747 //if (item->d->mRect.contains(viewPos))
748 if (QRect(item->d->x, item->d->y, d->mItemWidth, item->height()).contains(viewPos)) 748 if (QRect(item->d->x, item->d->y, d->mItemWidth, item->height()).contains(viewPos))
749 found = true; 749 found = true;
750 } 750 }
751 751
752 if (found) 752 if (found)
753 return item; 753 return item;
754 754
755 return 0; 755 return 0;
756} 756}
757 757
758QRect CardView::itemRect(const CardViewItem *item) 758QRect CardView::itemRect(const CardViewItem *item)
759{ 759{
760 //return item->d->mRect; 760 //return item->d->mRect;
761 return QRect(item->d->x, item->d->y, d->mItemWidth, item->height()); 761 return QRect(item->d->x, item->d->y, d->mItemWidth, item->height());
762} 762}
763 763
764void CardView::ensureItemVisible(const CardViewItem *item) 764void CardView::ensureItemVisible(const CardViewItem *item)
765{ 765{
766 ensureVisible(item->d->x , item->d->y, d->mItemSpacing, 0); 766 ensureVisible(item->d->x , item->d->y, d->mItemSpacing, 0);
767 ensureVisible(item->d->x + d->mItemWidth, item->d->y, d->mItemSpacing, 0); 767 ensureVisible(item->d->x + d->mItemWidth, item->d->y, d->mItemSpacing, 0);
768} 768}
769 769
770void CardView::repaintItem(const CardViewItem *item) 770void CardView::repaintItem(const CardViewItem *item)
771{ 771{
772 //repaintContents(item->d->mRect); 772 //repaintContents(item->d->mRect);
773 repaintContents( QRect(item->d->x, item->d->y, d->mItemWidth, item->height()) ); 773 repaintContents( QRect(item->d->x, item->d->y, d->mItemWidth, item->height()) );
774} 774}
775 775
776void CardView::setSelectionMode(CardView::SelectionMode mode) 776void CardView::setSelectionMode(CardView::SelectionMode mode)
777{ 777{
778 selectAll(false); 778 selectAll(false);
779 779
780 d->mSelectionMode = mode; 780 d->mSelectionMode = mode;
781} 781}
782 782
783CardView::SelectionMode CardView::selectionMode() const 783CardView::SelectionMode CardView::selectionMode() const
784{ 784{
785 return d->mSelectionMode; 785 return d->mSelectionMode;
786} 786}
787 787
788void CardView::selectAll(bool state) 788void CardView::selectAll(bool state)
789{ 789{
790 QPtrListIterator<CardViewItem> iter(d->mItemList); 790 QPtrListIterator<CardViewItem> iter(d->mItemList);
791 if (!state) 791 if (!state)
792 { 792 {
793 for (iter.toFirst(); iter.current(); ++iter) 793 for (iter.toFirst(); iter.current(); ++iter)
794 { 794 {
795 if ((*iter)->isSelected()) 795 if ((*iter)->isSelected())
796 { 796 {
797 (*iter)->setSelected(false); 797 (*iter)->setSelected(false);
798 (*iter)->repaintCard(); 798 (*iter)->repaintCard();
799 } 799 }
800 } 800 }
801 //emit selectionChanged(); // WARNING FIXME 801 //emit selectionChanged(); // WARNING FIXME
802 emit selectionChanged(0); 802 emit selectionChanged(0);
803 } 803 }
804 else if (d->mSelectionMode != CardView::Single) 804 else if (d->mSelectionMode != CardView::Single)
805 { 805 {
806 for (iter.toFirst(); iter.current(); ++iter) 806 for (iter.toFirst(); iter.current(); ++iter)
807 { 807 {
808 (*iter)->setSelected(true); 808 (*iter)->setSelected(true);
809 } 809 }
810 810
811 if (d->mItemList.count() > 0) 811 if (d->mItemList.count() > 0)
812 { 812 {
813 // emit, since there must have been at least one selected 813 // emit, since there must have been at least one selected
814 emit selectionChanged(); 814 emit selectionChanged();
815 //repaint();//??? 815 //repaint();//???
816 viewport()->update(); 816 viewport()->update();
817 } 817 }
818 } 818 }
819} 819}
820 820
821void CardView::setSelected(CardViewItem *item, bool selected) 821void CardView::setSelected(CardViewItem *item, bool selected)
822{ 822{
823 if ((item == 0) || (item->isSelected() == selected)) 823 if ((item == 0) || (item->isSelected() == selected))
824 return; 824 return;
825 825
826 if ( selected && d->mCurrentItem != item ) 826 if ( selected && d->mCurrentItem != item )
827 { 827 {
828 CardViewItem *it = d->mCurrentItem; 828 CardViewItem *it = d->mCurrentItem;
829 d->mCurrentItem = item; 829 d->mCurrentItem = item;
830 if ( it ) 830 if ( it )
831 it->repaintCard(); 831 it->repaintCard();
832 } 832 }
833 833
834 if (d->mSelectionMode == CardView::Single) 834 if (d->mSelectionMode == CardView::Single)
835 { 835 {
836 bool b = signalsBlocked(); 836 bool b = signalsBlocked();
837 blockSignals(true); 837 blockSignals(true);
838 selectAll(false); 838 selectAll(false);
839 blockSignals(b); 839 blockSignals(b);
840 840
841 if (selected) 841 if (selected)
842 { 842 {
843 item->setSelected(selected); 843 item->setSelected(selected);
844 item->repaintCard(); 844 item->repaintCard();
845 emit selectionChanged(); 845 emit selectionChanged();
846 emit selectionChanged(item); 846 emit selectionChanged(item);
847 } 847 }
848 else 848 else
849 { 849 {
850 emit selectionChanged(); 850 emit selectionChanged();
851 emit selectionChanged(0); 851 emit selectionChanged(0);
852 } 852 }
853 } 853 }
854 else if (d->mSelectionMode == CardView::Multi) 854 else if (d->mSelectionMode == CardView::Multi)
855 { 855 {
856 item->setSelected(selected); 856 item->setSelected(selected);
857 item->repaintCard(); 857 item->repaintCard();
858 emit selectionChanged(); 858 emit selectionChanged();
859 } 859 }
860 else if (d->mSelectionMode == CardView::Extended) 860 else if (d->mSelectionMode == CardView::Extended)
861 { 861 {
862 bool b = signalsBlocked(); 862 bool b = signalsBlocked();
863 blockSignals(true); 863 blockSignals(true);
864 selectAll(false); 864 selectAll(false);
865 blockSignals(b); 865 blockSignals(b);
866 866
867 item->setSelected(selected); 867 item->setSelected(selected);
868 item->repaintCard(); 868 item->repaintCard();
869 emit selectionChanged(); 869 emit selectionChanged();
870 } 870 }
871} 871}
872 872
873bool CardView::isSelected(CardViewItem *item) const 873bool CardView::isSelected(CardViewItem *item) const
874{ 874{
875 return (item && item->isSelected()); 875 return (item && item->isSelected());
876} 876}
877 877
878CardViewItem *CardView::selectedItem() const 878CardViewItem *CardView::selectedItem() const
879{ 879{
880 // find the first selected item 880 // find the first selected item
881 QPtrListIterator<CardViewItem> iter(d->mItemList); 881 QPtrListIterator<CardViewItem> iter(d->mItemList);
882 for (iter.toFirst(); iter.current(); ++iter) 882 for (iter.toFirst(); iter.current(); ++iter)
883 { 883 {
884 if ((*iter)->isSelected()) 884 if ((*iter)->isSelected())
885 return *iter; 885 return *iter;
886 } 886 }
887 887
888 return 0; 888 return 0;
889} 889}
890 890
891CardViewItem *CardView::firstItem() const 891CardViewItem *CardView::firstItem() const
892{ 892{
893 return d->mItemList.first(); 893 return d->mItemList.first();
894} 894}
895 895
896int CardView::childCount() const 896int CardView::childCount() const
897{ 897{
898 return d->mItemList.count(); 898 return d->mItemList.count();
899} 899}
900/*US 900/*US
901CardViewItem *CardView::findItem(const QString &text, const QString &label, 901CardViewItem *CardView::findItem(const QString &text, const QString &label,
902 Qt::StringComparisonMode compare) 902 Qt::StringComparisonMode compare)
903{ 903{
904 // IF the text is empty, we will return null, since empty text will 904 // IF the text is empty, we will return null, since empty text will
905 // match anything! 905 // match anything!
906 if (text.isEmpty()) 906 if (text.isEmpty())
907 return 0; 907 return 0;
908 908
909 QPtrListIterator<CardViewItem> iter(d->mItemList); 909 QPtrListIterator<CardViewItem> iter(d->mItemList);
910 if (compare & Qt::BeginsWith) 910 if (compare & Qt::BeginsWith)
911 { 911 {
912 QString value; 912 QString value;
913 for (iter.toFirst(); iter.current(); ++iter) 913 for (iter.toFirst(); iter.current(); ++iter)
914 { 914 {
915 value = (*iter)->fieldValue(label).upper(); 915 value = (*iter)->fieldValue(label).upper();
916 if (value.startsWith(text.upper())) 916 if (value.startsWith(text.upper()))
917 return *iter; 917 return *iter;
918 } 918 }
919 } 919 }
920 else 920 else
921 { 921 {
922 kdDebug(5720) << "CardView::findItem: search method not implemented" << endl; 922 kdDebug(5720) << "CardView::findItem: search method not implemented" << endl;
923 } 923 }
924 924
925 return 0; 925 return 0;
926} 926}
927*/ 927*/
928 928
929uint CardView::columnWidth() 929uint CardView::columnWidth()
930{ 930{
931 return d->mDrawSeparators ? 931 return d->mDrawSeparators ?
932 d->mItemWidth + ( 2 * d->mItemSpacing ) + d->mSepWidth : 932 d->mItemWidth + ( 2 * d->mItemSpacing ) + d->mSepWidth :
933 d->mItemWidth + d->mItemSpacing; 933 d->mItemWidth + d->mItemSpacing;
934} 934}
935 935
936void CardView::drawContents(QPainter *p, int clipx, int clipy, 936void CardView::drawContents(QPainter *p, int clipx, int clipy,
937 int clipw, int cliph) 937 int clipw, int cliph)
938{ 938{
939 QScrollView::drawContents(p, clipx, clipy, clipw, cliph); 939 //QScrollView::drawContents(p, clipx, clipy, clipw, cliph);
940
941 if (d->mLayoutDirty) 940 if (d->mLayoutDirty)
942 calcLayout(); 941 calcLayout();
943 942
944 //kdDebug() << "CardView::drawContents: " << clipx << ", " << clipy 943 //kdDebug() << "CardView::drawContents: " << clipx << ", " << clipy
945 // << ", " << clipw << ", " << cliph << endl; 944 // << ", " << clipw << ", " << cliph << endl;
946 945
947 QColorGroup cg = viewport()->palette().active(); // allow setting costum colors in the viewport pale 946 QColorGroup cg = viewport()->palette().active(); // allow setting costum colors in the viewport pale
948 947 int cX, cY;
948 contentsToViewport ( clipx, clipy, cX, cY );
949 QRect clipRect(clipx, clipy, clipw, cliph); 949 QRect clipRect(clipx, clipy, clipw, cliph);
950 QRect cardRect; 950 QRect cardRect;
951 QRect sepRect; 951 QRect sepRect;
952 CardViewItem *item; 952 CardViewItem *item;
953 CardViewSeparator *sep; 953 CardViewSeparator *sep;
954
955 // make sure the viewport is a pure background 954 // make sure the viewport is a pure background
956 viewport()->erase(clipRect); 955 viewport()->erase( QRect ( cX, cY , clipw, cliph ) );
957 956
958 // Now tell the cards to draw, if they are in the clip region 957 // Now tell the cards to draw, if they are in the clip region
959 QPtrListIterator<CardViewItem> iter(d->mItemList); 958 QPtrListIterator<CardViewItem> iter(d->mItemList);
960 for (iter.toFirst(); iter.current(); ++iter) 959 for (iter.toFirst(); iter.current(); ++iter)
961 { 960 {
962 item = *iter; 961 item = *iter;
963 cardRect.setRect( item->d->x, item->d->y, d->mItemWidth, item->height() ); 962 cardRect.setRect( item->d->x, item->d->y, d->mItemWidth, item->height() );
964 963
965 if (clipRect.intersects(cardRect) || clipRect.contains(cardRect)) 964 if (clipRect.intersects(cardRect) || clipRect.contains(cardRect))
966 { 965 {
967 //kdDebug() << "\trepainting card at: " << cardRect.x() << ", " 966 //kdDebug() << "\trepainting card at: " << cardRect.x() << ", "
968 // << cardRect.y() << endl; 967 // << cardRect.y() << endl;
969 968
970 // Tell the card to paint 969 // Tell the card to paint
971 p->save(); 970 p->save();
972 p->translate(cardRect.x(), cardRect.y()); 971 p->translate(cardRect.x(), cardRect.y());
973 item->paintCard(p, cg); 972 item->paintCard(p, cg);
974 p->restore(); 973 p->restore();
975 } 974 }
976 } 975 }
977 976
978 // Followed by the separators if they are in the clip region 977 // Followed by the separators if they are in the clip region
979 QPtrListIterator<CardViewSeparator> sepIter(d->mSeparatorList); 978 QPtrListIterator<CardViewSeparator> sepIter(d->mSeparatorList);
980 for (sepIter.toFirst(); sepIter.current(); ++sepIter) 979 for (sepIter.toFirst(); sepIter.current(); ++sepIter)
981 { 980 {
982 sep = *sepIter; 981 sep = *sepIter;
983 sepRect = sep->mRect; 982 sepRect = sep->mRect;
984 983
985 if (clipRect.intersects(sepRect) || clipRect.contains(sepRect)) 984 if (clipRect.intersects(sepRect) || clipRect.contains(sepRect))
986 { 985 {
987 p->save(); 986 p->save();
988 p->translate(sepRect.x(), sepRect.y()); 987 p->translate(sepRect.x(), sepRect.y());
989 sep->paintSeparator(p, cg); 988 sep->paintSeparator(p, cg);
990 p->restore(); 989 p->restore();
991 } 990 }
992 } 991 }
993} 992}
994 993
995void CardView::resizeEvent(QResizeEvent *e) 994void CardView::resizeEvent(QResizeEvent *e)
996{ 995{
997 QScrollView::resizeEvent(e); 996 QScrollView::resizeEvent(e);
998 997
999 setLayoutDirty(true); 998 setLayoutDirty(true);
1000} 999}
1001 1000
1002void CardView::calcLayout() 1001void CardView::calcLayout()
1003{ 1002{
1004 //kdDebug() << "CardView::calcLayout:" << endl; 1003 //kdDebug() << "CardView::calcLayout:" << endl;
1005 1004
1006 // Start in the upper left corner and layout all the 1005 // Start in the upper left corner and layout all the
1007 // cars using their height and width 1006 // cars using their height and width
1008 int maxWidth = 0; 1007 int maxWidth = 0;
1009 int maxHeight = 0; 1008 int maxHeight = 0;
1010 int xPos = 0; 1009 int xPos = 0;
1011 int yPos = 0; 1010 int yPos = 0;
1012 int cardSpacing = d->mItemSpacing; 1011 int cardSpacing = d->mItemSpacing;
1013 1012
1014 // delete the old separators 1013 // delete the old separators
1015 d->mSeparatorList.clear(); 1014 d->mSeparatorList.clear();
1016 1015
1017 QPtrListIterator<CardViewItem> iter(d->mItemList); 1016 QPtrListIterator<CardViewItem> iter(d->mItemList);
1018 CardViewItem *item = 0; 1017 CardViewItem *item = 0;
1019 CardViewSeparator *sep = 0; 1018 CardViewSeparator *sep = 0;
1020 xPos += cardSpacing; 1019 xPos += cardSpacing;
1021 1020
1022 for (iter.toFirst(); iter.current(); ++iter) 1021 for (iter.toFirst(); iter.current(); ++iter)
1023 { 1022 {
1024 item = *iter; 1023 item = *iter;
1025 1024
1026 yPos += cardSpacing; 1025 yPos += cardSpacing;
1027 1026
1028 if (yPos + item->height() + cardSpacing >= height() - horizontalScrollBar()->height()) 1027 if (yPos + item->height() + cardSpacing >= height() - horizontalScrollBar()->height())
1029 { 1028 {
1030 maxHeight = QMAX(maxHeight, yPos); 1029 maxHeight = QMAX(maxHeight, yPos);
1031 1030
1032 // Drawing in this column would be greater than the height 1031 // Drawing in this column would be greater than the height
1033 // of the scroll view, so move to next column 1032 // of the scroll view, so move to next column
1034 yPos = cardSpacing; 1033 yPos = cardSpacing;
1035 xPos += cardSpacing + maxWidth; 1034 xPos += cardSpacing + maxWidth;
1036 if (d->mDrawSeparators) 1035 if (d->mDrawSeparators)
1037 { 1036 {
1038 // Create a separator since the user asked 1037 // Create a separator since the user asked
1039 sep = new CardViewSeparator(this); 1038 sep = new CardViewSeparator(this);
1040 sep->mRect.moveTopLeft(QPoint(xPos, yPos+d->mItemMargin)); 1039 sep->mRect.moveTopLeft(QPoint(xPos, yPos+d->mItemMargin));
1041 xPos += d->mSepWidth + cardSpacing; 1040 xPos += d->mSepWidth + cardSpacing;
1042 d->mSeparatorList.append(sep); 1041 d->mSeparatorList.append(sep);
1043 } 1042 }
1044 1043
1045 maxWidth = 0; 1044 maxWidth = 0;
1046 } 1045 }
1047 1046
1048 item->d->x = xPos; 1047 item->d->x = xPos;
1049 item->d->y = yPos; 1048 item->d->y = yPos;
1050 1049
1051 yPos += item->height(); 1050 yPos += item->height();
1052 maxWidth = QMAX(maxWidth, d->mItemWidth); 1051 maxWidth = QMAX(maxWidth, d->mItemWidth);
1053 } 1052 }
1054 1053
1055 xPos += maxWidth; 1054 xPos += maxWidth;
1056 resizeContents( xPos + cardSpacing, maxHeight ); 1055 resizeContents( xPos + cardSpacing, maxHeight );
1057 1056
1058 // Update the height of all the separators now that we know the 1057 // Update the height of all the separators now that we know the
1059 // max height of a column 1058 // max height of a column
1060 QPtrListIterator<CardViewSeparator> sepIter(d->mSeparatorList); 1059 QPtrListIterator<CardViewSeparator> sepIter(d->mSeparatorList);
1061 for (sepIter.toFirst(); sepIter.current(); ++sepIter) 1060 for (sepIter.toFirst(); sepIter.current(); ++sepIter)
1062 { 1061 {
1063 (*sepIter)->mRect.setHeight(maxHeight - 2*cardSpacing - 2*d->mItemMargin); 1062 (*sepIter)->mRect.setHeight(maxHeight - 2*cardSpacing - 2*d->mItemMargin);
1064 } 1063 }
1065 1064
1066 d->mLayoutDirty = false; 1065 d->mLayoutDirty = false;
1067} 1066}
1068 1067
1069CardViewItem *CardView::itemAfter(CardViewItem *item) 1068CardViewItem *CardView::itemAfter(CardViewItem *item)
1070{ 1069{
1071 /*int pos = */d->mItemList.findRef(item); 1070 /*int pos = */d->mItemList.findRef(item);
1072 return d->mItemList.next();//at(pos+1); 1071 return d->mItemList.next();//at(pos+1);
1073} 1072}
1074 1073
1075uint CardView::itemMargin() 1074uint CardView::itemMargin()
1076{ 1075{
1077 return d->mItemMargin; 1076 return d->mItemMargin;
1078} 1077}
1079 1078
1080void CardView::setItemMargin( uint margin ) 1079void CardView::setItemMargin( uint margin )
1081{ 1080{
1082 if ( margin == d->mItemMargin ) 1081 if ( margin == d->mItemMargin )
1083 return; 1082 return;
1084 1083
1085 d->mItemMargin = margin; 1084 d->mItemMargin = margin;
1086 setLayoutDirty( true ); 1085 setLayoutDirty( true );
1087} 1086}
1088 1087
1089uint CardView::itemSpacing() 1088uint CardView::itemSpacing()
1090{ 1089{
1091 return d->mItemSpacing; 1090 return d->mItemSpacing;
1092} 1091}
1093 1092
1094void CardView::setItemSpacing( uint spacing ) 1093void CardView::setItemSpacing( uint spacing )
1095{ 1094{
1096 if ( spacing == d->mItemSpacing ) 1095 if ( spacing == d->mItemSpacing )
1097 return; 1096 return;
1098 1097
1099 d->mItemSpacing = spacing; 1098 d->mItemSpacing = spacing;
1100 setLayoutDirty( true ); 1099 setLayoutDirty( true );
1101} 1100}
1102 1101
1103void CardView::contentsMousePressEvent(QMouseEvent *e) 1102void CardView::contentsMousePressEvent(QMouseEvent *e)
1104{ 1103{
1105 QScrollView::contentsMousePressEvent(e); 1104 QScrollView::contentsMousePressEvent(e);
1106 1105
1107 QPoint pos = e->pos(); 1106 QPoint pos = e->pos();
1108 d->mLastClickPos = pos; 1107 d->mLastClickPos = pos;
1109 1108
1110 CardViewItem *item = itemAt(pos); 1109 CardViewItem *item = itemAt(pos);
1111 1110
1112 if (item == 0) 1111 if (item == 0)
1113 { 1112 {
1114 d->mLastClickOnItem = false; 1113 d->mLastClickOnItem = false;
1115 if ( d->mOnSeparator) 1114 if ( d->mOnSeparator)
1116 { 1115 {
1117 d->mResizeAnchor = e->x()+contentsX(); 1116 d->mResizeAnchor = e->x()+contentsX();
1118 d->colspace = (2*d->mItemSpacing) /*+ (2*d->mItemMargin)*/; 1117 d->colspace = (2*d->mItemSpacing) /*+ (2*d->mItemMargin)*/;
1119 int ccw = d->mItemWidth + d->colspace + d->mSepWidth; 1118 int ccw = d->mItemWidth + d->colspace + d->mSepWidth;
1120 d->first = (contentsX()+d->mSepWidth)/ccw; 1119 d->first = (contentsX()+d->mSepWidth)/ccw;
1121 d->pressed = (d->mResizeAnchor+d->mSepWidth)/ccw; 1120 d->pressed = (d->mResizeAnchor+d->mSepWidth)/ccw;
1122 d->span = d->pressed - d->first; 1121 d->span = d->pressed - d->first;
1123 d->firstX = d->first * ccw; 1122 d->firstX = d->first * ccw;
1124 if ( d->firstX ) d->firstX -= d->mSepWidth; // (no sep in col 0) 1123 if ( d->firstX ) d->firstX -= d->mSepWidth; // (no sep in col 0)
1125 } 1124 }
1126 else 1125 else
1127 { 1126 {
1128 selectAll(false); 1127 selectAll(false);
1129 } 1128 }
1130 return; 1129 return;
1131 } 1130 }
1132 1131
1133 d->mLastClickOnItem = true; 1132 d->mLastClickOnItem = true;
1134 1133
1135 CardViewItem *other = d->mCurrentItem; 1134 CardViewItem *other = d->mCurrentItem;
1136 setCurrentItem( item ); 1135 setCurrentItem( item );
1137 1136
1138 // Always emit the selection 1137 // Always emit the selection
1139 emit clicked(item); 1138 emit clicked(item);
1140 1139
1141 // Check the selection type and update accordingly 1140 // Check the selection type and update accordingly
1142 if (d->mSelectionMode == CardView::Single) 1141 if (d->mSelectionMode == CardView::Single)
1143 { 1142 {
1144 // make sure it isn't already selected 1143 // make sure it isn't already selected
1145 if (item->isSelected()) 1144 if (item->isSelected())
1146 return; 1145 return;
1147 1146
1148 bool b = signalsBlocked(); 1147 bool b = signalsBlocked();
1149 blockSignals(true); 1148 blockSignals(true);
1150 selectAll(false); 1149 selectAll(false);
1151 blockSignals(b); 1150 blockSignals(b);
1152 1151
1153 item->setSelected(true); 1152 item->setSelected(true);
1154 item->repaintCard(); 1153 item->repaintCard();
1155 emit selectionChanged(item); 1154 emit selectionChanged(item);
1156 } 1155 }
1157 1156
1158 else if (d->mSelectionMode == CardView::Multi) 1157 else if (d->mSelectionMode == CardView::Multi)
1159 { 1158 {
1160 // toggle the selection 1159 // toggle the selection
1161 item->setSelected(!item->isSelected()); 1160 item->setSelected(!item->isSelected());
1162 item->repaintCard(); 1161 item->repaintCard();
1163 emit selectionChanged(); 1162 emit selectionChanged();
1164 } 1163 }
1165 1164
1166 else if (d->mSelectionMode == CardView::Extended) 1165 else if (d->mSelectionMode == CardView::Extended)
1167 { 1166 {
1168 if ((e->button() & Qt::LeftButton) && 1167 if ((e->button() & Qt::LeftButton) &&
1169 (e->state() & Qt::ShiftButton)) 1168 (e->state() & Qt::ShiftButton))
1170 { 1169 {
1171 if ( item == other ) return; 1170 if ( item == other ) return;
1172 1171
1173 bool s = ! item->isSelected(); 1172 bool s = ! item->isSelected();
1174 1173
1175 if ( s && ! (e->state() & ControlButton) ) 1174 if ( s && ! (e->state() & ControlButton) )
1176 { 1175 {
1177 bool b = signalsBlocked(); 1176 bool b = signalsBlocked();
1178 blockSignals(true); 1177 blockSignals(true);
1179 selectAll(false); 1178 selectAll(false);
1180 blockSignals(b); 1179 blockSignals(b);
1181 } 1180 }
1182 1181
1183 int from, to, a, b; 1182 int from, to, a, b;
1184 a = d->mItemList.findRef( item ); 1183 a = d->mItemList.findRef( item );
1185 b = d->mItemList.findRef( other ); 1184 b = d->mItemList.findRef( other );
1186 from = a < b ? a : b; 1185 from = a < b ? a : b;
1187 to = a > b ? a : b; 1186 to = a > b ? a : b;
1188 //kdDebug()<<"selecting items "<<from<<" - "<<to<<" ( "<<s<<" )"<<endl; 1187 //kdDebug()<<"selecting items "<<from<<" - "<<to<<" ( "<<s<<" )"<<endl;
1189 CardViewItem *aItem; 1188 CardViewItem *aItem;
1190 for ( ; from <= to; from++ ) 1189 for ( ; from <= to; from++ )
1191 { 1190 {
1192 aItem = d->mItemList.at( from ); 1191 aItem = d->mItemList.at( from );
1193 aItem->setSelected( s ); 1192 aItem->setSelected( s );
1194 repaintItem( aItem ); 1193 repaintItem( aItem );
1195 } 1194 }
1196 emit selectionChanged(); 1195 emit selectionChanged();
1197 } 1196 }
1198 else if ((e->button() & Qt::LeftButton) && 1197 else if ((e->button() & Qt::LeftButton) &&
1199 (e->state() & Qt::ControlButton)) 1198 (e->state() & Qt::ControlButton))
1200 { 1199 {
1201 item->setSelected(!item->isSelected()); 1200 item->setSelected(!item->isSelected());
1202 item->repaintCard(); 1201 item->repaintCard();
1203 emit selectionChanged(); 1202 emit selectionChanged();
1204 } 1203 }
1205 1204
1206 else if (e->button() & Qt::LeftButton) 1205 else if (e->button() & Qt::LeftButton)
1207 { 1206 {
1208 bool b = signalsBlocked(); 1207 bool b = signalsBlocked();
1209 blockSignals(true); 1208 blockSignals(true);
1210 selectAll(false); 1209 selectAll(false);
1211 blockSignals(b); 1210 blockSignals(b);
1212 1211
1213 item->setSelected(true); 1212 item->setSelected(true);
1214 item->repaintCard(); 1213 item->repaintCard();
1215 emit selectionChanged(); 1214 emit selectionChanged();
1216 } 1215 }
1217 } 1216 }
1218 1217
1219} 1218}
1220 1219
1221void CardView::contentsMouseReleaseEvent(QMouseEvent *e) 1220void CardView::contentsMouseReleaseEvent(QMouseEvent *e)
1222{ 1221{
1223 QScrollView::contentsMouseReleaseEvent(e); 1222 QScrollView::contentsMouseReleaseEvent(e);
1224 1223
1225 if ( d->mResizeAnchor ) 1224 if ( d->mResizeAnchor )
1226 { 1225 {
1227 // finish the resizing: 1226 // finish the resizing:
1228 unsetCursor(); 1227 unsetCursor();
1229 // hide rubber bands 1228 // hide rubber bands
1230 int newiw = d->mItemWidth - ((d->mResizeAnchor - d->mRubberBandAnchor)/d->span); 1229 int newiw = d->mItemWidth - ((d->mResizeAnchor - d->mRubberBandAnchor)/d->span);
1231 drawRubberBands( 0 ); 1230 drawRubberBands( 0 );
1232 // we should move to reflect the new position if we are scrolled. 1231 // we should move to reflect the new position if we are scrolled.
1233 if ( contentsX() ) 1232 if ( contentsX() )
1234 { 1233 {
1235 int newX = QMAX( 0, ( d->pressed * ( newiw + d->colspace + d->mSepWidth ) ) - e->x() ); 1234 int newX = QMAX( 0, ( d->pressed * ( newiw + d->colspace + d->mSepWidth ) ) - e->x() );
1236 setContentsPos( newX, contentsY() ); 1235 setContentsPos( newX, contentsY() );
1237 } 1236 }
1238 // set new item width 1237 // set new item width
1239 setItemWidth( newiw ); 1238 setItemWidth( newiw );
1240 // reset anchors 1239 // reset anchors
1241 d->mResizeAnchor = 0; 1240 d->mResizeAnchor = 0;
1242 d->mRubberBandAnchor = 0; 1241 d->mRubberBandAnchor = 0;
1243 return; 1242 return;
1244 } 1243 }
1245 1244
1246 // If there are accel keys, we will not emit signals 1245 // If there are accel keys, we will not emit signals
1247 if ((e->state() & Qt::ShiftButton) || (e->state() & Qt::ControlButton)) 1246 if ((e->state() & Qt::ShiftButton) || (e->state() & Qt::ControlButton))
1248 return; 1247 return;
1249 1248
1250 // Get the item at this position 1249 // Get the item at this position
1251 CardViewItem *item = itemAt(e->pos()); 1250 CardViewItem *item = itemAt(e->pos());
1252 1251
1253 if (item && KABPrefs::instance()->mHonorSingleClick) 1252 if (item && KABPrefs::instance()->mHonorSingleClick)
1254 { 1253 {
1255 emit executed(item); 1254 emit executed(item);
1256 } 1255 }
1257} 1256}
1258 1257
1259void CardView::contentsMouseDoubleClickEvent(QMouseEvent *e) 1258void CardView::contentsMouseDoubleClickEvent(QMouseEvent *e)
1260{ 1259{
1261 QScrollView::contentsMouseDoubleClickEvent(e); 1260 QScrollView::contentsMouseDoubleClickEvent(e);
1262 1261
1263 CardViewItem *item = itemAt(e->pos()); 1262 CardViewItem *item = itemAt(e->pos());
1264 1263
1265 if (item) 1264 if (item)
1266 { 1265 {
1267 d->mCurrentItem = item; 1266 d->mCurrentItem = item;
1268 } 1267 }
1269 1268
1270 if (item && !KABPrefs::instance()->mHonorSingleClick) 1269 if (item && !KABPrefs::instance()->mHonorSingleClick)
1271 { 1270 {
1272 emit executed(item); 1271 emit executed(item);
1273 } else 1272 } else
1274 emit doubleClicked(item); 1273 emit doubleClicked(item);
1275} 1274}
1276 1275
1277void CardView::contentsMouseMoveEvent( QMouseEvent *e ) 1276void CardView::contentsMouseMoveEvent( QMouseEvent *e )
1278{ 1277{
1279 // resizing 1278 // resizing
1280 if ( d->mResizeAnchor ) 1279 if ( d->mResizeAnchor )
1281 { 1280 {
1282 int x = e->x(); 1281 int x = e->x();
1283 if ( x != d->mRubberBandAnchor ) 1282 if ( x != d->mRubberBandAnchor )
1284 drawRubberBands( x ); 1283 drawRubberBands( x );
1285 return; 1284 return;
1286 } 1285 }
1287 1286
1288 if (d->mLastClickOnItem && (e->state() & Qt::LeftButton) && 1287 if (d->mLastClickOnItem && (e->state() & Qt::LeftButton) &&
1289 ((e->pos() - d->mLastClickPos).manhattanLength() > 4)) { 1288 ((e->pos() - d->mLastClickPos).manhattanLength() > 4)) {
1290 1289
1291 startDrag(); 1290 startDrag();
1292 return; 1291 return;
1293 } 1292 }
1294 1293
1295 d->mTimer->start( 500 ); 1294 d->mTimer->start( 500 );
1296 1295
1297 // see if we are over a separator 1296 // see if we are over a separator
1298 // only if we actually have them painted? 1297 // only if we actually have them painted?
1299 if ( d->mDrawSeparators ) 1298 if ( d->mDrawSeparators )
1300 { 1299 {
1301 int colcontentw = d->mItemWidth + (2*d->mItemSpacing); 1300 int colcontentw = d->mItemWidth + (2*d->mItemSpacing);
1302 int colw = colcontentw + d->mSepWidth; 1301 int colw = colcontentw + d->mSepWidth;
1303 int m = e->x()%colw; 1302 int m = e->x()%colw;
1304 if ( m >= colcontentw && m > 0 ) 1303 if ( m >= colcontentw && m > 0 )
1305 { 1304 {
1306 setCursor( SplitVCursor ); // Why does this fail sometimes? 1305 setCursor( SplitVCursor ); // Why does this fail sometimes?
1307 d->mOnSeparator = true; 1306 d->mOnSeparator = true;
1308 } 1307 }
1309 else 1308 else
1310 { 1309 {
1311 setCursor( ArrowCursor ); 1310 setCursor( ArrowCursor );
1312 d->mOnSeparator = false; 1311 d->mOnSeparator = false;
1313 } 1312 }
1314 } 1313 }
1315} 1314}
1316 1315
1317void CardView::enterEvent( QEvent * ) 1316void CardView::enterEvent( QEvent * )
1318{ 1317{
1319 d->mTimer->start( 500 ); 1318 d->mTimer->start( 500 );
1320} 1319}
1321 1320
1322void CardView::leaveEvent( QEvent * ) 1321void CardView::leaveEvent( QEvent * )
1323{ 1322{
1324 d->mTimer->stop(); 1323 d->mTimer->stop();
1325 if (d->mOnSeparator) 1324 if (d->mOnSeparator)
1326 { 1325 {
1327 d->mOnSeparator = false; 1326 d->mOnSeparator = false;
1328 setCursor( ArrowCursor ); 1327 setCursor( ArrowCursor );
1329 } 1328 }
1330} 1329}
1331 1330
1332void CardView::focusInEvent( QFocusEvent * ) 1331void CardView::focusInEvent( QFocusEvent * )
1333{ 1332{
1334 if (!d->mCurrentItem && d->mItemList.count() ) 1333 if (!d->mCurrentItem && d->mItemList.count() )
1335 { 1334 {
1336 setCurrentItem( d->mItemList.first() ); 1335 setCurrentItem( d->mItemList.first() );
1337 } 1336 }
1338 else if ( d->mCurrentItem ) 1337 else if ( d->mCurrentItem )
1339 { 1338 {
1340 d->mCurrentItem->repaintCard(); 1339 d->mCurrentItem->repaintCard();
1341 } 1340 }
1342} 1341}
1343 1342
1344void CardView::focusOutEvent( QFocusEvent * ) 1343void CardView::focusOutEvent( QFocusEvent * )
1345{ 1344{
1346 if (d->mCurrentItem) 1345 if (d->mCurrentItem)
1347 d->mCurrentItem->repaintCard(); 1346 d->mCurrentItem->repaintCard();
1348} 1347}
1349 1348
1350void CardView::keyPressEvent( QKeyEvent *e ) 1349void CardView::keyPressEvent( QKeyEvent *e )
1351{ 1350{
1352 if ( ! ( childCount() && d->mCurrentItem ) ) 1351 if ( ! ( childCount() && d->mCurrentItem ) )
1353 { 1352 {
1354 e->ignore(); 1353 e->ignore();
1355 return; 1354 return;
1356 } 1355 }
1357 if ( mFlagBlockKeyPressed ) 1356 if ( mFlagBlockKeyPressed )
1358 return; 1357 return;
1359 qApp->processEvents(); 1358 qApp->processEvents();
1360 if ( e->isAutoRepeat() && !mFlagKeyPressed ) { 1359 if ( e->isAutoRepeat() && !mFlagKeyPressed ) {
1361 e->accept(); 1360 e->accept();
1362 return; 1361 return;
1363 } 1362 }
1364 if (! e->isAutoRepeat() ) 1363 if (! e->isAutoRepeat() )
1365 mFlagKeyPressed = true; 1364 mFlagKeyPressed = true;
1366 uint pos = d->mItemList.findRef( d->mCurrentItem ); 1365 uint pos = d->mItemList.findRef( d->mCurrentItem );
1367 CardViewItem *aItem = 0L; // item that gets the focus 1366 CardViewItem *aItem = 0L; // item that gets the focus
1368 CardViewItem *old = d->mCurrentItem; 1367 CardViewItem *old = d->mCurrentItem;
1369 1368
1370 switch ( e->key() ) 1369 switch ( e->key() )
1371 { 1370 {
1372 case Key_Up: 1371 case Key_Up:
1373 if ( pos > 0 ) 1372 if ( pos > 0 )
1374 { 1373 {
1375 aItem = d->mItemList.at( pos - 1 ); 1374 aItem = d->mItemList.at( pos - 1 );
1376 setCurrentItem( aItem ); 1375 setCurrentItem( aItem );
1377 } 1376 }
1378 break; 1377 break;
1379 case Key_Down: 1378 case Key_Down:
1380 if ( pos < d->mItemList.count() - 1 ) 1379 if ( pos < d->mItemList.count() - 1 )
1381 { 1380 {
1382 aItem = d->mItemList.at( pos + 1 ); 1381 aItem = d->mItemList.at( pos + 1 );
1383 setCurrentItem( aItem ); 1382 setCurrentItem( aItem );
1384 } 1383 }
1385 break; 1384 break;
1386 case Key_Left: 1385 case Key_Left:
1387 { 1386 {
1388 // look for an item in the previous/next column, starting from 1387 // look for an item in the previous/next column, starting from
1389 // the vertical middle of the current item. 1388 // the vertical middle of the current item.
1390 // FIXME use nice calculatd measures!!! 1389 // FIXME use nice calculatd measures!!!
1391 QPoint aPoint( d->mCurrentItem->d->x, d->mCurrentItem->d->y ); 1390 QPoint aPoint( d->mCurrentItem->d->x, d->mCurrentItem->d->y );
1392 aPoint -= QPoint( 30,-(d->mCurrentItem->height()/2) ); 1391 aPoint -= QPoint( 30,-(d->mCurrentItem->height()/2) );
1393 aItem = itemAt( aPoint ); 1392 aItem = itemAt( aPoint );
1394 // maybe we hit some space below an item 1393 // maybe we hit some space below an item
1395 while ( !aItem && aPoint.y() > 27 ) 1394 while ( !aItem && aPoint.y() > 27 )
1396 { 1395 {
1397 aPoint -= QPoint( 0, 16 ); 1396 aPoint -= QPoint( 0, 16 );
1398 aItem = itemAt( aPoint ); 1397 aItem = itemAt( aPoint );
1399 } 1398 }
1400 if ( aItem ) 1399 if ( aItem )
1401 setCurrentItem( aItem ); 1400 setCurrentItem( aItem );
1402 } 1401 }
1403 break; 1402 break;
1404 case Key_Right: 1403 case Key_Right:
1405 { 1404 {
1406 // FIXME use nice calculated measures!!! 1405 // FIXME use nice calculated measures!!!
1407 QPoint aPoint( d->mCurrentItem->d->x + d->mItemWidth, d->mCurrentItem->d->y ); 1406 QPoint aPoint( d->mCurrentItem->d->x + d->mItemWidth, d->mCurrentItem->d->y );
1408 aPoint += QPoint( 30,(d->mCurrentItem->height()/2) ); 1407 aPoint += QPoint( 30,(d->mCurrentItem->height()/2) );
1409 aItem = itemAt( aPoint ); 1408 aItem = itemAt( aPoint );
1410 while ( !aItem && aPoint.y() > 27 ) 1409 while ( !aItem && aPoint.y() > 27 )
1411 { 1410 {
1412 aPoint -= QPoint( 0, 16 ); 1411 aPoint -= QPoint( 0, 16 );
1413 aItem = itemAt( aPoint ); 1412 aItem = itemAt( aPoint );
1414 } 1413 }
1415 if ( aItem ) 1414 if ( aItem )
1416 setCurrentItem( aItem ); 1415 setCurrentItem( aItem );
1417 } 1416 }
1418 break; 1417 break;
1419 case Key_Home: 1418 case Key_Home:
1420 aItem = d->mItemList.first(); 1419 aItem = d->mItemList.first();
1421 setCurrentItem( aItem ); 1420 setCurrentItem( aItem );
1422 break; 1421 break;
1423 case Key_End: 1422 case Key_End:
1424 aItem = d->mItemList.last(); 1423 aItem = d->mItemList.last();
1425 setCurrentItem( aItem ); 1424 setCurrentItem( aItem );
1426 break; 1425 break;
1427 case Key_Prior: // PageUp 1426 case Key_Prior: // PageUp
1428 { 1427 {
1429 // QListView: "Make the item above the top visible and current" 1428 // QListView: "Make the item above the top visible and current"
1430 // TODO if contentsY(), pick the top item of the leftmost visible column 1429 // TODO if contentsY(), pick the top item of the leftmost visible column
1431 if ( contentsX() <= 0 ) 1430 if ( contentsX() <= 0 )
1432 return; 1431 return;
1433 int cw = columnWidth(); 1432 int cw = columnWidth();
1434 int theCol = ( QMAX( 0, ( contentsX()/cw) * cw ) ) + d->mItemSpacing; 1433 int theCol = ( QMAX( 0, ( contentsX()/cw) * cw ) ) + d->mItemSpacing;
1435 aItem = itemAt( QPoint( theCol + 1, d->mItemSpacing + 1 ) ); 1434 aItem = itemAt( QPoint( theCol + 1, d->mItemSpacing + 1 ) );
1436 if ( aItem ) 1435 if ( aItem )
1437 setCurrentItem( aItem ); 1436 setCurrentItem( aItem );
1438 } 1437 }
1439 break; 1438 break;
1440 case Key_Next: // PageDown 1439 case Key_Next: // PageDown
1441 { 1440 {
1442 // QListView: "Make the item below the bottom visible and current" 1441 // QListView: "Make the item below the bottom visible and current"
1443 // find the first not fully visible column. 1442 // find the first not fully visible column.
1444 // TODO: consider if a partly visible (or even hidden) item at the 1443 // TODO: consider if a partly visible (or even hidden) item at the
1445 // bottom of the rightmost column exists 1444 // bottom of the rightmost column exists
1446 int cw = columnWidth(); 1445 int cw = columnWidth();
1447 int theCol = ( (( contentsX() + visibleWidth() )/cw) * cw ) + d->mItemSpacing + 1; 1446 int theCol = ( (( contentsX() + visibleWidth() )/cw) * cw ) + d->mItemSpacing + 1;
1448 // if separators are on, we may need to we may be one column further right if only the spacing/sep is hidden 1447 // if separators are on, we may need to we may be one column further right if only the spacing/sep is hidden
1449 if ( d->mDrawSeparators && cw - (( contentsX() + visibleWidth() )%cw) <= int( d->mItemSpacing + d->mSepWidth ) ) 1448 if ( d->mDrawSeparators && cw - (( contentsX() + visibleWidth() )%cw) <= int( d->mItemSpacing + d->mSepWidth ) )
1450 theCol += cw; 1449 theCol += cw;
1451 1450
1452 // make sure this is not too far right 1451 // make sure this is not too far right
1453 while ( theCol > contentsWidth() ) 1452 while ( theCol > contentsWidth() )
1454 theCol -= columnWidth(); 1453 theCol -= columnWidth();
1455 1454
1456 aItem = itemAt( QPoint( theCol, d->mItemSpacing + 1 ) ); 1455 aItem = itemAt( QPoint( theCol, d->mItemSpacing + 1 ) );
1457 1456
1458 if ( aItem ) 1457 if ( aItem )
1459 setCurrentItem( aItem ); 1458 setCurrentItem( aItem );
1460 } 1459 }
1461 break; 1460 break;
1462 case Key_Space: 1461 case Key_Space:
1463 setSelected( d->mCurrentItem, !d->mCurrentItem->isSelected() ); 1462 setSelected( d->mCurrentItem, !d->mCurrentItem->isSelected() );
1464 emit selectionChanged(); 1463 emit selectionChanged();
1465 break; 1464 break;
1466 case Key_Return: 1465 case Key_Return:
1467 case Key_Enter: 1466 case Key_Enter:
1468 { 1467 {