1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
3 * This file is part of the LibreOffice project.
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/.
10 #include <SignSignatureLineDialog.hxx>
12 #include <sal/log.hxx>
13 #include <sal/types.h>
15 #include <dialmgr.hxx>
16 #include <strings.hrc>
18 #include <comphelper/graphicmimetype.hxx>
19 #include <comphelper/processfactory.hxx>
20 #include <comphelper/propertyvalue.hxx>
21 #include <sfx2/filedlghelper.hxx>
22 #include <sfx2/objsh.hxx>
23 #include <svx/xoutbmp.hxx>
25 #include <vcl/graph.hxx>
26 #include <vcl/weld.hxx>
27 #include <svx/signaturelinehelper.hxx>
28 #include <tools/urlobj.hxx>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/graphic/GraphicProvider.hpp>
32 #include <com/sun/star/graphic/XGraphic.hpp>
33 #include <com/sun/star/graphic/XGraphicProvider.hpp>
34 #include <com/sun/star/security/CertificateKind.hpp>
35 #include <com/sun/star/security/XCertificate.hpp>
36 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
37 #include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
39 using namespace comphelper
;
41 using namespace css::uno
;
42 using namespace css::beans
;
43 using namespace css::frame
;
44 using namespace css::frame
;
45 using namespace css::text
;
46 using namespace css::graphic
;
47 using namespace css::security
;
48 using namespace css::ui::dialogs
;
50 SignSignatureLineDialog::SignSignatureLineDialog(weld::Widget
* pParent
, Reference
<XModel
> xModel
)
51 : SignatureLineDialogBase(pParent
, std::move(xModel
), u
"cui/ui/signsignatureline.ui"_ustr
,
52 u
"SignSignatureLineDialog"_ustr
)
53 , m_xEditName(m_xBuilder
->weld_entry(u
"edit_name"_ustr
))
54 , m_xEditComment(m_xBuilder
->weld_text_view(u
"edit_comment"_ustr
))
55 , m_xBtnLoadImage(m_xBuilder
->weld_button(u
"btn_load_image"_ustr
))
56 , m_xBtnClearImage(m_xBuilder
->weld_button(u
"btn_clear_image"_ustr
))
57 , m_xBtnChooseCertificate(m_xBuilder
->weld_button(u
"btn_select_certificate"_ustr
))
58 , m_xBtnSign(m_xBuilder
->weld_button(u
"ok"_ustr
))
59 , m_xLabelHint(m_xBuilder
->weld_label(u
"label_hint"_ustr
))
60 , m_xLabelHintText(m_xBuilder
->weld_label(u
"label_hint_text"_ustr
))
61 , m_xLabelAddComment(m_xBuilder
->weld_label(u
"label_add_comment"_ustr
))
62 , m_bShowSignDate(false)
64 Reference
<container::XIndexAccess
> xIndexAccess(m_xModel
->getCurrentSelection(),
66 m_xShapeProperties
.set(xIndexAccess
->getByIndex(0), UNO_QUERY_THROW
);
68 bool bIsSignatureLine(false);
69 m_xShapeProperties
->getPropertyValue(u
"IsSignatureLine"_ustr
) >>= bIsSignatureLine
;
70 if (!bIsSignatureLine
)
72 SAL_WARN("cui.dialogs", "No signature line selected!");
76 m_xBtnLoadImage
->connect_clicked(LINK(this, SignSignatureLineDialog
, loadImage
));
77 m_xBtnClearImage
->connect_clicked(LINK(this, SignSignatureLineDialog
, clearImage
));
78 m_xBtnChooseCertificate
->connect_clicked(
79 LINK(this, SignSignatureLineDialog
, chooseCertificate
));
80 m_xEditName
->connect_changed(LINK(this, SignSignatureLineDialog
, entryChanged
));
82 // Read properties from selected signature line
83 m_xShapeProperties
->getPropertyValue(u
"SignatureLineId"_ustr
) >>= m_aSignatureLineId
;
84 m_xShapeProperties
->getPropertyValue(u
"SignatureLineSuggestedSignerName"_ustr
)
85 >>= m_aSuggestedSignerName
;
86 m_xShapeProperties
->getPropertyValue(u
"SignatureLineSuggestedSignerTitle"_ustr
)
87 >>= m_aSuggestedSignerTitle
;
88 OUString aSigningInstructions
;
89 m_xShapeProperties
->getPropertyValue(u
"SignatureLineSigningInstructions"_ustr
)
90 >>= aSigningInstructions
;
91 m_xShapeProperties
->getPropertyValue(u
"SignatureLineShowSignDate"_ustr
) >>= m_bShowSignDate
;
92 bool bCanAddComment(false);
93 m_xShapeProperties
->getPropertyValue(u
"SignatureLineCanAddComment"_ustr
) >>= bCanAddComment
;
95 if (aSigningInstructions
.isEmpty())
98 m_xLabelHintText
->hide();
102 m_xLabelHintText
->set_label(aSigningInstructions
);
107 m_xEditComment
->set_size_request(m_xEditComment
->get_approximate_digit_width() * 48,
108 m_xEditComment
->get_text_height() * 5);
112 m_xLabelAddComment
->hide();
113 m_xEditComment
->hide();
114 m_xEditComment
->set_size_request(0, 0);
120 IMPL_LINK_NOARG(SignSignatureLineDialog
, loadImage
, weld::Button
&, void)
122 const Reference
<XComponentContext
>& xContext
= comphelper::getProcessComponentContext();
123 sfx2::FileDialogHelper
aHelper(TemplateDescription::FILEOPEN_PREVIEW
, FileDialogFlags::NONE
,
125 aHelper
.SetContext(sfx2::FileDialogHelper::SignatureLine
);
126 Reference
<XFilePicker3
> xFilePicker
= aHelper
.GetFilePicker();
127 if (!xFilePicker
->execute())
130 Sequence
<OUString
> aSelectedFiles
= xFilePicker
->getSelectedFiles();
131 if (!aSelectedFiles
.hasElements())
134 Reference
<XGraphicProvider
> xProvider
= GraphicProvider::create(xContext
);
135 Sequence
<PropertyValue
> aMediaProperties
{ comphelper::makePropertyValue(u
"URL"_ustr
,
136 aSelectedFiles
[0]) };
137 m_xSignatureImage
= xProvider
->queryGraphic(aMediaProperties
);
138 m_sOriginalImageBtnLabel
= m_xBtnLoadImage
->get_label();
140 INetURLObject
aObj(aSelectedFiles
[0]);
141 m_xBtnLoadImage
->set_label(aObj
.GetLastName());
146 IMPL_LINK_NOARG(SignSignatureLineDialog
, clearImage
, weld::Button
&, void)
148 m_xSignatureImage
.clear();
149 m_xBtnLoadImage
->set_label(m_sOriginalImageBtnLabel
);
153 IMPL_LINK_NOARG(SignSignatureLineDialog
, chooseCertificate
, weld::Button
&, void)
155 // Document needs to be saved before selecting a certificate
156 SfxObjectShell
* pShell
= SfxObjectShell::Current();
157 if (!pShell
|| !pShell
->PrepareForSigning(m_xDialog
.get()))
160 Reference
<XCertificate
> xSignCertificate
161 = svx::SignatureLineHelper::getSignatureCertificate(pShell
, m_xDialog
.get());
163 if (xSignCertificate
.is())
165 m_xSelectedCertifate
= xSignCertificate
;
166 m_xBtnChooseCertificate
->set_label(
167 svx::SignatureLineHelper::getSignerName(xSignCertificate
));
172 IMPL_LINK_NOARG(SignSignatureLineDialog
, entryChanged
, weld::Entry
&, void) { ValidateFields(); }
174 void SignSignatureLineDialog::ValidateFields()
176 bool bEnableSignBtn
= m_xSelectedCertifate
.is()
177 && (!m_xEditName
->get_text().isEmpty() || m_xSignatureImage
.is());
178 m_xBtnSign
->set_sensitive(bEnableSignBtn
);
180 m_xEditName
->set_sensitive(!m_xSignatureImage
.is());
181 m_xBtnLoadImage
->set_sensitive(m_xEditName
->get_text().isEmpty());
182 m_xBtnClearImage
->set_sensitive(m_xSignatureImage
.is());
185 void SignSignatureLineDialog::Apply()
187 if (!m_xSelectedCertifate
.is())
189 SAL_WARN("cui.dialogs", "No certificate selected!");
193 SfxObjectShell
* pShell
= SfxObjectShell::Current();
196 SAL_WARN("cui.dialogs", "No SfxObjectShell!");
200 Reference
<XGraphic
> xValidGraphic
= getSignedGraphic(true);
201 Reference
<XGraphic
> xInvalidGraphic
= getSignedGraphic(false);
202 pShell
->SignSignatureLine(m_xDialog
.get(), m_aSignatureLineId
, m_xSelectedCertifate
,
203 xValidGraphic
, xInvalidGraphic
, m_xEditComment
->get_text());
206 css::uno::Reference
<css::graphic::XGraphic
> SignSignatureLineDialog::getSignedGraphic(bool bValid
)
208 // Read svg and replace placeholder texts
209 OUString
aSvgImage(svx::SignatureLineHelper::getSignatureImage());
210 aSvgImage
= aSvgImage
.replaceAll("[SIGNER_NAME]", getCDataString(m_aSuggestedSignerName
));
211 aSvgImage
= aSvgImage
.replaceAll("[SIGNER_TITLE]", getCDataString(m_aSuggestedSignerTitle
));
214 = CuiResId(RID_CUISTR_SIGNATURELINE_SIGNED_BY
)
215 .replaceFirst("%1", svx::SignatureLineHelper::getSignerName(m_xSelectedCertifate
));
216 aSvgImage
= aSvgImage
.replaceAll("[SIGNED_BY]", getCDataString(aIssuerLine
));
218 aSvgImage
= aSvgImage
.replaceAll("[INVALID_SIGNATURE]", "");
221 if (m_bShowSignDate
&& bValid
)
223 aDate
= svx::SignatureLineHelper::getLocalizedDate();
225 aSvgImage
= aSvgImage
.replaceAll("[DATE]", aDate
);
227 // Custom signature image
228 if (m_xSignatureImage
.is())
230 OUString aGraphicInBase64
;
231 Graphic
aGraphic(m_xSignatureImage
);
232 if (!XOutBitmap::GraphicToBase64(aGraphic
, aGraphicInBase64
, false))
233 SAL_WARN("cui.dialogs", "Could not convert graphic to base64");
235 OUString aImagePart
= u
"<image y=\"825\" x=\"1300\" "
236 "xlink:href=\"data:[MIMETYPE];base64,[BASE64_IMG]>\" "
237 "preserveAspectRatio=\"xMidYMid\" height=\"1520\" "
238 "width=\"7600\" />"_ustr
;
239 aImagePart
= aImagePart
.replaceAll(
240 "[MIMETYPE]", GraphicMimeTypeHelper::GetMimeTypeForXGraphic(m_xSignatureImage
));
241 aImagePart
= aImagePart
.replaceAll("[BASE64_IMG]", aGraphicInBase64
);
242 aSvgImage
= aSvgImage
.replaceAll("[SIGNATURE_IMAGE]", aImagePart
);
244 aSvgImage
= aSvgImage
.replaceAll("[SIGNATURE]", "");
248 aSvgImage
= aSvgImage
.replaceAll("[SIGNATURE_IMAGE]", "");
249 aSvgImage
= aSvgImage
.replaceAll("[SIGNATURE]", getCDataString(m_xEditName
->get_text()));
253 return svx::SignatureLineHelper::importSVG(aSvgImage
);
256 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */