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 <jsdialog/jsdialogbuilder.hxx>
11 #include <vcl/weld.hxx>
12 #include <vcl/jsdialog/executor.hxx>
13 #include <sal/log.hxx>
14 #include <rtl/uri.hxx>
15 #include <boost/property_tree/json_parser.hpp>
19 StringMap
jsonToStringMap(const char* pJSON
)
22 if (pJSON
&& pJSON
[0] != '\0')
24 std::stringstream
aStream(pJSON
);
25 boost::property_tree::ptree aTree
;
26 boost::property_tree::read_json(aStream
, aTree
);
28 for (const auto& rPair
: aTree
)
30 aArgs
[OUString::fromUtf8(rPair
.first
.c_str())]
31 = OUString::fromUtf8(rPair
.second
.get_value
<std::string
>(".").c_str());
37 void SendFullUpdate(const std::string
& nWindowId
, const OString
& rWidget
)
39 weld::Widget
* pWidget
= JSInstanceBuilder::FindWeldWidgetsMap(nWindowId
, rWidget
);
41 if (pWidget
!= nullptr)
43 auto pJSWidget
= dynamic_cast<BaseJSWidget
*>(pWidget
);
44 pJSWidget
->sendFullUpdate();
48 bool ExecuteAction(const std::string
& nWindowId
, const OString
& rWidget
, StringMap
& rData
)
50 weld::Widget
* pWidget
= JSInstanceBuilder::FindWeldWidgetsMap(nWindowId
, rWidget
);
52 OUString sControlType
= rData
["type"];
53 OUString sAction
= rData
["cmd"];
55 if (sControlType
== "responsebutton")
57 if (pWidget
== nullptr)
59 // welded wrapper not found - use response code instead
60 pWidget
= JSInstanceBuilder::FindWeldWidgetsMap(nWindowId
, "__DIALOG__");
61 sControlType
= "dialog";
66 // welded wrapper for button found - use it
67 sControlType
= "pushbutton";
71 if (pWidget
!= nullptr)
73 if (sControlType
== "tabcontrol")
75 auto pNotebook
= dynamic_cast<weld::Notebook
*>(pWidget
);
78 if (sAction
== "selecttab")
80 OString pageId
= OUStringToOString(rData
["data"], RTL_TEXTENCODING_ASCII_US
);
81 int page
= std::atoi(pageId
.getStr());
83 pNotebook
->set_current_page(page
);
89 else if (sControlType
== "combobox")
91 auto pCombobox
= dynamic_cast<weld::ComboBox
*>(pWidget
);
94 if (sAction
== "selected")
96 int separatorPos
= rData
["data"].indexOf(';');
99 OUString entryPos
= rData
["data"].copy(0, separatorPos
);
100 OString posString
= OUStringToOString(entryPos
, RTL_TEXTENCODING_ASCII_US
);
101 int pos
= std::atoi(posString
.getStr());
102 pCombobox
->set_active(pos
);
103 LOKTrigger::trigger_changed(*pCombobox
);
107 else if (sAction
== "change")
109 pCombobox
->set_entry_text(rData
["data"]);
110 LOKTrigger::trigger_changed(*pCombobox
);
115 else if (sControlType
== "pushbutton")
117 auto pButton
= dynamic_cast<weld::Button
*>(pWidget
);
120 if (sAction
== "click")
127 else if (sControlType
== "menubutton")
129 auto pButton
= dynamic_cast<weld::MenuButton
*>(pWidget
);
132 if (sAction
== "toggle")
134 if (pButton
->get_active())
135 pButton
->set_active(false);
137 pButton
->set_active(true);
139 BaseJSWidget
* pMenuButton
= dynamic_cast<BaseJSWidget
*>(pButton
);
141 pMenuButton
->sendUpdate(true);
147 else if (sControlType
== "checkbox")
149 auto pCheckButton
= dynamic_cast<weld::CheckButton
*>(pWidget
);
152 if (sAction
== "change")
154 bool bChecked
= rData
["data"] == "true";
155 pCheckButton
->set_state(bChecked
? TRISTATE_TRUE
: TRISTATE_FALSE
);
156 LOKTrigger::trigger_clicked(*static_cast<weld::Button
*>(pCheckButton
));
157 LOKTrigger::trigger_toggled(*static_cast<weld::ToggleButton
*>(pCheckButton
));
162 else if (sControlType
== "drawingarea")
164 auto pArea
= dynamic_cast<weld::DrawingArea
*>(pWidget
);
167 if (sAction
== "click")
169 int separatorPos
= rData
["data"].indexOf(';');
170 if (separatorPos
> 0)
173 OString clickPosX
= OUStringToOString(rData
["data"].copy(0, separatorPos
),
174 RTL_TEXTENCODING_ASCII_US
);
175 OString clickPosY
= OUStringToOString(rData
["data"].copy(separatorPos
+ 1),
176 RTL_TEXTENCODING_ASCII_US
);
177 if (!clickPosX
.isEmpty() && !clickPosY
.isEmpty())
179 double posX
= std::atof(clickPosX
.getStr());
180 double posY
= std::atof(clickPosY
.getStr());
181 OutputDevice
& rRefDevice
= pArea
->get_ref_device();
182 // We send OutPutSize for the drawing area bitmap
183 // get_size_request is not necessarily updated
184 // therefore it may be incorrect.
185 Size size
= rRefDevice
.GetOutputSize();
186 posX
= posX
* size
.Width();
187 posY
= posY
* size
.Height();
188 LOKTrigger::trigger_click(*pArea
, Point(posX
, posY
));
192 LOKTrigger::trigger_click(*pArea
, Point(10, 10));
197 else if (sControlType
== "spinfield")
199 auto pSpinField
= dynamic_cast<weld::SpinButton
*>(pWidget
);
202 if (sAction
== "change" || sAction
== "value")
204 if (rData
["data"] == "undefined")
207 OString sValue
= OUStringToOString(rData
["data"], RTL_TEXTENCODING_ASCII_US
);
208 double nValue
= std::atof(sValue
.getStr());
209 pSpinField
->set_value(nValue
210 * weld::SpinButton::Power10(pSpinField
->get_digits()));
211 LOKTrigger::trigger_value_changed(*pSpinField
);
214 if (sAction
== "plus")
216 pSpinField
->set_value(pSpinField
->get_value() + 1);
217 LOKTrigger::trigger_value_changed(*pSpinField
);
220 else if (sAction
== "minus")
222 pSpinField
->set_value(pSpinField
->get_value() - 1);
223 LOKTrigger::trigger_value_changed(*pSpinField
);
228 else if (sControlType
== "toolbox")
230 auto pToolbar
= dynamic_cast<weld::Toolbar
*>(pWidget
);
233 if (sAction
== "click")
235 LOKTrigger::trigger_clicked(
236 *pToolbar
, OUStringToOString(rData
["data"], RTL_TEXTENCODING_ASCII_US
));
239 else if (sAction
== "togglemenu")
241 pToolbar
->set_menu_item_active(
242 OUStringToOString(rData
["data"], RTL_TEXTENCODING_ASCII_US
), true);
247 else if (sControlType
== "edit")
249 auto pEdit
= dynamic_cast<JSEntry
*>(pWidget
);
252 if (sAction
== "change")
254 pEdit
->set_text_without_notify(rData
["data"]);
255 LOKTrigger::trigger_changed(*pEdit
);
260 auto pTextView
= dynamic_cast<weld::TextView
*>(pWidget
);
263 if (sAction
== "change")
265 pTextView
->set_text(rData
["data"]);
266 LOKTrigger::trigger_changed(*pTextView
);
271 else if (sControlType
== "treeview")
273 auto pTreeView
= dynamic_cast<JSTreeView
*>(pWidget
);
276 if (sAction
== "change")
278 OUString sDataJSON
= rtl::Uri::decode(
279 rData
["data"], rtl_UriDecodeMechanism::rtl_UriDecodeWithCharset
,
280 RTL_TEXTENCODING_UTF8
);
281 StringMap
aMap(jsonToStringMap(
282 OUStringToOString(sDataJSON
, RTL_TEXTENCODING_ASCII_US
).getStr()));
284 OString nRowString
= OUStringToOString(aMap
["row"], RTL_TEXTENCODING_ASCII_US
);
285 int nRow
= std::atoi(nRowString
.getStr());
286 bool bValue
= aMap
["value"] == "true";
288 pTreeView
->set_toggle(nRow
, bValue
? TRISTATE_TRUE
: TRISTATE_FALSE
);
292 else if (sAction
== "select")
295 = OUStringToOString(rData
["data"], RTL_TEXTENCODING_ASCII_US
);
297 pTreeView
->unselect_all();
299 int nAbsPos
= std::atoi(nRowString
.getStr());
301 std::unique_ptr
<weld::TreeIter
> itEntry(pTreeView
->make_iterator());
302 pTreeView
->get_iter_abs_pos(*itEntry
, nAbsPos
);
303 pTreeView
->select(*itEntry
);
304 pTreeView
->set_cursor(*itEntry
);
305 LOKTrigger::trigger_changed(*pTreeView
);
308 else if (sAction
== "activate")
311 = OUStringToOString(rData
["data"], RTL_TEXTENCODING_ASCII_US
);
312 int nRow
= std::atoi(nRowString
.getStr());
314 pTreeView
->unselect_all();
315 pTreeView
->select(nRow
);
316 pTreeView
->set_cursor(nRow
);
317 LOKTrigger::trigger_changed(*pTreeView
);
318 LOKTrigger::trigger_row_activated(*pTreeView
);
321 else if (sAction
== "expand")
324 = OUStringToOString(rData
["data"], RTL_TEXTENCODING_ASCII_US
);
325 int nAbsPos
= std::atoi(nRowString
.getStr());
326 std::unique_ptr
<weld::TreeIter
> itEntry(pTreeView
->make_iterator());
327 pTreeView
->get_iter_abs_pos(*itEntry
, nAbsPos
);
328 pTreeView
->expand_row(*itEntry
);
331 else if (sAction
== "dragstart")
334 = OUStringToOString(rData
["data"], RTL_TEXTENCODING_ASCII_US
);
335 int nRow
= std::atoi(nRowString
.getStr());
337 pTreeView
->select(nRow
);
338 pTreeView
->drag_start();
342 else if (sAction
== "dragend")
344 pTreeView
->drag_end();
349 else if (sControlType
== "iconview")
351 auto pIconView
= dynamic_cast<weld::IconView
*>(pWidget
);
354 if (sAction
== "select")
357 = OUStringToOString(rData
["data"], RTL_TEXTENCODING_ASCII_US
);
358 int nPos
= std::atoi(nPosString
.getStr());
360 pIconView
->select(nPos
);
361 LOKTrigger::trigger_changed(*pIconView
);
365 else if (sAction
== "activate")
368 = OUStringToOString(rData
["data"], RTL_TEXTENCODING_ASCII_US
);
369 int nPos
= std::atoi(nPosString
.getStr());
371 pIconView
->select(nPos
);
372 LOKTrigger::trigger_changed(*pIconView
);
373 LOKTrigger::trigger_item_activated(*pIconView
);
379 else if (sControlType
== "expander")
381 auto pExpander
= dynamic_cast<weld::Expander
*>(pWidget
);
384 if (sAction
== "toggle")
386 pExpander
->set_expanded(!pExpander
->get_expanded());
391 else if (sControlType
== "dialog")
393 auto pDialog
= dynamic_cast<weld::Dialog
*>(pWidget
);
396 if (sAction
== "close")
398 pDialog
->response(RET_CANCEL
);
401 else if (sAction
== "response")
403 OString nResponseString
404 = OUStringToOString(rData
["data"], RTL_TEXTENCODING_ASCII_US
);
405 int nResponse
= std::atoi(nResponseString
.getStr());
406 pDialog
->response(nResponse
);
411 else if (sControlType
== "popover")
413 auto pPopover
= dynamic_cast<weld::Popover
*>(pWidget
);
416 if (sAction
== "close")
418 LOKTrigger::trigger_closed(*pPopover
);
423 else if (sControlType
== "radiobutton")
425 auto pRadioButton
= dynamic_cast<weld::RadioButton
*>(pWidget
);
428 if (sAction
== "change")
430 bool bChecked
= rData
["data"] == "true";
431 pRadioButton
->set_state(bChecked
? TRISTATE_TRUE
: TRISTATE_FALSE
);
432 LOKTrigger::trigger_clicked(*static_cast<weld::Button
*>(pRadioButton
));
433 LOKTrigger::trigger_toggled(*static_cast<weld::ToggleButton
*>(pRadioButton
));
444 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */