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
31#include <o3tl/safeint.hxx>
32#include <vcl/svapp.hxx>
33#include <svl/intitem.hxx>
34#include <vcl/settings.hxx>
35
36#include <officecfg/Office/Common.hxx>
38#include <cuioptgenrl.hxx>
39#include <svx/svxids.hrc>
40#include <svx/optgenrl.hxx>
41
42using namespace css;
43
44namespace
45{
46
47// rows
48enum RowType
49{
50 Row_Company,
51 Row_Name,
52 Row_Name_Russian,
53 Row_Name_Eastern,
54 Row_Street,
55 Row_Street_Russian,
56 Row_City,
57 Row_City_US,
58 Row_Country,
59 Row_TitlePos,
60 Row_Phone,
61 Row_FaxMail,
62
63 nRowCount
64};
65
66// language flags
67namespace Lang
68{
69 unsigned const Others = 1;
70 unsigned const Russian = 2;
71 unsigned const Eastern = 4;
72 unsigned const US = 8;
73 unsigned const All = static_cast<unsigned>(-1);
74}
75
76
77// vRowInfo[] -- rows (text + one or more edit boxes)
78// The order is the same as in RowType above, which is up to down.
79
80struct
81{
82 // id of the text
83 const char *pTextId;
84 // language flags (see Lang above):
85 // which language is this row for?
86 unsigned nLangFlags;
87}
88const vRowInfo[] =
89{
90 { "companyft", Lang::All },
91 { "nameft", Lang::All & ~Lang::Russian & ~Lang::Eastern },
92 { "rusnameft", Lang::Russian },
93 { "eastnameft", Lang::Eastern },
94 { "streetft", Lang::All & ~Lang::Russian },
95 { "russtreetft", Lang::Russian },
96 { "icityft", Lang::All & ~Lang::US },
97 { "cityft", Lang::US },
98 { "countryft", Lang::All },
99 { "titleft", Lang::All },
100 { "phoneft", Lang::All },
101 { "faxft", Lang::All },
102};
103
104
105// vFieldInfo[] -- edit boxes
106// The order is up to down, and then left to right.
107
108struct
109{
110 // in which row?
111 RowType eRow;
112 // id of the edit box
113 const char *pEditId;
114 // id for SvtUserOptions in unotools/useroptions.hxx
115 UserOptToken nUserOptionsId;
116 // id for settings the focus (defined in svx/optgenrl.hxx)
117 EditPosition nGrabFocusId;
118}
119const vFieldInfo[] =
120{
121 // Company
122 { Row_Company, "company", UserOptToken::Company, EditPosition::COMPANY },
123 // Name
124 { Row_Name, "firstname", UserOptToken::FirstName, EditPosition::FIRSTNAME },
125 { Row_Name, "lastname", UserOptToken::LastName, EditPosition::LASTNAME },
126 { Row_Name, "shortname", UserOptToken::ID, EditPosition::SHORTNAME },
127 // Name (russian)
128 { Row_Name_Russian, "ruslastname", UserOptToken::LastName, EditPosition::LASTNAME },
129 { Row_Name_Russian, "rusfirstname", UserOptToken::FirstName, EditPosition::FIRSTNAME },
130 { Row_Name_Russian, "rusfathersname", UserOptToken::FathersName, EditPosition::UNKNOWN },
131 { Row_Name_Russian, "russhortname", UserOptToken::ID, EditPosition::SHORTNAME },
132 // Name (eastern: reversed name ord
133 { Row_Name_Eastern, "eastlastname", UserOptToken::LastName, EditPosition::LASTNAME },
134 { Row_Name_Eastern, "eastfirstname", UserOptToken::FirstName, EditPosition::FIRSTNAME },
135 { Row_Name_Eastern, "eastshortname", UserOptToken::ID, EditPosition::SHORTNAME },
136 // Street
137 { Row_Street, "street", UserOptToken::Street, EditPosition::STREET },
138 // Street (russian)
139 { Row_Street_Russian, "russtreet", UserOptToken::Street, EditPosition::STREET },
140 { Row_Street_Russian, "apartnum", UserOptToken::Apartment, EditPosition::UNKNOWN },
141 // City
142 { Row_City, "izip", UserOptToken::Zip, EditPosition::PLZ },
143 { Row_City, "icity", UserOptToken::City, EditPosition::CITY },
144 // City (US)
145 { Row_City_US, "city", UserOptToken::City, EditPosition::CITY },
146 { Row_City_US, "state", UserOptToken::State, EditPosition::STATE },
147 { Row_City_US, "zip", UserOptToken::Zip, EditPosition::PLZ },
148 // Country
149 { Row_Country, "country", UserOptToken::Country, EditPosition::COUNTRY },
150 // Title/Position
151 { Row_TitlePos, "title", UserOptToken::Title, EditPosition::TITLE },
152 { Row_TitlePos, "position", UserOptToken::Position, EditPosition::POSITION },
153 // Phone
154 { Row_Phone, "home", UserOptToken::TelephoneHome, EditPosition::TELPRIV },
155 { Row_Phone, "work", UserOptToken::TelephoneWork, EditPosition::TELCOMPANY },
156 // Fax/Mail
157 { Row_FaxMail, "fax", UserOptToken::Fax, EditPosition::FAX },
158 { Row_FaxMail, "email", UserOptToken::Email, EditPosition::EMAIL },
159};
160
161
162} // namespace
163
164
165// Row
166
168{
169 // row label
170 std::unique_ptr<weld::Label> xLabel;
171 // first and last field in the row (last is exclusive)
173
174public:
175 explicit Row (std::unique_ptr<weld::Label> xLabel_)
176 : xLabel(std::move(xLabel_))
177 , nFirstField(0)
178 , nLastField(0)
179 {
180 xLabel->show();
181 }
182};
183
184
185// Field
186
188{
189 // which field is this? (in vFieldInfo[] above)
190 unsigned iField;
191 // edit box
192 std::unique_ptr<weld::Entry> xEdit;
193 std::unique_ptr<weld::Container> xParent;
194
195public:
196 Field (std::unique_ptr<weld::Entry> xEdit_, unsigned iField_)
197 : iField(iField_)
198 , xEdit(std::move(xEdit_))
199 , xParent(xEdit->weld_parent())
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 visible
205 xParent->show();
206 xEdit->show();
207 }
208};
209
211 : SfxTabPage(pPage, pController, "cui/ui/optuserpage.ui", "OptUserPage", &rCoreSet)
212 , m_xUseDataCB(m_xBuilder->weld_check_button("usefordocprop"))
213 , m_xCryptoFrame(m_xBuilder->weld_widget( "cryptography"))
214 , m_xSigningKeyLB(m_xBuilder->weld_combo_box("signingkey"))
215 , m_xEncryptionKeyLB(m_xBuilder->weld_combo_box("encryptionkey"))
216 , m_xEncryptToSelfCB(m_xBuilder->weld_check_button("encrypttoself"))
217{
218 InitControls();
219#if HAVE_FEATURE_GPGME
221#else
222 m_xCryptoFrame->hide();
223#endif
224
225 SetExchangeSupport(); // this page needs ExchangeSupport
226 SetLinks();
227}
228
230{
231}
232
233// Initializes the titles and the edit boxes,
234// according to vRowInfo[] and vFieldInfo[] above.
236{
237 // which language bit do we use? (see Lang and vRowInfo[] above)
238 unsigned LangBit;
240 if (l == LANGUAGE_ENGLISH_US)
241 LangBit = Lang::US;
242 else if (l == LANGUAGE_RUSSIAN)
243 LangBit = Lang::Russian;
244 else
245 {
247 LangBit = Lang::Eastern;
248 else
249 LangBit = Lang::Others;
250 }
251
252 // creating rows
253 unsigned iField = 0;
254 for (unsigned iRow = 0; iRow != nRowCount; ++iRow)
255 {
256 RowType const eRow = static_cast<RowType>(iRow);
257 // is the row visible?
258 if (!(vRowInfo[iRow].nLangFlags & LangBit))
259 continue;
260 // creating row
261 vRows.push_back(std::make_shared<Row>(
262 m_xBuilder->weld_label(vRowInfo[iRow].pTextId)));
263 Row& rRow = *vRows.back();
264 // fields in the row
265 static unsigned const nFieldCount = std::size(vFieldInfo);
266 // skipping other (invisible) rows
267 while (iField != nFieldCount && vFieldInfo[iField].eRow != eRow)
268 ++iField;
269 // fields in the row
270 rRow.nFirstField = vFields.size();
271 for ( ; iField != nFieldCount && vFieldInfo[iField].eRow == eRow; ++iField)
272 {
273 // creating edit field
274 vFields.push_back(std::make_shared<Field>(
275 m_xBuilder->weld_entry(vFieldInfo[iField].pEditId), iField));
276 // "short name" field?
277 if (vFieldInfo[iField].nUserOptionsId == UserOptToken::ID)
278 {
279 nNameRow = vRows.size() - 1;
280 nShortNameField = vFields.size() - 1;
281 }
282 }
283 rRow.nLastField = vFields.size();
284 }
285}
286
288{
289#if HAVE_FEATURE_GPGME
290 m_xCryptoFrame->show();
291
293 try
294 {
295 xSEInitializer = xml::crypto::GPGSEInitializer::create( comphelper::getProcessComponentContext() );
296 uno::Reference<xml::crypto::XXMLSecurityContext> xSC = xSEInitializer->createSecurityContext( OUString() );
297 if (xSC.is())
298 {
299 uno::Reference<xml::crypto::XSecurityEnvironment> xSE = xSC->getSecurityEnvironment();
300 uno::Sequence<uno::Reference<security::XCertificate>> xCertificates = xSE->getPersonalCertificates();
301
302 if (xCertificates.hasElements())
303 {
304 for (auto& xCert : asNonConstRange(xCertificates))
305 {
306 m_xSigningKeyLB->append_text( xCert->getIssuerName());
307 m_xEncryptionKeyLB->append_text( xCert->getIssuerName());
308 }
309 }
310
311 //tdf#115015: wrap checkbox text and listboxes if necessary
312 int nPrefWidth(m_xEncryptToSelfCB->get_preferred_size().Width());
313 int nMaxWidth = m_xEncryptToSelfCB->get_approximate_digit_width() * 40;
314 if (nPrefWidth > nMaxWidth)
315 {
316 m_xSigningKeyLB->set_size_request(nMaxWidth, -1);
317 m_xEncryptionKeyLB->set_size_request(nMaxWidth, -1);
318 m_xEncryptToSelfCB->set_label_wrap(true);
319 m_xEncryptToSelfCB->set_size_request(nMaxWidth, -1);
320 }
321 }
322 }
323 catch ( uno::Exception const & )
324 {}
325#endif
326
327}
328
330{
331 // link for updating the initials
332 Link<weld::Entry&,void> aLink = LINK( this, SvxGeneralTabPage, ModifyHdl_Impl );
333 Row& rNameRow = *vRows[nNameRow];
334 for (unsigned i = rNameRow.nFirstField; i != rNameRow.nLastField - 1; ++i)
335 vFields[i]->xEdit->connect_changed(aLink);
336}
337
338
339std::unique_ptr<SfxTabPage> SvxGeneralTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet )
340{
341 return std::make_unique<SvxGeneralTabPage>( pPage, pController, *rAttrSet );
342}
343
345{
346 // remove leading and trailing whitespaces
347 for (auto const & i: vFields)
348 i->xEdit->set_text(comphelper::string::strip(i->xEdit->get_text(), ' '));
349
350 bool bModified = false;
351 bModified |= GetData_Impl();
352 if (m_xUseDataCB->get_active() != officecfg::Office::Common::Save::Document::UseUserData::get())
353 {
355 officecfg::Office::Common::Save::Document::UseUserData::set(m_xUseDataCB->get_active(), xChanges);
356 xChanges->commit();
357 bModified = true;
358 }
359 return bModified;
360}
361
363{
364 SetData_Impl();
365
366 if (rSet->GetItemState(SID_FIELD_GRABFOCUS) == SfxItemState::SET)
367 {
368 EditPosition nField = static_cast<EditPosition>(static_cast<const SfxUInt16Item&>(rSet->Get(SID_FIELD_GRABFOCUS)).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_active(officecfg::Office::Common::Save::Document::UseUserData::get());
380}
381
382
383// ModifyHdl_Impl()
384// This handler updates the initials (short name)
385// when one of the name fields was updated.
386IMPL_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 return;
403
404 OUString sShortName = rShortName.xEdit->get_text();
405 // clear short name if it contains more characters than the number of initials
406 if (o3tl::make_unsigned(sShortName.getLength()) > nInits)
407 {
408 rShortName.xEdit->set_text(OUString());
409 }
410 while (o3tl::make_unsigned(sShortName.getLength()) < nInits)
411 sShortName += " ";
412 OUString sName = rEdit.get_text();
413 OUString sLetter = sName.isEmpty()
414 ? OUString(u' ') : sName.copy(0, 1);
415 rShortName.xEdit->set_text(sShortName.replaceAt(nField, 1, sLetter).trim());
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: */
const LanguageTag & GetUILanguageTag() const
static const AllSettings & GetSettings()
LanguageType getLanguageType(bool bResolveSystem=true) const
static bool isFamilyNameFirst(LanguageType nLang)
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
void SetExchangeSupport()
bool IsTokenReadonly(UserOptToken nToken) const
bool GetEncryptToSelf() const
OUString GetToken(UserOptToken nToken) const
void SetBoolValue(UserOptToken nToken, bool bNewValue)
void SetToken(UserOptToken nToken, OUString const &rNewToken)
void InitCryptography()
Definition: optgenrl.cxx:287
std::vector< std::shared_ptr< Row > > vRows
Definition: cuioptgenrl.hxx:40
virtual ~SvxGeneralTabPage() override
Definition: optgenrl.cxx:229
std::vector< std::shared_ptr< Field > > vFields
Definition: cuioptgenrl.hxx:43
virtual void Reset(const SfxItemSet *rSet) override
Definition: optgenrl.cxx:362
std::unique_ptr< weld::CheckButton > m_xEncryptToSelfCB
Definition: cuioptgenrl.hxx:38
static std::unique_ptr< SfxTabPage > Create(weld::Container *pPage, weld::DialogController *pController, const SfxItemSet *rAttrSet)
Definition: optgenrl.cxx:339
std::unique_ptr< weld::CheckButton > m_xUseDataCB
Definition: cuioptgenrl.hxx:34
virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override
Definition: optgenrl.cxx:500
SvxGeneralTabPage(weld::Container *pPage, weld::DialogController *pController, const SfxItemSet &rSet)
Definition: optgenrl.cxx:210
std::unique_ptr< weld::Widget > m_xCryptoFrame
Definition: cuioptgenrl.hxx:35
std::unique_ptr< weld::ComboBox > m_xSigningKeyLB
Definition: cuioptgenrl.hxx:36
std::unique_ptr< weld::ComboBox > m_xEncryptionKeyLB
Definition: cuioptgenrl.hxx:37
unsigned nShortNameField
Definition: cuioptgenrl.hxx:47
virtual bool FillItemSet(SfxItemSet *rSet) override
Definition: optgenrl.cxx:344
static std::shared_ptr< ConfigurationChanges > create()
virtual tools::Long GetValue() const override
float u
#define LANGUAGE_RUSSIAN
#define LANGUAGE_ENGLISH_US
const char * sName
OString strip(const OString &rIn, char c)
Reference< XComponentContext > getProcessComponentContext()
int i
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
IMPL_LINK(SvxGeneralTabPage, ModifyHdl_Impl, weld::Entry &, rEdit, void)
Definition: optgenrl.cxx:386
DefTokenId nToken
static SfxItemSet & rSet
Field(std::unique_ptr< weld::Entry > xEdit_, unsigned iField_)
Definition: optgenrl.cxx:196
std::unique_ptr< weld::Entry > xEdit
Definition: optgenrl.cxx:192
std::unique_ptr< weld::Container > xParent
Definition: optgenrl.cxx:193
Row(std::unique_ptr< weld::Label > xLabel_)
Definition: optgenrl.cxx:175
std::unique_ptr< weld::Label > xLabel
Definition: optgenrl.cxx:170
DeactivateRC
UserOptToken