LibreOffice Module cui (master)  1
optgenrl.cxx
Go to the documentation of this file.
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>
22 
23 #include <config_gpgme.h>
24 #if HAVE_FEATURE_GPGME
25 # include <com/sun/star/xml/crypto/GPGSEInitializer.hpp>
26 # include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp>
27 #endif
28 
30 #include <i18nlangtag/mslangid.hxx>
31 #include <vcl/svapp.hxx>
32 #include <unotools/saveopt.hxx>
33 #include <svl/intitem.hxx>
34 #include <vcl/settings.hxx>
35 
36 #include <unotools/useroptions.hxx>
37 #include <cuioptgenrl.hxx>
38 #include <svx/svxids.hrc>
39 #include <svx/optgenrl.hxx>
40 
41 using namespace css;
42 
43 namespace
44 {
45 
46 // rows
47 enum RowType
48 {
49  Row_Company,
50  Row_Name,
51  Row_Name_Russian,
52  Row_Name_Eastern,
53  Row_Street,
54  Row_Street_Russian,
55  Row_City,
56  Row_City_US,
57  Row_Country,
58  Row_TitlePos,
59  Row_Phone,
60  Row_FaxMail,
61 
62  nRowCount
63 };
64 
65 // language flags
66 namespace Lang
67 {
68  unsigned const Others = 1;
69  unsigned const Russian = 2;
70  unsigned const Eastern = 4;
71  unsigned const US = 8;
72  unsigned const All = static_cast<unsigned>(-1);
73 }
74 
75 
76 // vRowInfo[] -- rows (text + one or more edit boxes)
77 // The order is the same as in RowType above, which is up to down.
78 
79 struct
80 {
81  // id of the text
82  const char *pTextId;
83  // language flags (see Lang above):
84  // which language is this row for?
85  unsigned nLangFlags;
86 }
87 const vRowInfo[] =
88 {
89  { "companyft", Lang::All },
90  { "nameft", Lang::All & ~Lang::Russian & ~Lang::Eastern },
91  { "rusnameft", Lang::Russian },
92  { "eastnameft", Lang::Eastern },
93  { "streetft", Lang::All & ~Lang::Russian },
94  { "russtreetft", Lang::Russian },
95  { "icityft", Lang::All & ~Lang::US },
96  { "cityft", Lang::US },
97  { "countryft", Lang::All },
98  { "titleft", Lang::All },
99  { "phoneft", Lang::All },
100  { "faxft", Lang::All },
101 };
102 
103 
104 // vFieldInfo[] -- edit boxes
105 // The order is up to down, and then left to right.
106 
107 struct
108 {
109  // in which row?
110  RowType eRow;
111  // id of the edit box
112  const char *pEditId;
113  // id for SvtUserOptions in unotools/useroptions.hxx
114  UserOptToken nUserOptionsId;
115  // id for settings the focus (defined in svx/optgenrl.hxx)
116  EditPosition nGrabFocusId;
117 }
118 const vFieldInfo[] =
119 {
120  // Company
121  { Row_Company, "company", UserOptToken::Company, EditPosition::COMPANY },
122  // Name
123  { Row_Name, "firstname", UserOptToken::FirstName, EditPosition::FIRSTNAME },
124  { Row_Name, "lastname", UserOptToken::LastName, EditPosition::LASTNAME },
125  { Row_Name, "shortname", UserOptToken::ID, EditPosition::SHORTNAME },
126  // Name (russian)
127  { Row_Name_Russian, "ruslastname", UserOptToken::LastName, EditPosition::LASTNAME },
128  { Row_Name_Russian, "rusfirstname", UserOptToken::FirstName, EditPosition::FIRSTNAME },
129  { Row_Name_Russian, "rusfathersname", UserOptToken::FathersName, EditPosition::UNKNOWN },
130  { Row_Name_Russian, "russhortname", UserOptToken::ID, EditPosition::SHORTNAME },
131  // Name (eastern: reversed name ord
132  { Row_Name_Eastern, "eastlastname", UserOptToken::LastName, EditPosition::LASTNAME },
133  { Row_Name_Eastern, "eastfirstname", UserOptToken::FirstName, EditPosition::FIRSTNAME },
134  { Row_Name_Eastern, "eastshortname", UserOptToken::ID, EditPosition::SHORTNAME },
135  // Street
136  { Row_Street, "street", UserOptToken::Street, EditPosition::STREET },
137  // Street (russian)
138  { Row_Street_Russian, "russtreet", UserOptToken::Street, EditPosition::STREET },
139  { Row_Street_Russian, "apartnum", UserOptToken::Apartment, EditPosition::UNKNOWN },
140  // City
141  { Row_City, "izip", UserOptToken::Zip, EditPosition::PLZ },
142  { Row_City, "icity", UserOptToken::City, EditPosition::CITY },
143  // City (US)
144  { Row_City_US, "city", UserOptToken::City, EditPosition::CITY },
145  { Row_City_US, "state", UserOptToken::State, EditPosition::STATE },
146  { Row_City_US, "zip", UserOptToken::Zip, EditPosition::PLZ },
147  // Country
148  { Row_Country, "country", UserOptToken::Country, EditPosition::COUNTRY },
149  // Title/Position
150  { Row_TitlePos, "title", UserOptToken::Title, EditPosition::TITLE },
151  { Row_TitlePos, "position", UserOptToken::Position, EditPosition::POSITION },
152  // Phone
153  { Row_Phone, "home", UserOptToken::TelephoneHome, EditPosition::TELPRIV },
154  { Row_Phone, "work", UserOptToken::TelephoneWork, EditPosition::TELCOMPANY },
155  // Fax/Mail
156  { Row_FaxMail, "fax", UserOptToken::Fax, EditPosition::FAX },
157  { Row_FaxMail, "email", UserOptToken::Email, EditPosition::EMAIL },
158 };
159 
160 
161 } // namespace
162 
163 
164 // Row
165 
167 {
168  // row label
169  std::unique_ptr<weld::Label> xLabel;
170  // first and last field in the row (last is exclusive)
171  unsigned nFirstField, nLastField;
172 
173 public:
174  explicit Row (std::unique_ptr<weld::Label> xLabel_)
175  : xLabel(std::move(xLabel_))
176  , nFirstField(0)
177  , nLastField(0)
178  {
179  xLabel->show();
180  }
181 };
182 
183 
184 // Field
185 
187 {
188  // which field is this? (in vFieldInfo[] above)
189  unsigned iField;
190  // edit box
191  std::unique_ptr<weld::Entry> xEdit;
192  std::unique_ptr<weld::Container> xParent;
193 
194 public:
195  Field (std::unique_ptr<weld::Entry> xEdit_, unsigned iField_)
196  : iField(iField_)
197  , xEdit(std::move(xEdit_))
198  , xParent(xEdit->weld_parent())
199  {
200  //We want all widgets inside a container, so each row of the toplevel
201  //grid has another container in it. To avoid adding spacing to these
202  //empty grids they all default to invisible, so show them if their
203  //children are visible
204  xParent->show();
205  xEdit->show();
206  }
207 };
208 
210  : SfxTabPage(pPage, pController, "cui/ui/optuserpage.ui", "OptUserPage", &rCoreSet)
211  , m_xUseDataCB(m_xBuilder->weld_check_button("usefordocprop"))
212  , m_xCryptoFrame(m_xBuilder->weld_widget( "cryptography"))
213  , m_xSigningKeyLB(m_xBuilder->weld_combo_box("signingkey"))
214  , m_xEncryptionKeyLB(m_xBuilder->weld_combo_box("encryptionkey"))
215  , m_xEncryptToSelfCB(m_xBuilder->weld_check_button("encrypttoself"))
216 {
217  InitControls();
218 #if HAVE_FEATURE_GPGME
220 #else
221  m_xCryptoFrame->hide();
222 #endif
223 
224  SetExchangeSupport(); // this page needs ExchangeSupport
225  SetLinks();
226 }
227 
229 {
230 }
231 
232 // Initializes the titles and the edit boxes,
233 // according to vRowInfo[] and vFieldInfo[] above.
235 {
236  // which language bit do we use? (see Lang and vRowInfo[] above)
237  unsigned LangBit;
239  if (l == LANGUAGE_ENGLISH_US)
240  LangBit = Lang::US;
241  else if (l == LANGUAGE_RUSSIAN)
242  LangBit = Lang::Russian;
243  else
244  {
246  LangBit = Lang::Eastern;
247  else
248  LangBit = Lang::Others;
249  }
250 
251  // creating rows
252  unsigned iField = 0;
253  for (unsigned iRow = 0; iRow != nRowCount; ++iRow)
254  {
255  RowType const eRow = static_cast<RowType>(iRow);
256  // is the row visible?
257  if (!(vRowInfo[iRow].nLangFlags & LangBit))
258  continue;
259  // creating row
260  vRows.push_back(std::make_shared<Row>(
261  m_xBuilder->weld_label(vRowInfo[iRow].pTextId)));
262  Row& rRow = *vRows.back();
263  // fields in the row
264  static unsigned const nFieldCount = SAL_N_ELEMENTS(vFieldInfo);
265  // skipping other (invisible) rows
266  while (iField != nFieldCount && vFieldInfo[iField].eRow != eRow)
267  ++iField;
268  // fields in the row
269  rRow.nFirstField = vFields.size();
270  for ( ; iField != nFieldCount && vFieldInfo[iField].eRow == eRow; ++iField)
271  {
272  // creating edit field
273  vFields.push_back(std::make_shared<Field>(
274  m_xBuilder->weld_entry(vFieldInfo[iField].pEditId), iField));
275  // "short name" field?
276  if (vFieldInfo[iField].nUserOptionsId == UserOptToken::ID)
277  {
278  nNameRow = vRows.size() - 1;
279  nShortNameField = vFields.size() - 1;
280  }
281  }
282  rRow.nLastField = vFields.size();
283  }
284 }
285 
287 {
288 #if HAVE_FEATURE_GPGME
289  m_xCryptoFrame->show();
290 
291  uno::Reference< xml::crypto::XSEInitializer > xSEInitializer;
292  try
293  {
294  xSEInitializer = xml::crypto::GPGSEInitializer::create( comphelper::getProcessComponentContext() );
295  uno::Reference<xml::crypto::XXMLSecurityContext> xSC = xSEInitializer->createSecurityContext( OUString() );
296  if (xSC.is())
297  {
298  uno::Reference<xml::crypto::XSecurityEnvironment> xSE = xSC->getSecurityEnvironment();
299  uno::Sequence<uno::Reference<security::XCertificate>> xCertificates = xSE->getPersonalCertificates();
300 
301  if (xCertificates.hasElements())
302  {
303  for (auto& xCert : xCertificates)
304  {
305  m_xSigningKeyLB->append_text( xCert->getIssuerName());
306  m_xEncryptionKeyLB->append_text( xCert->getIssuerName());
307  }
308  }
309 
310  //tdf#115015: wrap checkbox text and listboxes if necessary
311  int nPrefWidth(m_xEncryptToSelfCB->get_preferred_size().Width());
312  int nMaxWidth = m_xEncryptToSelfCB->get_approximate_digit_width() * 40;
313  if (nPrefWidth > nMaxWidth)
314  {
315  m_xSigningKeyLB->set_size_request(nMaxWidth, -1);
316  m_xEncryptionKeyLB->set_size_request(nMaxWidth, -1);
317  m_xEncryptToSelfCB->set_label_line_wrap(true);
318  m_xEncryptToSelfCB->set_size_request(nMaxWidth, -1);
319  }
320  }
321  }
322  catch ( uno::Exception const & )
323  {}
324 #endif
325 
326 }
327 
329 {
330  // link for updating the initials
331  Link<weld::Entry&,void> aLink = LINK( this, SvxGeneralTabPage, ModifyHdl_Impl );
332  Row& rNameRow = *vRows[nNameRow];
333  for (unsigned i = rNameRow.nFirstField; i != rNameRow.nLastField - 1; ++i)
334  vFields[i]->xEdit->connect_changed(aLink);
335 }
336 
337 
338 std::unique_ptr<SfxTabPage> SvxGeneralTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet )
339 {
340  return std::make_unique<SvxGeneralTabPage>( pPage, pController, *rAttrSet );
341 }
342 
344 {
345  // remove leading and trailing whitespaces
346  for (auto const & i: vFields)
347  i->xEdit->set_text(comphelper::string::strip(i->xEdit->get_text(), ' '));
348 
349  bool bModified = false;
350  bModified |= GetData_Impl();
351  SvtSaveOptions aSaveOpt;
352  if (m_xUseDataCB->get_active() != aSaveOpt.IsUseUserData())
353  {
354  aSaveOpt.SetUseUserData(m_xUseDataCB->get_active());
355  bModified = true;
356  }
357  return bModified;
358 }
359 
361 {
362  SetData_Impl();
363 
364  sal_uInt16 const nWhich = GetWhich(SID_FIELD_GRABFOCUS);
365 
366  if (rSet->GetItemState(nWhich) == SfxItemState::SET)
367  {
368  EditPosition nField = static_cast<EditPosition>(static_cast<const SfxUInt16Item&>(rSet->Get(nWhich)).GetValue());
369  if (nField != EditPosition::UNKNOWN)
370  {
371  for (auto const & i: vFields)
372  if (nField == vFieldInfo[i->iField].nGrabFocusId)
373  i->xEdit->grab_focus();
374  }
375  else
376  vFields.front()->xEdit->grab_focus();
377  }
378 
379  m_xUseDataCB->set_sensitive( SvtSaveOptions().IsUseUserData() );
380 }
381 
382 
383 // ModifyHdl_Impl()
384 // This handler updates the initials (short name)
385 // when one of the name fields was updated.
386 IMPL_LINK( SvxGeneralTabPage, ModifyHdl_Impl, weld::Entry&, rEdit, void )
387 {
388  // short name field and row
389  Field& rShortName = *vFields[nShortNameField];
390  Row& rNameRow = *vRows[nNameRow];
391  // number of initials
392  unsigned const nInits = rNameRow.nLastField - rNameRow.nFirstField - 1;
393  // which field was updated? (in rNameRow)
394  unsigned nField = nInits;
395  for (unsigned i = 0; i != nInits; ++i)
396  {
397  if (vFields[rNameRow.nFirstField + i]->xEdit.get() == &rEdit)
398  nField = i;
399  }
400  // updating the initial
401  if (nField < nInits && rShortName.xEdit->get_sensitive())
402  {
403  OUString sShortName = rShortName.xEdit->get_text();
404  // clear short name if it contains more characters than the number of initials
405  if (static_cast<unsigned>(sShortName.getLength()) > nInits)
406  {
407  rShortName.xEdit->set_text(OUString());
408  }
409  while (static_cast<unsigned>(sShortName.getLength()) < nInits)
410  sShortName += " ";
411  OUString sName = rEdit.get_text();
412  OUString sLetter = sName.isEmpty()
413  ? OUString(u' ') : sName.copy(0, 1);
414  rShortName.xEdit->set_text(sShortName.replaceAt(nField, 1, sLetter).trim());
415  }
416 }
417 
418 
420 {
421  // updating
422  SvtUserOptions aUserOpt;
423  for (auto const & i: vFields)
424  aUserOpt.SetToken(
425  vFieldInfo[i->iField].nUserOptionsId,
426  i->xEdit->get_text()
427  );
428 
429  // modified?
430  bool bModified = false;
431  for (auto const & i: vFields)
432  {
433  if (i->xEdit->get_value_changed_from_saved())
434  {
435  bModified = true;
436  break;
437  }
438  }
439 
440 #if HAVE_FEATURE_GPGME
441  OUString aSK = m_xSigningKeyLB->get_active() == 0 ? OUString() //i.e. no key
442  : m_xSigningKeyLB->get_active_text();
443  OUString aEK = m_xEncryptionKeyLB->get_active() == 0 ? OUString()
444  : m_xEncryptionKeyLB->get_active_text();
445 
446  aUserOpt.SetToken( UserOptToken::SigningKey, aSK );
447  aUserOpt.SetToken( UserOptToken::EncryptionKey, aEK );
448  aUserOpt.SetBoolValue( UserOptToken::EncryptToSelf, m_xEncryptToSelfCB->get_active() );
449 
450  bModified |= m_xSigningKeyLB->get_value_changed_from_saved() ||
451  m_xEncryptionKeyLB->get_value_changed_from_saved() ||
452  m_xEncryptToSelfCB->get_state_changed_from_saved();
453 #endif
454 
455  return bModified;
456 }
457 
458 
460 {
461  // updating and disabling edit boxes
462  SvtUserOptions aUserOpt;
463  for (auto const & i: vRows)
464  {
465  Row& rRow = *i;
466  // the label is enabled if any of its edit fields are enabled
467  bool bEnableLabel = false;
468  for (unsigned iField = rRow.nFirstField; iField != rRow.nLastField; ++iField)
469  {
470  Field& rField = *vFields[iField];
471  // updating content
472  UserOptToken const nToken = vFieldInfo[rField.iField].nUserOptionsId;
473  rField.xEdit->set_text(aUserOpt.GetToken(nToken));
474  // is enabled?
475  bool const bEnableEdit = !aUserOpt.IsTokenReadonly(nToken);
476  rField.xEdit->set_sensitive(bEnableEdit);
477  bEnableLabel = bEnableLabel || bEnableEdit;
478  }
479  rRow.xLabel->set_sensitive(bEnableLabel);
480  }
481 
482  // saving
483  for (auto const & i: vFields)
484  i->xEdit->save_value();
485 
486 #if HAVE_FEATURE_GPGME
487  OUString aSK = aUserOpt.GetToken(UserOptToken::SigningKey);
488  aSK.isEmpty() ? m_xSigningKeyLB->set_active( 0 ) //i.e. 'No Key'
489  : m_xSigningKeyLB->set_active_text( aSK );
490 
491  OUString aEK = aUserOpt.GetToken(UserOptToken::EncryptionKey);
492  aEK.isEmpty() ? m_xEncryptionKeyLB->set_active( 0 ) //i.e. 'No Key'
493  : m_xEncryptionKeyLB->set_active_text( aEK );
494 
495  m_xEncryptToSelfCB->set_active( aUserOpt.GetEncryptToSelf() );
496 #endif
497 }
498 
499 
501 {
502  if ( pSet_ )
503  FillItemSet( pSet_ );
504  return DeactivateRC::LeavePage;
505 }
506 
507 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString GetToken(UserOptToken nToken) const
#define LANGUAGE_ENGLISH_US
const LanguageTag & GetUILanguageTag() const
std::string GetValue
unsigned nShortNameField
Definition: cuioptgenrl.hxx:48
LanguageType getLanguageType(bool bResolveSystem=true) const
static const AllSettings & GetSettings()
#define LANGUAGE_RUSSIAN
std::unique_ptr< weld::Entry > xEdit
Definition: optgenrl.cxx:191
std::unique_ptr< weld::Widget > m_xCryptoFrame
Definition: cuioptgenrl.hxx:36
RowType
Definition: optgenrl.cxx:47
std::unique_ptr< weld::ComboBox > m_xSigningKeyLB
Definition: cuioptgenrl.hxx:37
std::vector< std::shared_ptr< Row > > vRows
Definition: cuioptgenrl.hxx:41
bool IsTokenReadonly(UserOptToken nToken) const
std::unique_ptr< weld::CheckButton > m_xEncryptToSelfCB
Definition: cuioptgenrl.hxx:39
void SetExchangeSupport()
SvxGeneralTabPage(weld::Container *pPage, weld::DialogController *pController, const SfxItemSet &rSet)
Definition: optgenrl.cxx:209
OString strip(const OString &rIn, sal_Char c)
virtual bool FillItemSet(SfxItemSet *rSet) override
Definition: optgenrl.cxx:343
#define SAL_N_ELEMENTS(arr)
void SetUseUserData(bool b)
Field(std::unique_ptr< weld::Entry > xEdit_, unsigned iField_)
Definition: optgenrl.cxx:195
static bool isFamilyNameFirst(LanguageType nLang)
void SetBoolValue(UserOptToken nToken, bool bNewValue)
void InitCryptography()
Definition: optgenrl.cxx:286
bool IsUseUserData() const
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
bool GetEncryptToSelf() const
OUString sName
int i
std::unique_ptr< weld::CheckButton > m_xUseDataCB
Definition: cuioptgenrl.hxx:35
float u
IMPL_LINK(SvxGeneralTabPage, ModifyHdl_Impl, weld::Entry &, rEdit, void)
Definition: optgenrl.cxx:386
virtual OUString get_text() const =0
virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override
Definition: optgenrl.cxx:500
void SetToken(UserOptToken nToken, OUString const &rNewToken)
std::vector< std::shared_ptr< Field > > vFields
Definition: cuioptgenrl.hxx:44
weld::Entry & rEdit
UserOptToken
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
virtual void Reset(const SfxItemSet *rSet) override
Definition: optgenrl.cxx:360
Reference< XComponentContext > getProcessComponentContext()
std::unique_ptr< weld::Label > xLabel
Definition: optgenrl.cxx:169
DeactivateRC
virtual ~SvxGeneralTabPage() override
Definition: optgenrl.cxx:228
std::unique_ptr< weld::ComboBox > m_xEncryptionKeyLB
Definition: cuioptgenrl.hxx:38
DefTokenId const nToken
static std::unique_ptr< SfxTabPage > Create(weld::Container *pPage, weld::DialogController *pController, const SfxItemSet *rAttrSet)
Definition: optgenrl.cxx:338
Row(std::unique_ptr< weld::Label > xLabel_)
Definition: optgenrl.cxx:174
sal_uInt16 GetWhich(sal_uInt16 nSlot, bool bDeep=true) const
std::unique_ptr< weld::Container > xParent
Definition: optgenrl.cxx:192