[Libreoffice-commits] core.git: Branch 'feature/ui-test' - 83 commits - bin/gbuild-to-ide comphelper/qa comphelper/source include/comphelper include/sfx2 include/svtools include/vcl Makefile.in offapi/com oox/source RepositoryModule_host.mk sc/Library_sc.mk sc/source sd/Library_sd.mk sd/source sfx2/inc sfx2/source solenv/gbuild svtools/inc svtools/Library_svt.mk svtools/source sw/Library_sw.mk sw/source uitest/calc_tests uitest/connection.py uitest/demo_ui uitest/helper.py uitest/impress_tests uitest/main.py uitest/Makefile uitest/Module_uitest.mk uitest/README uitest/uihelper uitest/UITest_calc_demo.mk uitest/uitest_helper.py uitest/UITest_writer_demo.mk uitest/writer_tests vcl/inc vcl/source

Markus Mohrhard markus.mohrhard at googlemail.com
Sat Jun 18 00:57:51 UTC 2016


Rebased ref, commits from common ancestor:
commit 7133422859e1d47905acdaa45c1f81552c15c2b2
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu May 26 12:44:34 2016 +0200

    uitest: make the calc keycode demo a bit easier to understand
    
    Change-Id: Ia24747994dc45b8c6636aee37a55d2ba4672993a

diff --git a/uitest/calc_tests/gridwindow.py b/uitest/calc_tests/gridwindow.py
index ae16e40..1f01ec9 100644
--- a/uitest/calc_tests/gridwindow.py
+++ b/uitest/calc_tests/gridwindow.py
@@ -55,10 +55,11 @@ def special_keys(xContext):
     selectProps = mkPropertyValues({"CELL": "C3"})
     xGridWindow.executeAction("SELECT", selectProps)
 
-    # TODO: how to handle the enter
     typeProps = mkPropertyValues({"KEYCODE": "CTRL+DOWN"})
     xGridWindow.executeAction("TYPE", typeProps)
 
+    time.sleep(2)
+
     ui_test.close_doc()
 
 # vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 0522ffc54a798849e967650fa07a2ced00632a0c
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu May 26 12:43:23 2016 +0200

    uitest: add more impress tests
    
    Change-Id: I89bd0af49e530382f0201a108f8798f9a9d689e3

diff --git a/uitest/impress_tests/start.py b/uitest/impress_tests/start.py
index 0c5ef2a..c817cfe 100644
--- a/uitest/impress_tests/start.py
+++ b/uitest/impress_tests/start.py
@@ -29,6 +29,86 @@ def start_impress(xContext):
 
     ui_test.create_doc_in_start_center("impress")
 
+    xImpressDoc = xUITest.getTopFocusWindow()
+    print(get_state_as_dict(xImpressDoc))
+    print(xImpressDoc.getChildren())
+
+    xEditWin = xImpressDoc.getChild("impress_win")
+    xEditWin.executeAction("SET", mkPropertyValues({"ZOOM": "200"}))
+
+    print(xEditWin.getChildren())
+
+    time.sleep(5)
+
+    ui_test.close_doc()
+
+def select_page(xContext):
+    xUITest = xContext.ServiceManager.createInstanceWithContext(
+            "org.libreoffice.uitest.UITest", xContext)
+
+    ui_test = UITest(xUITest, xContext)
+
+    ui_test.create_doc_in_start_center("impress")
+
+    xImpressDoc = xUITest.getTopFocusWindow()
+    print(get_state_as_dict(xImpressDoc))
+    print(xImpressDoc.getChildren())
+
+    xEditWin = xImpressDoc.getChild("impress_win")
+
+    time.sleep(10)
+    print(get_state_as_dict(xEditWin))
+
+    xEditWin.executeAction("GOTO", mkPropertyValues({"PAGE": "2"}))
+
+    time.sleep(5)
+
+    print(get_state_as_dict(xEditWin))
+
+    ui_test.close_doc()
+
+def select_text(xContext):
+    xUITest = xContext.ServiceManager.createInstanceWithContext(
+            "org.libreoffice.uitest.UITest", xContext)
+
+    ui_test = UITest(xUITest, xContext)
+
+    ui_test.create_doc_in_start_center("impress")
+
+    xImpressDoc = xUITest.getTopFocusWindow()
+    print(get_state_as_dict(xImpressDoc))
+    print(xImpressDoc.getChildren())
+
+    xEditWin = xImpressDoc.getChild("impress_win")
+
+    time.sleep(10)
+
+    print(get_state_as_dict(xEditWin))
+
+    ui_test.close_doc()
+
+def select_object(xContext):
+    xUITest = xContext.ServiceManager.createInstanceWithContext(
+            "org.libreoffice.uitest.UITest", xContext)
+
+    ui_test = UITest(xUITest, xContext)
+
+    ui_test.create_doc_in_start_center("impress")
+
+    xImpressDoc = xUITest.getTopFocusWindow()
+    print(get_state_as_dict(xImpressDoc))
+    print(xImpressDoc.getChildren())
+
+    xEditWin = xImpressDoc.getChild("impress_win")
+
+    xEditWin.executeAction("SELECT", mkPropertyValues({"OBJECT":"Unnamed Drawinglayer object 1"}))
+    time.sleep(2)
+    xEditWin.executeAction("DESELECT", tuple())
+
+    time.sleep(4)
+
+    print(get_state_as_dict(xEditWin))
+
     ui_test.close_doc()
 
 # vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 36340321ea9eb076746c3e982b9d95b2d547dcf0
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Mon May 23 05:22:33 2016 +0200

    uitest: support more impress operations
    
    Change-Id: I74ab526dabbee1f8c203274f187c065d9fb413fd

diff --git a/sd/source/ui/inc/uiobject.hxx b/sd/source/ui/inc/uiobject.hxx
index f8b7e57..8e3d479 100644
--- a/sd/source/ui/inc/uiobject.hxx
+++ b/sd/source/ui/inc/uiobject.hxx
@@ -16,6 +16,9 @@ class DrawViewShell;
 
 }
 
+class SdrObject;
+class SdrPageView;
+
 class ImpressWindowUIObject : public WindowUIObject
 {
 public:
@@ -27,6 +30,8 @@ public:
     virtual void execute(const OUString& rAction,
             const StringMap& rParameters) override;
 
+    virtual std::set<OUString> get_children() const override;
+
     static std::unique_ptr<UIObject> create(vcl::Window* pWindow);
 
 protected:
@@ -37,7 +42,11 @@ private:
 
     VclPtr<sd::Window> mxWindow;
 
-    sd::DrawViewShell* getViewShell();
+    sd::DrawViewShell* getViewShell() const;
+
+    SdrObject* getObject(const OUString& rName);
+
+    SdrPageView* getPageView();
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/uitest/uiobject.cxx b/sd/source/ui/uitest/uiobject.cxx
index 90535c6..a8c0227 100644
--- a/sd/source/ui/uitest/uiobject.cxx
+++ b/sd/source/ui/uitest/uiobject.cxx
@@ -11,6 +11,7 @@
 
 #include "Window.hxx"
 #include "DrawViewShell.hxx"
+#include "sdpage.hxx"
 
 ImpressWindowUIObject::ImpressWindowUIObject(VclPtr<sd::Window> xWindow):
     WindowUIObject(xWindow),
@@ -51,7 +52,53 @@ void ImpressWindowUIObject::execute(const OUString& rAction,
             getViewShell()->SwitchPage(nVal);
         }
     }
-    WindowUIObject::execute(rAction, rParameters);
+    else if (rAction == "SELECT")
+    {
+        if (rParameters.find("OBJECT") != rParameters.end())
+        {
+            auto itr = rParameters.find("OBJECT");
+            OUString aName = itr->second;
+            SdrObject* pObj = getObject(aName);
+            SdrPageView* pPageView = getPageView();
+            getViewShell()->GetView()->MarkObj(pObj, pPageView);
+        }
+    }
+    else if (rAction == "DESELECT")
+    {
+        getViewShell()->GetView()->UnMarkAll();
+    }
+    else
+        WindowUIObject::execute(rAction, rParameters);
+}
+
+namespace {
+
+OUString getObjectName(SdrObject* pObject)
+{
+    if (pObject->GetName().isEmpty())
+        return OUString("Unnamed Drawinglayer object ") + OUString::number(pObject->GetOrdNum());
+    else
+        return pObject->GetName();
+}
+
+}
+
+std::set<OUString> ImpressWindowUIObject::get_children() const
+{
+    SdrPage* pPage = getViewShell()->getCurrentPage();
+
+    std::set<OUString> aRet;
+    if (!pPage)
+        return aRet;
+
+    size_t nObjs = pPage->GetObjCount();
+    for (size_t i = 0; i < nObjs; ++i)
+    {
+        SdrObject* pObject = pPage->GetObj(i);
+        aRet.insert(getObjectName(pObject));
+    }
+
+    return aRet;
 }
 
 OUString ImpressWindowUIObject::get_name() const
@@ -66,7 +113,7 @@ std::unique_ptr<UIObject> ImpressWindowUIObject::create(vcl::Window* pWindow)
     return std::unique_ptr<UIObject>(new ImpressWindowUIObject(pWin));
 }
 
-sd::DrawViewShell* ImpressWindowUIObject::getViewShell()
+sd::DrawViewShell* ImpressWindowUIObject::getViewShell() const
 {
     sd::DrawViewShell* pViewShell = dynamic_cast<sd::DrawViewShell*>(mxWindow->GetViewShell());
     assert(pViewShell);
@@ -74,4 +121,27 @@ sd::DrawViewShell* ImpressWindowUIObject::getViewShell()
     return pViewShell;
 }
 
+SdrObject* ImpressWindowUIObject::getObject(const OUString& rName)
+{
+    SdrPage* pPage = getViewShell()->getCurrentPage();
+
+    if (!pPage)
+        return nullptr;
+
+    size_t nObjs = pPage->GetObjCount();
+    for (size_t i = 0; i < nObjs; ++i)
+    {
+        SdrObject* pObj = pPage->GetObj(i);
+        if (rName == getObjectName(pObj))
+            return pObj;
+    }
+
+    return nullptr;
+}
+
+SdrPageView* ImpressWindowUIObject::getPageView()
+{
+    return getViewShell()->GetView()->GetSdrPageView();
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit b9c9d4b87b5a28724826cfe77a42f1de86eaddb2
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sun May 22 05:54:11 2016 +0200

    uitest: add initial code for impress main edit window
    
    Change-Id: I82eabe1df33878316907e664ddbcd8edf6a73d33

diff --git a/sd/Library_sd.mk b/sd/Library_sd.mk
index 76e35ae..ae04336 100644
--- a/sd/Library_sd.mk
+++ b/sd/Library_sd.mk
@@ -411,6 +411,7 @@ $(eval $(call gb_Library_add_exception_objects,sd,\
 	sd/source/ui/tools/SdGlobalResourceContainer \
 	sd/source/ui/tools/SlotStateListener \
 	sd/source/ui/tools/TimerBasedTaskExecution \
+	sd/source/ui/uitest/uiobject \
 	sd/source/ui/unoidl/DrawController \
 	sd/source/ui/unoidl/SdUnoDrawView \
 	sd/source/ui/unoidl/SdUnoOutlineView \
diff --git a/sd/source/ui/inc/Window.hxx b/sd/source/ui/inc/Window.hxx
index 6d9d869..bfd38f4 100644
--- a/sd/source/ui/inc/Window.hxx
+++ b/sd/source/ui/inc/Window.hxx
@@ -49,6 +49,7 @@ public:
     virtual void dispose() override;
 
     void    SetViewShell (ViewShell* pViewSh);
+    ViewShell* GetViewShell();
 
     /** Set the zoom factor to the specified value and center the display
         area around the zoom center.
@@ -192,6 +193,8 @@ protected:
     Selection GetSurroundingTextSelection() const override;
     /// @see OutputDevice::LogicInvalidate().
     void LogicInvalidate(const Rectangle* pRectangle) override;
+
+    FactoryFunction GetUITestFactory() const override;
 };
 
 } // end of namespace sd
diff --git a/sd/source/ui/inc/uiobject.hxx b/sd/source/ui/inc/uiobject.hxx
new file mode 100644
index 0000000..f8b7e57
--- /dev/null
+++ b/sd/source/ui/inc/uiobject.hxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <vcl/uitest/uiobject.hxx>
+
+namespace sd {
+
+class Window;
+class DrawViewShell;
+
+}
+
+class ImpressWindowUIObject : public WindowUIObject
+{
+public:
+
+    ImpressWindowUIObject(VclPtr<sd::Window> xWindow);
+
+    virtual StringMap get_state() override;
+
+    virtual void execute(const OUString& rAction,
+            const StringMap& rParameters) override;
+
+    static std::unique_ptr<UIObject> create(vcl::Window* pWindow);
+
+protected:
+
+    virtual OUString get_name() const override;
+
+private:
+
+    VclPtr<sd::Window> mxWindow;
+
+    sd::DrawViewShell* getViewShell();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/uitest/uiobject.cxx b/sd/source/ui/uitest/uiobject.cxx
new file mode 100644
index 0000000..90535c6
--- /dev/null
+++ b/sd/source/ui/uitest/uiobject.cxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "uiobject.hxx"
+
+#include "Window.hxx"
+#include "DrawViewShell.hxx"
+
+ImpressWindowUIObject::ImpressWindowUIObject(VclPtr<sd::Window> xWindow):
+    WindowUIObject(xWindow),
+    mxWindow(xWindow)
+{
+}
+
+StringMap ImpressWindowUIObject::get_state()
+{
+    StringMap aMap = WindowUIObject::get_state();
+
+    aMap["SelectedText"] = getViewShell()->GetSelectionText();
+    aMap["CurrentSlide"] = OUString::number(getViewShell()->GetCurPageId());
+
+    return aMap;
+}
+
+void ImpressWindowUIObject::execute(const OUString& rAction,
+        const StringMap& rParameters)
+{
+    if (rAction == "SET")
+    {
+        if (rParameters.find("ZOOM") != rParameters.end())
+        {
+            auto itr = rParameters.find("ZOOM");
+            OUString aVal = itr->second;
+            sal_Int32 nVal = aVal.toInt32();
+            getViewShell()->SetZoom(nVal);
+        }
+    }
+    else if (rAction == "GOTO")
+    {
+        if (rParameters.find("PAGE") != rParameters.end())
+        {
+            auto itr = rParameters.find("PAGE");
+            OUString aVal = itr->second;
+            sal_Int32 nVal = aVal.toInt32();
+            getViewShell()->SwitchPage(nVal);
+        }
+    }
+    WindowUIObject::execute(rAction, rParameters);
+}
+
+OUString ImpressWindowUIObject::get_name() const
+{
+    return OUString("ImpressWindowUIObject");
+}
+
+std::unique_ptr<UIObject> ImpressWindowUIObject::create(vcl::Window* pWindow)
+{
+    sd::Window* pWin = dynamic_cast<sd::Window*>(pWindow);
+    assert(pWin);
+    return std::unique_ptr<UIObject>(new ImpressWindowUIObject(pWin));
+}
+
+sd::DrawViewShell* ImpressWindowUIObject::getViewShell()
+{
+    sd::DrawViewShell* pViewShell = dynamic_cast<sd::DrawViewShell*>(mxWindow->GetViewShell());
+    assert(pViewShell);
+
+    return pViewShell;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/view/sdwindow.cxx b/sd/source/ui/view/sdwindow.cxx
index ab9917e..fca21eb 100644
--- a/sd/source/ui/view/sdwindow.cxx
+++ b/sd/source/ui/view/sdwindow.cxx
@@ -38,6 +38,7 @@
 #include "AccessibleDrawDocumentView.hxx"
 #include "WindowUpdater.hxx"
 #include "ViewShellBase.hxx"
+#include "uiobject.hxx"
 
 #include <vcl/svapp.hxx>
 #include <vcl/settings.hxx>
@@ -129,6 +130,11 @@ void Window::SetViewShell (ViewShell* pViewSh)
     }
 }
 
+ViewShell* Window::GetViewShell()
+{
+    return mpViewShell;
+}
+
 void Window::CalcMinZoom()
 {
     // Are we entitled to change the minimal zoom factor?
@@ -1026,6 +1032,14 @@ void Window::LogicInvalidate(const Rectangle* pRectangle)
         mpViewShell->GetDoc()->libreOfficeKitCallback(LOK_CALLBACK_INVALIDATE_TILES, sRectangle.getStr());
 }
 
+FactoryFunction Window::GetUITestFactory() const
+{
+    if (get_id() == "impress_win")
+        return ImpressWindowUIObject::create;
+
+    return WindowUIObject::create;
+}
+
 } // end of namespace sd
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 49f2149df295121f46a38c40a6f9df6c00de162d
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sun May 22 05:52:36 2016 +0200

    uitest: dump the implementation name as well
    
    Change-Id: Ifefc5eb8c271aae0c815bb68535b1e3eb8afb2cd

diff --git a/vcl/source/uitest/uiobject.cxx b/vcl/source/uitest/uiobject.cxx
index 512d053..0f399f1 100644
--- a/vcl/source/uitest/uiobject.cxx
+++ b/vcl/source/uitest/uiobject.cxx
@@ -392,6 +392,7 @@ OUString WindowUIObject::get_name() const
 void WindowUIObject::dumpState() const
 {
     DUMP_UITEST(get_name() << " " << mxWindow->get_id());
+    DUMP_UITEST("Implementation Name: " << typeid(*mxWindow.get()).name());
     StringMap aState = const_cast<WindowUIObject*>(this)->get_state();
     for (auto itr = aState.begin(), itrEnd = aState.end(); itr != itrEnd; ++itr)
     {
commit 7ac107d2d79c61ff802360f6b39c9c7137ffd085
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sun May 22 03:03:07 2016 +0200

    uitest: annotate a few draw/impress windows
    
    Change-Id: I6352842535fddc99d30a4d0180ac01e7f8d5cd48

diff --git a/sd/source/ui/framework/factories/BasicViewFactory.cxx b/sd/source/ui/framework/factories/BasicViewFactory.cxx
index 3c8cc02..de3d4d5 100644
--- a/sd/source/ui/framework/factories/BasicViewFactory.cxx
+++ b/sd/source/ui/framework/factories/BasicViewFactory.cxx
@@ -36,6 +36,7 @@
 #include "SlideSorterViewShell.hxx"
 #include "FrameView.hxx"
 #include "facreg.hxx"
+#include "Window.hxx"
 
 #include <sfx2/viewfrm.hxx>
 #include <vcl/wrkwin.hxx>
@@ -341,6 +342,7 @@ std::shared_ptr<ViewShell> BasicViewFactory::CreateViewShell (
                 &rWindow,
                 PK_STANDARD,
                 pFrameView));
+        pViewShell->GetContentWindow()->set_id("impress_win");
     }
     else if (rsViewURL.equals(FrameworkHelper::msDrawViewURL))
     {
@@ -350,6 +352,7 @@ std::shared_ptr<ViewShell> BasicViewFactory::CreateViewShell (
                 *mpBase,
                 &rWindow,
                 pFrameView));
+        pViewShell->GetContentWindow()->set_id("draw_win");
     }
     else if (rsViewURL.equals(FrameworkHelper::msOutlineViewURL))
     {
@@ -359,6 +362,7 @@ std::shared_ptr<ViewShell> BasicViewFactory::CreateViewShell (
                 *mpBase,
                 &rWindow,
                 pFrameView));
+        pViewShell->GetContentWindow()->set_id("outline_win");
     }
     else if (rsViewURL.equals(FrameworkHelper::msNotesViewURL))
     {
@@ -369,6 +373,7 @@ std::shared_ptr<ViewShell> BasicViewFactory::CreateViewShell (
                 &rWindow,
                 PK_NOTES,
                 pFrameView));
+        pViewShell->GetContentWindow()->set_id("notes_win");
     }
     else if (rsViewURL.equals(FrameworkHelper::msHandoutViewURL))
     {
@@ -379,6 +384,7 @@ std::shared_ptr<ViewShell> BasicViewFactory::CreateViewShell (
                 &rWindow,
                 PK_HANDOUT,
                 pFrameView));
+        pViewShell->GetContentWindow()->set_id("handout_win");
     }
     else if (rsViewURL.equals(FrameworkHelper::msPresentationViewURL))
     {
@@ -388,6 +394,7 @@ std::shared_ptr<ViewShell> BasicViewFactory::CreateViewShell (
                 *mpBase,
                 &rWindow,
                 pFrameView));
+        pViewShell->GetContentWindow()->set_id("presentation_win");
     }
     else if (rsViewURL.equals(FrameworkHelper::msSlideSorterURL))
     {
diff --git a/sd/source/ui/inc/ViewShell.hxx b/sd/source/ui/inc/ViewShell.hxx
index 462bfc5..4dd4fd9 100644
--- a/sd/source/ui/inc/ViewShell.hxx
+++ b/sd/source/ui/inc/ViewShell.hxx
@@ -142,6 +142,8 @@ public:
     */
     inline vcl::Window* GetParentWindow() const { return mpParentWindow; }
 
+    sd::Window* GetContentWindow() const;
+
     inline ::sd::View* GetView() const { return mpView; }
     inline SdrView* GetDrawView() const;
     SD_DLLPUBLIC DrawDocShell* GetDocSh() const;
diff --git a/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx b/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx
index 0b7ce99..ac9a8fc 100644
--- a/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx
+++ b/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx
@@ -123,6 +123,7 @@ SlideSorterViewShell::SlideSorterViewShell (
       mpSlideSorter(),
       mbIsArrangeGUIElementsPending(true)
 {
+    GetContentWindow()->set_id("slidesorter");
     meShellType = ST_SLIDE_SORTER;
 
     if (pFrameViewArgument != nullptr)
diff --git a/sd/source/ui/view/viewshel.cxx b/sd/source/ui/view/viewshel.cxx
index 942f9a5..84d5d19 100644
--- a/sd/source/ui/view/viewshel.cxx
+++ b/sd/source/ui/view/viewshel.cxx
@@ -1604,6 +1604,11 @@ void ViewShell::NotifyAccUpdate( )
     GetViewShellBase().GetDrawController().NotifyAccUpdate();
 }
 
+sd::Window* ViewShell::GetContentWindow() const
+{
+    return mpContentWindow.get();
+}
+
 } // end of namespace sd
 
 //===== ViewShellObjectBarFactory =============================================
commit 042328f4da9b96d3b50782c1d653739576634f19
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sun May 22 01:43:16 2016 +0200

    uitest: start with work on impress demos
    
    Change-Id: I8407fe37f8906e21abc1033d6adf44f31cad1572

diff --git a/uitest/impress_tests/start.py b/uitest/impress_tests/start.py
new file mode 100644
index 0000000..0c5ef2a
--- /dev/null
+++ b/uitest/impress_tests/start.py
@@ -0,0 +1,34 @@
+# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+from uitest_helper import UITest, get_state_as_dict
+
+from helper import mkPropertyValues
+
+import time
+
+try:
+    import pyuno
+    import uno
+    import unohelper
+except ImportError:
+    print("pyuno not found: try to set PYTHONPATH and URE_BOOTSTRAP variables")
+    print("PYTHONPATH=/installation/opt/program")
+    print("URE_BOOTSTRAP=file:///installation/opt/program/fundamentalrc")
+    raise
+
+def start_impress(xContext):
+    xUITest = xContext.ServiceManager.createInstanceWithContext(
+            "org.libreoffice.uitest.UITest", xContext)
+
+    ui_test = UITest(xUITest, xContext)
+
+    ui_test.create_doc_in_start_center("impress")
+
+    ui_test.close_doc()
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 8afaa93c7537dc17f64eb84f2cbe205e6acab08b
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sun May 22 01:39:09 2016 +0200

    uitest: add writer demo ui tests to makefile
    
    Change-Id: I4ba2321deb196f22c95db533266d82c541a95f0a

diff --git a/uitest/Module_uitest.mk b/uitest/Module_uitest.mk
index 9ebc2f7..2530bee 100644
--- a/uitest/Module_uitest.mk
+++ b/uitest/Module_uitest.mk
@@ -12,5 +12,5 @@ $(eval $(call gb_Module_Module,uitest))
 
 $(eval $(call gb_Module_add_uicheck_targets,uitest,\
     UITest_calc_demo \
-    UITest_demo_ui \
+    UITest_writer_demo \
 ))
diff --git a/uitest/UITest_writer_demo.mk b/uitest/UITest_writer_demo.mk
new file mode 100644
index 0000000..c0c7f3d
--- /dev/null
+++ b/uitest/UITest_writer_demo.mk
@@ -0,0 +1,15 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_UITest_UITest,writer_demo))
+
+$(eval $(call gb_UITest_add_modules,writer_demo,$(SRCDIR)/uitest,\
+	writer_tests/writer_demo.txt \
+))
+# vim: set noet sw=4 ts=4:
diff --git a/uitest/writer_tests/writer_demo.txt b/uitest/writer_tests/writer_demo.txt
new file mode 100644
index 0000000..0045e2a
--- /dev/null
+++ b/uitest/writer_tests/writer_demo.txt
@@ -0,0 +1,4 @@
+writer_tests.start.start_writer
+writer_tests.start.type_text
+writer_tests.start.goto_first_page
+writer_tests.start.select_text
commit b510c2738850be42476c8d3a5dc1b8c48f5a99e4
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sat May 21 01:50:46 2016 +0200

    uitest: add demo for selecting writer text
    
    Change-Id: Iffc3e16bf0fa5a02058b6ad008ff3f61ea2a23af

diff --git a/uitest/writer_tests/start.py b/uitest/writer_tests/start.py
index a0fe7d2..a5a23ca 100644
--- a/uitest/writer_tests/start.py
+++ b/uitest/writer_tests/start.py
@@ -81,4 +81,29 @@ def goto_first_page(xContext):
 
     ui_test.close_doc()
 
+
+def select_text(xContext):
+    xUITest = xContext.ServiceManager.createInstanceWithContext(
+            "org.libreoffice.uitest.UITest", xContext)
+
+    ui_test = UITest(xUITest, xContext)
+
+    ui_test.create_doc_in_start_center("writer")
+
+    xWriterDoc = xUITest.getTopFocusWindow()
+    xWriterEdit = xWriterDoc.getChild("writer_edit")
+
+    xWriterEdit.executeAction("TYPE", mkPropertyValues({"TEXT": "This is my first writer text written through the UI testing"}))
+
+    time.sleep(2)
+    print(get_state_as_dict(xWriterEdit))
+
+    xWriterEdit.executeAction("SELECT", mkPropertyValues({"START_POS": "0", "END_POS": "4"}))
+
+    print(get_state_as_dict(xWriterEdit))
+
+    time.sleep(2)
+
+    ui_test.close_doc()
+
 # vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit f29c6c738f5652838de03f77fff719d3f242282d
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sat May 21 01:50:13 2016 +0200

    uitest: the demo is supposed to show how to goto the page start
    
    Change-Id: I61d2a74b50be2ab8b5077344ecd41cfa0cba2e64

diff --git a/uitest/writer_tests/start.py b/uitest/writer_tests/start.py
index a9b722a..a0fe7d2 100644
--- a/uitest/writer_tests/start.py
+++ b/uitest/writer_tests/start.py
@@ -75,6 +75,8 @@ def goto_first_page(xContext):
         xWriterEdit.executeAction("TYPE", mkPropertyValues({"KEYCODE": "RETURN"}))
         state = get_state_as_dict(xWriterEdit)
 
+    xWriterEdit.executeAction("GOTO", mkPropertyValues({"PAGE": "1"}))
+    print(state)
     time.sleep(2)
 
     ui_test.close_doc()
commit 3e876960bcd3fea8121c8a543b600c60efb63de4
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sat May 21 01:49:19 2016 +0200

    uitest: support selecting writer text
    
    Change-Id: I6d1c4e5a05bdcb3299af86a9044d912239659fb9

diff --git a/sw/source/uibase/uitest/uiobject.cxx b/sw/source/uibase/uitest/uiobject.cxx
index 0102c98..9f4529d 100644
--- a/sw/source/uibase/uitest/uiobject.cxx
+++ b/sw/source/uibase/uitest/uiobject.cxx
@@ -79,6 +79,22 @@ void SwEditWinUIObject::execute(const OUString& rAction,
             getWrtShell(mxEditWin).GotoPage(nVal, false);
         }
     }
+    else if (rAction == "SELECT")
+    {
+        if (rParameters.find("START_POS") != rParameters.end())
+        {
+            auto itr = rParameters.find("START_POS");
+            OUString aStartPos = itr->second;
+            sal_Int32 nStartPos = aStartPos.toInt32();
+
+            itr = rParameters.find("END_POS");
+            assert(itr != rParameters.end());
+            OUString aEndPos = itr->second;
+            sal_Int32 nEndPos = aEndPos.toInt32();
+
+            getWrtShell(mxEditWin).SelectText(nStartPos, nEndPos);
+        }
+    }
     else
         WindowUIObject::execute(rAction, rParameters);
 }
commit 917f7fdb34858f143cbd855761a21df4e335dc36
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sat May 21 01:48:44 2016 +0200

    uitest: add more properties to writer state
    
    Change-Id: Iadf223b38d84c1a6fb9892642f39e63dd16c72c8

diff --git a/sw/source/uibase/uitest/uiobject.cxx b/sw/source/uibase/uitest/uiobject.cxx
index c6df6e1..0102c98 100644
--- a/sw/source/uibase/uitest/uiobject.cxx
+++ b/sw/source/uibase/uitest/uiobject.cxx
@@ -35,11 +35,24 @@ StringMap SwEditWinUIObject::get_state()
 
     sal_uInt16 nPageNum = 0;
     sal_uInt16 nVirtPageNum = 0;
-    getWrtShell(mxEditWin).GetPageNum(nPageNum, nVirtPageNum);
+    SwWrtShell& rWrtShell = getWrtShell(mxEditWin);
+    rWrtShell.GetPageNum(nPageNum, nVirtPageNum);
     aMap["CurrentPage"] = OUString::number(nPageNum);
-    getWrtShell(mxEditWin).GetPageNum(nPageNum, nVirtPageNum, false);
+    rWrtShell.GetPageNum(nPageNum, nVirtPageNum, false);
     aMap["TopVisiblePage"] = OUString::number(nPageNum);
 
+    sal_uInt16 nPages = rWrtShell.GetPageCnt();
+    aMap["Pages"] = OUString::number(nPages);
+
+    aMap["StartWord"] = OUString::number(rWrtShell.IsStartWord());
+    aMap["EndWord"] = OUString::number(rWrtShell.IsEndWord());
+    aMap["StartSentence"] = OUString::number(rWrtShell.IsStartSentence());
+    aMap["EndSentence"] = OUString::number(rWrtShell.IsEndSentence());
+    aMap["StartPara"] = OUString::number(rWrtShell.IsSttPara());
+    aMap["EndPara"] = OUString::number(rWrtShell.IsEndPara());
+    aMap["StartDoc"] = OUString::number(rWrtShell.IsStartOfDoc());
+    aMap["EndDoc"] = OUString::number(rWrtShell.IsEndOfDoc());
+
     return aMap;
 }
 
commit 8f1f41b2c602582f4c1d553f29a9e0abe7d643b8
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sat May 21 01:24:01 2016 +0200

    uitest: add demo showing how to use page number
    
    Change-Id: I718f4c6c8f01ceb556b9beadce5af88491c4efe0

diff --git a/uitest/writer_tests/start.py b/uitest/writer_tests/start.py
index 83b5ad2..a9b722a 100644
--- a/uitest/writer_tests/start.py
+++ b/uitest/writer_tests/start.py
@@ -5,7 +5,7 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
 
-from uitest_helper import UITest
+from uitest_helper import UITest, get_state_as_dict
 
 from helper import mkPropertyValues
 
@@ -58,4 +58,25 @@ def type_text(xContext):
 
     ui_test.close_doc()
 
+def goto_first_page(xContext):
+    xUITest = xContext.ServiceManager.createInstanceWithContext(
+            "org.libreoffice.uitest.UITest", xContext)
+
+    ui_test = UITest(xUITest, xContext)
+
+    ui_test.create_doc_in_start_center("writer")
+
+    xWriterDoc = xUITest.getTopFocusWindow()
+    xWriterEdit = xWriterDoc.getChild("writer_edit")
+
+    state = get_state_as_dict(xWriterEdit)
+    print(state)
+    while state["CurrentPage"] is "1":
+        xWriterEdit.executeAction("TYPE", mkPropertyValues({"KEYCODE": "RETURN"}))
+        state = get_state_as_dict(xWriterEdit)
+
+    time.sleep(2)
+
+    ui_test.close_doc()
+
 # vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 4ae2477b97f94488ff5dfd218a350ca4818ad178
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sat May 21 01:22:36 2016 +0200

    uitest: provide a way to jump at the beginning of page
    
    Note that page numbers in writer are 1-based
    
    Change-Id: I614ff08927b4cb92d3819b557ec6791199da69a4

diff --git a/sw/source/uibase/uitest/uiobject.cxx b/sw/source/uibase/uitest/uiobject.cxx
index 555aef4..c6df6e1 100644
--- a/sw/source/uibase/uitest/uiobject.cxx
+++ b/sw/source/uibase/uitest/uiobject.cxx
@@ -56,6 +56,16 @@ void SwEditWinUIObject::execute(const OUString& rAction,
             mxEditWin->GetView().SetZoom(SvxZoomType::PERCENT, nVal);
         }
     }
+    else if (rAction == "GOTO")
+    {
+        if (rParameters.find("PAGE") != rParameters.end())
+        {
+            auto itr = rParameters.find("PAGE");
+            OUString aVal = itr->second;
+            sal_Int32 nVal = aVal.toInt32();
+            getWrtShell(mxEditWin).GotoPage(nVal, false);
+        }
+    }
     else
         WindowUIObject::execute(rAction, rParameters);
 }
commit 6df2fc7004054b680288ef9fc63b9570d96742e7
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sat May 21 01:22:01 2016 +0200

    uitest: provide information about current page
    
    Change-Id: Ie0ef65a023e156f65370e11f024fa6349841841e

diff --git a/sw/source/uibase/uitest/uiobject.cxx b/sw/source/uibase/uitest/uiobject.cxx
index 907e7b9..555aef4 100644
--- a/sw/source/uibase/uitest/uiobject.cxx
+++ b/sw/source/uibase/uitest/uiobject.cxx
@@ -10,6 +10,7 @@
 #include "uiobject.hxx"
 #include "edtwin.hxx"
 #include "view.hxx"
+#include "wrtsh.hxx"
 
 SwEditWinUIObject::SwEditWinUIObject(VclPtr<SwEditWin> xEditWin):
     WindowUIObject(xEditWin),
@@ -17,11 +18,28 @@ SwEditWinUIObject::SwEditWinUIObject(VclPtr<SwEditWin> xEditWin):
 {
 }
 
+namespace {
+
+SwWrtShell& getWrtShell(VclPtr<SwEditWin> xEditWin)
+{
+    return xEditWin->GetView().GetWrtShell();
+}
+
+}
+
 StringMap SwEditWinUIObject::get_state()
 {
     StringMap aMap = WindowUIObject::get_state();
 
-    // aMap["SelectedText"] = mxEditWin
+    aMap["SelectedText"] = mxEditWin->GetView().GetSelectionText();
+
+    sal_uInt16 nPageNum = 0;
+    sal_uInt16 nVirtPageNum = 0;
+    getWrtShell(mxEditWin).GetPageNum(nPageNum, nVirtPageNum);
+    aMap["CurrentPage"] = OUString::number(nPageNum);
+    getWrtShell(mxEditWin).GetPageNum(nPageNum, nVirtPageNum, false);
+    aMap["TopVisiblePage"] = OUString::number(nPageNum);
+
     return aMap;
 }
 
commit 826a3fb0d163a36ca79972e38a5f27d08477b081
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sat May 21 01:21:08 2016 +0200

    uitest: make handling the state of an object easier
    
    Change-Id: I3dcb78752b62a42d3aa283910241fef813dc352b

diff --git a/uitest/uitest_helper.py b/uitest/uitest_helper.py
index cac4ea1..925010e 100644
--- a/uitest/uitest_helper.py
+++ b/uitest/uitest_helper.py
@@ -9,6 +9,8 @@ import time
 
 from helper import EventListener
 
+from helper import convert_property_values_to_dict
+
 class DialogNotExecutedException(Exception):
     def __init__(self, command):
         self.command = command
@@ -82,4 +84,7 @@ class UITest(object):
                 time_ += self.DEFAULT_SLEEP
                 time.sleep(self.DEFAULT_SLEEP)
 
+def get_state_as_dict(ui_object):
+    return convert_property_values_to_dict(ui_object.getState())
+
 # vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 2fc4d74aa55e8617312137330610cced61ecfe16
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sat May 21 01:19:00 2016 +0200

    uitest: add a way to convert property values to dicts
    
    Change-Id: I21afd1c9b88525e576745905ee1ce21746f2d50c

diff --git a/uitest/helper.py b/uitest/helper.py
index 2d771e1..fcb9618 100644
--- a/uitest/helper.py
+++ b/uitest/helper.py
@@ -68,4 +68,13 @@ def mkPropertyValues(vals):
     """
     return tuple([mkPropertyValue(name, value) for (name, value) in vals.items()])
 
+def convert_property_values_to_dict(propMap):
+    ret = {}
+    for entry in propMap:
+        name = entry.Name
+        val = entry.Value
+        ret[name] = val
+
+    return ret
+
 # vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 6c86f7392d3987fbaa42b298afe63a1cb0d0fd16
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 20 20:58:47 2016 +0200

    uitest: add demo showing how to type text into writer
    
    Change-Id: I32598d12c85ad36d5c5d9ab00c184bfb7e39a4bd

diff --git a/uitest/writer_tests/start.py b/uitest/writer_tests/start.py
index 65ca0ed..83b5ad2 100644
--- a/uitest/writer_tests/start.py
+++ b/uitest/writer_tests/start.py
@@ -41,4 +41,21 @@ def start_writer(xContext):
 
     ui_test.close_doc()
 
+def type_text(xContext):
+    xUITest = xContext.ServiceManager.createInstanceWithContext(
+            "org.libreoffice.uitest.UITest", xContext)
+
+    ui_test = UITest(xUITest, xContext)
+
+    ui_test.create_doc_in_start_center("writer")
+
+    xWriterDoc = xUITest.getTopFocusWindow()
+    xWriterEdit = xWriterDoc.getChild("writer_edit")
+
+    xWriterEdit.executeAction("TYPE", mkPropertyValues({"TEXT": "This is my first writer text written through the UI testing"}))
+
+    time.sleep(2)
+
+    ui_test.close_doc()
+
 # vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 04c8f511ce9df8aeab723b0ebd79491373eafcdb
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 20 20:57:44 2016 +0200

    uitest: forward unhandled actions to the base class
    
    Change-Id: Iac08e77d9b0e80f2af93c8b229d083603f1d22d4

diff --git a/sw/source/uibase/uitest/uiobject.cxx b/sw/source/uibase/uitest/uiobject.cxx
index 9d45be1..907e7b9 100644
--- a/sw/source/uibase/uitest/uiobject.cxx
+++ b/sw/source/uibase/uitest/uiobject.cxx
@@ -38,6 +38,8 @@ void SwEditWinUIObject::execute(const OUString& rAction,
             mxEditWin->GetView().SetZoom(SvxZoomType::PERCENT, nVal);
         }
     }
+    else
+        WindowUIObject::execute(rAction, rParameters);
 }
 
 OUString SwEditWinUIObject::get_name() const
commit 32e9a9ef55c7141d5cfe7e3c908ee0e665e1a2b4
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 20 20:50:43 2016 +0200

    uitest: add initial writer demos
    
    Change-Id: If0aaf07b061fde3d5efa0d604af002efc872f726

diff --git a/uitest/writer_tests/start.py b/uitest/writer_tests/start.py
new file mode 100644
index 0000000..65ca0ed
--- /dev/null
+++ b/uitest/writer_tests/start.py
@@ -0,0 +1,44 @@
+# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+from uitest_helper import UITest
+
+from helper import mkPropertyValues
+
+import time
+
+try:
+    import pyuno
+    import uno
+    import unohelper
+except ImportError:
+    print("pyuno not found: try to set PYTHONPATH and URE_BOOTSTRAP variables")
+    print("PYTHONPATH=/installation/opt/program")
+    print("URE_BOOTSTRAP=file:///installation/opt/program/fundamentalrc")
+    raise
+
+def start_writer(xContext):
+    xUITest = xContext.ServiceManager.createInstanceWithContext(
+            "org.libreoffice.uitest.UITest", xContext)
+
+    ui_test = UITest(xUITest, xContext)
+
+    ui_test.create_doc_in_start_center("writer")
+
+    xWriterDoc = xUITest.getTopFocusWindow()
+    print(xWriterDoc.getChildren())
+
+    xWriterEdit = xWriterDoc.getChild("writer_edit")
+    print(xWriterEdit.getState())
+
+    xWriterEdit.executeAction("SET", mkPropertyValues({"ZOOM": "200"}))
+
+    time.sleep(2)
+
+    ui_test.close_doc()
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 6b4e95480d6d1e328911ac4e242a30a03a524042
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 20 20:49:40 2016 +0200

    uitest: add wrapper for writer's main edit window
    
    Change-Id: Ibd6ffe85ca95cdc915f5c73b1b566de1d7413ee7

diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk
index 0555d16..ea8c362 100644
--- a/sw/Library_sw.mk
+++ b/sw/Library_sw.mk
@@ -691,6 +691,7 @@ $(eval $(call gb_Library_add_exception_objects,sw,\
     sw/source/uibase/table/chartins \
     sw/source/uibase/table/swtablerep \
     sw/source/uibase/table/tablemgr \
+    sw/source/uibase/uitest/uiobject \
     sw/source/uibase/uiview/formatclipboard \
     sw/source/uibase/uiview/pview \
     sw/source/uibase/uiview/scroll \
diff --git a/sw/source/uibase/docvw/edtwin3.cxx b/sw/source/uibase/docvw/edtwin3.cxx
index 745bbd4..52c56de 100644
--- a/sw/source/uibase/docvw/edtwin3.cxx
+++ b/sw/source/uibase/docvw/edtwin3.cxx
@@ -34,6 +34,7 @@
 #include "pagedesc.hxx"
 #include <frmatr.hxx>
 #include <editeng/frmdiritem.hxx>
+#include "uiobject.hxx"
 
 // Core-Notify
 void ScrollMDI( SwViewShell* pVwSh, const SwRect &rRect,
@@ -165,4 +166,9 @@ void SwEditWin::DataChanged( const DataChangedEvent& rDCEvt )
         pSh->UnlockPaint();
 }
 
+FactoryFunction SwEditWin::GetUITestFactory() const
+{
+    return SwEditWinUIObject::create;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/edtwin.hxx b/sw/source/uibase/inc/edtwin.hxx
index cc4d528..1b713de 100644
--- a/sw/source/uibase/inc/edtwin.hxx
+++ b/sw/source/uibase/inc/edtwin.hxx
@@ -307,6 +307,8 @@ public:
     void SetCursorTwipPosition(const Point& rPosition, bool bPoint, bool bClearMark);
     /// Allows starting or ending a graphic move or resize action.
     void SetGraphicTwipPosition(bool bStart, const Point& rPosition);
+
+    virtual FactoryFunction GetUITestFactory() const override;
 };
 
 #endif
diff --git a/sw/source/uibase/inc/uiobject.hxx b/sw/source/uibase/inc/uiobject.hxx
new file mode 100644
index 0000000..568aa6c
--- /dev/null
+++ b/sw/source/uibase/inc/uiobject.hxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef SW_SOURCE_UIBASE_INC_UIOBJECT_HXX
+#define SW_SOURCE_UIBASE_INC_UIOBJECT_HXX
+
+#include <vcl/uitest/uiobject.hxx>
+
+class SwEditWin;
+
+class SwEditWinUIObject : public WindowUIObject
+{
+public:
+
+    SwEditWinUIObject(VclPtr<SwEditWin> xEditWin);
+
+    virtual StringMap get_state() override;
+
+    virtual void execute(const OUString& rAction,
+            const StringMap& rParameters) override;
+
+    static std::unique_ptr<UIObject> create(vcl::Window* pWindow);
+
+protected:
+
+    virtual OUString get_name() const override;
+
+private:
+
+    VclPtr<SwEditWin> mxEditWin;
+
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uitest/uiobject.cxx b/sw/source/uibase/uitest/uiobject.cxx
new file mode 100644
index 0000000..9d45be1
--- /dev/null
+++ b/sw/source/uibase/uitest/uiobject.cxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "uiobject.hxx"
+#include "edtwin.hxx"
+#include "view.hxx"
+
+SwEditWinUIObject::SwEditWinUIObject(VclPtr<SwEditWin> xEditWin):
+    WindowUIObject(xEditWin),
+    mxEditWin(xEditWin)
+{
+}
+
+StringMap SwEditWinUIObject::get_state()
+{
+    StringMap aMap = WindowUIObject::get_state();
+
+    // aMap["SelectedText"] = mxEditWin
+    return aMap;
+}
+
+void SwEditWinUIObject::execute(const OUString& rAction,
+        const StringMap& rParameters)
+{
+    if (rAction == "SET")
+    {
+        if (rParameters.find("ZOOM") != rParameters.end())
+        {
+            auto itr = rParameters.find("ZOOM");
+            OUString aVal = itr->second;
+            sal_Int32 nVal = aVal.toInt32();
+            mxEditWin->GetView().SetZoom(SvxZoomType::PERCENT, nVal);
+        }
+    }
+}
+
+OUString SwEditWinUIObject::get_name() const
+{
+    return OUString("SwEditWinUIObject");
+}
+
+std::unique_ptr<UIObject> SwEditWinUIObject::create(vcl::Window* pWindow)
+{
+    SwEditWin* pEditWin = dynamic_cast<SwEditWin*>(pWindow);
+    assert(pEditWin);
+    return std::unique_ptr<UIObject>(new SwEditWinUIObject(pEditWin));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit c90eaf55429b0f55a778cccd4340d8f942c449e9
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 20 05:34:45 2016 +0200

    uitest: set id for main writer edit window
    
    Change-Id: Ie039b9983dd2aa6ec2c79b35bfd87161a57438b5

diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx
index fafaf0e..1d7a179 100644
--- a/sw/source/uibase/docvw/edtwin.cxx
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -5089,6 +5089,7 @@ SwEditWin::SwEditWin(vcl::Window *pParent, SwView &rMyView):
     m_nKS_NUMINDENTINC_Count(0),
     m_pFrameControlsManager(new SwFrameControlsManager(this))
 {
+    set_id("writer_edit");
     SetHelpId(HID_EDIT_WIN);
     EnableChildTransparentMode();
     SetDialogControlFlags( DialogControlFlags::Return | DialogControlFlags::WantFocus );
commit 7d8a0f3f7aabfae457f0014407ef0158101cd7b1
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 20 05:12:33 2016 +0200

    uitest: use the new cell content enter function
    
    Change-Id: I75ff56a903226797284dff7f556bd425d40b4fd4

diff --git a/uitest/calc_tests/gridwindow.py b/uitest/calc_tests/gridwindow.py
index b67275a..ae16e40 100644
--- a/uitest/calc_tests/gridwindow.py
+++ b/uitest/calc_tests/gridwindow.py
@@ -9,6 +9,8 @@ from uitest_helper import UITest
 
 from helper import mkPropertyValues
 
+from uihelper.calc import enter_text_to_cell
+
 import time
 
 try:
@@ -32,6 +34,11 @@ def input(xContext):
 
     xGridWindow = xTopWindow.getChild("grid_window")
 
+    enter_text_to_cell(xGridWindow, "C3", "=A1")
+    enter_text_to_cell(xGridWindow, "A1", "2")
+
+    time.sleep(2)
+
     ui_test.close_doc()
 
 def special_keys(xContext):
commit 37d2bbcf98cd392048ea0ff0edbfb7b91af74a91
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 20 05:11:39 2016 +0200

    uitest: split the demo
    
    Change-Id: Iec2acce4e7777995d3e5a8e4bea5f069f579721d

diff --git a/uitest/calc_tests/gridwindow.py b/uitest/calc_tests/gridwindow.py
index 642da4b..b67275a 100644
--- a/uitest/calc_tests/gridwindow.py
+++ b/uitest/calc_tests/gridwindow.py
@@ -32,6 +32,19 @@ def input(xContext):
 
     xGridWindow = xTopWindow.getChild("grid_window")
 
+    ui_test.close_doc()
+
+def special_keys(xContext):
+    xUITest = xContext.ServiceManager.createInstanceWithContext(
+            "org.libreoffice.uitest.UITest", xContext)
+
+    ui_test = UITest(xUITest, xContext)
+
+    ui_test.create_doc_in_start_center("calc")
+    xTopWindow = xUITest.getTopFocusWindow()
+
+    xGridWindow = xTopWindow.getChild("grid_window")
+
     selectProps = mkPropertyValues({"CELL": "C3"})
     xGridWindow.executeAction("SELECT", selectProps)
 
commit b4e4ecbbbec89acfeb88e7fd03b3bda54db76f6e
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 20 05:07:33 2016 +0200

    uitest: add a demo case for new keycodes
    
    Change-Id: Ieec7fcd9b942d99d0dc16794856af4b1eabebde8

diff --git a/uitest/calc_tests/gridwindow.py b/uitest/calc_tests/gridwindow.py
index 55005b2..642da4b 100644
--- a/uitest/calc_tests/gridwindow.py
+++ b/uitest/calc_tests/gridwindow.py
@@ -36,7 +36,7 @@ def input(xContext):
     xGridWindow.executeAction("SELECT", selectProps)
 
     # TODO: how to handle the enter
-    typeProps = mkPropertyValues({"TEXT": "=2"})
+    typeProps = mkPropertyValues({"KEYCODE": "CTRL+DOWN"})
     xGridWindow.executeAction("TYPE", typeProps)
 
     ui_test.close_doc()
commit 5a803bb15cfc9046c886cd22c21dfa09e5e90b6f
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 20 04:59:37 2016 +0200

    uitest: add calc uitest helper functions
    
    Change-Id: I9201f697ede4d5f9a541eb06f20162ec5ad0542d

diff --git a/uitest/uihelper/__init__.py b/uitest/uihelper/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/uitest/uihelper/calc.py b/uitest/uihelper/calc.py
new file mode 100644
index 0000000..66e85e1
--- /dev/null
+++ b/uitest/uihelper/calc.py
@@ -0,0 +1,15 @@
+# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+from helper import mkPropertyValues
+
+def enter_text_to_cell(gridwin, cell, text):
+    gridwin.executeAction("SELECT", mkPropertyValues({"CELL": cell}))
+    gridwin.executeAction("TYPE", mkPropertyValues({"TEXT": text}))
+    gridwin.executeAction("TYPE", mkPropertyValues({"KEYCODE": "RETURN"}))
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 820d9f96b18475e88fa9db6419fa52d37b396c10
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 20 04:58:56 2016 +0200

    uitest: support more special keycodes
    
    Change-Id: Ief5fde7c9840de0f7b0a34fec24837e3a8e5ae70

diff --git a/vcl/source/uitest/uiobject.cxx b/vcl/source/uitest/uiobject.cxx
index b7b39ea..512d053 100644
--- a/vcl/source/uitest/uiobject.cxx
+++ b/vcl/source/uitest/uiobject.cxx
@@ -132,6 +132,22 @@ std::vector<KeyEvent> generate_key_events_from_keycode(const OUString& rStr)
 {
     std::vector<KeyEvent> aEvents;
 
+    std::map<OUString, sal_uInt16> aKeyMap = {
+        {"ESC", KEY_ESCAPE},
+        {"DOWN", KEY_DOWN},
+        {"UP", KEY_UP},
+        {"LEFT", KEY_LEFT},
+        {"RIGHT", KEY_RIGHT},
+        {"DELETE", KEY_DELETE},
+        {"INSERT", KEY_INSERT},
+        {"BACKSPACE", KEY_BACKSPACE},
+        {"RETURN", KEY_RETURN},
+        {"HOME", KEY_HOME},
+        {"END", KEY_END},
+        {"PAGEUP", KEY_PAGEUP},
+        {"PAGEDOWN", KEY_PAGEDOWN}
+    };
+
     // split string along '+'
     // then translate to keycodes
     bool bShift = false;
@@ -159,12 +175,21 @@ std::vector<KeyEvent> generate_key_events_from_keycode(const OUString& rStr)
             aRemainingText = aToken;
     }
 
-    for (sal_Int32 i = 0; i < aRemainingText.getLength(); ++i)
+    if (aKeyMap.find(aRemainingText) != aKeyMap.end())
+    {
+        sal_uInt16 nKey = aKeyMap[aRemainingText];
+        vcl::KeyCode aCode(nKey, bShift, bMod1, bMod2, false);
+        aEvents.push_back(KeyEvent( 'a', aCode));
+    }
+    else
     {
-        bool bShiftThroughKey = false;
-        sal_uInt16 nKey = get_key(aRemainingText[i], bShiftThroughKey);
-        vcl::KeyCode aCode(nKey, bShift || bShiftThroughKey, bMod1, bMod2, false);
-        aEvents.push_back(KeyEvent(aRemainingText[i], aCode));
+        for (sal_Int32 i = 0; i < aRemainingText.getLength(); ++i)
+        {
+            bool bShiftThroughKey = false;
+            sal_uInt16 nKey = get_key(aRemainingText[i], bShiftThroughKey);
+            vcl::KeyCode aCode(nKey, bShift || bShiftThroughKey, bMod1, bMod2, false);
+            aEvents.push_back(KeyEvent(aRemainingText[i], aCode));
+        }
     }
 
     return aEvents;
commit 5200a9aed8f0bcd3ec1cbe3240c7043cd9bd6382
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu May 19 20:52:43 2016 +0200

    uitest: add demo showing how to activate chart
    
    Change-Id: I40293ca1f786c08a51d01fde5e90b75af2e67f6b

diff --git a/uitest/calc_tests/create_chart.py b/uitest/calc_tests/create_chart.py
index 30f0aa7..1e72df7 100644
--- a/uitest/calc_tests/create_chart.py
+++ b/uitest/calc_tests/create_chart.py
@@ -150,4 +150,37 @@ def deselect_chart(xContext):
 
     ui_test.close_doc()
 
+def activate_chart(xContext):
+    xUITest = xContext.ServiceManager.createInstanceWithContext(
+            "org.libreoffice.uitest.UITest", xContext)
+
+    ui_test = UITest(xUITest, xContext)
+
+    ui_test.create_doc_in_start_center("calc")
+
+    fill_spreadsheet(xUITest)
+
+    xCalcDoc = xUITest.getTopFocusWindow()
+    xGridWindow = xCalcDoc.getChild("grid_window")
+
+    ui_test.execute_dialog_through_command(".uno:InsertObjectChart")
+
+    xChartDlg = xUITest.getTopFocusWindow()
+
+    xNextBtn = xChartDlg.getChild("finish")
+    xNextBtn.executeAction("CLICK", tuple())
+
+    xGridWindow.executeAction("DESELECT", mkPropertyValues({"OBJECT": ""}))
+
+    time.sleep(2)
+
+    xGridWindow.executeAction("SELECT", mkPropertyValues({"OBJECT": "Object 1"}))
+    xGridWindow.executeAction("ACTIVATE", tuple())
+
+    time.sleep(2)
+
+    xGridWindow.executeAction("DESELECT", mkPropertyValues({"OBJECT": ""}))
+
+    ui_test.close_doc()
+
 # vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit cb650619abf6f363bb0d3a02b721059e7f3b3ed9
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu May 19 20:46:58 2016 +0200

    uitest: add demo showing how to deselect an UI object
    
    Change-Id: Ie755dd93296de4031abe36833872c58032271d22

diff --git a/uitest/calc_tests/create_chart.py b/uitest/calc_tests/create_chart.py
index 7bb331c..30f0aa7 100644
--- a/uitest/calc_tests/create_chart.py
+++ b/uitest/calc_tests/create_chart.py
@@ -124,4 +124,30 @@ def create_from_second_page(xContext):
 
     ui_test.close_doc()
 
+def deselect_chart(xContext):
+    xUITest = xContext.ServiceManager.createInstanceWithContext(
+            "org.libreoffice.uitest.UITest", xContext)
+
+    ui_test = UITest(xUITest, xContext)
+
+    ui_test.create_doc_in_start_center("calc")
+
+    fill_spreadsheet(xUITest)
+
+    xCalcDoc = xUITest.getTopFocusWindow()
+    xGridWindow = xCalcDoc.getChild("grid_window")
+
+    ui_test.execute_dialog_through_command(".uno:InsertObjectChart")
+
+    xChartDlg = xUITest.getTopFocusWindow()
+
+    xNextBtn = xChartDlg.getChild("finish")
+    xNextBtn.executeAction("CLICK", tuple())
+
+    xGridWindow.executeAction("DESELECT", mkPropertyValues({"OBJECT": ""}))
+
+    time.sleep(2)
+
+    ui_test.close_doc()
+
 # vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 8afcb5ca7951202ad2225f48769ffe59839a004e
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu May 19 20:46:26 2016 +0200

    uitest: add way to deselect OLE object
    
    Change-Id: I34515de0b149147e40c23df6fef1339d0b69d469

diff --git a/sc/source/ui/uitest/uiobject.cxx b/sc/source/ui/uitest/uiobject.cxx
index 4405fd9..f46ce5b 100644
--- a/sc/source/ui/uitest/uiobject.cxx
+++ b/sc/source/ui/uitest/uiobject.cxx
@@ -133,6 +133,17 @@ void ScGridWinUIObject::execute(const OUString& rAction,
             SAL_WARN("sc.uitest", "unknown selection method");
         }
     }
+    else if (rAction == "DESELECT")
+    {
+        if (rParameters.find("OBJECT") != rParameters.end())
+        {
+            ScDrawView* pDrawView = getDrawView();
+            pDrawView->UnmarkAll();
+
+            ScTabViewShell* pViewShell = getViewShell();
+            pViewShell->SetDrawShell(false);
+        }
+    }
     else if (rAction == "ACTIVATE")
     {
         ScDrawView* pDrawView = getDrawView();
commit 3ff666b1997e1afe39b06272ed31f4bdd2fa3f59
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu May 19 20:21:06 2016 +0200

    uitest: allow activating OLE objects
    
    Change-Id: I960f5d644afb9392f8b3fe1d2f393c499af57bdb

diff --git a/sc/source/ui/inc/uiobject.hxx b/sc/source/ui/inc/uiobject.hxx
index 85dee59..f5e6ba9 100644
--- a/sc/source/ui/inc/uiobject.hxx
+++ b/sc/source/ui/inc/uiobject.hxx
@@ -12,6 +12,7 @@
 class ScGridWindow;
 class ScDBFunc;
 class ScDrawView;
+class ScTabViewShell;
 
 class ScGridWinUIObject : public WindowUIObject
 {
@@ -40,6 +41,7 @@ private:
 
     ScDBFunc* getDBFunc();
     ScDrawView* getDrawView();
+    ScTabViewShell* getViewShell();
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/uitest/uiobject.cxx b/sc/source/ui/uitest/uiobject.cxx
index 84808c4..4405fd9 100644
--- a/sc/source/ui/uitest/uiobject.cxx
+++ b/sc/source/ui/uitest/uiobject.cxx
@@ -74,6 +74,14 @@ ScDrawView* ScGridWinUIObject::getDrawView()
     return pDrawView;
 }
 
+ScTabViewShell* ScGridWinUIObject::getViewShell()
+{
+    ScViewData* pViewData = mxGridWindow->getViewData();
+    ScTabViewShell* pViewShell = pViewData->GetViewShell();
+
+    return pViewShell;
+}
+
 void ScGridWinUIObject::execute(const OUString& rAction,
         const StringMap& rParameters)
 {
@@ -125,6 +133,28 @@ void ScGridWinUIObject::execute(const OUString& rAction,
             SAL_WARN("sc.uitest", "unknown selection method");
         }
     }
+    else if (rAction == "ACTIVATE")
+    {
+        ScDrawView* pDrawView = getDrawView();
+        const SdrMarkList& rMarkList = pDrawView->GetMarkedObjectList();
+        if (rMarkList.GetMarkCount() == 1)
+        {
+            SdrMark* pMark = rMarkList.GetMark(0);
+            SdrObject* pObj = pMark->GetMarkedSdrObj();
+            sal_uInt16 nSdrObjKind = pObj->GetObjIdentifier();
+            if (nSdrObjKind == OBJ_OLE2)
+            {
+                ScTabViewShell* pViewShell = getViewShell();
+                pViewShell->ActivateObject( static_cast<SdrOle2Obj*>(pObj), 0 );
+            }
+            else
+            {
+                SAL_WARN("sc.uitest", "can't activate non-ole objects");
+            }
+        }
+        else
+            SAL_WARN("sc.uitest", "can't activate the current selection");
+    }
     else
     {
         WindowUIObject::execute(rAction, rParameters);
commit ea54347fbe8bf89fb2d89ffe282853c4140e25cc
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu May 19 19:30:19 2016 +0200

    uitest: allow to select charts in calc
    
    Change-Id: I7fd899d7abda968e9c849e46714208a650b3cfdb

diff --git a/sc/source/ui/inc/uiobject.hxx b/sc/source/ui/inc/uiobject.hxx
index 91d21a4..85dee59 100644
--- a/sc/source/ui/inc/uiobject.hxx
+++ b/sc/source/ui/inc/uiobject.hxx
@@ -11,6 +11,7 @@
 
 class ScGridWindow;
 class ScDBFunc;
+class ScDrawView;
 
 class ScGridWinUIObject : public WindowUIObject
 {
@@ -38,6 +39,7 @@ protected:
 private:
 
     ScDBFunc* getDBFunc();
+    ScDrawView* getDrawView();
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/uitest/uiobject.cxx b/sc/source/ui/uitest/uiobject.cxx
index 550aeef..84808c4 100644
--- a/sc/source/ui/uitest/uiobject.cxx
+++ b/sc/source/ui/uitest/uiobject.cxx
@@ -14,6 +14,7 @@
 
 #include "viewdata.hxx"
 #include "dbfunc.hxx"
+#include "tabvwsh.hxx"
 
 #include <svx/svditer.hxx>
 #include <svx/svdobj.hxx>
@@ -65,6 +66,14 @@ ScDBFunc* ScGridWinUIObject::getDBFunc()
     return pFunc;
 }
 
+ScDrawView* ScGridWinUIObject::getDrawView()
+{
+    ScViewData* pViewData = mxGridWindow->getViewData();
+    ScDrawView* pDrawView = pViewData->GetScDrawView();
+
+    return pDrawView;
+}
+
 void ScGridWinUIObject::execute(const OUString& rAction,
         const StringMap& rParameters)
 {
@@ -103,6 +112,14 @@ void ScGridWinUIObject::execute(const OUString& rAction,
             sal_Int32 nTab = rStr.toUInt32();
             mxGridWindow->getViewData()->SetTabNo(nTab);
         }
+        else if (rParameters.find("OBJECT") != rParameters.end())
+        {
+            auto itr = rParameters.find("OBJECT");
+            const OUString rStr = itr->second;
+
+            ScDrawView* pDrawView = getDrawView();
+            pDrawView->SelectObject(rStr);
+        }
         else
         {
             SAL_WARN("sc.uitest", "unknown selection method");
commit 3b31057a4d1046b95340a254b2f667c9d89226f8
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu May 19 19:28:58 2016 +0200

    uitest: provide charts as children of calc's grid window

diff --git a/sc/source/ui/inc/uiobject.hxx b/sc/source/ui/inc/uiobject.hxx
index df14daf..91d21a4 100644
--- a/sc/source/ui/inc/uiobject.hxx
+++ b/sc/source/ui/inc/uiobject.hxx
@@ -29,6 +29,8 @@ public:
 
     static std::unique_ptr<UIObject> create(vcl::Window* pWindow);
 
+    virtual std::set<OUString> get_children() const override;
+
 protected:
 
     virtual OUString get_name() const override;
diff --git a/sc/source/ui/uitest/uiobject.cxx b/sc/source/ui/uitest/uiobject.cxx
index d257b41..550aeef 100644
--- a/sc/source/ui/uitest/uiobject.cxx
+++ b/sc/source/ui/uitest/uiobject.cxx
@@ -15,6 +15,11 @@
 #include "viewdata.hxx"
 #include "dbfunc.hxx"
 
+#include <svx/svditer.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdoole2.hxx>
+
 namespace {
 
 ScAddress get_address_from_string(const OUString& rStr)
@@ -109,6 +114,54 @@ void ScGridWinUIObject::execute(const OUString& rAction,
     }
 }
 
+namespace {
+
+ScDrawLayer* get_draw_layer(VclPtr<ScGridWindow> xGridWindow)
+{
+    return xGridWindow->getViewData()->GetDocument()->GetDrawLayer();
+}
+
+SdrPage* get_draw_page(VclPtr<ScGridWindow> xGridWindow, SCTAB nTab)
+{
+    ScDrawLayer* pDrawLayer = get_draw_layer(xGridWindow);
+
+    return pDrawLayer->GetPage(nTab);
+}
+
+std::set<OUString> collect_charts(VclPtr<ScGridWindow> xGridWindow)
+{
+    SCTAB nTab = xGridWindow->getViewData()->GetTabNo();
+    SdrPage* pPage = get_draw_page(xGridWindow, nTab);
+
+    std::set<OUString> aRet;
+
+    if (!pPage)
+        return aRet;
+
+    SdrObjListIter aIter( *pPage, IM_FLAT );
+    SdrObject* pObject = aIter.Next();
+    while (pObject)
+    {
+        if (pObject->GetObjIdentifier() == OBJ_OLE2)
+        {
+            aRet.insert(static_cast<SdrOle2Obj*>(pObject)->GetPersistName());
+        }
+        else
+            SAL_DEBUG(pObject->GetName());
+        pObject = aIter.Next();
+    }
+
+    return aRet;
+}
+
+}
+
+std::set<OUString> ScGridWinUIObject::get_children() const
+{
+    std::set<OUString> aChildren = collect_charts(mxGridWindow);
+    return aChildren;
+}
+
 std::unique_ptr<UIObject> ScGridWinUIObject::get_child(const OUString& /*rID*/)
 {
     return nullptr;
commit a3c911cee88a3e99c50b88d4e7c133416804495c
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu May 19 03:36:42 2016 +0200

    uitest: add demo for chart wizard
    
    Change-Id: I36b89e167408c2ab8b2a0f7d275ecb2dda4722b7

diff --git a/uitest/calc_tests/create_chart.py b/uitest/calc_tests/create_chart.py
new file mode 100644
index 0000000..7bb331c
--- /dev/null
+++ b/uitest/calc_tests/create_chart.py
@@ -0,0 +1,127 @@
+# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+from uitest_helper import UITest
+
+from helper import mkPropertyValues
+
+import time
+
+try:
+    import pyuno
+    import uno
+    import unohelper
+except ImportError:
+    print("pyuno not found: try to set PYTHONPATH and URE_BOOTSTRAP variables")
+    print("PYTHONPATH=/installation/opt/program")
+    print("URE_BOOTSTRAP=file:///installation/opt/program/fundamentalrc")
+    raise
+
+def add_content_to_cell(gridwin, cell, content):
+    selectProps = mkPropertyValues({"CELL": cell})
+    gridwin.executeAction("SELECT", selectProps)
+
+    contentProps = mkPropertyValues({"TEXT": content})
+    gridwin.executeAction("TYPE", contentProps)
+
+
+def fill_spreadsheet(xUITest):
+    xCalcDoc = xUITest.getTopFocusWindow()
+    xGridWindow = xCalcDoc.getChild("grid_window")
+
+    add_content_to_cell(xGridWindow, "A1", "col1")
+    add_content_to_cell(xGridWindow, "B1", "col2")
+    add_content_to_cell(xGridWindow, "C1", "col3")
+    add_content_to_cell(xGridWindow, "A2", "1")
+    add_content_to_cell(xGridWindow, "B2", "3")
+    add_content_to_cell(xGridWindow, "C2", "5")
+
+    xGridWindow.executeAction("SELECT", mkPropertyValues({"RANGE": "A1:C2"}))
+
+def cancel_immediately(xContext):
+    xUITest = xContext.ServiceManager.createInstanceWithContext(
+            "org.libreoffice.uitest.UITest", xContext)
+
+    ui_test = UITest(xUITest, xContext)
+
+    ui_test.create_doc_in_start_center("calc")
+
+    fill_spreadsheet(xUITest)
+
+    ui_test.execute_dialog_through_command(".uno:InsertObjectChart")
+
+    xChartDlg = xUITest.getTopFocusWindow()
+
+    xCancelBtn = xChartDlg.getChild("cancel")
+    xCancelBtn.executeAction("CLICK", tuple())
+
+    ui_test.close_doc()
+
+def create_from_first_page(xContext):
+    xUITest = xContext.ServiceManager.createInstanceWithContext(
+            "org.libreoffice.uitest.UITest", xContext)
+
+    ui_test = UITest(xUITest, xContext)
+
+    ui_test.create_doc_in_start_center("calc")
+
+    fill_spreadsheet(xUITest)
+
+    ui_test.execute_dialog_through_command(".uno:InsertObjectChart")
+
+    xChartDlg = xUITest.getTopFocusWindow()
+    print(xChartDlg.getChildren())
+    time.sleep(2)
+
+    xOkBtn = xChartDlg.getChild("finish")
+    xOkBtn.executeAction("CLICK", tuple())
+
+    time.sleep(2)
+
+    ui_test.close_doc()
+
+def create_from_second_page(xContext):
+    xUITest = xContext.ServiceManager.createInstanceWithContext(
+            "org.libreoffice.uitest.UITest", xContext)
+
+    ui_test = UITest(xUITest, xContext)
+
+    ui_test.create_doc_in_start_center("calc")
+
+    fill_spreadsheet(xUITest)
+
+    ui_test.execute_dialog_through_command(".uno:InsertObjectChart")
+
+    xChartDlg = xUITest.getTopFocusWindow()
+    print(xChartDlg.getChildren())
+    time.sleep(2)
+
+    xNextBtn = xChartDlg.getChild("next")
+    xNextBtn.executeAction("CLICK", tuple())
+
+    print(xChartDlg.getChildren())
+
+    time.sleep(2)
+
+    xDataInRows = xChartDlg.getChild("RB_DATAROWS")
+    xDataInRows.executeAction("CLICK", tuple())
+
+    time.sleep(2)
+
+    xDataInCols = xChartDlg.getChild("RB_DATACOLS")
+    xDataInCols.executeAction("CLICK", tuple())
+
+    time.sleep(2)
+
+    xCancelBtn = xChartDlg.getChild("finish")
+    xCancelBtn.executeAction("CLICK", tuple())
+
+    time.sleep(5)
+
+    ui_test.close_doc()
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit d9b4b717f365b70801b5f694fdc194b664a07777
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu May 19 03:36:18 2016 +0200

    uitest: add wrapper for radio button
    
    Change-Id: I8b4b35ac313796364502f8e9e2e836dc21f48a42

diff --git a/include/vcl/button.hxx b/include/vcl/button.hxx
index e9c8df9..0fb7c98 100644
--- a/include/vcl/button.hxx
+++ b/include/vcl/button.hxx
@@ -388,6 +388,8 @@ public:
      */
     void group(RadioButton &rOther);
     virtual void ShowFocus(const Rectangle& rRect) override;
+
+    virtual FactoryFunction GetUITestFactory() const override;
 };
 
 class VCL_DLLPUBLIC CheckBox : public Button
diff --git a/include/vcl/uitest/uiobject.hxx b/include/vcl/uitest/uiobject.hxx
index f00d80f..0baddeb 100644
--- a/include/vcl/uitest/uiobject.hxx
+++ b/include/vcl/uitest/uiobject.hxx
@@ -199,6 +199,27 @@ protected:
     virtual OUString get_name() const override;
 };
 
+class UITEST_DLLPUBLIC RadioButtonUIObject : public WindowUIObject
+{
+private:
+    VclPtr<RadioButton> mxRadioButton;
+
+public:
+    RadioButtonUIObject(VclPtr<RadioButton> xCheckbox);
+    virtual ~RadioButtonUIObject();
+
+    virtual void execute(const OUString& rAction,
+            const StringMap& rParameters) override;
+
+    virtual StringMap get_state() override;
+
+    static std::unique_ptr<UIObject> create(vcl::Window* pWindow);
+
+protected:
+
+    virtual OUString get_name() const override;
+};
+
 class UITEST_DLLPUBLIC TabPageUIObject : public WindowUIObject
 {
 private:
diff --git a/vcl/source/control/button.cxx b/vcl/source/control/button.cxx
index d366be4..dfec6b9 100644
--- a/vcl/source/control/button.cxx
+++ b/vcl/source/control/button.cxx
@@ -2949,6 +2949,11 @@ void RadioButton::ShowFocus(const Rectangle& rRect)
     Button::ShowFocus(rRect);
 }
 
+FactoryFunction RadioButton::GetUITestFactory() const
+{
+    return RadioButtonUIObject::create;
+}
+
 void CheckBox::ImplInitCheckBoxData()
 {
     meState         = TRISTATE_FALSE;
diff --git a/vcl/source/uitest/uiobject.cxx b/vcl/source/uitest/uiobject.cxx
index 6b4c471..b7b39ea 100644
--- a/vcl/source/uitest/uiobject.cxx
+++ b/vcl/source/uitest/uiobject.cxx
@@ -581,6 +581,44 @@ std::unique_ptr<UIObject> CheckBoxUIObject::create(vcl::Window* pWindow)
     return std::unique_ptr<UIObject>(new CheckBoxUIObject(pCheckBox));
 }
 
+RadioButtonUIObject::RadioButtonUIObject(VclPtr<RadioButton> xRadioButton):
+    WindowUIObject(xRadioButton),
+    mxRadioButton(xRadioButton)
+{
+}
+
+RadioButtonUIObject::~RadioButtonUIObject()
+{
+}
+
+void RadioButtonUIObject::execute(const OUString& rAction,
+        const StringMap& /*rParameters*/)
+{
+    if (rAction == "CLICK")
+    {
+        mxRadioButton->ImplCallClick();
+    }
+}
+
+StringMap RadioButtonUIObject::get_state()
+{
+    StringMap aMap = WindowUIObject::get_state();
+
+    return aMap;
+}
+
+OUString RadioButtonUIObject::get_name() const
+{
+    return OUString("RadioButtonUIObject");
+}
+
+std::unique_ptr<UIObject> RadioButtonUIObject::create(vcl::Window* pWindow)
+{
+    RadioButton* pRadioButton = dynamic_cast<RadioButton*>(pWindow);
+    assert(pRadioButton);
+    return std::unique_ptr<UIObject>(new RadioButtonUIObject(pRadioButton));
+}
+
 TabPageUIObject::TabPageUIObject(VclPtr<TabPage> xTabPage):
     WindowUIObject(xTabPage),
     mxTabPage(xTabPage)
commit b354b48fdb2540825ffffb6d63d3120cc16f7c17
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu May 19 03:35:08 2016 +0200

    uitest: allow to disable tests
    
    Change-Id: I67afd5d537e8dd80549c1bf6de51fc92b127f836

diff --git a/uitest/main.py b/uitest/main.py
index 9cda053..9039320 100644
--- a/uitest/main.py
+++ b/uitest/main.py
@@ -13,6 +13,9 @@ import importlib
 from connection import PersistentConnection, OfficeConnection
 
 def load_test(name):
+    if name.startswith("#"):
+        return None
+
     module_name, obj_name = name.rsplit(".", 1)
     module = importlib.import_module(module_name)
     obj = getattr(module, obj_name)
@@ -20,10 +23,13 @@ def load_test(name):
 
 def generic_test(opts, test_name):
     print("executing: " + test_name)
+    func = load_test(test_name)
+    if func is None:
+        return
+
     connection = PersistentConnection(opts)
     connection.setUp()
     xContext = connection.getContext()
-    func = load_test(test_name)
     func(xContext)
     connection.tearDown()
 
commit 9539508a5311b013f72e3368addd632c97506c52
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu May 19 02:20:31 2016 +0200

    uitest: add missing override
    
    Change-Id: I5f3941550bd9256125d74f25e9e512b302e1e27d

diff --git a/include/vcl/button.hxx b/include/vcl/button.hxx
index 472949d..e9c8df9 100644
--- a/include/vcl/button.hxx
+++ b/include/vcl/button.hxx
@@ -96,7 +96,7 @@ public:
     /// Sets the button state according to the FeatureStateEvent emitted by an Uno state change.
     virtual void        statusChanged(const css::frame::FeatureStateEvent& rEvent);
 
-    virtual FactoryFunction GetUITestFactory() const;
+    virtual FactoryFunction GetUITestFactory() const override;
 
 protected:
 
commit 93fb230b461e70c20db4d8675605ed817c62d92a
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu May 19 02:19:33 2016 +0200

    uitest: set ids for a few UI objects created in code
    
    Change-Id: I421b97448bb596b134908ca6ddd60d7b4f60b186

diff --git a/sfx2/source/dialog/tabdlg.cxx b/sfx2/source/dialog/tabdlg.cxx
index 4b33e31..84dcd1c 100644
--- a/sfx2/source/dialog/tabdlg.cxx
+++ b/sfx2/source/dialog/tabdlg.cxx
@@ -440,14 +440,20 @@ void SfxTabDialog::Init_Impl(bool bFmtFlag)
     m_pResetBtn = m_pUIBuilder->get<PushButton>("reset");
     m_bOwnsResetBtn = m_pResetBtn == nullptr;
     if (m_bOwnsResetBtn)
+    {
         m_pResetBtn = VclPtr<PushButton>::Create(m_pActionArea.get());
+        m_pResetBtn->set_id("reset");
+    }
     else
         m_pImpl->bHideResetBtn = !m_pResetBtn->IsVisible();
 
     m_pBaseFmtBtn = m_pUIBuilder->get<PushButton>("standard");
     m_bOwnsBaseFmtBtn = m_pBaseFmtBtn == nullptr;
     if (m_bOwnsBaseFmtBtn)
+    {
         m_pBaseFmtBtn = VclPtr<PushButton>::Create(m_pActionArea.get());
+        m_pBaseFmtBtn->set_id("standard");
+    }
 
     m_pOKBtn->SetClickHdl( LINK( this, SfxTabDialog, OkHdl ) );
     m_pCancelBtn->SetClickHdl( LINK( this, SfxTabDialog, CancelHdl ) );
diff --git a/svtools/source/dialogs/wizardmachine.cxx b/svtools/source/dialogs/wizardmachine.cxx
index f7066e0..b83ca08 100644
--- a/svtools/source/dialogs/wizardmachine.cxx
+++ b/svtools/source/dialogs/wizardmachine.cxx
@@ -143,6 +143,7 @@ namespace svt
             m_pPrevPage->SetSizePixel( LogicToPixel( Size( 50, 14 ), MAP_APPFONT ) );
             m_pPrevPage->SetText(SVT_RESSTR(STR_WIZDLG_PREVIOUS));
             m_pPrevPage->Show();
+            m_pPrevPage->set_id("previous");
 
             if (_nButtonFlags & WizardButtonFlags::NEXT)
                 AddButton( m_pPrevPage, ( WIZARDDIALOG_BUTTON_SMALLSTDOFFSET_X) );      // half x-offset to the next button
@@ -160,6 +161,7 @@ namespace svt
             m_pNextPage->SetSizePixel( LogicToPixel( Size( 50, 14 ), MAP_APPFONT ) );
             m_pNextPage->SetText(OUString(SVT_RESSTR(STR_WIZDLG_NEXT)));
             m_pNextPage->Show();
+            m_pNextPage->set_id("next");
 
             AddButton( m_pNextPage, WIZARDDIALOG_BUTTON_STDOFFSET_X );
             SetNextButton( m_pNextPage );
@@ -173,6 +175,7 @@ namespace svt
             m_pFinish->SetSizePixel( LogicToPixel( Size( 50, 14 ), MAP_APPFONT ) );
             m_pFinish->SetText(SVT_RESSTR(STR_WIZDLG_FINISH));
             m_pFinish->Show();
+            m_pFinish->set_id("finish");
 
             AddButton( m_pFinish, WIZARDDIALOG_BUTTON_STDOFFSET_X );
             m_pFinish->SetClickHdl( LINK( this, OWizardMachine, OnFinish ) );
diff --git a/vcl/source/control/button.cxx b/vcl/source/control/button.cxx
index 73155de..d366be4 100644
--- a/vcl/source/control/button.cxx
+++ b/vcl/source/control/button.cxx
@@ -1703,6 +1703,7 @@ void PushButton::ShowFocus(const Rectangle& rRect)
 
 void OKButton::ImplInit( vcl::Window* pParent, WinBits nStyle )
 {
+    set_id("ok");
     PushButton::ImplInit( pParent, nStyle );
 
     SetText( Button::GetStandardText( StandardButtonType::OK ) );
@@ -1748,6 +1749,7 @@ void OKButton::Click()
 
 void CancelButton::ImplInit( vcl::Window* pParent, WinBits nStyle )
 {
+    set_id("cancel");
     PushButton::ImplInit( pParent, nStyle );
 
     SetText( Button::GetStandardText( StandardButtonType::Cancel ) );
@@ -1799,6 +1801,7 @@ CloseButton::CloseButton( vcl::Window* pParent, WinBits nStyle )
 
 void HelpButton::ImplInit( vcl::Window* pParent, WinBits nStyle )
 {
+    set_id("help");
     PushButton::ImplInit( pParent, nStyle | WB_NOPOINTERFOCUS );
 
     SetText( Button::GetStandardText( StandardButtonType::Help ) );
commit 4b88b7ad5400a62c1c4112beb639c2f3a44b72bf
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 13 04:07:00 2016 +0200

    Wall is a good idea for the vim ide integration
    
    Change-Id: Ifb3c602335097ec1e837b60c236683382cfde3e1

diff --git a/bin/gbuild-to-ide b/bin/gbuild-to-ide
index 169cd16..fb2e888 100755
--- a/bin/gbuild-to-ide
+++ b/bin/gbuild-to-ide
@@ -441,7 +441,7 @@ class VimIntegrationGenerator(IdeIntegrationGenerator):
         json.dump(global_list, export_file)
 
     def generateCommand(self, lib, file):
-        command = 'clang++ '
+        command = 'clang++ -Wall'
         for key, value in lib.defs.items():
             command += ' -D'
             command += key
commit fd69d1e67a447efec6a595a4873a27d5bbfc7e37
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed May 11 01:44:17 2016 +0200

    uitest: now we can actually enable the ui test demo
    
    Change-Id: I18557ea0a7801ba118fd2486338112d8aa917b75

diff --git a/uitest/Module_uitest.mk b/uitest/Module_uitest.mk
index 4dbf020..9ebc2f7 100644
--- a/uitest/Module_uitest.mk
+++ b/uitest/Module_uitest.mk
@@ -12,4 +12,5 @@ $(eval $(call gb_Module_Module,uitest))
 
 $(eval $(call gb_Module_add_uicheck_targets,uitest,\
     UITest_calc_demo \
+    UITest_demo_ui \
 ))
commit d28cc34fcdf812350bad30d645bc29dffa63c1dd
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed May 11 01:44:00 2016 +0200

    uitest: close all the documents in the tests
    
    Change-Id: I4ad9c2603edbf3ac6fc4db60481dc93c16ea63ff

diff --git a/uitest/demo_ui/checkbox.py b/uitest/demo_ui/checkbox.py
index 8a8bf08..5cc456b 100644
--- a/uitest/demo_ui/checkbox.py
+++ b/uitest/demo_ui/checkbox.py
@@ -34,6 +34,9 @@ def toggle_checkbox(xContext):
     xNegativeNumRedCB = xCellsDlg.getChild("negnumred")
     xNegativeNumRedCB.executeAction("CLICK",tuple())
 
+    okBtn = xCellsDlg.getChild("ok")
+    okBtn.executeAction("CLICK", tuple())
+
     ui_test.close_doc()
 
 # vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/uitest/demo_ui/combobox.py b/uitest/demo_ui/combobox.py
index ba917bb..6df980b 100644
--- a/uitest/demo_ui/combobox.py
+++ b/uitest/demo_ui/combobox.py
@@ -25,6 +25,9 @@ def select_entry_pos(xContext):
     actionProps = mkPropertyValues(props)
     scopeCB.executeAction("SELECT", actionProps)
 
+    xCancelBtn = xAddNameDlg.getChild("cancel")
+    xCancelBtn.executeAction("CLICK", tuple())
+
     ui_test.close_doc()
 
 # vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/uitest/demo_ui/edit.py b/uitest/demo_ui/edit.py
index 2b44f20..f418a36 100644
--- a/uitest/demo_ui/edit.py
+++ b/uitest/demo_ui/edit.py
@@ -39,8 +39,6 @@ def type_text(xContext):
     xAddBtn = xAddNameDlg.getChild("cancel")
     xAddBtn.executeAction("CLICK", tuple())
 
-    xUITest.executeCommand(".uno:CloseDoc")
-    
     ui_test.close_doc()
 
 # vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/uitest/demo_ui/listbox.py b/uitest/demo_ui/listbox.py
index 21b19d4..03a4c9e 100644
--- a/uitest/demo_ui/listbox.py
+++ b/uitest/demo_ui/listbox.py
@@ -25,6 +25,9 @@ def select_entry_pos(xContext):
     actionProps = mkPropertyValues(props)
     categoryLB.executeAction("SELECT", actionProps)
 
+    xOkBtn = xCellsDlg.getChild("ok")
+    xOkBtn.executeAction("CLICK", tuple())
+
     ui_test.close_doc()
 
 def select_entry_text(xContext):
@@ -44,6 +47,9 @@ def select_entry_text(xContext):
     actionProps = mkPropertyValues(props)
     categoryLB.executeAction("SELECT", actionProps)
 
+    xOkBtn = xCellsDlg.getChild("ok")
+    xOkBtn.executeAction("CLICK", tuple())
+
     ui_test.close_doc()
 
 # vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/uitest/demo_ui/tabdialog.py b/uitest/demo_ui/tabdialog.py
index 9a6f720..09bf600 100644
--- a/uitest/demo_ui/tabdialog.py
+++ b/uitest/demo_ui/tabdialog.py
@@ -26,6 +26,9 @@ def select_tab_page_pos(xContext):
     propsUNO = mkPropertyValues(props)
     xCellsDlg.executeAction("SELECT", propsUNO)
 
+    xOkBtn = xCellsDlg.getChild("ok")
+    xOkBtn.executeAction("CLICK", tuple())
+
     ui_test.close_doc()
 
 def select_tab_page_name(xContext):
@@ -43,6 +46,9 @@ def select_tab_page_name(xContext):
     propsUNO = mkPropertyValues(props)
     xCellsDlg.executeAction("SELECT", propsUNO)
 
+    xOkBtn = xCellsDlg.getChild("ok")
+    xOkBtn.executeAction("CLICK", tuple())
+
     ui_test.close_doc()
 
 # vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 4cdc922aa71b047d61e1fab82006065d72ec045b
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed May 11 01:42:39 2016 +0200

    uitest: add method to get all children of a ui object
    
    This makes writing ui tests so much easier.
    
    Change-Id: Ice7d98c354fc9b68ee4532bc854561b5b9446e3f

diff --git a/include/vcl/uitest/uiobject.hxx b/include/vcl/uitest/uiobject.hxx
index b9a3f48..f00d80f 100644
--- a/include/vcl/uitest/uiobject.hxx
+++ b/include/vcl/uitest/uiobject.hxx
@@ -22,6 +22,8 @@
 
 #include <vcl/dllapi.h>
 
+#include <set>
+
 typedef std::map<const OUString, OUString> StringMap;
 
 /**
@@ -63,6 +65,11 @@ public:
     virtual std::unique_ptr<UIObject> get_child(const OUString& rID);
 
     /**
+     * Returns a set containing all decendants of the object.
+     */
+    virtual std::set<OUString> get_children() const;
+
+    /**
      * Currently an internal method to dump the state of the current UIObject as represented by get_state().
      *
      * This method should not be exposed to the outside world.
@@ -96,6 +103,8 @@ public:
 
     virtual std::unique_ptr<UIObject> get_child(const OUString& rID) override;
 
+    virtual std::set<OUString> get_children() const override;
+
     virtual void dumpState() const override;
 
     virtual void dumpHierarchy() const override;
diff --git a/offapi/com/sun/star/ui/test/XUIObject.idl b/offapi/com/sun/star/ui/test/XUIObject.idl
index 9a0ca6b..9409490 100644
--- a/offapi/com/sun/star/ui/test/XUIObject.idl
+++ b/offapi/com/sun/star/ui/test/XUIObject.idl
@@ -23,6 +23,8 @@ interface XUIObject
     com::sun::star::beans::PropertyValues getState();
 
     string getType();
+
+    sequence<string> getChildren();
 };
 
 }; }; }; }; };
diff --git a/vcl/source/uitest/uiobject.cxx b/vcl/source/uitest/uiobject.cxx
index 2852415..6b4c471 100644
--- a/vcl/source/uitest/uiobject.cxx
+++ b/vcl/source/uitest/uiobject.cxx
@@ -56,6 +56,11 @@ std::unique_ptr<UIObject> UIObject::get_child(const OUString&)
     return std::unique_ptr<UIObject>();
 }
 
+std::set<OUString> UIObject::get_children() const
+{
+    return std::set<OUString>();
+}
+
 void UIObject::dumpState() const
 {
 }
@@ -311,6 +316,29 @@ vcl::Window* findChild(vcl::Window* pParent, const OUString& rID)
     return nullptr;
 }
 
+void addChildren(vcl::Window* pParent, std::set<OUString>& rChildren)
+{
+    if (!pParent)
+        return;
+
+    size_t nCount = pParent->GetChildCount();
+    for (size_t i = 0; i < nCount; ++i)
+    {
+        vcl::Window* pChild = pParent->GetChild(i);
+        if (pChild)
+        {
+            OUString aId = pChild->get_id();
+            if (!aId.isEmpty())
+            {
+                auto ret = rChildren.insert(aId);
+                SAL_WARN_IF(!ret.second, "vcl.uitest", "duplicate ids for ui elements. violates locally unique requirement");
+            }
+
+            addChildren(pChild, rChildren);
+        }
+    }
+}
+
 }
 
 std::unique_ptr<UIObject> WindowUIObject::get_child(const OUString& rID)
@@ -322,6 +350,15 @@ std::unique_ptr<UIObject> WindowUIObject::get_child(const OUString& rID)
     return aFunction(pWindow);
 }
 
+std::set<OUString> WindowUIObject::get_children() const
+{
+    vcl::Window* pDialogParent = get_dialog_parent(mxWindow.get());
+    std::set<OUString> aChildren;
+    aChildren.insert(pDialogParent->get_id());
+    addChildren(pDialogParent, aChildren);
+    return aChildren;
+}
+
 OUString WindowUIObject::get_name() const
 {
     return OUString("WindowUIObject");
diff --git a/vcl/source/uitest/uno/uiobject_uno.cxx b/vcl/source/uitest/uno/uiobject_uno.cxx
index 998a0d9..7c6ca83 100644
--- a/vcl/source/uitest/uno/uiobject_uno.cxx
+++ b/vcl/source/uitest/uno/uiobject_uno.cxx
@@ -10,6 +10,8 @@
 #include "uiobject_uno.hxx"
 #include <vcl/svapp.hxx>
 
+#include <set>
+
 UIObjectUnoObj::UIObjectUnoObj(std::unique_ptr<UIObject> pObj):
     UIObjectBase(m_aMutex),
     mpObj(std::move(pObj))
@@ -69,6 +71,24 @@ css::uno::Sequence<css::beans::PropertyValue> UIObjectUnoObj::getState()
     return aProps;
 }
 
+css::uno::Sequence<OUString> UIObjectUnoObj::getChildren()
+    throw (css::uno::RuntimeException, std::exception)
+{
+    if (!mpObj)
+        throw css::uno::RuntimeException();
+
+    std::set<OUString> aChildren = mpObj->get_children();
+
+    css::uno::Sequence<OUString> aRet(aChildren.size());
+    sal_Int32 i = 0;
+    for (auto itr = aChildren.begin(), itrEnd = aChildren.end(); itr != itrEnd; ++itr, ++i)
+    {
+        aRet[i] = *itr;
+    }
+
+    return aRet;
+}
+
 OUString SAL_CALL UIObjectUnoObj::getType()
     throw (css::uno::RuntimeException, std::exception)
 {
diff --git a/vcl/source/uitest/uno/uiobject_uno.hxx b/vcl/source/uitest/uno/uiobject_uno.hxx
index d3519bf..fe0669a 100644
--- a/vcl/source/uitest/uno/uiobject_uno.hxx
+++ b/vcl/source/uitest/uno/uiobject_uno.hxx
@@ -46,6 +46,9 @@ public:
     css::uno::Sequence<css::beans::PropertyValue> SAL_CALL getState()
         throw (css::uno::RuntimeException, std::exception) override;
 
+    css::uno::Sequence<OUString> SAL_CALL getChildren()
+        throw (css::uno::RuntimeException, std::exception) override;
+
     OUString SAL_CALL getType()
         throw (css::uno::RuntimeException, std::exception) override;
 
commit ea0ec429eddd84c5c1ce9d35f9dcb3f6bbdf0cf9
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Tue May 10 01:27:59 2016 +0200

    uitest: add the ui demo tests
    
    The makefile part needs to be added but the tests currently hang as I'm
    not closing the dialogs yet.
    
    Change-Id: I8f938fb9b46213e6b1c7295bde780f119053447e

diff --git a/uitest/demo_ui/demo_ui.txt b/uitest/demo_ui/demo_ui.txt
new file mode 100644
index 0000000..6db5b79
--- /dev/null
+++ b/uitest/demo_ui/demo_ui.txt
@@ -0,0 +1,10 @@
+demo_ui.checkbox.toggle_checkbox
+demo_ui.combobox.select_entry_pos
+demo_ui.edit.type_text
+demo_ui.gridwin.select_cell
+demo_ui.gridwin.select_range
+demo_ui.gridwin.extend_range
+demo_ui.listbox.select_entry_pos
+demo_ui.listbox.select_entry_text
+demo_ui.tabdialog.select_tab_page_pos
+demo_ui.tabdialog.select_tab_page_name
commit d351f751bf3d467ceb608783a78e2a68668a7c69
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Tue May 10 01:26:56 2016 +0200

    uitest: report when a dialog was not executed correctly
    
    Change-Id: Ibe603045b095e020e572bac986d766ac555b0e04

diff --git a/uitest/uitest_helper.py b/uitest/uitest_helper.py
index 5d5f158..cac4ea1 100644
--- a/uitest/uitest_helper.py
+++ b/uitest/uitest_helper.py
@@ -9,6 +9,13 @@ import time
 
 from helper import EventListener
 
+class DialogNotExecutedException(Exception):
+    def __init__(self, command):
+        self.command = command
+
+    def __str__(self):
+        return "Dialog not executed for: " + self.command
+
 class UITest(object):
 
     DEFAULT_SLEEP = 0.1
@@ -28,8 +35,7 @@ class UITest(object):
                 time_ += self.DEFAULT_SLEEP
                 time.sleep(self.DEFAULT_SLEEP)
 
-        # report a failure here
-        print("failure execute modal dialog")
+        raise DialogNotExecutedException(command)
 
     def execute_modeless_dialog_through_command(self, command):
         with EventListener(self._xContext, "ModelessDialogVisible") as event:
@@ -42,8 +48,7 @@ class UITest(object):
                 time_ += self.DEFAULT_SLEEP
                 time.sleep(self.DEFAULT_SLEEP)
 
-        # report a failure here
-        print("failure execute modeless dialog")
+        raise DialogNotExecutedException(command)
 
     def create_doc_in_start_center(self, app):
         xStartCenter = self._xUITest.getTopFocusWindow()
commit 5764c850c69a53fe92460deb3a51e618a80c4269
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Tue May 10 01:26:33 2016 +0200

    uitest: make it easier to debug which test is causing issues
    
    Change-Id: I10a777d15d99a1fea756160ec39093a2781119b1

diff --git a/uitest/main.py b/uitest/main.py
index 4ec8ad5..9cda053 100644
--- a/uitest/main.py
+++ b/uitest/main.py
@@ -19,6 +19,7 @@ def load_test(name):
     return obj
 
 def generic_test(opts, test_name):
+    print("executing: " + test_name)
     connection = PersistentConnection(opts)
     connection.setUp()
     xContext = connection.getContext()
commit b028346e2c385414fa4af8cc8c2a4126fc4273ce
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Tue May 10 00:56:09 2016 +0200

    uitest: add all calc demo tests
    
    Change-Id: I33417d49665f48cb20b1fb1dbe20a7a2cbbf5074

diff --git a/uitest/calc_tests/calc_demo.txt b/uitest/calc_tests/calc_demo.txt
index fd921da..6ff4e22 100644
--- a/uitest/calc_tests/calc_demo.txt
+++ b/uitest/calc_tests/calc_demo.txt
@@ -1 +1,5 @@
 calc_tests.create_range_name.create_range_name
+calc_tests.create_range_name.create_local_range_name
+calc_tests.function_wizard.open_function_wizard
+calc_tests.gridwindow.input
+calc_tests.about_test.test_about_dlg
commit 088165efe32ef5c526c1991976becd572acb7251
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Mon May 9 22:09:44 2016 +0200

    uitest: add README
    
    Change-Id: I9511da3100bda9cedd18f6a4e3765bc6f3fbcb78

diff --git a/uitest/README b/uitest/README
new file mode 100644
index 0000000..c941673
--- /dev/null
+++ b/uitest/README
@@ -0,0 +1 @@
+The code for the UI testing framework and the UI tests.
commit df09346453821ca59cf5eb248b222a0490fa8209
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Mon May 9 10:05:14 2016 +0200

    uitest: build system part for new uitests
    
    We now can call the uitests with make uitest.uickeck
    
    Change-Id: I20c73efd93c7987f3b841cd0e3e7842ee7a5dab9

diff --git a/Makefile.in b/Makefile.in
index 5e8b9de..23ccc95 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -7,7 +7,7 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
 
-gb_Top_MODULE_CHECK_TARGETS := slowcheck unitcheck subsequentcheck perfcheck
+gb_Top_MODULE_CHECK_TARGETS := slowcheck unitcheck subsequentcheck perfcheck uicheck
 
 .PHONY : all check-if-root bootstrap gbuild build build-non-l10n-only build-l10n-only check clean clean-build clean-host test-install distclean distro-pack-install docs download etags fetch findunusedcode get-submodules id install install-strip tags debugrun help showmodules translations packageinfo internal.clean $(gb_Top_MODULE_CHECK_TARGETS)
 
@@ -144,6 +144,7 @@ gbuild_TARGETS := AllLangHelp \
 	Rdb \
 	StaticLibrary \
 	UIConfig \
+	UITest \
 	UnoApi \
 	UnpackedTarball \
 	WinResTarget \
diff --git a/RepositoryModule_host.mk b/RepositoryModule_host.mk
index d2f1d84..5954a50 100644
--- a/RepositoryModule_host.mk
+++ b/RepositoryModule_host.mk
@@ -138,6 +138,7 @@ $(eval $(call gb_Module_add_moduledirs,libreoffice,\
 	ucb \
 	ucbhelper \
 	udkapi \
+	$(call gb_Helper_optional,PYUNO,uitest) \
 	UnoControls \
 	unodevtools \
 	unoil \
@@ -181,7 +182,7 @@ endef
 # otherwise cyclic dependencies ruin everything.
 # do not serialize on a partial build as that may fail due to missing deps.
 # the default goal is all (see Module.mk)
-ifeq (,$(filter-out all build check unitcheck slowcheck subsequentcheck,$(MAKECMDGOALS)))
+ifeq (,$(filter-out all build check unitcheck slowcheck subsequentcheck uicheck,$(MAKECMDGOALS)))
 $(eval $(call repositorymodule_serialize,\
 	scfilt \
 	$(call gb_Helper_optional,SCRIPTING,vbaobj) \
diff --git a/solenv/gbuild/Module.mk b/solenv/gbuild/Module.mk
index 468b80b..d4217ea 100644
--- a/solenv/gbuild/Module.mk
+++ b/solenv/gbuild/Module.mk
@@ -27,12 +27,14 @@
 #                                                          recursive Module/checks
 # Module/slowcheck            run all slow unit tests
 # Module/subsequentcheck      run system tests             all system tests
+# Module/uicheck	      run uitests	           all uitests
 #                                                          recursive Module/subsequentchecks
 # build (global)              build the product            top-level Module
 # unitcheck (global)          run unit tests               top-level Module/unitcheck
 # slowcheck (global)          run slow unit tests          top-level Module/slowcheck
 # subsequentcheck (global)    run system tests             top-level Module/subsequentcheck
 # perfcheck (global)          run performance unit tests   top-level Module/perfcheck
+# uicheck (global) 	      run the uitests 		   run all uitests
 # all (global)                default goal                 build unitcheck
 
 
@@ -47,6 +49,7 @@ gb_Module_SLOWCHECKTARGETSTACK :=
 gb_Module_SUBSEQUENTCHECKTARGETSTACK :=
 gb_Module_STAGINGCHECKTARGETSTACK :=
 gb_Module_PERFCHECKTARGETSTACK :=
+gb_Module_UICHECKTARGETSTACK :=
 gb_Module_CLEANTARGETSTACK :=
 
 # The currently read gbuild makefile.
@@ -68,7 +71,7 @@ $(call gb_Module_get_clean_target,%) :
 	$(call gb_Output_announce,$*,$(false),MOD,5)
 	$(call gb_Output_announce_title,module $* cleared.)
 	-$(call gb_Helper_abbreviate_dirs,\
-		rm -f $(call gb_Module_get_target,$*) $(call gb_Module_get_nonl10n_target,$*) $(call gb_Module_get_l10n_target,$*) $(call gb_Module_get_check_target,$*) $(call gb_Module_get_slowcheck_target,$*) $(call gb_Module_get_subsequentcheck_target,$*) $(call gb_Module_get_perfcheck_target,$*))
+		rm -f $(call gb_Module_get_target,$*) $(call gb_Module_get_nonl10n_target,$*) $(call gb_Module_get_l10n_target,$*) $(call gb_Module_get_check_target,$*) $(call gb_Module_get_slowcheck_target,$*) $(call gb_Module_get_subsequentcheck_target,$*) $(call gb_Module_get_perfcheck_target,$*) $(call gb_Module_get_uicheck,$*))
 
 $(call gb_Module_get_l10n_target,%) :
 	$(call gb_Output_announce,$*,$(true),LOC,5)
@@ -112,6 +115,13 @@ $(call gb_Module_get_perfcheck_target,%) :
 		mkdir -p $(dir $@) && \
 		touch $@)
 
+$(call gb_Module_get_uicheck_target,%) :
+	$(call gb_Output_announce,$*,$(true),UIT,5)
+	$(call gb_Output_announce_title,module $* uicheck done.)
+	-$(call gb_Helper_abbreviate_dirs,\
+		mkdir -p $(dir $@) && \
+		touch $@)
+
 $(call gb_Module_get_target,%) :
 	$(call gb_Output_announce,$*,$(true),MOD,5)
 	$(call gb_Output_announce_title,module $* done.)
@@ -119,7 +129,7 @@ $(call gb_Module_get_target,%) :
 		mkdir -p $(dir $@) && \
 		touch $@)
 
-.PHONY : all build build-l10n-only build-non-l10n-only unitcheck slowcheck subsequentcheck stagingcheck perfcheck clean check debugrun help showmodules translations
+.PHONY : all build build-l10n-only build-non-l10n-only unitcheck slowcheck subsequentcheck stagingcheck perfcheck uicheck clean check debugrun help showmodules translations
 .DEFAULT_GOAL := all
 
 all : build $(if $(CROSS_COMPILING),,unitcheck $(if $(gb_PARTIAL_BUILD),,slowcheck))
@@ -174,6 +184,11 @@ perfcheck :
 	$(call gb_Output_announce_title,all perftests checked.)
 	$(call gb_Output_announce_bell)
 
+uicheck : build
+	$(if $(gb_VERBOSE),$(call gb_Output_announce,loaded modules: $(sort $(gb_Module_ALLMODULES)),$(true),UIT,6))
+	$(call gb_Output_announce_title,all uicheck checked.)
+	$(call gb_Output_announce_bell)
+
 clean :
 	$(if $(gb_VERBOSE),$(call gb_Output_announce,top level modules: $(foreach module,$^,$(notdir $(module))),$(false),ALL,6))
 	$(call gb_Output_announce,loaded modules: $(sort $(gb_Module_ALLMODULES)),$(false),ALL,6)
@@ -217,6 +232,7 @@ gb_Module_TARGETSTACK := $(call gb_Module_get_target,$(1)) $(gb_Module_TARGETSTA
 gb_Module_L10NTARGETSTACK := $(call gb_Module_get_l10n_target,$(1)) $(gb_Module_L10NTARGETSTACK)
 gb_Module_CHECKTARGETSTACK := $(call gb_Module_get_check_target,$(1)) $(gb_Module_CHECKTARGETSTACK)
 gb_Module_SLOWCHECKTARGETSTACK := $(call gb_Module_get_slowcheck_target,$(1)) $(gb_Module_SLOWCHECKTARGETSTACK)
+gb_Module_UICHECKTARGETSTACK := $(call gb_Module_get_uicheck_target,$(1)) $(gb_Module_UICHECKTARGETSTACK)
 gb_Module_SUBSEQUENTCHECKTARGETSTACK := $(call gb_Module_get_subsequentcheck_target,$(1)) $(gb_Module_SUBSEQUENTCHECKTARGETSTACK)
 gb_Module_STAGINGCHECKTARGETSTACK := $(call gb_Module_get_stagingcheck_target,$(1)) $(gb_Module_STAGINGCHECKTARGETSTACK)
 gb_Module_PERFCHECKTARGETSTACK := $(call gb_Module_get_perfcheck_target,$(1)) $(gb_Module_PERFCHECKTARGETSTACK)
@@ -229,6 +245,7 @@ $(if $(filter-out libreoffice instsetoo_native android ios,$(1)),\
 
 $(call gb_Postprocess_get_target,AllModuleTests) : $(call gb_Module_get_check_target,$(1))
 $(call gb_Postprocess_get_target,AllModuleSlowtests) : $(call gb_Module_get_slowcheck_target,$(1))
+$(call gb_Postprocess_get_target,AllModuleUITest) : $(call gb_Module_get_uicheck_target,$(1))
 
 endef
 
@@ -324,6 +341,14 @@ $(call gb_Module_get_clean_target,$(1)) : $$(gb_Module_CURRENTCLEANTARGET)
 
 endef
 
+define gb_Module_add_uicheck_target
+$(call gb_Module__read_targetfile,$(1),$(2),uicheck target)
+
+$(call gb_Module_get_uicheck_target,$(1)) : $$(gb_Module_CURRENTTARGET)
+$(call gb_Module_get_clean_target,$(1)) : $$(gb_Module_CURRENTCLEANTARGET)
+
+endef
+
 define gb_Module_add_moduledir
 include $(patsubst $(1):%,%,$(filter $(1):%,$(gb_Module_MODULELOCATIONS)))/$(2)/Module_$(2).mk
 $(call gb_Module_get_target,$(1)) : $$(firstword $$(gb_Module_TARGETSTACK))
@@ -333,6 +358,7 @@ $(call gb_Module_get_slowcheck_target,$(1)) : $$(firstword $$(gb_Module_SLOWCHEC
 $(call gb_Module_get_subsequentcheck_target,$(1)) : $$(firstword $$(gb_Module_SUBSEQUENTCHECKTARGETSTACK))
 $(call gb_Module_get_stagingcheck_target,$(1)) : $$(firstword $$(gb_Module_STAGINGCHECKTARGETSTACK))
 $(call gb_Module_get_perfcheck_target,$(1)) : $$(firstword $$(gb_Module_PERFCHECKTARGETSTACK))
+$(call gb_Module_get_uicheck_target,$(1)) : $$(firstword $$(gb_Module_UICHECKTARGETSTACK))
 $(call gb_Module_get_clean_target,$(1)) : $$(firstword $$(gb_Module_CLEANTARGETSTACK))
 gb_Module_TARGETSTACK := $$(wordlist 2,$$(words $$(gb_Module_TARGETSTACK)),$$(gb_Module_TARGETSTACK))
 gb_Module_L10NTARGETSTACK := $$(wordlist 2,$$(words $$(gb_Module_L10NTARGETSTACK)),$$(gb_Module_L10NTARGETSTACK))
@@ -341,6 +367,7 @@ gb_Module_SLOWCHECKTARGETSTACK := $$(wordlist 2,$$(words $$(gb_Module_SLOWCHECKT
 gb_Module_SUBSEQUENTCHECKTARGETSTACK := $$(wordlist 2,$$(words $$(gb_Module_SUBSEQUENTCHECKTARGETSTACK)),$$(gb_Module_SUBSEQUENTCHECKTARGETSTACK))
 gb_Module_STAGINGCHECKTARGETSTACK := $$(wordlist 2,$$(words $$(gb_Module_STAGINGCHECKTARGETSTACK)),$$(gb_Module_STAGINGCHECKTARGETSTACK))
 gb_Module_PERFCHECKTARGETSTACK := $$(wordlist 2,$$(words $$(gb_Module_PERFCHECKTARGETSTACK)),$$(gb_Module_PERFCHECKTARGETSTACK))
+gb_Module_UICHECKTARGETSTACK := $$(wordlist 2,$$(words $$(gb_Module_UICHECKTARGETSTACK)),$$(gb_Module_UICHECKTARGETSTACK))
 gb_Module_CLEANTARGETSTACK := $$(wordlist 2,$$(words $$(gb_Module_CLEANTARGETSTACK)),$$(gb_Module_CLEANTARGETSTACK))
 
 endef
@@ -389,6 +416,11 @@ $(foreach target,$(sort $(2)),$(call gb_Module_add_moduledir,$(1),$(target)))
 
 endef
 
+define gb_Module_add_uicheck_targets
+$(foreach target,$(2),$(call gb_Module_add_uicheck_target,$(1),$(target)))
+
+endef
+
 define gb_Module_make_global_targets
 ifneq ($$(gb_Module_TARGETSTACK),)
 $$(eval $$(call gb_Output_error,Corrupted module target stack!1))
@@ -404,6 +436,7 @@ slowcheck : $$(firstword $$(gb_Module_SLOWCHECKTARGETSTACK))
 subsequentcheck : $$(firstword $$(gb_Module_SUBSEQUENTCHECKTARGETSTACK))
 stagingcheck : $$(firstword $$(gb_Module_STAGINGCHECKTARGETSTACK))
 perfcheck : $$(firstword $$(gb_Module_PERFCHECKTARGETSTACK))
+uicheck : $$(firstword $$(gb_Module_UICHECKTARGETSTACK))
 clean : $$(firstword $$(gb_Module_CLEANTARGETSTACK))
 
 ifneq ($$(words $$(gb_Module_TARGETSTACK)),1)
@@ -415,11 +448,12 @@ gb_Module_L10NTARGETSTACK := $$(wordlist 2,$$(words $$(gb_Module_L10NTARGETSTACK
 gb_Module_CHECKTARGETSTACK := $$(wordlist 2,$$(words $$(gb_Module_CHECKTARGETSTACK)),$$(gb_Module_CHECKTARGETSTACK))
 gb_Module_SLOWCHECKTARGETSTACK := $$(wordlist 2,$$(words $$(gb_Module_SLOWCHECKTARGETSTACK)),$$(gb_Module_SLOWCHECKTARGETSTACK))
 gb_Module_SUBSEQUENTCHECKTARGETSTACK := $$(wordlist 2,$$(words $$(gb_Module_SUBSEQUENTCHECKTARGETSTACK)),$$(gb_Module_SUBSEQUENTCHECKTARGETSTACK))
+gb_Module_UICHECKTARGETSTACK := $$(wordlist 2,$$(words $$(gb_Module_UICHECKTARGETSTACK)),$$(gb_Module_UICHECKTARGETSTACK))
 gb_Module_STAGINGCHECKTARGETSTACK := $$(wordlist 2,$$(words $$(gb_Module_STAGINGCHECKTARGETSTACK)),$$(gb_Module_STAGINGCHECKTARGETSTACK))
 gb_Module_PERFCHECKTARGETSTACK := $$(wordlist 2,$$(words $$(gb_Module_PERFCHECKTARGETSTACK)),$$(gb_Module_PERFCHECKTARGETSTACK))
 gb_Module_CLEANTARGETSTACK := $$(wordlist 2,$$(words $$(gb_Module_CLEANTARGETSTACK)),$$(gb_Module_CLEANTARGETSTACK))
 
-ifneq ($$(and $$(gb_Module_TARGETSTACK),$$(gb_Module_CHECKTARGETSTACK),$$(gb_Module_SLOWCHECKTARGETSTACK),$$(gb_Module_SUBSEQUENTCHECKTARGETSTACK),$$(gb_Module_STAGINGCHECKTARGETSTACK),$$(gb_Module_PERFCHECKTARGETSTACK),$$(gb_Module_L10NTARGETSTACK)),)
+ifneq ($$(and $$(gb_Module_TARGETSTACK),$$(gb_Module_CHECKTARGETSTACK),$$(gb_Module_SLOWCHECKTARGETSTACK),$$(gb_Module_SUBSEQUENTCHECKTARGETSTACK),$$(gb_Module_UICHECKTARGETSTACK),$$(gb_Module_STAGINGCHECKTARGETSTACK),$$(gb_Module_PERFCHECKTARGETSTACK),$$(gb_Module_L10NTARGETSTACK)),)
 $$(eval $$(call gb_Output_error,Corrupted module target stack!3))
 endif
 
diff --git a/solenv/gbuild/Postprocess.mk b/solenv/gbuild/Postprocess.mk
index 0676646..a256a21 100644
--- a/solenv/gbuild/Postprocess.mk
+++ b/solenv/gbuild/Postprocess.mk
@@ -47,6 +47,7 @@ $(call gb_Postprocess_Postprocess,AllResources,All resources,$(WORKDIR)/AllLangR
 $(call gb_Postprocess_Postprocess,AllUIConfigs,All UI configuration files,$(WORKDIR)/UIConfig/)
 $(call gb_Postprocess_Postprocess,AllModuleTests,All modules' tests,$(WORKDIR)/Module/check/)
 $(call gb_Postprocess_Postprocess,AllModuleSlowtests,All modules' slowtests,$(WORKDIR)/Module/slowcheck/)
+$(call gb_Postprocess_Postprocess,AllModuleUITests,All modules' uitests,$(WORKDIR)/Module/uicheck/)
 
 endef
 
diff --git a/solenv/gbuild/TargetLocations.mk b/solenv/gbuild/TargetLocations.mk
index 9c15d8e..34577ca 100644
--- a/solenv/gbuild/TargetLocations.mk
+++ b/solenv/gbuild/TargetLocations.mk
@@ -121,6 +121,7 @@ gb_Module_get_slowcheck_target = $(WORKDIR)/Module/slowcheck/$(1)
 gb_Module_get_subsequentcheck_target = $(WORKDIR)/Module/subsequentcheck/$(1)
 gb_Module_get_stagingcheck_target = $(WORKDIR)/Module/stagingcheck/$(1)
 gb_Module_get_perfcheck_target = $(WORKDIR)/Module/perfcheck/$(1)
+gb_Module_get_uicheck_target = $(WORKDIR)/Module/uicheck/$(1)
 gb_Module_get_target = $(WORKDIR)/Module/$(1)
 gb_ObjCxxObject_get_target = $(WORKDIR)/ObjCxxObject/$(1).o
 gb_ObjCObject_get_target = $(WORKDIR)/ObjCObject/$(1).o
@@ -160,6 +161,7 @@ gb_UIImageListTarget_get_target = $(WORKDIR)/UIImageListTarget/$(1).ilst
 gb_UILocalizeTarget_get_target = $(WORKDIR)/UILocalizeTarget/$(1).done
 gb_UILocalizeTarget_get_workdir = $(WORKDIR)/UILocalizeTarget/$(1)
 gb_UIMenubarTarget_get_target = $(WORKDIR)/UIMenubarTarget/$(1).xml
+gb_UITest_get_target = $(WORKDIR)/UITest/$(1)/done
 gb_UnoApiTarget_get_target = $(WORKDIR)/UnoApiTarget/$(1).rdb
 gb_UnoApiHeadersTarget_get_bootstrap_dir = $(WORKDIR)/UnoApiHeadersTarget/$(1)/$(call gb_UnoApiHeadersTarget_select_variant,$(1),bootstrap)
 gb_UnoApiHeadersTarget_get_comprehensive_dir = $(WORKDIR)/UnoApiHeadersTarget/$(1)/$(call gb_UnoApiHeadersTarget_select_variant,$(1),comprehensive)
@@ -284,6 +286,7 @@ $(eval $(call gb_Helper_make_clean_targets,\
 	UIImageListTarget \
 	UILocalizeTarget \
 	UIMenubarTarget \
+	UITest \
 	UnoApi \
 	UnoApiHeadersTarget \
 	UnoApiTarget \
diff --git a/solenv/gbuild/UITest.mk b/solenv/gbuild/UITest.mk
new file mode 100644
index 0000000..bbe76f6
--- /dev/null
+++ b/solenv/gbuild/UITest.mk
@@ -0,0 +1,114 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list