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 <QrCodeGenDialog.hxx>
12 #include <comphelper/processfactory.hxx>
13 #include <tools/stream.hxx>
14 #include <unotools/streamwrap.hxx>
16 #include <vcl/weld.hxx>
17 #include <sal/log.hxx>
19 #include <config_qrcodegen.h>
22 #if defined(SYSTEM_QRCODEGEN)
23 #include <qrcodegen/QrCode.hpp>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
31 #include <com/sun/star/drawing/XShape.hpp>
32 #include <com/sun/star/graphic/GraphicProvider.hpp>
33 #include <com/sun/star/graphic/XGraphic.hpp>
34 #include <com/sun/star/drawing/QRCode.hpp>
35 #include <com/sun/star/drawing/QRCodeErrorCorrection.hpp>
36 #include <com/sun/star/graphic/XGraphicProvider.hpp>
37 #include <com/sun/star/io/XInputStream.hpp>
38 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
39 #include <com/sun/star/lang/XServiceInfo.hpp>
40 #include <com/sun/star/sheet/XSpreadsheet.hpp>
41 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
42 #include <com/sun/star/sheet/XSpreadsheetView.hpp>
43 #include <com/sun/star/text/TextContentAnchorType.hpp>
44 #include <com/sun/star/text/XTextContent.hpp>
45 #include <com/sun/star/text/XTextDocument.hpp>
46 #include <com/sun/star/text/XTextViewCursor.hpp>
47 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
48 #include <config_fuzzers.h>
49 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
50 #include <com/sun/star/drawing/XDrawView.hpp>
51 #include <com/sun/star/drawing/XDrawPage.hpp>
54 using namespace css::uno
;
55 using namespace css::beans
;
56 using namespace css::container
;
57 using namespace css::frame
;
58 using namespace css::io
;
59 using namespace css::lang
;
60 using namespace css::frame
;
61 using namespace css::sheet
;
62 using namespace css::text
;
63 using namespace css::drawing
;
64 using namespace css::graphic
;
66 using namespace qrcodegen
;
69 QrCodeGenDialog::QrCodeGenDialog(weld::Widget
* pParent
, Reference
<XModel
> xModel
,
71 : GenericDialogController(pParent
, "cui/ui/qrcodegen.ui", "QrCodeGenDialog")
72 , m_xModel(std::move(xModel
))
73 , m_xEdittext(m_xBuilder
->weld_entry("edit_text"))
74 , m_xECC
{ m_xBuilder
->weld_radio_button("button_low"),
75 m_xBuilder
->weld_radio_button("button_medium"),
76 m_xBuilder
->weld_radio_button("button_quartile"),
77 m_xBuilder
->weld_radio_button("button_high") }
78 , m_xSpinBorder(m_xBuilder
->weld_spin_button("edit_border"))
82 // TODO: This only works in Writer doc. Should also work in shapes
83 Reference
<XIndexAccess
> xSelections(m_xModel
->getCurrentSelection(), UNO_QUERY
);
86 Reference
<XTextRange
> xSelection(xSelections
->getByIndex(0), UNO_QUERY
);
88 m_xEdittext
->set_text(xSelection
->getString());
93 Reference
<container::XIndexAccess
> xIndexAccess(m_xModel
->getCurrentSelection(),
95 Reference
<XPropertySet
> xProps(xIndexAccess
->getByIndex(0), UNO_QUERY_THROW
);
97 // Read properties from selected QR Code
98 css::drawing::QRCode aQRCode
;
99 xProps
->getPropertyValue("QRCodeProperties") >>= aQRCode
;
101 m_xEdittext
->set_text(aQRCode
.Payload
);
103 //Get Error Correction Constant from selected QR Code
104 GetErrorCorrection(aQRCode
.ErrorCorrection
);
106 m_xSpinBorder
->set_value(aQRCode
.Border
);
108 // Mark this as existing shape
109 m_xExistingShapeProperties
= xProps
;
112 short QrCodeGenDialog::run()
115 short nRet
= GenericDialogController::run();
124 void QrCodeGenDialog::Apply()
127 css::drawing::QRCode aQRCode
;
128 aQRCode
.Payload
= m_xEdittext
->get_text();
130 bool bLowECCActive(m_xECC
[0]->get_active());
131 bool bMediumECCActive(m_xECC
[1]->get_active());
132 bool bQuartileECCActive(m_xECC
[2]->get_active());
136 aQRCode
.ErrorCorrection
= css::drawing::QRCodeErrorCorrection::LOW
;
138 else if (bMediumECCActive
)
140 aQRCode
.ErrorCorrection
= css::drawing::QRCodeErrorCorrection::MEDIUM
;
142 else if (bQuartileECCActive
)
144 aQRCode
.ErrorCorrection
= css::drawing::QRCodeErrorCorrection::QUARTILE
;
148 aQRCode
.ErrorCorrection
= css::drawing::QRCodeErrorCorrection::HIGH
;
151 aQRCode
.Border
= m_xSpinBorder
->get_value();
153 // Read svg and replace placeholder texts
154 OUString aSvgImage
= GenerateQRCode(aQRCode
.Payload
, aQRCode
.ErrorCorrection
, aQRCode
.Border
);
156 // Insert/Update graphic
157 SvMemoryStream
aSvgStream(4096, 4096);
158 aSvgStream
.WriteOString(OUStringToOString(aSvgImage
, RTL_TEXTENCODING_UTF8
));
159 Reference
<XInputStream
> xInputStream(new utl::OSeekableInputStreamWrapper(aSvgStream
));
160 Reference
<XComponentContext
> xContext(comphelper::getProcessComponentContext());
161 Reference
<XGraphicProvider
> xProvider
= css::graphic::GraphicProvider::create(xContext
);
163 Sequence
<PropertyValue
> aMediaProperties(1);
164 aMediaProperties
[0].Name
= "InputStream";
165 aMediaProperties
[0].Value
<<= xInputStream
;
166 Reference
<XGraphic
> xGraphic(xProvider
->queryGraphic(aMediaProperties
));
168 bool bIsExistingQRCode
= m_xExistingShapeProperties
.is();
169 Reference
<XPropertySet
> xShapeProps
;
170 if (bIsExistingQRCode
)
171 xShapeProps
= m_xExistingShapeProperties
;
173 xShapeProps
.set(Reference
<lang::XMultiServiceFactory
>(m_xModel
, UNO_QUERY_THROW
)
174 ->createInstance("com.sun.star.drawing.GraphicObjectShape"),
177 xShapeProps
->setPropertyValue("Graphic", Any(xGraphic
));
179 // Set QRCode properties
180 xShapeProps
->setPropertyValue("QRCodeProperties", Any(aQRCode
));
182 if (!bIsExistingQRCode
)
185 Reference
<XShape
> xShape(xShapeProps
, UNO_QUERY
);
186 awt::Size aShapeSize
;
187 aShapeSize
.Height
= 4000;
188 aShapeSize
.Width
= 4000;
189 xShape
->setSize(aShapeSize
);
192 xShapeProps
->setPropertyValue("AnchorType", Any(TextContentAnchorType_AT_PARAGRAPH
));
194 const Reference
<XServiceInfo
> xServiceInfo(m_xModel
, UNO_QUERY_THROW
);
197 if (xServiceInfo
->supportsService("com.sun.star.text.TextDocument"))
199 Reference
<XTextContent
> xTextContent(xShape
, UNO_QUERY_THROW
);
200 Reference
<XTextViewCursorSupplier
> xViewCursorSupplier(m_xModel
->getCurrentController(),
202 Reference
<XTextViewCursor
> xCursor
= xViewCursorSupplier
->getViewCursor();
203 // use cursor's XText - it might be in table cell, frame, ...
204 Reference
<XText
> const xText(xCursor
->getText());
206 xText
->insertTextContent(xCursor
, xTextContent
, true);
211 else if (xServiceInfo
->supportsService("com.sun.star.sheet.SpreadsheetDocument"))
213 Reference
<XPropertySet
> xSheetCell(m_xModel
->getCurrentSelection(), UNO_QUERY_THROW
);
214 awt::Point aCellPosition
;
215 xSheetCell
->getPropertyValue("Position") >>= aCellPosition
;
216 xShape
->setPosition(aCellPosition
);
218 Reference
<XSpreadsheetView
> xView(m_xModel
->getCurrentController(), UNO_QUERY_THROW
);
219 Reference
<XSpreadsheet
> xSheet(xView
->getActiveSheet(), UNO_SET_THROW
);
220 Reference
<XDrawPageSupplier
> xDrawPageSupplier(xSheet
, UNO_QUERY_THROW
);
221 Reference
<XDrawPage
> xDrawPage(xDrawPageSupplier
->getDrawPage(), UNO_SET_THROW
);
222 Reference
<XShapes
> xShapes(xDrawPage
, UNO_QUERY_THROW
);
224 xShapes
->add(xShape
);
229 else if (xServiceInfo
->supportsService("com.sun.star.presentation.PresentationDocument")
230 || xServiceInfo
->supportsService("com.sun.star.drawing.DrawingDocument"))
232 Reference
<XDrawView
> xView(m_xModel
->getCurrentController(), UNO_QUERY_THROW
);
233 Reference
<XDrawPage
> xPage(xView
->getCurrentPage(), UNO_SET_THROW
);
234 Reference
<XShapes
> xShapes(xPage
, UNO_QUERY_THROW
);
236 xShapes
->add(xShape
);
242 //Not implemented for math,base and other apps.
243 throw uno::RuntimeException("Not implemented");
249 OUString
QrCodeGenDialog::GenerateQRCode(OUString aQRText
, long aQRECC
, int aQRBorder
)
252 //Select ECC:: value from aQrECC
253 qrcodegen::QrCode::Ecc bqrEcc
= qrcodegen::QrCode::Ecc::LOW
;
259 bqrEcc
= qrcodegen::QrCode::Ecc::LOW
;
264 bqrEcc
= qrcodegen::QrCode::Ecc::MEDIUM
;
269 bqrEcc
= qrcodegen::QrCode::Ecc::QUARTILE
;
274 bqrEcc
= qrcodegen::QrCode::Ecc::HIGH
;
279 //OuString to char* qrtext
280 OString o
= OUStringToOString(aQRText
, RTL_TEXTENCODING_UTF8
);
281 const char* qrtext
= o
.pData
->buffer
;
283 //From Qr Code library.
284 qrcodegen::QrCode qr0
= qrcodegen::QrCode::encodeText(qrtext
, bqrEcc
);
285 std::string svg
= qr0
.toSvgString(aQRBorder
);
286 //cstring to OUString
287 return OUString::createFromAscii(svg
.c_str());
296 void QrCodeGenDialog::GetErrorCorrection(long ErrorCorrection
)
298 switch (ErrorCorrection
)
300 case css::drawing::QRCodeErrorCorrection::LOW
:
302 m_xECC
[0]->set_active(true);
305 case css::drawing::QRCodeErrorCorrection::MEDIUM
:
307 m_xECC
[1]->set_active(true);
310 case css::drawing::QRCodeErrorCorrection::QUARTILE
:
312 m_xECC
[2]->set_active(true);
315 case css::drawing::QRCodeErrorCorrection::HIGH
:
317 m_xECC
[3]->set_active(true);
323 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */