Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <comphelper/string.hxx>
21 : #include <i18nlangtag/mslangid.hxx>
22 : #include <vcl/svapp.hxx>
23 : #include <vcl/msgbox.hxx>
24 : #include <unotools/saveopt.hxx>
25 : #include <svl/intitem.hxx>
26 : #include <vcl/edit.hxx>
27 : #include <vcl/settings.hxx>
28 :
29 : #include <cuires.hrc>
30 : #include <unotools/useroptions.hxx>
31 : #include "cuioptgenrl.hxx"
32 : #include <dialmgr.hxx>
33 : #include <svx/dlgutil.hxx>
34 : #include <svx/svxids.hrc>
35 :
36 : #include <boost/ref.hpp>
37 : #include <boost/make_shared.hpp>
38 :
39 : namespace
40 : {
41 :
42 : // rows
43 : enum RowType
44 : {
45 : Row_Company,
46 : Row_Name,
47 : Row_Name_Russian,
48 : Row_Name_Eastern,
49 : Row_Street,
50 : Row_Street_Russian,
51 : Row_City,
52 : Row_City_US,
53 : Row_Country,
54 : Row_TitlePos,
55 : Row_Phone,
56 : Row_FaxMail,
57 :
58 : nRowCount
59 : };
60 :
61 : // language flags
62 : namespace Lang
63 : {
64 : unsigned const Others = 1;
65 : unsigned const Russian = 2;
66 : unsigned const Eastern = 4;
67 : unsigned const US = 8;
68 : unsigned const All = static_cast<unsigned>(-1);
69 : }
70 :
71 :
72 : // vRowInfo[] -- rows (text + one or more edit boxes)
73 : // The order is the same as in RowType above, which is up to down.
74 :
75 : struct
76 : {
77 : // id of the text
78 : const char *pTextId;
79 : // language flags (see Lang above):
80 : // which language is this row for?
81 : unsigned nLangFlags;
82 : }
83 : const vRowInfo[] =
84 : {
85 : { "companyft", Lang::All },
86 : { "nameft", Lang::All & ~Lang::Russian & ~Lang::Eastern },
87 : { "rusnameft", Lang::Russian },
88 : { "eastnameft", Lang::Eastern },
89 : { "streetft", Lang::All & ~Lang::Russian },
90 : { "russtreetft", Lang::Russian },
91 : { "icityft", Lang::All & ~Lang::US },
92 : { "cityft", Lang::US },
93 : { "countryft", Lang::All },
94 : { "titleft", Lang::All },
95 : { "phoneft", Lang::All },
96 : { "faxft", Lang::All },
97 : };
98 :
99 :
100 : // vFieldInfo[] -- edit boxes
101 : // The order is up to down, and then left to right.
102 :
103 : struct
104 : {
105 : // in which row?
106 : RowType eRow;
107 : // id of the edit box
108 : const char *pEditId;
109 : // id for SvtUserOptions in unotools/useroptions.hxx
110 : int nUserOptionsId;
111 : // id for settings the focus (defined in svx/optgenrl.hxx)
112 : int nGrabFocusId;
113 : }
114 : const vFieldInfo[] =
115 : {
116 : // Company
117 : { Row_Company, "company", USER_OPT_COMPANY, COMPANY_EDIT },
118 : // Name
119 : { Row_Name, "firstname", USER_OPT_FIRSTNAME, FIRSTNAME_EDIT },
120 : { Row_Name, "lastname", USER_OPT_LASTNAME, LASTNAME_EDIT },
121 : { Row_Name, "shortname", USER_OPT_ID, SHORTNAME_EDIT },
122 : // Name (russian)
123 : { Row_Name_Russian, "ruslastname", USER_OPT_LASTNAME, LASTNAME_EDIT },
124 : { Row_Name_Russian, "rusfirstname", USER_OPT_FIRSTNAME, FIRSTNAME_EDIT },
125 : { Row_Name_Russian, "rusfathersname", USER_OPT_FATHERSNAME, 0 },
126 : { Row_Name_Russian, "russhortname", USER_OPT_ID, SHORTNAME_EDIT },
127 : // Name (eastern: reversed name ord
128 : { Row_Name_Eastern, "eastlastname", USER_OPT_LASTNAME, LASTNAME_EDIT },
129 : { Row_Name_Eastern, "eastfirstname", USER_OPT_FIRSTNAME, FIRSTNAME_EDIT },
130 : { Row_Name_Eastern, "eastshortname", USER_OPT_ID, SHORTNAME_EDIT },
131 : // Street
132 : { Row_Street, "street", USER_OPT_STREET, STREET_EDIT },
133 : // Street (russian)
134 : { Row_Street_Russian, "russtreet", USER_OPT_STREET, STREET_EDIT },
135 : { Row_Street_Russian, "apartnum", USER_OPT_APARTMENT, 0 },
136 : // City
137 : { Row_City, "izip", USER_OPT_ZIP, PLZ_EDIT },
138 : { Row_City, "icity", USER_OPT_CITY, CITY_EDIT },
139 : // City (US)
140 : { Row_City_US, "city", USER_OPT_CITY, CITY_EDIT },
141 : { Row_City_US, "state", USER_OPT_STATE, STATE_EDIT },
142 : { Row_City_US, "zip", USER_OPT_ZIP, PLZ_EDIT },
143 : // Country
144 : { Row_Country, "country", USER_OPT_COUNTRY, COUNTRY_EDIT },
145 : // Title/Position
146 : { Row_TitlePos, "title", USER_OPT_TITLE, TITLE_EDIT },
147 : { Row_TitlePos, "position", USER_OPT_POSITION, POSITION_EDIT },
148 : // Phone
149 : { Row_Phone, "home", USER_OPT_TELEPHONEHOME, TELPRIV_EDIT },
150 : { Row_Phone, "work", USER_OPT_TELEPHONEWORK, TELCOMPANY_EDIT },
151 : // Fax/Mail
152 : { Row_FaxMail, "fax", USER_OPT_FAX, FAX_EDIT },
153 : { Row_FaxMail, "email", USER_OPT_EMAIL, EMAIL_EDIT },
154 : };
155 :
156 :
157 : } // namespace
158 :
159 :
160 :
161 :
162 : // Row
163 :
164 : struct SvxGeneralTabPage::Row
165 : {
166 : // which row is it?
167 : RowType eRow;
168 : // row label
169 : FixedText* pLabel;
170 : // first and last field in the row (last is exclusive)
171 : unsigned nFirstField, nLastField;
172 :
173 : public:
174 0 : Row (FixedText *pLabel_, RowType eRow_)
175 : : eRow(eRow_)
176 : , pLabel(pLabel_)
177 : , nFirstField(0)
178 0 : , nLastField(0)
179 : {
180 0 : pLabel->Show();
181 0 : }
182 : };
183 :
184 :
185 :
186 :
187 : // Field
188 :
189 : struct SvxGeneralTabPage::Field
190 : {
191 : // which field is this? (in vFieldInfo[] above)
192 : unsigned iField;
193 : // edit box
194 : Edit *pEdit;
195 :
196 : public:
197 0 : Field (Edit *pEdit_, unsigned iField_)
198 : : iField(iField_)
199 0 : , pEdit(pEdit_)
200 : {
201 : //We want all widgets inside a container, so each row of the toplevel
202 : //grid has another container in it. To avoid adding spacing to these
203 : //empty grids they all default to invisible, so show them if their
204 : //children are visibles
205 0 : pEdit->GetParent()->Show();
206 0 : pEdit->Show();
207 0 : }
208 : };
209 :
210 :
211 :
212 0 : SvxGeneralTabPage::SvxGeneralTabPage(vcl::Window* pParent, const SfxItemSet& rCoreSet)
213 :
214 0 : : SfxTabPage(pParent, "OptUserPage", "cui/ui/optuserpage.ui", &rCoreSet)
215 : {
216 0 : get(m_pUseDataCB, "usefordocprop");
217 0 : InitControls();
218 0 : SetExchangeSupport(); // this page needs ExchangeSupport
219 0 : SetLinks();
220 0 : }
221 :
222 :
223 :
224 0 : SvxGeneralTabPage::~SvxGeneralTabPage ()
225 0 : { }
226 :
227 :
228 :
229 : // Initializes the titles and the edit boxes,
230 : // according to vRowInfo[] and vFieldInfo[] above.
231 0 : void SvxGeneralTabPage::InitControls ()
232 : {
233 : // which language bit do we use? (see Lang and vRowInfo[] above)
234 : unsigned LangBit;
235 0 : switch (LanguageType const eLang = Application::GetSettings().GetUILanguageTag().getLanguageType())
236 : {
237 : case LANGUAGE_ENGLISH_US:
238 0 : LangBit = Lang::US;
239 0 : break;
240 : case LANGUAGE_RUSSIAN:
241 0 : LangBit = Lang::Russian;
242 0 : break;
243 : default:
244 0 : if (MsLangId::isFamilyNameFirst(eLang))
245 0 : LangBit = Lang::Eastern;
246 : else
247 0 : LangBit = Lang::Others;
248 0 : break;
249 : }
250 :
251 : // creating rows
252 0 : unsigned iField = 0;
253 0 : for (unsigned iRow = 0; iRow != nRowCount; ++iRow)
254 : {
255 0 : RowType const eRow = static_cast<RowType>(iRow);
256 : // is the row visible?
257 0 : if (!(vRowInfo[iRow].nLangFlags & LangBit))
258 0 : continue;
259 : // creating row
260 : vRows.push_back(boost::make_shared<Row>(
261 0 : get<FixedText>(vRowInfo[iRow].pTextId), eRow));
262 0 : Row& rRow = *vRows.back();
263 : // fields in the row
264 : static unsigned const nFieldCount = SAL_N_ELEMENTS(vFieldInfo);
265 : // skipping other (invisible) rows
266 0 : while (iField != nFieldCount && vFieldInfo[iField].eRow != eRow)
267 0 : ++iField;
268 : // fields in the row
269 0 : rRow.nFirstField = vFields.size();
270 0 : for ( ; iField != nFieldCount && vFieldInfo[iField].eRow == eRow; ++iField)
271 : {
272 : // creating edit field
273 : vFields.push_back(boost::make_shared<Field>(
274 0 : get<Edit>(vFieldInfo[iField].pEditId), iField));
275 : // "short name" field?
276 0 : if (vFieldInfo[iField].nUserOptionsId == USER_OPT_ID)
277 : {
278 0 : nNameRow = vRows.size() - 1;
279 0 : nShortNameField = vFields.size() - 1;
280 : }
281 : }
282 0 : rRow.nLastField = vFields.size();
283 : }
284 0 : }
285 :
286 :
287 :
288 0 : void SvxGeneralTabPage::SetLinks ()
289 : {
290 : // link for updating the initials
291 0 : Link aLink = LINK( this, SvxGeneralTabPage, ModifyHdl_Impl );
292 0 : Row& rNameRow = *vRows[nNameRow];
293 0 : for (unsigned i = rNameRow.nFirstField; i != rNameRow.nLastField - 1; ++i)
294 0 : vFields[i]->pEdit->SetModifyHdl(aLink);
295 0 : }
296 :
297 :
298 :
299 0 : SfxTabPage* SvxGeneralTabPage::Create( vcl::Window* pParent, const SfxItemSet* rAttrSet )
300 : {
301 0 : return ( new SvxGeneralTabPage( pParent, *rAttrSet ) );
302 : }
303 :
304 :
305 :
306 0 : bool SvxGeneralTabPage::FillItemSet( SfxItemSet* )
307 : {
308 : // remove leading and trailing whitespaces
309 0 : for (unsigned i = 0; i != vFields.size(); ++i)
310 0 : vFields[i]->pEdit->SetText(comphelper::string::strip(vFields[i]->pEdit->GetText(), ' '));
311 :
312 0 : bool bModified = false;
313 0 : bModified |= GetAddress_Impl();
314 0 : SvtSaveOptions aSaveOpt;
315 0 : if ( m_pUseDataCB->IsChecked() != aSaveOpt.IsUseUserData() )
316 : {
317 0 : aSaveOpt.SetUseUserData( m_pUseDataCB->IsChecked() );
318 0 : bModified |= true;
319 : }
320 0 : return bModified;
321 : }
322 :
323 :
324 :
325 0 : void SvxGeneralTabPage::Reset( const SfxItemSet* rSet )
326 : {
327 0 : SetAddress_Impl();
328 :
329 0 : sal_uInt16 const nWhich = GetWhich(SID_FIELD_GRABFOCUS);
330 :
331 0 : if (rSet->GetItemState(nWhich) == SfxItemState::SET)
332 : {
333 0 : if (sal_uInt16 const nField = static_cast<const SfxUInt16Item&>(rSet->Get(nWhich)).GetValue())
334 : {
335 0 : for (unsigned i = 0; i != vFields.size(); ++i)
336 0 : if (nField == vFieldInfo[vFields[i]->iField].nGrabFocusId)
337 0 : vFields[i]->pEdit->GrabFocus();
338 : }
339 : else
340 0 : vFields.front()->pEdit->GrabFocus();
341 : }
342 :
343 0 : m_pUseDataCB->Check( SvtSaveOptions().IsUseUserData() );
344 0 : }
345 :
346 :
347 :
348 : // ModifyHdl_Impl()
349 : // This handler updates the initials (short name)
350 : // when one of the name fields was updated.
351 0 : IMPL_LINK( SvxGeneralTabPage, ModifyHdl_Impl, Edit *, pEdit )
352 : {
353 : // short name field and row
354 0 : Field& rShortName = *vFields[nShortNameField];
355 0 : Row& rNameRow = *vRows[nNameRow];
356 : // number of initials
357 0 : unsigned const nInits = rNameRow.nLastField - rNameRow.nFirstField - 1;
358 : // which field was updated? (in rNameRow)
359 0 : unsigned nField = nInits;
360 0 : for (unsigned i = 0; i != nInits; ++i)
361 : {
362 0 : if (vFields[rNameRow.nFirstField + i]->pEdit == pEdit)
363 0 : nField = i;
364 : }
365 : // updating the initial
366 0 : if (nField < nInits && rShortName.pEdit->IsEnabled())
367 : {
368 0 : OUString sShortName = rShortName.pEdit->GetText();
369 : // clear short name if it contains more characters than the number of initials
370 0 : if ((unsigned)sShortName.getLength() > nInits)
371 : {
372 0 : rShortName.pEdit->SetText(OUString());
373 : }
374 0 : while ((unsigned)sShortName.getLength() < nInits)
375 0 : sShortName += OUString(' ');
376 0 : OUString sName = pEdit->GetText();
377 0 : OUString sLetter = OUString(sName.getLength() ? sName.toChar() : ' ');
378 0 : rShortName.pEdit->SetText(sShortName.replaceAt(nField, 1, sLetter).trim());
379 : }
380 0 : return 0;
381 : }
382 :
383 :
384 :
385 0 : bool SvxGeneralTabPage::GetAddress_Impl()
386 : {
387 : // updating
388 0 : SvtUserOptions aUserOpt;
389 0 : for (unsigned i = 0; i != vFields.size(); ++i)
390 : aUserOpt.SetToken(
391 0 : vFieldInfo[vFields[i]->iField].nUserOptionsId,
392 0 : vFields[i]->pEdit->GetText()
393 0 : );
394 :
395 : // modified?
396 0 : for (unsigned i = 0; i != vFields.size(); ++i)
397 0 : if (vFields[i]->pEdit->IsValueChangedFromSaved())
398 0 : return true;
399 0 : return false;
400 : }
401 :
402 :
403 :
404 0 : void SvxGeneralTabPage::SetAddress_Impl()
405 : {
406 : // updating and disabling edit boxes
407 0 : SvtUserOptions aUserOpt;
408 0 : for (unsigned iRow = 0; iRow != vRows.size(); ++iRow)
409 : {
410 0 : Row& rRow = *vRows[iRow];
411 : // the label is enabled if any of its edit fields are enabled
412 0 : bool bEnableLabel = false;
413 0 : for (unsigned iField = rRow.nFirstField; iField != rRow.nLastField; ++iField)
414 : {
415 0 : Field& rField = *vFields[iField];
416 : // updating content
417 0 : unsigned const nToken = vFieldInfo[rField.iField].nUserOptionsId;
418 0 : rField.pEdit->SetText(aUserOpt.GetToken(nToken));
419 : // is enabled?
420 0 : bool const bEnableEdit = !aUserOpt.IsTokenReadonly(nToken);
421 0 : rField.pEdit->Enable(bEnableEdit);
422 0 : bEnableLabel = bEnableLabel || bEnableEdit;
423 : }
424 0 : rRow.pLabel->Enable(bEnableLabel);
425 : }
426 :
427 : // saving
428 0 : for (unsigned i = 0; i != vFields.size(); ++i)
429 0 : vFields[i]->pEdit->SaveValue();
430 0 : }
431 :
432 :
433 :
434 0 : int SvxGeneralTabPage::DeactivatePage( SfxItemSet* pSet_ )
435 : {
436 0 : if ( pSet_ )
437 0 : FillItemSet( pSet_ );
438 0 : return LEAVE_PAGE;
439 0 : }
440 :
441 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|