diff options
Diffstat (limited to 'cui/source/options/optgenrl.cxx')
-rw-r--r-- | cui/source/options/optgenrl.cxx | 558 |
1 files changed, 558 insertions, 0 deletions
diff --git a/cui/source/options/optgenrl.cxx b/cui/source/options/optgenrl.cxx new file mode 100644 index 0000000000..d2cf40244d --- /dev/null +++ b/cui/source/options/optgenrl.cxx @@ -0,0 +1,558 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <comphelper/string.hxx> +#include <comphelper/processfactory.hxx> + +#include <config_gpgme.h> +#if HAVE_FEATURE_GPGME +# include <com/sun/star/xml/crypto/GPGSEInitializer.hpp> +# include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp> +#endif + +#include <i18nlangtag/languagetag.hxx> +#include <i18nlangtag/mslangid.hxx> +#include <o3tl/safeint.hxx> +#include <vcl/svapp.hxx> +#include <svl/intitem.hxx> +#include <vcl/settings.hxx> + +#include <officecfg/Office/Common.hxx> +#include <unotools/useroptions.hxx> +#include <cuioptgenrl.hxx> +#include <svx/svxids.hrc> +#include <svx/optgenrl.hxx> + +using namespace css; + +namespace +{ + +// rows +enum RowType +{ + Row_Company, + Row_Name, + Row_Name_Russian, + Row_Name_Eastern, + Row_Street, + Row_Street_Russian, + Row_City, + Row_City_US, + Row_Country, + Row_TitlePos, + Row_Phone, + Row_FaxMail, + + nRowCount +}; + +// language flags +namespace Lang +{ + unsigned const Others = 1; + unsigned const Russian = 2; + unsigned const Eastern = 4; + unsigned const US = 8; + unsigned const All = static_cast<unsigned>(-1); +} + + +// vRowInfo[] -- rows (text + one or more edit boxes) +// The order is the same as in RowType above, which is up to down. + +struct +{ + // id of the lockimage + OUString pLockId; + // id of the text + OUString pTextId; + // language flags (see Lang above): + // which language is this row for? + unsigned nLangFlags; +} +const vRowInfo[] = +{ + { "lockcompanyft", "companyft", Lang::All }, + { "locknameft", "nameft", Lang::All & ~Lang::Russian & ~Lang::Eastern }, + { "lockrusnameft", "rusnameft", Lang::Russian }, + { "lockeastnameft", "eastnameft", Lang::Eastern }, + { "lockstreetft", "streetft", Lang::All & ~Lang::Russian }, + { "lockrusstreetft","russtreetft", Lang::Russian }, + { "lockicityft", "icityft", Lang::All & ~Lang::US }, + { "lockcityft", "cityft", Lang::US }, + { "lockcountryft", "countryft", Lang::All }, + { "locktitleft", "titleft", Lang::All }, + { "lockphoneft", "phoneft", Lang::All }, + { "lockfaxft", "faxft", Lang::All }, +}; + + +// vFieldInfo[] -- edit boxes +// The order is up to down, and then left to right. + +struct +{ + // in which row? + RowType eRow; + // id of the edit box + OUString pEditId; + // id for SvtUserOptions in unotools/useroptions.hxx + UserOptToken nUserOptionsId; + // id for settings the focus (defined in svx/optgenrl.hxx) + EditPosition nGrabFocusId; +} +const vFieldInfo[] = +{ + // Company + { Row_Company, "company", UserOptToken::Company, EditPosition::COMPANY }, + // Name + { Row_Name, "firstname", UserOptToken::FirstName, EditPosition::FIRSTNAME }, + { Row_Name, "lastname", UserOptToken::LastName, EditPosition::LASTNAME }, + { Row_Name, "shortname", UserOptToken::ID, EditPosition::SHORTNAME }, + // Name (russian) + { Row_Name_Russian, "ruslastname", UserOptToken::LastName, EditPosition::LASTNAME }, + { Row_Name_Russian, "rusfirstname", UserOptToken::FirstName, EditPosition::FIRSTNAME }, + { Row_Name_Russian, "rusfathersname", UserOptToken::FathersName, EditPosition::UNKNOWN }, + { Row_Name_Russian, "russhortname", UserOptToken::ID, EditPosition::SHORTNAME }, + // Name (eastern: reversed name ord + { Row_Name_Eastern, "eastlastname", UserOptToken::LastName, EditPosition::LASTNAME }, + { Row_Name_Eastern, "eastfirstname", UserOptToken::FirstName, EditPosition::FIRSTNAME }, + { Row_Name_Eastern, "eastshortname", UserOptToken::ID, EditPosition::SHORTNAME }, + // Street + { Row_Street, "street", UserOptToken::Street, EditPosition::STREET }, + // Street (russian) + { Row_Street_Russian, "russtreet", UserOptToken::Street, EditPosition::STREET }, + { Row_Street_Russian, "apartnum", UserOptToken::Apartment, EditPosition::UNKNOWN }, + // City + { Row_City, "izip", UserOptToken::Zip, EditPosition::PLZ }, + { Row_City, "icity", UserOptToken::City, EditPosition::CITY }, + // City (US) + { Row_City_US, "city", UserOptToken::City, EditPosition::CITY }, + { Row_City_US, "state", UserOptToken::State, EditPosition::STATE }, + { Row_City_US, "zip", UserOptToken::Zip, EditPosition::PLZ }, + // Country + { Row_Country, "country", UserOptToken::Country, EditPosition::COUNTRY }, + // Title/Position + { Row_TitlePos, "title", UserOptToken::Title, EditPosition::TITLE }, + { Row_TitlePos, "position", UserOptToken::Position, EditPosition::POSITION }, + // Phone + { Row_Phone, "home", UserOptToken::TelephoneHome, EditPosition::TELPRIV }, + { Row_Phone, "work", UserOptToken::TelephoneWork, EditPosition::TELCOMPANY }, + // Fax/Mail + { Row_FaxMail, "fax", UserOptToken::Fax, EditPosition::FAX }, + { Row_FaxMail, "email", UserOptToken::Email, EditPosition::EMAIL }, +}; + + +} // namespace + + +// Row + +struct SvxGeneralTabPage::Row +{ + // row lockdown icon + std::unique_ptr<weld::Widget> xLockImg; + // row label + std::unique_ptr<weld::Label> xLabel; + // first and last field in the row (last is exclusive) + unsigned nFirstField, nLastField; + +public: + explicit Row (std::unique_ptr<weld::Widget> xLockImg_, std::unique_ptr<weld::Label> xLabel_) + : xLockImg(std::move(xLockImg_)) + , xLabel(std::move(xLabel_)) + , nFirstField(0) + , nLastField(0) + { + xLabel->show(); + } +}; + + +// Field + +struct SvxGeneralTabPage::Field +{ + // which field is this? (in vFieldInfo[] above) + unsigned iField; + // edit box + std::unique_ptr<weld::Entry> xEdit; + std::unique_ptr<weld::Container> xParent; + +public: + Field (std::unique_ptr<weld::Entry> xEdit_, unsigned iField_) + : iField(iField_) + , xEdit(std::move(xEdit_)) + , xParent(xEdit->weld_parent()) + { + //We want all widgets inside a container, so each row of the toplevel + //grid has another container in it. To avoid adding spacing to these + //empty grids they all default to invisible, so show them if their + //children are visible + xParent->show(); + xEdit->show(); + } +}; + +SvxGeneralTabPage::SvxGeneralTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet) + : SfxTabPage(pPage, pController, "cui/ui/optuserpage.ui", "OptUserPage", &rCoreSet) + , m_xUseDataCB(m_xBuilder->weld_check_button("usefordocprop")) + , m_xUseDataImg(m_xBuilder->weld_widget("lockusefordocprop")) + , m_xCryptoFrame(m_xBuilder->weld_widget( "cryptography")) + , m_xSigningKeyLB(m_xBuilder->weld_combo_box("signingkey")) + , m_xSigningKeyFT(m_xBuilder->weld_label("signingkeylabel")) + , m_xSigningKeyImg(m_xBuilder->weld_widget("locksigningkey")) + , m_xEncryptionKeyLB(m_xBuilder->weld_combo_box("encryptionkey")) + , m_xEncryptionKeyFT(m_xBuilder->weld_label("encryptionkeylabel")) + , m_xEncryptionKeyImg(m_xBuilder->weld_widget("lockencryptionkey")) + , m_xEncryptToSelfCB(m_xBuilder->weld_check_button("encrypttoself")) + , m_xEncryptToSelfImg(m_xBuilder->weld_widget("lockencrypttoself")) +{ + InitControls(); +#if HAVE_FEATURE_GPGME + InitCryptography(); +#else + m_xCryptoFrame->hide(); +#endif + + SetExchangeSupport(); // this page needs ExchangeSupport + SetLinks(); +} + +SvxGeneralTabPage::~SvxGeneralTabPage() +{ +} + +// Initializes the titles and the edit boxes, +// according to vRowInfo[] and vFieldInfo[] above. +void SvxGeneralTabPage::InitControls () +{ + // which language bit do we use? (see Lang and vRowInfo[] above) + unsigned LangBit; + LanguageType l = Application::GetSettings().GetUILanguageTag().getLanguageType(); + if (l == LANGUAGE_ENGLISH_US) + LangBit = Lang::US; + else if (l == LANGUAGE_RUSSIAN) + LangBit = Lang::Russian; + else + { + if (MsLangId::isFamilyNameFirst(l)) + LangBit = Lang::Eastern; + else + LangBit = Lang::Others; + } + + // creating rows + unsigned iField = 0; + for (unsigned iRow = 0; iRow != nRowCount; ++iRow) + { + RowType const eRow = static_cast<RowType>(iRow); + // is the row visible? + if (!(vRowInfo[iRow].nLangFlags & LangBit)) + continue; + // creating row + vRows.push_back(std::make_shared<Row>(m_xBuilder->weld_widget(vRowInfo[iRow].pLockId), + m_xBuilder->weld_label(vRowInfo[iRow].pTextId))); + Row& rRow = *vRows.back(); + // fields in the row + static unsigned const nFieldCount = std::size(vFieldInfo); + // skipping other (invisible) rows + while (iField != nFieldCount && vFieldInfo[iField].eRow != eRow) + ++iField; + // fields in the row + rRow.nFirstField = vFields.size(); + for ( ; iField != nFieldCount && vFieldInfo[iField].eRow == eRow; ++iField) + { + // creating edit field + vFields.push_back(std::make_shared<Field>( + m_xBuilder->weld_entry(vFieldInfo[iField].pEditId), iField)); + // "short name" field? + if (vFieldInfo[iField].nUserOptionsId == UserOptToken::ID) + { + nNameRow = vRows.size() - 1; + nShortNameField = vFields.size() - 1; + } + } + rRow.nLastField = vFields.size(); + } +} + +void SvxGeneralTabPage::InitCryptography() +{ +#if HAVE_FEATURE_GPGME + m_xCryptoFrame->show(); + + uno::Reference< xml::crypto::XSEInitializer > xSEInitializer; + try + { + xSEInitializer = xml::crypto::GPGSEInitializer::create( comphelper::getProcessComponentContext() ); + uno::Reference<xml::crypto::XXMLSecurityContext> xSC = xSEInitializer->createSecurityContext( OUString() ); + if (xSC.is()) + { + uno::Reference<xml::crypto::XSecurityEnvironment> xSE = xSC->getSecurityEnvironment(); + uno::Sequence<uno::Reference<security::XCertificate>> xCertificates = xSE->getPersonalCertificates(); + + if (xCertificates.hasElements()) + { + for (auto& xCert : asNonConstRange(xCertificates)) + { + m_xSigningKeyLB->append_text( xCert->getIssuerName()); + m_xEncryptionKeyLB->append_text( xCert->getIssuerName()); + } + } + + //tdf#115015: wrap checkbox text and listboxes if necessary + int nPrefWidth(m_xEncryptToSelfCB->get_preferred_size().Width()); + int nMaxWidth = m_xEncryptToSelfCB->get_approximate_digit_width() * 40; + if (nPrefWidth > nMaxWidth) + { + m_xSigningKeyLB->set_size_request(nMaxWidth, -1); + m_xEncryptionKeyLB->set_size_request(nMaxWidth, -1); + m_xEncryptToSelfCB->set_label_wrap(true); + m_xEncryptToSelfCB->set_size_request(nMaxWidth, -1); + } + } + } + catch ( uno::Exception const & ) + {} +#endif + +} + +void SvxGeneralTabPage::SetLinks () +{ + // link for updating the initials + Link<weld::Entry&,void> aLink = LINK( this, SvxGeneralTabPage, ModifyHdl_Impl ); + Row& rNameRow = *vRows[nNameRow]; + for (unsigned i = rNameRow.nFirstField; i != rNameRow.nLastField - 1; ++i) + vFields[i]->xEdit->connect_changed(aLink); +} + + +std::unique_ptr<SfxTabPage> SvxGeneralTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) +{ + return std::make_unique<SvxGeneralTabPage>( pPage, pController, *rAttrSet ); +} + +OUString SvxGeneralTabPage::GetAllStrings() +{ + OUString sAllStrings; + OUString labels[] + = { "label1", "companyft", "nameft", "rusnameft", + "eastnameft", "streetft", "russtreetft", "icityft", + "cityft", "countryft", "titleft", "phoneft", + "faxft", "cryptographylabel", "signingkeylabel", "encryptionkeylabel" }; + + for (const auto& label : labels) + { + if (const auto& pString = m_xBuilder->weld_label(label)) + sAllStrings += pString->get_label() + " "; + } + + sAllStrings += m_xUseDataCB->get_label() + " " + m_xEncryptToSelfCB->get_label() + " "; + + return sAllStrings.replaceAll("_", ""); +} + +bool SvxGeneralTabPage::FillItemSet( SfxItemSet* ) +{ + // remove leading and trailing whitespaces + for (auto const & i: vFields) + i->xEdit->set_text(comphelper::string::strip(i->xEdit->get_text(), ' ')); + + bool bModified = false; + bModified |= GetData_Impl(); + if (m_xUseDataCB->get_active() != officecfg::Office::Common::Save::Document::UseUserData::get()) + { + auto xChanges = comphelper::ConfigurationChanges::create(); + officecfg::Office::Common::Save::Document::UseUserData::set(m_xUseDataCB->get_active(), xChanges); + xChanges->commit(); + bModified = true; + } + return bModified; +} + +void SvxGeneralTabPage::Reset( const SfxItemSet* rSet ) +{ + SetData_Impl(); + + if (rSet->GetItemState(SID_FIELD_GRABFOCUS) == SfxItemState::SET) + { + EditPosition nField = static_cast<EditPosition>(rSet->Get(SID_FIELD_GRABFOCUS).GetValue()); + if (nField != EditPosition::UNKNOWN) + { + for (auto const & i: vFields) + if (nField == vFieldInfo[i->iField].nGrabFocusId) + i->xEdit->grab_focus(); + } + else + vFields.front()->xEdit->grab_focus(); + } + + m_xUseDataCB->set_active(officecfg::Office::Common::Save::Document::UseUserData::get()); +} + + +// ModifyHdl_Impl() +// This handler updates the initials (short name) +// when one of the name fields was updated. +IMPL_LINK( SvxGeneralTabPage, ModifyHdl_Impl, weld::Entry&, rEdit, void ) +{ + // short name field and row + Field& rShortName = *vFields[nShortNameField]; + Row& rNameRow = *vRows[nNameRow]; + // number of initials + unsigned const nInits = rNameRow.nLastField - rNameRow.nFirstField - 1; + // which field was updated? (in rNameRow) + unsigned nField = nInits; + for (unsigned i = 0; i != nInits; ++i) + { + if (vFields[rNameRow.nFirstField + i]->xEdit.get() == &rEdit) + nField = i; + } + // updating the initial + if (!(nField < nInits && rShortName.xEdit->get_sensitive())) + return; + + OUString sShortName = rShortName.xEdit->get_text(); + // clear short name if it contains more characters than the number of initials + if (o3tl::make_unsigned(sShortName.getLength()) > nInits) + { + rShortName.xEdit->set_text(OUString()); + } + while (o3tl::make_unsigned(sShortName.getLength()) < nInits) + sShortName += " "; + OUString sName = rEdit.get_text(); + OUString sLetter = sName.isEmpty() + ? OUString(u' ') : sName.copy(0, 1); + rShortName.xEdit->set_text(sShortName.replaceAt(nField, 1, sLetter).trim()); +} + + +bool SvxGeneralTabPage::GetData_Impl() +{ + // updating + SvtUserOptions aUserOpt; + for (auto const & i: vFields) + aUserOpt.SetToken( + vFieldInfo[i->iField].nUserOptionsId, + i->xEdit->get_text() + ); + + // modified? + bool bModified = false; + for (auto const & i: vFields) + { + if (i->xEdit->get_value_changed_from_saved()) + { + bModified = true; + break; + } + } + +#if HAVE_FEATURE_GPGME + OUString aSK = m_xSigningKeyLB->get_active() == 0 ? OUString() //i.e. no key + : m_xSigningKeyLB->get_active_text(); + OUString aEK = m_xEncryptionKeyLB->get_active() == 0 ? OUString() + : m_xEncryptionKeyLB->get_active_text(); + + aUserOpt.SetToken( UserOptToken::SigningKey, aSK ); + aUserOpt.SetToken( UserOptToken::EncryptionKey, aEK ); + aUserOpt.SetBoolValue( UserOptToken::EncryptToSelf, m_xEncryptToSelfCB->get_active() ); + + bModified |= m_xSigningKeyLB->get_value_changed_from_saved() || + m_xEncryptionKeyLB->get_value_changed_from_saved() || + m_xEncryptToSelfCB->get_state_changed_from_saved(); +#endif + + return bModified; +} + + +void SvxGeneralTabPage::SetData_Impl() +{ + // updating and disabling edit boxes + SvtUserOptions aUserOpt; + for (auto const & i: vRows) + { + Row& rRow = *i; + // the label is enabled if any of its edit fields are enabled + bool bEnableLabel = false; + for (unsigned iField = rRow.nFirstField; iField != rRow.nLastField; ++iField) + { + Field& rField = *vFields[iField]; + // updating content + UserOptToken const nToken = vFieldInfo[rField.iField].nUserOptionsId; + rField.xEdit->set_text(aUserOpt.GetToken(nToken)); + // is enabled? + bool const bEnableEdit = !aUserOpt.IsTokenReadonly(nToken); + rField.xEdit->set_sensitive(bEnableEdit); + bEnableLabel = bEnableLabel || bEnableEdit; + } + rRow.xLabel->set_sensitive(bEnableLabel); + rRow.xLockImg->set_visible(!bEnableLabel); + } + + // saving + for (auto const & i: vFields) + i->xEdit->save_value(); + + //enabling and disabling remaining fields + bool bEnable = !officecfg::Office::Common::Save::Document::UseUserData::isReadOnly(); + m_xUseDataCB->set_sensitive(bEnable); + m_xUseDataImg->set_visible(!bEnable); + +#if HAVE_FEATURE_GPGME + bEnable = !aUserOpt.IsTokenReadonly(UserOptToken::SigningKey); + m_xSigningKeyLB->set_sensitive(bEnable); + m_xSigningKeyFT->set_sensitive(bEnable); + m_xSigningKeyImg->set_visible(!bEnable); + + bEnable = !aUserOpt.IsTokenReadonly(UserOptToken::EncryptionKey); + m_xEncryptionKeyLB->set_sensitive(bEnable); + m_xEncryptionKeyFT->set_sensitive(bEnable); + m_xEncryptionKeyImg->set_visible(!bEnable); + + bEnable = !aUserOpt.IsTokenReadonly(UserOptToken::EncryptToSelf); + m_xEncryptToSelfCB->set_sensitive(bEnable); + m_xEncryptToSelfImg->set_visible(!bEnable); + + OUString aSK = aUserOpt.GetToken(UserOptToken::SigningKey); + aSK.isEmpty() ? m_xSigningKeyLB->set_active( 0 ) //i.e. 'No Key' + : m_xSigningKeyLB->set_active_text( aSK ); + + OUString aEK = aUserOpt.GetToken(UserOptToken::EncryptionKey); + aEK.isEmpty() ? m_xEncryptionKeyLB->set_active( 0 ) //i.e. 'No Key' + : m_xEncryptionKeyLB->set_active_text( aEK ); + + m_xEncryptToSelfCB->set_active( aUserOpt.GetEncryptToSelf() ); +#endif +} + + +DeactivateRC SvxGeneralTabPage::DeactivatePage( SfxItemSet* pSet_ ) +{ + if ( pSet_ ) + FillItemSet( pSet_ ); + return DeactivateRC::LeavePage; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |