jsdialog: implement TreeView

Change-Id: I7c1cc683e8c5d5bdc00c1e3d3d0a2c85846bbda0
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/106560
Tested-by: Jenkins
Reviewed-by: Szymon Kłos <szymon.klos@collabora.com>
This commit is contained in:
Szymon Kłos 2020-10-30 10:51:08 +01:00
parent adb2e4e192
commit 0de158b4eb
7 changed files with 172 additions and 42 deletions

View File

@ -441,24 +441,6 @@ std::vector<beans::PropertyValue> desktop::jsonToPropertyValuesVector(const char
}
static StringMap jsonToStringMap(const char* pJSON)
{
StringMap aArgs;
if (pJSON && pJSON[0] != '\0')
{
std::stringstream aStream(pJSON);
boost::property_tree::ptree aTree;
boost::property_tree::read_json(aStream, aTree);
for (const auto& rPair : aTree)
{
aArgs[OUString::fromUtf8(rPair.first.c_str())] = OUString::fromUtf8(rPair.second.get_value<std::string>(".").c_str());
}
}
return aArgs;
}
static boost::property_tree::ptree unoAnyToPropertyTree(const uno::Any& anyItem)
{
boost::property_tree::ptree aTree;
@ -3710,7 +3692,7 @@ static void doc_sendDialogEvent(LibreOfficeKitDocument* /*pThis*/, unsigned long
{
SolarMutexGuard aGuard;
StringMap aMap(jsonToStringMap(pArguments));
StringMap aMap(jsdialog::jsonToStringMap(pArguments));
VclPtr<Window> pWindow = vcl::Window::FindLOKWindow(nWindowId);
if (!pWindow && nWindowId >= 1000000000 /* why unsigned? */)
@ -5686,7 +5668,7 @@ static void doc_sendFormFieldEvent(LibreOfficeKitDocument* pThis, const char* pA
if (doc_getDocumentType(pThis) != LOK_DOCTYPE_TEXT)
return;
StringMap aMap(jsonToStringMap(pArguments));
StringMap aMap(jsdialog::jsonToStringMap(pArguments));
ITiledRenderable* pDoc = getTiledRenderable(pThis);
if (!pDoc)
{

View File

@ -22,6 +22,11 @@ public:
static void trigger_changed(weld::ComboBox& rComboBox) { rComboBox.signal_changed(); }
static void trigger_row_activated(weld::TreeView& rTreeView)
{
rTreeView.signal_row_activated();
}
static void trigger_clicked(weld::Toolbar& rToolbar, const OString& rIdent)
{
rToolbar.signal_clicked(rIdent);
@ -36,6 +41,7 @@ public:
namespace jsdialog
{
VCL_DLLPUBLIC bool ExecuteAction(sal_uInt64 nWindowId, const OString& rWidget, StringMap& rData);
VCL_DLLPUBLIC StringMap jsonToStringMap(const char* pJSON);
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */

View File

@ -782,6 +782,8 @@ public:
*/
class VCL_DLLPUBLIC TreeView : virtual public Container
{
friend class ::LOKTrigger;
public:
typedef std::pair<const TreeIter&, int> iter_col;
typedef std::pair<const TreeIter&, OUString> iter_string;

View File

@ -22,6 +22,7 @@
class ToolBox;
class ComboBox;
class VclMultiLineEdit;
class SvTabListBox;
typedef std::map<OString, weld::Widget*> WidgetMap;
@ -108,8 +109,9 @@ public:
weld_drawing_area(const OString& id, const a11yref& rA11yImpl = nullptr,
FactoryFunction pUITestFactoryFunction = nullptr,
void* pUserData = nullptr) override;
std::unique_ptr<weld::Toolbar> weld_toolbar(const OString& id) override;
std::unique_ptr<weld::TextView> weld_text_view(const OString& id) override;
virtual std::unique_ptr<weld::Toolbar> weld_toolbar(const OString& id) override;
virtual std::unique_ptr<weld::TextView> weld_text_view(const OString& id) override;
virtual std::unique_ptr<weld::TreeView> weld_tree_view(const OString& id) override;
static weld::MessageDialog* CreateMessageDialog(weld::Widget* pParent,
VclMessageType eMessageType,
@ -145,6 +147,7 @@ public:
notifyDialogState();
}
using BaseInstanceClass::set_sensitive;
virtual void set_sensitive(bool sensitive) override
{
BaseInstanceClass::set_sensitive(sensitive);
@ -290,4 +293,20 @@ public:
virtual void set_text(const OUString& rText) override;
};
class JSTreeView : public JSWidget<SalInstanceTreeView, ::SvTabListBox>
{
public:
JSTreeView(VclPtr<vcl::Window> aNotifierWindow, VclPtr<vcl::Window> aContentWindow,
::SvTabListBox* pTextView, SalInstanceBuilder* pBuilder, bool bTakeOwnership,
std::string sTypeOfJSON);
using SalInstanceTreeView::set_toggle;
/// pos is used differently here, it defines how many steps of iterator we need to perform to take entry
virtual void set_toggle(int pos, TriState eState, int col = -1) override;
using SalInstanceTreeView::select;
/// pos is used differently here, it defines how many steps of iterator we need to perform to take entry
virtual void select(int pos) override;
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */

View File

@ -1302,7 +1302,7 @@ public:
class SalInstanceTreeView : public SalInstanceContainer, public virtual weld::TreeView
{
private:
protected:
// owner for UserData
std::vector<std::unique_ptr<OUString>> m_aUserData;
VclPtr<SvTabListBox> m_xTreeView;

View File

@ -11,9 +11,29 @@
#include <vcl/weld.hxx>
#include <vcl/jsdialog/executor.hxx>
#include <sal/log.hxx>
#include <rtl/uri.hxx>
#include <boost/property_tree/json_parser.hpp>
namespace jsdialog
{
StringMap jsonToStringMap(const char* pJSON)
{
StringMap aArgs;
if (pJSON && pJSON[0] != '\0')
{
std::stringstream aStream(pJSON);
boost::property_tree::ptree aTree;
boost::property_tree::read_json(aStream, aTree);
for (const auto& rPair : aTree)
{
aArgs[OUString::fromUtf8(rPair.first.c_str())]
= OUString::fromUtf8(rPair.second.get_value<std::string>(".").c_str());
}
}
return aArgs;
}
bool ExecuteAction(sal_uInt64 nWindowId, const OString& rWidget, StringMap& rData)
{
weld::Widget* pWidget = JSInstanceBuilder::FindWeldWidgetsMap(nWindowId, rWidget);
@ -143,6 +163,38 @@ bool ExecuteAction(sal_uInt64 nWindowId, const OString& rWidget, StringMap& rDat
}
}
}
else if (sControlType == "treeview")
{
auto pTreeView = dynamic_cast<weld::TreeView*>(pWidget);
if (pTreeView)
{
if (sAction == "change")
{
OUString sDataJSON = rtl::Uri::decode(
rData["data"], rtl_UriDecodeMechanism::rtl_UriDecodeWithCharset,
RTL_TEXTENCODING_UTF8);
StringMap aMap(jsonToStringMap(
OUStringToOString(sDataJSON, RTL_TEXTENCODING_ASCII_US).getStr()));
OString nRowString = OUStringToOString(aMap["row"], RTL_TEXTENCODING_ASCII_US);
int nRow = std::atoi(nRowString.getStr());
bool bValue = aMap["value"] == "true";
pTreeView->set_toggle(nRow, bValue ? TRISTATE_TRUE : TRISTATE_FALSE);
return true;
}
else if (sAction == "select")
{
OString nRowString
= OUStringToOString(rData["data"], RTL_TEXTENCODING_ASCII_US);
int nRow = std::atoi(nRowString.getStr());
pTreeView->select(nRow);
LOKTrigger::trigger_row_activated(*pTreeView);
}
}
}
}
return false;

View File

@ -22,6 +22,8 @@
#include <vcl/toolbox.hxx>
#include <vcl/toolkit/vclmedit.hxx>
#include <boost/property_tree/json_parser.hpp>
#include <vcl/toolkit/treelistentry.hxx>
#include <vcl/jsdialog/executor.hxx>
JSDialogNotifyIdle::JSDialogNotifyIdle(VclPtr<vcl::Window> aNotifierWindow,
VclPtr<vcl::Window> aContentWindow, std::string sTypeOfJSON)
@ -39,30 +41,42 @@ void JSDialogNotifyIdle::ForceUpdate() { m_bForce = true; }
void JSDialogNotifyIdle::Invoke()
{
try
{
if (!m_aNotifierWindow)
return;
if (!m_aNotifierWindow)
return;
const vcl::ILibreOfficeKitNotifier* pNotifier = m_aNotifierWindow->GetLOKNotifier();
if (pNotifier)
const vcl::ILibreOfficeKitNotifier* pNotifier = m_aNotifierWindow->GetLOKNotifier();
if (pNotifier)
{
tools::JsonWriter aJsonWriter;
m_aContentWindow->DumpAsPropertyTree(aJsonWriter);
aJsonWriter.put("id", m_aNotifierWindow->GetLOKWindowId());
aJsonWriter.put("jsontype", m_sTypeOfJSON);
if (m_sTypeOfJSON == "autofilter")
{
tools::JsonWriter aJsonWriter;
m_aContentWindow->DumpAsPropertyTree(aJsonWriter);
aJsonWriter.put("id", m_aNotifierWindow->GetLOKWindowId());
aJsonWriter.put("jsontype", m_sTypeOfJSON);
if (m_bForce || !aJsonWriter.isDataEquals(m_LastNotificationMessage))
vcl::Window* pWindow = m_aContentWindow.get();
DockingWindow* pDockingWIndow = dynamic_cast<DockingWindow*>(pWindow);
while (pWindow && !pDockingWIndow)
{
m_bForce = false;
m_LastNotificationMessage = aJsonWriter.extractAsStdString();
pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG,
m_LastNotificationMessage.c_str());
pWindow = pWindow->GetParent();
pDockingWIndow = dynamic_cast<DockingWindow*>(pWindow);
}
if (pDockingWIndow)
{
Point aPos = pDockingWIndow->GetFloatingPos();
aJsonWriter.put("posx", aPos.getX());
aJsonWriter.put("posy", aPos.getY());
}
}
}
catch (boost::property_tree::json_parser::json_parser_error& rError)
{
SAL_WARN("vcl", rError.message());
if (m_bForce || !aJsonWriter.isDataEquals(m_LastNotificationMessage))
{
m_bForce = false;
m_LastNotificationMessage = aJsonWriter.extractAsStdString();
pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG,
m_LastNotificationMessage.c_str());
}
}
}
@ -412,6 +426,20 @@ std::unique_ptr<weld::TextView> JSInstanceBuilder::weld_text_view(const OString&
return pWeldWidget;
}
std::unique_ptr<weld::TreeView> JSInstanceBuilder::weld_tree_view(const OString& id)
{
SvTabListBox* pTreeView = m_xBuilder->get<SvTabListBox>(id);
auto pWeldWidget = pTreeView
? std::make_unique<JSTreeView>(GetNotifierWindow(), GetContentWindow(),
pTreeView, this, false, m_sTypeOfJSON)
: nullptr;
if (pWeldWidget)
RememberWidget(id, pWeldWidget.get());
return pWeldWidget;
}
weld::MessageDialog* JSInstanceBuilder::CreateMessageDialog(weld::Widget* pParent,
VclMessageType eMessageType,
VclButtonsType eButtonType,
@ -693,4 +721,45 @@ void JSTextView::set_text(const OUString& rText)
notifyDialogState();
}
JSTreeView::JSTreeView(VclPtr<vcl::Window> aNotifierWindow, VclPtr<vcl::Window> aContentWindow,
::SvTabListBox* pTreeView, SalInstanceBuilder* pBuilder, bool bTakeOwnership,
std::string sTypeOfJSON)
: JSWidget<SalInstanceTreeView, ::SvTabListBox>(aNotifierWindow, aContentWindow, pTreeView,
pBuilder, bTakeOwnership, sTypeOfJSON)
{
}
void JSTreeView::set_toggle(int pos, TriState eState, int col)
{
SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, 0);
while (pEntry && pos--)
pEntry = m_xTreeView->Next(pEntry);
if (pEntry)
SalInstanceTreeView::set_toggle(pEntry, eState, col);
}
void JSTreeView::select(int pos)
{
assert(m_xTreeView->IsUpdateMode() && "don't select when frozen");
disable_notify_events();
if (pos == -1 || (pos == 0 && n_children() == 0))
m_xTreeView->SelectAll(false);
else
{
SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, 0);
while (pEntry && pos--)
pEntry = m_xTreeView->Next(pEntry);
if (pEntry)
{
m_xTreeView->Select(pEntry, true);
m_xTreeView->MakeVisible(pEntry);
}
}
enable_notify_events();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */