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:
@@ -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)
|
static boost::property_tree::ptree unoAnyToPropertyTree(const uno::Any& anyItem)
|
||||||
{
|
{
|
||||||
boost::property_tree::ptree aTree;
|
boost::property_tree::ptree aTree;
|
||||||
@@ -3710,7 +3692,7 @@ static void doc_sendDialogEvent(LibreOfficeKitDocument* /*pThis*/, unsigned long
|
|||||||
{
|
{
|
||||||
SolarMutexGuard aGuard;
|
SolarMutexGuard aGuard;
|
||||||
|
|
||||||
StringMap aMap(jsonToStringMap(pArguments));
|
StringMap aMap(jsdialog::jsonToStringMap(pArguments));
|
||||||
VclPtr<Window> pWindow = vcl::Window::FindLOKWindow(nWindowId);
|
VclPtr<Window> pWindow = vcl::Window::FindLOKWindow(nWindowId);
|
||||||
|
|
||||||
if (!pWindow && nWindowId >= 1000000000 /* why unsigned? */)
|
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)
|
if (doc_getDocumentType(pThis) != LOK_DOCTYPE_TEXT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
StringMap aMap(jsonToStringMap(pArguments));
|
StringMap aMap(jsdialog::jsonToStringMap(pArguments));
|
||||||
ITiledRenderable* pDoc = getTiledRenderable(pThis);
|
ITiledRenderable* pDoc = getTiledRenderable(pThis);
|
||||||
if (!pDoc)
|
if (!pDoc)
|
||||||
{
|
{
|
||||||
|
@@ -22,6 +22,11 @@ public:
|
|||||||
|
|
||||||
static void trigger_changed(weld::ComboBox& rComboBox) { rComboBox.signal_changed(); }
|
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)
|
static void trigger_clicked(weld::Toolbar& rToolbar, const OString& rIdent)
|
||||||
{
|
{
|
||||||
rToolbar.signal_clicked(rIdent);
|
rToolbar.signal_clicked(rIdent);
|
||||||
@@ -36,6 +41,7 @@ public:
|
|||||||
namespace jsdialog
|
namespace jsdialog
|
||||||
{
|
{
|
||||||
VCL_DLLPUBLIC bool ExecuteAction(sal_uInt64 nWindowId, const OString& rWidget, StringMap& rData);
|
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: */
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
||||||
|
@@ -782,6 +782,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
class VCL_DLLPUBLIC TreeView : virtual public Container
|
class VCL_DLLPUBLIC TreeView : virtual public Container
|
||||||
{
|
{
|
||||||
|
friend class ::LOKTrigger;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::pair<const TreeIter&, int> iter_col;
|
typedef std::pair<const TreeIter&, int> iter_col;
|
||||||
typedef std::pair<const TreeIter&, OUString> iter_string;
|
typedef std::pair<const TreeIter&, OUString> iter_string;
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
class ToolBox;
|
class ToolBox;
|
||||||
class ComboBox;
|
class ComboBox;
|
||||||
class VclMultiLineEdit;
|
class VclMultiLineEdit;
|
||||||
|
class SvTabListBox;
|
||||||
|
|
||||||
typedef std::map<OString, weld::Widget*> WidgetMap;
|
typedef std::map<OString, weld::Widget*> WidgetMap;
|
||||||
|
|
||||||
@@ -108,8 +109,9 @@ public:
|
|||||||
weld_drawing_area(const OString& id, const a11yref& rA11yImpl = nullptr,
|
weld_drawing_area(const OString& id, const a11yref& rA11yImpl = nullptr,
|
||||||
FactoryFunction pUITestFactoryFunction = nullptr,
|
FactoryFunction pUITestFactoryFunction = nullptr,
|
||||||
void* pUserData = nullptr) override;
|
void* pUserData = nullptr) override;
|
||||||
std::unique_ptr<weld::Toolbar> weld_toolbar(const OString& id) override;
|
virtual 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::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,
|
static weld::MessageDialog* CreateMessageDialog(weld::Widget* pParent,
|
||||||
VclMessageType eMessageType,
|
VclMessageType eMessageType,
|
||||||
@@ -145,6 +147,7 @@ public:
|
|||||||
notifyDialogState();
|
notifyDialogState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using BaseInstanceClass::set_sensitive;
|
||||||
virtual void set_sensitive(bool sensitive) override
|
virtual void set_sensitive(bool sensitive) override
|
||||||
{
|
{
|
||||||
BaseInstanceClass::set_sensitive(sensitive);
|
BaseInstanceClass::set_sensitive(sensitive);
|
||||||
@@ -290,4 +293,20 @@ public:
|
|||||||
virtual void set_text(const OUString& rText) override;
|
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: */
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
||||||
|
@@ -1302,7 +1302,7 @@ public:
|
|||||||
|
|
||||||
class SalInstanceTreeView : public SalInstanceContainer, public virtual weld::TreeView
|
class SalInstanceTreeView : public SalInstanceContainer, public virtual weld::TreeView
|
||||||
{
|
{
|
||||||
private:
|
protected:
|
||||||
// owner for UserData
|
// owner for UserData
|
||||||
std::vector<std::unique_ptr<OUString>> m_aUserData;
|
std::vector<std::unique_ptr<OUString>> m_aUserData;
|
||||||
VclPtr<SvTabListBox> m_xTreeView;
|
VclPtr<SvTabListBox> m_xTreeView;
|
||||||
|
@@ -11,9 +11,29 @@
|
|||||||
#include <vcl/weld.hxx>
|
#include <vcl/weld.hxx>
|
||||||
#include <vcl/jsdialog/executor.hxx>
|
#include <vcl/jsdialog/executor.hxx>
|
||||||
#include <sal/log.hxx>
|
#include <sal/log.hxx>
|
||||||
|
#include <rtl/uri.hxx>
|
||||||
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
|
|
||||||
namespace jsdialog
|
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)
|
bool ExecuteAction(sal_uInt64 nWindowId, const OString& rWidget, StringMap& rData)
|
||||||
{
|
{
|
||||||
weld::Widget* pWidget = JSInstanceBuilder::FindWeldWidgetsMap(nWindowId, rWidget);
|
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;
|
return false;
|
||||||
|
@@ -22,6 +22,8 @@
|
|||||||
#include <vcl/toolbox.hxx>
|
#include <vcl/toolbox.hxx>
|
||||||
#include <vcl/toolkit/vclmedit.hxx>
|
#include <vcl/toolkit/vclmedit.hxx>
|
||||||
#include <boost/property_tree/json_parser.hpp>
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
|
#include <vcl/toolkit/treelistentry.hxx>
|
||||||
|
#include <vcl/jsdialog/executor.hxx>
|
||||||
|
|
||||||
JSDialogNotifyIdle::JSDialogNotifyIdle(VclPtr<vcl::Window> aNotifierWindow,
|
JSDialogNotifyIdle::JSDialogNotifyIdle(VclPtr<vcl::Window> aNotifierWindow,
|
||||||
VclPtr<vcl::Window> aContentWindow, std::string sTypeOfJSON)
|
VclPtr<vcl::Window> aContentWindow, std::string sTypeOfJSON)
|
||||||
@@ -39,30 +41,42 @@ void JSDialogNotifyIdle::ForceUpdate() { m_bForce = true; }
|
|||||||
|
|
||||||
void JSDialogNotifyIdle::Invoke()
|
void JSDialogNotifyIdle::Invoke()
|
||||||
{
|
{
|
||||||
try
|
if (!m_aNotifierWindow)
|
||||||
{
|
return;
|
||||||
if (!m_aNotifierWindow)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const vcl::ILibreOfficeKitNotifier* pNotifier = m_aNotifierWindow->GetLOKNotifier();
|
const vcl::ILibreOfficeKitNotifier* pNotifier = m_aNotifierWindow->GetLOKNotifier();
|
||||||
if (pNotifier)
|
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;
|
vcl::Window* pWindow = m_aContentWindow.get();
|
||||||
m_aContentWindow->DumpAsPropertyTree(aJsonWriter);
|
DockingWindow* pDockingWIndow = dynamic_cast<DockingWindow*>(pWindow);
|
||||||
aJsonWriter.put("id", m_aNotifierWindow->GetLOKWindowId());
|
while (pWindow && !pDockingWIndow)
|
||||||
aJsonWriter.put("jsontype", m_sTypeOfJSON);
|
|
||||||
if (m_bForce || !aJsonWriter.isDataEquals(m_LastNotificationMessage))
|
|
||||||
{
|
{
|
||||||
m_bForce = false;
|
pWindow = pWindow->GetParent();
|
||||||
m_LastNotificationMessage = aJsonWriter.extractAsStdString();
|
pDockingWIndow = dynamic_cast<DockingWindow*>(pWindow);
|
||||||
pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG,
|
}
|
||||||
m_LastNotificationMessage.c_str());
|
|
||||||
|
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)
|
if (m_bForce || !aJsonWriter.isDataEquals(m_LastNotificationMessage))
|
||||||
{
|
{
|
||||||
SAL_WARN("vcl", rError.message());
|
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;
|
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,
|
weld::MessageDialog* JSInstanceBuilder::CreateMessageDialog(weld::Widget* pParent,
|
||||||
VclMessageType eMessageType,
|
VclMessageType eMessageType,
|
||||||
VclButtonsType eButtonType,
|
VclButtonsType eButtonType,
|
||||||
@@ -693,4 +721,45 @@ void JSTextView::set_text(const OUString& rText)
|
|||||||
notifyDialogState();
|
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: */
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
||||||
|
Reference in New Issue
Block a user