[Libreoffice-commits] core.git: include/vcl sd/inc sd/qa sd/source sd/uiconfig vcl/source vcl/unx

Caolán McNamara caolanm at redhat.com
Thu May 10 12:37:31 UTC 2018


 include/vcl/field.hxx                         |   26 +-
 include/vcl/vclenum.hxx                       |    5 
 include/vcl/weld.hxx                          |   83 ++++++++
 sd/inc/sdabstdlg.hxx                          |    2 
 sd/qa/unit/dialogs-test.cxx                   |    5 
 sd/source/ui/dlg/present.cxx                  |  262 +++++++++++---------------
 sd/source/ui/dlg/sddlgfact.cxx                |   14 -
 sd/source/ui/dlg/sddlgfact.hxx                |   11 -
 sd/source/ui/func/fusldlg.cxx                 |    2 
 sd/source/ui/inc/present.hxx                  |   78 +++----
 sd/uiconfig/simpress/ui/presentationdialog.ui |  156 ++++++++-------
 vcl/source/app/salvtables.cxx                 |   43 ++++
 vcl/source/control/field.cxx                  |   60 +++--
 vcl/source/control/field2.cxx                 |  242 +++++++++++++-----------
 vcl/source/window/builder.cxx                 |   78 +++++++
 vcl/unx/gtk3/gtk3gtkinst.cxx                  |   35 +++
 16 files changed, 686 insertions(+), 416 deletions(-)

New commits:
commit 476ed0aed1c09055fa05209485919a026e5f014e
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Sun May 6 15:21:33 2018 +0100

    weld SdStartPresentationDlg
    
    to get duration spinbutton working need to know where the cursor
    is in the spinbutton and to change the adjustment factor depending
    on that, and need to additionally disable the vcl round to nearest base unit on
    up/down
    
    Change-Id: I6dd09e1639454cb4820d3aeb0c0c698fcebd417e
    Reviewed-on: https://gerrit.libreoffice.org/54065
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/include/vcl/field.hxx b/include/vcl/field.hxx
index 3af20ff93558..8f4bf5b07219 100644
--- a/include/vcl/field.hxx
+++ b/include/vcl/field.hxx
@@ -40,7 +40,6 @@ class VCL_DLLPUBLIC FormatterBase
 {
 private:
     VclPtr<Edit>            mpField;
-    Link<Edit&, bool>       maOutputHdl;
     std::unique_ptr<LocaleDataWrapper>
                             mpLocaleDataWrapper;
     bool                    mbReformat;
@@ -85,8 +84,6 @@ public:
 
     void                    EnableEmptyFieldValue( bool bEnable )   { mbEmptyFieldValueEnabled = bEnable; }
     bool                    IsEmptyFieldValueEnabled() const        { return mbEmptyFieldValueEnabled; }
-
-    void                    SetOutputHdl(const Link<Edit&, bool>& rLink) { maOutputHdl = rLink; }
 };
 
 #define PATTERN_FORMAT_EMPTYLITERALS    (sal_uInt16(0x0001))
@@ -152,6 +149,7 @@ public:
     void                    SetShowTrailingZeros( bool bShowTrailingZeros );
     bool                    IsShowTrailingZeros() const { return mbShowTrailingZeros; }
 
+    void                    DisableRemainderFactor();
 
     void                    SetUserValue( sal_Int64 nNewValue );
     virtual void            SetValue( sal_Int64 nNewValue );
@@ -163,12 +161,16 @@ public:
     sal_Int64               Normalize( sal_Int64 nValue ) const;
     sal_Int64               Denormalize( sal_Int64 nValue ) const;
 
+    void  SetInputHdl(const Link<sal_Int64*,TriState>& rLink) { m_aInputHdl = rLink; }
+    void  SetOutputHdl(const Link<Edit&, bool>& rLink) { m_aOutputHdl = rLink; }
 protected:
     sal_Int64               mnFieldValue;
     sal_Int64               mnLastValue;
     sal_Int64               mnMin;
     sal_Int64               mnMax;
     bool                    mbWrapOnLimits;
+    bool                    mbFormatting;
+    bool                    mbDisableRemainderFactor;
 
     // the members below are used in all derivatives of NumericFormatter
     // not in NumericFormatter itself.
@@ -182,8 +184,9 @@ protected:
     void                    FieldDown();
     void                    FieldFirst();
     void                    FieldLast();
+    void                    FormatValue(Selection const * pNewSelection = nullptr);
 
-    SAL_DLLPRIVATE void     ImplNumericReformat( sal_Int64& rValue, OUString& rOutStr );
+    SAL_DLLPRIVATE void     ImplNumericReformat();
     SAL_DLLPRIVATE void     ImplNewFieldValue( sal_Int64 nNewValue );
     SAL_DLLPRIVATE void     ImplSetUserValue( sal_Int64 nNewValue, Selection const * pNewSelection = nullptr );
 
@@ -192,6 +195,8 @@ protected:
 private:
     SAL_DLLPRIVATE void     ImplInit();
 
+    Link<sal_Int64*, TriState> m_aInputHdl;
+    Link<Edit&, bool>       m_aOutputHdl;
     sal_uInt16              mnDecimalDigits;
     bool                    mbThousandSep;
     bool                    mbShowTrailingZeros;
@@ -358,12 +363,6 @@ public:
 
 class VCL_DLLPUBLIC TimeFormatter : public FormatterBase
 {
-public:
-                            enum class TimeFormat {
-                                Hour12,
-                                Hour24
-                            };
-
 private:
     tools::Time             maLastTime;
     tools::Time             maMin;
@@ -386,6 +385,13 @@ protected:
     SAL_DLLPRIVATE bool     ImplAllowMalformedInput() const;
 
 public:
+    static OUString         FormatTime(const tools::Time& rNewTime, TimeFieldFormat eFormat, TimeFormat eHourFormat, bool bDuration, const LocaleDataWrapper& rLocaleData);
+    static bool             TextToTime(const OUString& rStr, tools::Time& rTime, TimeFieldFormat eFormat, bool bDuration, const LocaleDataWrapper& rLocaleDataWrapper, bool _bSkipInvalidCharacters = true);
+    static int              GetTimeArea(TimeFieldFormat eFormat, const OUString& rText, int nCursor,
+                                        const LocaleDataWrapper& rLocaleDataWrapper);
+    static tools::Time      SpinTime(bool bUp, const tools::Time& rTime, TimeFieldFormat eFormat,
+                                     bool bDuration, const OUString& rText, int nCursor,
+                                     const LocaleDataWrapper& rLocaleDataWrapper);
 
     virtual                 ~TimeFormatter() override;
 
diff --git a/include/vcl/vclenum.hxx b/include/vcl/vclenum.hxx
index e31c7cc70e50..8697465af32d 100644
--- a/include/vcl/vclenum.hxx
+++ b/include/vcl/vclenum.hxx
@@ -118,6 +118,11 @@ namespace o3tl
     template<> struct typed_flags<WindowBorderStyle> : is_typed_flags<WindowBorderStyle, 0x3033> {};
 }
 
+enum class TimeFormat
+{
+    Hour12, Hour24
+};
+
 enum class ExtTimeFieldFormat
 {
     Short24H, Long24H
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 448a592fb15c..b7f53ab0e057 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -15,6 +15,7 @@
 #include <tools/link.hxx>
 #include <vcl/dllapi.h>
 #include <vcl/field.hxx>
+#include <vcl/vclenum.hxx>
 #include <vcl/virdev.hxx>
 
 #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
@@ -451,9 +452,10 @@ private:
 protected:
     Link<Entry&, void> m_aChangeHdl;
     Link<OUString&, bool> m_aInsertTextHdl;
+    Link<Entry&, void> m_aCursorPositionHdl;
 
     void signal_changed() { m_aChangeHdl.Call(*this); }
-
+    void signal_cursor_position() { m_aCursorPositionHdl.Call(*this); }
     void signal_insert_text(OUString& rString);
 
 public:
@@ -470,8 +472,11 @@ public:
     virtual void set_font(const vcl::Font& rFont) = 0;
 
     void connect_changed(const Link<Entry&, void>& rLink) { m_aChangeHdl = rLink; }
-
     void connect_insert_text(const Link<OUString&, bool>& rLink) { m_aInsertTextHdl = rLink; }
+    virtual void connect_cursor_position(const Link<Entry&, void>& rLink)
+    {
+        m_aCursorPositionHdl = rLink;
+    }
 
     void save_value() { m_sSavedValue = get_text(); }
 
@@ -483,6 +488,7 @@ class VCL_DLLPUBLIC SpinButton : virtual public Entry
 protected:
     Link<SpinButton&, void> m_aValueChangedHdl;
     Link<SpinButton&, void> m_aOutputHdl;
+    Link<int*, bool> m_aInputHdl;
 
     void signal_value_changed() { m_aValueChangedHdl.Call(*this); }
 
@@ -494,6 +500,13 @@ protected:
         return true;
     }
 
+    TriState signal_input(int* result)
+    {
+        if (!m_aInputHdl.IsSet())
+            return TRISTATE_INDET;
+        return m_aInputHdl.Call(result) ? TRISTATE_TRUE : TRISTATE_FALSE;
+    }
+
 public:
     virtual void set_value(int value) = 0;
     virtual int get_value() const = 0;
@@ -519,6 +532,7 @@ public:
     void connect_value_changed(const Link<SpinButton&, void>& rLink) { m_aValueChangedHdl = rLink; }
 
     void connect_output(const Link<SpinButton&, void>& rLink) { m_aOutputHdl = rLink; }
+    void connect_input(const Link<int*, bool>& rLink) { m_aInputHdl = rLink; }
 
     int normalize(int nValue) const { return (nValue * Power10(get_digits())); }
 
@@ -621,6 +635,8 @@ public:
         m_aValueChangedHdl = rLink;
     }
 
+    void connect_changed(const Link<Entry&, void>& rLink) { m_xSpinButton->connect_changed(rLink); }
+
     int normalize(int nValue) const { return m_xSpinButton->normalize(nValue); }
     int denormalize(int nValue) const { return m_xSpinButton->denormalize(nValue); }
     void set_sensitive(bool sensitive) { m_xSpinButton->set_sensitive(sensitive); }
@@ -653,9 +669,69 @@ public:
         m_xSpinButton->connect_focus_out(rLink);
     }
     void set_help_id(const OString& rName) { m_xSpinButton->set_help_id(rName); }
+    void set_position(int nCursorPos) { m_xSpinButton->set_position(nCursorPos); }
     const weld::SpinButton* get_widget() const { return m_xSpinButton.get(); }
 };
 
+class VCL_DLLPUBLIC TimeSpinButton
+{
+protected:
+    TimeFieldFormat m_eFormat;
+    std::unique_ptr<weld::SpinButton> m_xSpinButton;
+    Link<TimeSpinButton&, void> m_aValueChangedHdl;
+
+    DECL_LINK(spin_button_value_changed, weld::SpinButton&, void);
+    DECL_LINK(spin_button_output, weld::SpinButton&, void);
+    DECL_LINK(spin_button_input, int* result, bool);
+    DECL_LINK(spin_button_cursor_position, weld::Entry&, void);
+
+    void signal_value_changed() { m_aValueChangedHdl.Call(*this); }
+
+    tools::Time ConvertValue(int nValue) const;
+    int ConvertValue(const tools::Time& rTime) const;
+    OUString format_number(int nValue) const;
+    void update_width_chars();
+
+public:
+    TimeSpinButton(SpinButton* pSpinButton, TimeFieldFormat eFormat)
+        : m_eFormat(eFormat)
+        , m_xSpinButton(pSpinButton)
+    {
+        update_width_chars();
+        m_xSpinButton->connect_output(LINK(this, TimeSpinButton, spin_button_output));
+        m_xSpinButton->connect_input(LINK(this, TimeSpinButton, spin_button_input));
+        m_xSpinButton->connect_value_changed(LINK(this, TimeSpinButton, spin_button_value_changed));
+        m_xSpinButton->connect_cursor_position(
+            LINK(this, TimeSpinButton, spin_button_cursor_position));
+    }
+
+    void set_value(const tools::Time& rTime) { m_xSpinButton->set_value(ConvertValue(rTime)); }
+
+    tools::Time get_value() const { return ConvertValue(m_xSpinButton->get_value()); }
+
+    void connect_value_changed(const Link<TimeSpinButton&, void>& rLink)
+    {
+        m_aValueChangedHdl = rLink;
+    }
+
+    void connect_changed(const Link<Entry&, void>& rLink) { m_xSpinButton->connect_changed(rLink); }
+
+    void set_sensitive(bool sensitive) { m_xSpinButton->set_sensitive(sensitive); }
+    bool get_sensitive() const { return m_xSpinButton->get_sensitive(); }
+    bool get_visible() const { return m_xSpinButton->get_visible(); }
+    void grab_focus() { m_xSpinButton->grab_focus(); }
+    bool has_focus() const { return m_xSpinButton->has_focus(); }
+    void show(bool bShow = true) { m_xSpinButton->show(bShow); }
+    void hide() { m_xSpinButton->hide(); }
+    void save_value() { m_xSpinButton->save_value(); }
+    bool get_value_changed_from_saved() const
+    {
+        return m_xSpinButton->get_value_changed_from_saved();
+    }
+    void set_position(int nCursorPos) { m_xSpinButton->set_position(nCursorPos); }
+    weld::SpinButton* get_widget() { return m_xSpinButton.get(); }
+};
+
 class VCL_DLLPUBLIC Label : virtual public Widget
 {
 public:
@@ -782,6 +858,9 @@ public:
     {
         return new MetricSpinButton(weld_spin_button(id, bTakeOwnership), eUnit);
     }
+    virtual TimeSpinButton* weld_time_spin_button(const OString& id, TimeFieldFormat eFormat,
+                                                  bool bTakeOwnership = false)
+        = 0;
     virtual ComboBoxText* weld_combo_box_text(const OString& id, bool bTakeOwnership = false) = 0;
     virtual TreeView* weld_tree_view(const OString& id, bool bTakeOwnership = false) = 0;
     virtual Label* weld_label(const OString& id, bool bTakeOwnership = false) = 0;
diff --git a/sd/inc/sdabstdlg.hxx b/sd/inc/sdabstdlg.hxx
index 4b1e402f6eb7..65cfb1afeadc 100644
--- a/sd/inc/sdabstdlg.hxx
+++ b/sd/inc/sdabstdlg.hxx
@@ -190,7 +190,7 @@ public:
     virtual VclPtr<AbstractMorphDlg>           CreateMorphDlg(weld::Window* pParent, const SdrObject* pObj1, const SdrObject* pObj2) = 0;
     virtual VclPtr<SfxAbstractTabDialog>       CreateSdOutlineBulletTabDlg(vcl::Window* pParent, const SfxItemSet* pAttr, ::sd::View* pView) = 0;
     virtual VclPtr<SfxAbstractTabDialog>       CreateSdParagraphTabDlg(vcl::Window* pWindow, const SfxItemSet* pAttr) = 0;
-    virtual VclPtr<AbstractSdStartPresDlg>     CreateSdStartPresentationDlg( vcl::Window* pWindow, const SfxItemSet& rInAttrs,
+    virtual VclPtr<AbstractSdStartPresDlg>     CreateSdStartPresentationDlg(weld::Window* pWindow, const SfxItemSet& rInAttrs,
                                                                      const std::vector<OUString> &rPageNames, SdCustomShowList* pCSList ) = 0;
     virtual VclPtr<VclAbstractDialog>          CreateRemoteDialog( vcl::Window* pWindow ) = 0;
     virtual VclPtr<SfxAbstractTabDialog>       CreateSdPresLayoutTemplateDlg( SfxObjectShell* pDocSh, vcl::Window* pParent, bool bBackgroundDlg, SfxStyleSheetBase& rStyleBase, PresentationObjects ePO, SfxStyleSheetBasePool* pSSPool ) = 0;
diff --git a/sd/qa/unit/dialogs-test.cxx b/sd/qa/unit/dialogs-test.cxx
index 868388102e07..a30643293ed1 100644
--- a/sd/qa/unit/dialogs-test.cxx
+++ b/sd/qa/unit/dialogs-test.cxx
@@ -430,7 +430,7 @@ VclPtr<VclAbstractDialog> SdDialogsTest::createDialogByID(sal_uInt32 nID)
         }
         case 13:
         {
-            // CreateSdStartPresentationDlg(vcl::Window* pWindow, const SfxItemSet& rInAttrs, const std::vector<OUString> &rPageNames, SdCustomShowList* pCSList) override;
+            // CreateSdStartPresentationDlg(weld::Window* pWindow, const SfxItemSet& rInAttrs, const std::vector<OUString> &rPageNames, SdCustomShowList* pCSList) override;
             const std::vector<OUString> aPageNames;
             SdDrawDocument* pDrawDoc = getSdXImpressDocument()->GetDoc();
             CPPUNIT_ASSERT(pDrawDoc);
@@ -451,8 +451,9 @@ VclPtr<VclAbstractDialog> SdDialogsTest::createDialogByID(sal_uInt32 nID)
             aDlgSet.Put(SfxBoolItem(ATTR_PRESENT_SHOW_PAUSELOGO, rPresentationSettings.mbShowPauseLogo));
             //SdOptions* pOptions = SD_MOD()->GetSdOptions(DocumentType::Impress);
             aDlgSet.Put(SfxInt32Item(ATTR_PRESENT_DISPLAY, 0 /*pOptions->GetDisplay()*/));
+            vcl::Window* pWin = Application::GetDefDialogParent(),
             pRetval = getSdAbstractDialogFactory()->CreateSdStartPresentationDlg(
-                Application::GetDefDialogParent(),
+                pWin ? pWin->GetFrameWeld() : nullptr,
                 aDlgSet,
                 aPageNames,
                 nullptr);
diff --git a/sd/source/ui/dlg/present.cxx b/sd/source/ui/dlg/present.cxx
index 4bb21bcc460e..ea97037ef2ab 100644
--- a/sd/source/ui/dlg/present.cxx
+++ b/sd/source/ui/dlg/present.cxx
@@ -33,59 +33,51 @@ using namespace ::com::sun::star::lang;
 using namespace ::com::sun::star::container;
 using namespace ::com::sun::star::beans;
 
-SdStartPresentationDlg::SdStartPresentationDlg( vcl::Window* pWindow,
-                                  const SfxItemSet& rInAttrs,
-                                  const std::vector<OUString> &rPageNames, SdCustomShowList* pCSList ) :
-                ModalDialog     ( pWindow, "PresentationDialog", "modules/simpress/ui/presentationdialog.ui" ),
-                pCustomShowList         ( pCSList ),
-                rOutAttrs               ( rInAttrs ),
-                mnMonitors              ( 0 )
+SdStartPresentationDlg::SdStartPresentationDlg(weld::Window* pWindow, const SfxItemSet& rInAttrs,
+                                  const std::vector<OUString> &rPageNames, SdCustomShowList* pCSList)
+    : GenericDialogController(pWindow, "modules/simpress/ui/presentationdialog.ui", "PresentationDialog")
+    , pCustomShowList(pCSList)
+    , rOutAttrs(rInAttrs)
+    , mnMonitors(0)
+    , m_xRbtAll(m_xBuilder->weld_radio_button("allslides"))
+    , m_xRbtAtDia(m_xBuilder->weld_radio_button("from"))
+    , m_xRbtCustomshow(m_xBuilder->weld_radio_button("customslideshow"))
+    , m_xLbDias(m_xBuilder->weld_combo_box_text("from_cb"))
+    , m_xLbCustomshow(m_xBuilder->weld_combo_box_text("customslideshow_cb"))
+    , m_xRbtStandard(m_xBuilder->weld_radio_button("default"))
+    , m_xRbtWindow(m_xBuilder->weld_radio_button("window"))
+    , m_xRbtAuto(m_xBuilder->weld_radio_button("auto"))
+    , m_xTmfPause(m_xBuilder->weld_time_spin_button("pauseduration", TimeFieldFormat::F_SEC))
+    , m_xCbxAutoLogo(m_xBuilder->weld_check_button("showlogo"))
+    , m_xCbxManuel(m_xBuilder->weld_check_button("manualslides"))
+    , m_xCbxMousepointer(m_xBuilder->weld_check_button("pointervisible"))
+    , m_xCbxPen(m_xBuilder->weld_check_button("pointeraspen"))
+    , m_xCbxAnimationAllowed(m_xBuilder->weld_check_button("animationsallowed"))
+    , m_xCbxChangePage(m_xBuilder->weld_check_button("changeslidesbyclick"))
+    , m_xCbxAlwaysOnTop(m_xBuilder->weld_check_button("alwaysontop"))
+    , m_xFtMonitor(m_xBuilder->weld_label("presdisplay_label"))
+    , m_xLBMonitor(m_xBuilder->weld_combo_box_text("presdisplay_cb"))
+    , m_xMonitor(m_xBuilder->weld_label("monitor_str"))
+    , m_xAllMonitors(m_xBuilder->weld_label("allmonitors_str"))
+    , m_xMonitorExternal(m_xBuilder->weld_label("externalmonitor_str"))
+    , m_xExternal(m_xBuilder->weld_label("external_str"))
 {
-    get( aRbtAll,               "allslides"             );
-    get( aRbtAtDia,             "from"                  );
-    get( aRbtCustomshow,        "customslideshow"       );
-    get( aLbDias,               "from_cb"               );
-    get( aLbCustomshow,         "customslideshow_cb"    );
-
-    get( aRbtStandard,          "default"               );
-    get( aRbtWindow,            "window"                );
-    get( aRbtAuto,              "auto"                  );
-    get( aTmfPause,             "pauseduration"         );
-    get( aCbxAutoLogo,          "showlogo"              );
-
-    get( aCbxManuel,            "manualslides"          );
-    get( aCbxMousepointer,      "pointervisible"        );
-    get( aCbxPen,               "pointeraspen"          );
-    get( aCbxAnimationAllowed,  "animationsallowed"     );
-    get( aCbxChangePage,        "changeslidesbyclick"   );
-    get( aCbxAlwaysOnTop,       "alwaysontop"           );
-
-    get( maFtMonitor,           "presdisplay_label"     );
-    get( maLBMonitor,           "presdisplay_cb"        );
-
-    get( msMonitor,             "monitor_str"           );
-    get( msMonitorExternal,     "externalmonitor_str"   );
-    get( msExternal,            "external_str"          );
-    get( msMonitor,             "monitor_str"           );
-    get( msAllMonitors,         "allmonitors_str"       );
-
-    Link<Button*,void> aLink( LINK( this, SdStartPresentationDlg, ChangeRangeHdl ) );
-
-    aRbtAll->SetClickHdl( aLink );
-    aRbtAtDia->SetClickHdl( aLink );
-    aRbtCustomshow->SetClickHdl( aLink );
+    Link<weld::Button&,void> aLink( LINK( this, SdStartPresentationDlg, ChangeRangeHdl ) );
+
+    m_xRbtAll->connect_clicked( aLink );
+    m_xRbtAtDia->connect_clicked( aLink );
+    m_xRbtCustomshow->connect_clicked( aLink );
 
     aLink = LINK( this, SdStartPresentationDlg, ClickWindowPresentationHdl );
-    aRbtStandard->SetClickHdl( aLink );
-    aRbtWindow->SetClickHdl( aLink );
-    aRbtAuto->SetClickHdl( aLink );
+    m_xRbtStandard->connect_clicked( aLink );
+    m_xRbtWindow->connect_clicked( aLink );
+    m_xRbtAuto->connect_clicked( aLink );
 
-    aTmfPause->SetModifyHdl( LINK( this, SdStartPresentationDlg, ChangePauseHdl ) );
-    aTmfPause->SetFormat( TimeFieldFormat::F_SEC );
+    m_xTmfPause->connect_changed( LINK( this, SdStartPresentationDlg, ChangePauseHdl ) );
 
     // fill Listbox with page names
     for (std::vector<OUString>::const_iterator pIter = rPageNames.begin(); pIter != rPageNames.end(); ++pIter)
-        aLbDias->InsertEntry(*pIter);
+        m_xLbDias->append_text(*pIter);
 
     if( pCustomShowList )
     {
@@ -96,86 +88,56 @@ SdStartPresentationDlg::SdStartPresentationDlg( vcl::Window* pWindow,
              pCustomShow != nullptr;
              pCustomShow = pCustomShowList->Next() )
         {
-            aLbCustomshow->InsertEntry( pCustomShow->GetName() );
+            m_xLbCustomshow->append_text( pCustomShow->GetName() );
         }
-        aLbCustomshow->SelectEntryPos( nPosToSelect );
+        m_xLbCustomshow->set_active( nPosToSelect );
         pCustomShowList->Seek( nPosToSelect );
     }
     else
-        aRbtCustomshow->Disable();
+        m_xRbtCustomshow->set_sensitive(false);
 
     if( static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_CUSTOMSHOW ) ).GetValue() && pCSList )
-        aRbtCustomshow->Check();
+        m_xRbtCustomshow->set_active(true);
     else if( static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_ALL ) ).GetValue() )
-        aRbtAll->Check();
+        m_xRbtAll->set_active(true);
     else
-        aRbtAtDia->Check();
+        m_xRbtAtDia->set_active(true);
 
-    aLbDias->SelectEntry( static_cast<const SfxStringItem&>( rOutAttrs.Get( ATTR_PRESENT_DIANAME ) ).GetValue() );
-    aCbxManuel->Check( static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_MANUEL ) ).GetValue() );
-    aCbxMousepointer->Check( static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_MOUSE ) ).GetValue() );
-    aCbxPen->Check( static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_PEN ) ).GetValue() );
-    aCbxAnimationAllowed->Check( static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_ANIMATION_ALLOWED ) ).GetValue() );
-    aCbxChangePage->Check( static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_CHANGE_PAGE ) ).GetValue() );
-    aCbxAlwaysOnTop->Check( static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_ALWAYS_ON_TOP ) ).GetValue() );
+    m_xLbDias->set_active_text( static_cast<const SfxStringItem&>( rOutAttrs.Get( ATTR_PRESENT_DIANAME ) ).GetValue() );
+    m_xCbxManuel->set_active( static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_MANUEL ) ).GetValue() );
+    m_xCbxMousepointer->set_active( static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_MOUSE ) ).GetValue() );
+    m_xCbxPen->set_active( static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_PEN ) ).GetValue() );
+    m_xCbxAnimationAllowed->set_active( static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_ANIMATION_ALLOWED ) ).GetValue() );
+    m_xCbxChangePage->set_active( static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_CHANGE_PAGE ) ).GetValue() );
+    m_xCbxAlwaysOnTop->set_active( static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_ALWAYS_ON_TOP ) ).GetValue() );
 
     const bool  bEndless = static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_ENDLESS ) ).GetValue();
     const bool  bWindow = !static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_FULLSCREEN ) ).GetValue();
     const long  nPause = static_cast<const SfxUInt32Item&>( rOutAttrs.Get( ATTR_PRESENT_PAUSE_TIMEOUT ) ).GetValue();
 
-    aTmfPause->SetTime( tools::Time( 0, 0, nPause ) );
-    // set cursor in timefield
-    Edit *pEdit = aTmfPause->GetField();
-    Selection aSel( pEdit->GetMaxTextLen(), pEdit->GetMaxTextLen() );
-    pEdit->SetSelection( aSel );
+    m_xTmfPause->set_value( tools::Time( 0, 0, nPause ) );
+    // set cursor in timefield to end
+    m_xTmfPause->set_position(-1);
 
-    aCbxAutoLogo->Check( static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_SHOW_PAUSELOGO ) ).GetValue() );
+    m_xCbxAutoLogo->set_active( static_cast<const SfxBoolItem&>( rOutAttrs.Get( ATTR_PRESENT_SHOW_PAUSELOGO ) ).GetValue() );
 
     if( bWindow )
-        aRbtWindow->Check();
+        m_xRbtWindow->set_active(true);
     else if( bEndless )
-        aRbtAuto->Check();
+        m_xRbtAuto->set_active(true);
     else
-        aRbtStandard->Check();
+        m_xRbtStandard->set_active(true);
 
     InitMonitorSettings();
 
-    ChangeRangeHdl( nullptr );
+    ChangeRangeHdl(*m_xRbtCustomshow);
 
-    ClickWindowPresentationHdl( nullptr );
-    ChangePauseHdl( *aTmfPause );
+    ClickWindowPresentationHdl(*m_xRbtStandard);
+    ChangePause();
 }
 
 SdStartPresentationDlg::~SdStartPresentationDlg()
 {
-    disposeOnce();
-}
-
-void SdStartPresentationDlg::dispose()
-{
-    aRbtAll.clear();
-    aRbtAtDia.clear();
-    aRbtCustomshow.clear();
-    aLbDias.clear();
-    aLbCustomshow.clear();
-    aRbtStandard.clear();
-    aRbtWindow.clear();
-    aRbtAuto.clear();
-    aTmfPause.clear();
-    aCbxAutoLogo.clear();
-    aCbxManuel.clear();
-    aCbxMousepointer.clear();
-    aCbxPen.clear();
-    aCbxAnimationAllowed.clear();
-    aCbxChangePage.clear();
-    aCbxAlwaysOnTop.clear();
-    maFtMonitor.clear();
-    maLBMonitor.clear();
-    msMonitor.clear();
-    msAllMonitors.clear();
-    msMonitorExternal.clear();
-    msExternal.clear();
-    ModalDialog::dispose();
 }
 
 OUString SdStartPresentationDlg::GetDisplayName( sal_Int32   nDisplay,
@@ -186,14 +148,14 @@ OUString SdStartPresentationDlg::GetDisplayName( sal_Int32   nDisplay,
     switch ( eType )
     {
     case EXTERNAL_IS_NUMBER:
-        aName = msExternal->GetText();
+        aName = m_xExternal->get_label();
         break;
     case MONITOR_IS_EXTERNAL:
-        aName = msMonitorExternal->GetText();
+        aName = m_xMonitorExternal->get_label();
         break;
     default:
     case MONITOR_NORMAL:
-        aName = msMonitor->GetText();
+        aName = m_xMonitor->get_label();
         break;
     }
     aName = aName.replaceFirst( "%1", OUString::number( nDisplay ) );
@@ -205,26 +167,23 @@ OUString SdStartPresentationDlg::GetDisplayName( sal_Int32   nDisplay,
 sal_Int32 SdStartPresentationDlg::InsertDisplayEntry(const rtl::OUString &aName,
                                                      sal_Int32            nDisplay)
 {
-    maLBMonitor->InsertEntry( aName );
-    const sal_uInt32 nEntryIndex = maLBMonitor->GetEntryCount() - 1;
-    maLBMonitor->SetEntryData( nEntryIndex, reinterpret_cast<void*>(static_cast<sal_IntPtr>(nDisplay)) );
-
-    return nEntryIndex;
+    m_xLBMonitor->append(OUString::number(nDisplay), aName);
+    return m_xLBMonitor->get_count() - 1;
 }
 
 void SdStartPresentationDlg::InitMonitorSettings()
 {
     try
     {
-        maFtMonitor->Show();
-        maLBMonitor->Show();
+        m_xFtMonitor->show();
+        m_xLBMonitor->show();
 
         mnMonitors = Application::GetScreenCount();
 
         if( mnMonitors <= 1 )
         {
-            maFtMonitor->Enable( false );
-            maLBMonitor->Enable( false );
+            m_xFtMonitor->set_sensitive( false );
+            m_xLBMonitor->set_sensitive( false );
         }
         else
         {
@@ -264,7 +223,7 @@ void SdStartPresentationDlg::InitMonitorSettings()
 
             if( bUnifiedDisplay )
             {
-                nInsertedEntry = InsertDisplayEntry( msAllMonitors->GetText(), -1 );
+                nInsertedEntry = InsertDisplayEntry( m_xAllMonitors->get_label(), -1 );
                 if( nDefaultSelectedDisplay == -1 )
                     nSelectedIndex = nInsertedEntry;
             }
@@ -277,7 +236,7 @@ void SdStartPresentationDlg::InitMonitorSettings()
                     nSelectedIndex = nDefaultExternalIndex;
             }
 
-            maLBMonitor->SelectEntryPos(nSelectedIndex);
+            m_xLBMonitor->set_active(nSelectedIndex);
         }
     }
     catch( Exception& )
@@ -290,69 +249,74 @@ void SdStartPresentationDlg::InitMonitorSettings()
  */
 void SdStartPresentationDlg::GetAttr( SfxItemSet& rAttr )
 {
-    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_ALL, aRbtAll->IsChecked() ) );
-    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_CUSTOMSHOW, aRbtCustomshow->IsChecked() ) );
-    rAttr.Put( SfxStringItem ( ATTR_PRESENT_DIANAME, aLbDias->GetSelectedEntry() ) );
-    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_MANUEL, aCbxManuel->IsChecked() ) );
-    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_MOUSE, aCbxMousepointer->IsChecked() ) );
-    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_PEN, aCbxPen->IsChecked() ) );
-    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_ANIMATION_ALLOWED, aCbxAnimationAllowed->IsChecked() ) );
-    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_CHANGE_PAGE, aCbxChangePage->IsChecked() ) );
-    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_ALWAYS_ON_TOP, aCbxAlwaysOnTop->IsChecked() ) );
-    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_FULLSCREEN, !aRbtWindow->IsChecked() ) );
-    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_ENDLESS, aRbtAuto->IsChecked() ) );
-    rAttr.Put( SfxUInt32Item ( ATTR_PRESENT_PAUSE_TIMEOUT, aTmfPause->GetTime().GetMSFromTime() / 1000 ) );
-    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_SHOW_PAUSELOGO, aCbxAutoLogo->IsChecked() ) );
-
-    sal_Int32 nPos = maLBMonitor->GetSelectedEntryPos();
-    if( nPos != LISTBOX_ENTRY_NOTFOUND )
-        rAttr.Put( SfxInt32Item ( ATTR_PRESENT_DISPLAY, static_cast<sal_Int32>(reinterpret_cast<sal_IntPtr>(maLBMonitor->GetEntryData(nPos)))) );
-
-    nPos = aLbCustomshow->GetSelectedEntryPos();
-    if( nPos != LISTBOX_ENTRY_NOTFOUND )
+    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_ALL, m_xRbtAll->get_active() ) );
+    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_CUSTOMSHOW, m_xRbtCustomshow->get_active() ) );
+    rAttr.Put( SfxStringItem ( ATTR_PRESENT_DIANAME, m_xLbDias->get_active_text() ) );
+    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_MANUEL, m_xCbxManuel->get_active() ) );
+    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_MOUSE, m_xCbxMousepointer->get_active() ) );
+    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_PEN, m_xCbxPen->get_active() ) );
+    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_ANIMATION_ALLOWED, m_xCbxAnimationAllowed->get_active() ) );
+    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_CHANGE_PAGE, m_xCbxChangePage->get_active() ) );
+    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_ALWAYS_ON_TOP, m_xCbxAlwaysOnTop->get_active() ) );
+    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_FULLSCREEN, !m_xRbtWindow->get_active() ) );
+    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_ENDLESS, m_xRbtAuto->get_active() ) );
+    rAttr.Put( SfxUInt32Item ( ATTR_PRESENT_PAUSE_TIMEOUT, m_xTmfPause->get_value().GetMSFromTime() / 1000 ) );
+    rAttr.Put( SfxBoolItem ( ATTR_PRESENT_SHOW_PAUSELOGO, m_xCbxAutoLogo->get_active() ) );
+
+    int nPos = m_xLBMonitor->get_active();
+    if (nPos != -1)
+        rAttr.Put(SfxInt32Item(ATTR_PRESENT_DISPLAY, m_xLBMonitor->get_id(nPos).toInt32()));
+
+    nPos = m_xLbCustomshow->get_active();
+    if (nPos != -1)
         pCustomShowList->Seek( nPos );
 }
 
 /**
  *      Handler: Enabled/Disabled Listbox "Dias"
  */
-IMPL_LINK_NOARG(SdStartPresentationDlg, ChangeRangeHdl, Button*, void)
+IMPL_LINK_NOARG(SdStartPresentationDlg, ChangeRangeHdl, weld::Button&, void)
 {
-    aLbDias->Enable( aRbtAtDia->IsChecked() );
-    aLbCustomshow->Enable( aRbtCustomshow->IsChecked() );
+    m_xLbDias->set_sensitive( m_xRbtAtDia->get_active() );
+    m_xLbCustomshow->set_sensitive( m_xRbtCustomshow->get_active() );
 }
 
 /**
  *      Handler: Enabled/Disabled Checkbox "AlwaysOnTop"
  */
-IMPL_LINK_NOARG(SdStartPresentationDlg, ClickWindowPresentationHdl, Button*, void)
+IMPL_LINK_NOARG(SdStartPresentationDlg, ClickWindowPresentationHdl, weld::Button&, void)
 {
-    const bool bAuto = aRbtAuto->IsChecked();
-    const bool bWindow = aRbtWindow->IsChecked();
+    const bool bAuto = m_xRbtAuto->get_active();
+    const bool bWindow = m_xRbtWindow->get_active();
 
-    // aFtPause.Enable( bAuto );
-    aTmfPause->Enable( bAuto );
-    aCbxAutoLogo->Enable( bAuto && ( aTmfPause->GetTime().GetMSFromTime() > 0 ) );
+    // m_xFtPause.set_sensitive( bAuto );
+    m_xTmfPause->set_sensitive( bAuto );
+    m_xCbxAutoLogo->set_sensitive( bAuto && ( m_xTmfPause->get_value().GetMSFromTime() > 0 ) );
 
     const bool bDisplay = !bWindow && ( mnMonitors > 1 );
-    maFtMonitor->Enable( bDisplay );
-    maLBMonitor->Enable( bDisplay );
+    m_xFtMonitor->set_sensitive( bDisplay );
+    m_xLBMonitor->set_sensitive( bDisplay );
 
     if( bWindow )
     {
-        aCbxAlwaysOnTop->Enable( false );
-        aCbxAlwaysOnTop->Check( false );
+        m_xCbxAlwaysOnTop->set_sensitive(false);
+        m_xCbxAlwaysOnTop->set_active(false);
     }
     else
-        aCbxAlwaysOnTop->Enable();
+        m_xCbxAlwaysOnTop->set_sensitive(true);
 }
 
 /**
  *      Handler: Enabled/Disabled Checkbox "AlwaysOnTop"
  */
-IMPL_LINK_NOARG(SdStartPresentationDlg, ChangePauseHdl, Edit&, void)
+IMPL_LINK_NOARG(SdStartPresentationDlg, ChangePauseHdl, weld::Entry&, void)
+{
+    ChangePause();
+}
+
+void SdStartPresentationDlg::ChangePause()
 {
-    aCbxAutoLogo->Enable( aRbtAuto->IsChecked() && ( aTmfPause->GetTime().GetMSFromTime() > 0 ) );
+    m_xCbxAutoLogo->set_sensitive(m_xRbtAuto->get_active() && ( m_xTmfPause->get_value().GetMSFromTime() > 0 ));
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/dlg/sddlgfact.cxx b/sd/source/ui/dlg/sddlgfact.cxx
index 2c6131f7fd4b..af5f6345fccb 100644
--- a/sd/source/ui/dlg/sddlgfact.cxx
+++ b/sd/source/ui/dlg/sddlgfact.cxx
@@ -70,7 +70,11 @@ short AbstractMorphDlg_Impl::Execute()
     return m_xDlg->run();
 }
 
-IMPL_ABSTDLG_BASE(AbstractSdStartPresDlg_Impl);
+short AbstractSdStartPresDlg_Impl::Execute()
+{
+    return m_xDlg->run();
+}
+
 IMPL_ABSTDLG_BASE(AbstractSdPresLayoutDlg_Impl);
 IMPL_ABSTDLG_BASE(SdAbstractSfxDialog_Impl);
 IMPL_ABSTDLG_BASE(AbstractSdVectorizeDlg_Impl);
@@ -271,7 +275,7 @@ bool AbstractMorphDlg_Impl::IsOrientationFade() const
 
 void AbstractSdStartPresDlg_Impl::GetAttr( SfxItemSet& rOutAttrs )
 {
-    pDlg->GetAttr( rOutAttrs );
+    m_xDlg->GetAttr( rOutAttrs );
 }
 
 void AbstractSdPresLayoutDlg_Impl::GetAttr( SfxItemSet& rOutAttrs )
@@ -368,10 +372,10 @@ VclPtr<SfxAbstractTabDialog> SdAbstractDialogFactory_Impl::CreateSdParagraphTabD
     return VclPtr<SdAbstractTabDialog_Impl>::Create( VclPtr<SdParagraphDlg>::Create( pParent, pAttr ) );
 }
 
-VclPtr<AbstractSdStartPresDlg> SdAbstractDialogFactory_Impl::CreateSdStartPresentationDlg( vcl::Window* pParent, const SfxItemSet& rInAttrs,
-                                                                                     const std::vector<OUString> &rPageNames, SdCustomShowList* pCSList )
+VclPtr<AbstractSdStartPresDlg> SdAbstractDialogFactory_Impl::CreateSdStartPresentationDlg(weld::Window* pParent,
+        const SfxItemSet& rInAttrs, const std::vector<OUString> &rPageNames, SdCustomShowList* pCSList)
 {
-    return VclPtr<AbstractSdStartPresDlg_Impl>::Create( VclPtr<SdStartPresentationDlg>::Create( pParent, rInAttrs, rPageNames, pCSList ) );
+    return VclPtr<AbstractSdStartPresDlg_Impl>::Create(new SdStartPresentationDlg(pParent, rInAttrs, rPageNames, pCSList));
 }
 
 VclPtr<VclAbstractDialog> SdAbstractDialogFactory_Impl::CreateRemoteDialog( vcl::Window* pParent )
diff --git a/sd/source/ui/dlg/sddlgfact.hxx b/sd/source/ui/dlg/sddlgfact.hxx
index d8bb3438f65f..66ba0a90a1aa 100644
--- a/sd/source/ui/dlg/sddlgfact.hxx
+++ b/sd/source/ui/dlg/sddlgfact.hxx
@@ -202,7 +202,14 @@ public:
 class SdStartPresentationDlg;
 class AbstractSdStartPresDlg_Impl : public AbstractSdStartPresDlg
 {
-    DECL_ABSTDLG_BASE(AbstractSdStartPresDlg_Impl,SdStartPresentationDlg)
+private:
+    std::unique_ptr<SdStartPresentationDlg> m_xDlg;
+public:
+    AbstractSdStartPresDlg_Impl(SdStartPresentationDlg* pDlg)
+        : m_xDlg(pDlg)
+    {
+    }
+    virtual short   Execute() override;
     virtual void    GetAttr( SfxItemSet& rOutAttrs ) override;
 };
 
@@ -258,7 +265,7 @@ public:
     virtual VclPtr<AbstractMorphDlg>           CreateMorphDlg(weld::Window* pParent, const SdrObject* pObj1, const SdrObject* pObj2) override;
     virtual VclPtr<SfxAbstractTabDialog>       CreateSdOutlineBulletTabDlg(vcl::Window* pParent, const SfxItemSet* pAttr, ::sd::View* pView) override;
     virtual VclPtr<SfxAbstractTabDialog>       CreateSdParagraphTabDlg(vcl::Window* pParent, const SfxItemSet* pAttr) override;
-    virtual VclPtr<AbstractSdStartPresDlg>     CreateSdStartPresentationDlg( vcl::Window* pWindow, const SfxItemSet& rInAttrs,
+    virtual VclPtr<AbstractSdStartPresDlg>     CreateSdStartPresentationDlg(weld::Window* pWindow, const SfxItemSet& rInAttrs,
                                                                      const std::vector<OUString> &rPageNames, SdCustomShowList* pCSList ) override;
     virtual VclPtr<VclAbstractDialog>          CreateRemoteDialog( vcl::Window* pWindow ) override; // ad for RemoteDialog
     virtual VclPtr<SfxAbstractTabDialog>       CreateSdPresLayoutTemplateDlg( SfxObjectShell* pDocSh, vcl::Window* pParent, bool bBackgroundDlg, SfxStyleSheetBase& rStyleBase, PresentationObjects ePO, SfxStyleSheetBasePool* pSSPool ) override;
diff --git a/sd/source/ui/func/fusldlg.cxx b/sd/source/ui/func/fusldlg.cxx
index 13da0d20e957..1a5ee50eb6b7 100644
--- a/sd/source/ui/func/fusldlg.cxx
+++ b/sd/source/ui/func/fusldlg.cxx
@@ -106,7 +106,7 @@ void FuSlideShowDlg::DoExecute( SfxRequest& )
     aDlgSet.Put( SfxInt32Item( ATTR_PRESENT_DISPLAY, pOptions->GetDisplay() ) );
 
     SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create();
-    ScopedVclPtr<AbstractSdStartPresDlg> pDlg(pFact ? pFact->CreateSdStartPresentationDlg(mpWindow, aDlgSet, aPageNameList, pCustomShowList) : nullptr);
+    ScopedVclPtr<AbstractSdStartPresDlg> pDlg(pFact ? pFact->CreateSdStartPresentationDlg(mpWindow ? mpWindow->GetFrameWeld() : nullptr, aDlgSet, aPageNameList, pCustomShowList) : nullptr);
     if( pDlg && (pDlg->Execute() == RET_OK) )
     {
         OUString aPage;
diff --git a/sd/source/ui/inc/present.hxx b/sd/source/ui/inc/present.hxx
index f627bcf419ea..d81b2918e66e 100644
--- a/sd/source/ui/inc/present.hxx
+++ b/sd/source/ui/inc/present.hxx
@@ -20,57 +20,53 @@
 #ifndef INCLUDED_SD_SOURCE_UI_INC_PRESENT_HXX
 #define INCLUDED_SD_SOURCE_UI_INC_PRESENT_HXX
 
-#include <vcl/lstbox.hxx>
-#include <vcl/fixed.hxx>
-#include <vcl/button.hxx>
-#include <vcl/dialog.hxx>
-#include <vcl/field.hxx>
+#include <vcl/weld.hxx>
 
 class SfxItemSet;
 class List;
 class SdCustomShowList;
 
 /**
- * Dialog to define options and to start the presentation
+ * Dialog to define optionsm_xnd to start the presentation
  */
-class SdStartPresentationDlg : public ModalDialog
+class SdStartPresentationDlg : public weld::GenericDialogController
 {
 private:
+    SdCustomShowList*   pCustomShowList;
+    const SfxItemSet&   rOutAttrs;
+    sal_Int32           mnMonitors;
 
-    VclPtr<RadioButton>        aRbtAll;
-    VclPtr<RadioButton>        aRbtAtDia;
-    VclPtr<RadioButton>        aRbtCustomshow;
-    VclPtr<ListBox>            aLbDias;
-    VclPtr<ListBox>            aLbCustomshow;
-
-    VclPtr<RadioButton>        aRbtStandard;
-    VclPtr<RadioButton>        aRbtWindow;
-    VclPtr<RadioButton>        aRbtAuto;
-    VclPtr<TimeField>          aTmfPause;
-    VclPtr<CheckBox>           aCbxAutoLogo;
+    std::unique_ptr<weld::RadioButton> m_xRbtAll;
+    std::unique_ptr<weld::RadioButton> m_xRbtAtDia;
+    std::unique_ptr<weld::RadioButton> m_xRbtCustomshow;
+    std::unique_ptr<weld::ComboBoxText> m_xLbDias;
+    std::unique_ptr<weld::ComboBoxText> m_xLbCustomshow;
 
-    VclPtr<CheckBox>           aCbxManuel;
-    VclPtr<CheckBox>           aCbxMousepointer;
-    VclPtr<CheckBox>           aCbxPen;
-    VclPtr<CheckBox>           aCbxAnimationAllowed;
-    VclPtr<CheckBox>           aCbxChangePage;
-    VclPtr<CheckBox>           aCbxAlwaysOnTop;
+    std::unique_ptr<weld::RadioButton> m_xRbtStandard;
+    std::unique_ptr<weld::RadioButton> m_xRbtWindow;
+    std::unique_ptr<weld::RadioButton> m_xRbtAuto;
+    std::unique_ptr<weld::TimeSpinButton> m_xTmfPause;
+    std::unique_ptr<weld::CheckButton> m_xCbxAutoLogo;
 
-    VclPtr<FixedText>          maFtMonitor;
-    VclPtr<ListBox>            maLBMonitor;
+    std::unique_ptr<weld::CheckButton> m_xCbxManuel;
+    std::unique_ptr<weld::CheckButton> m_xCbxMousepointer;
+    std::unique_ptr<weld::CheckButton> m_xCbxPen;
+    std::unique_ptr<weld::CheckButton> m_xCbxAnimationAllowed;
+    std::unique_ptr<weld::CheckButton> m_xCbxChangePage;
+    std::unique_ptr<weld::CheckButton> m_xCbxAlwaysOnTop;
 
-    SdCustomShowList*   pCustomShowList;
-    const SfxItemSet&   rOutAttrs;
-    sal_Int32           mnMonitors;
+    std::unique_ptr<weld::Label> m_xFtMonitor;
+    std::unique_ptr<weld::ComboBoxText> m_xLBMonitor;
 
-    VclPtr<FixedText>          msMonitor;
-    VclPtr<FixedText>          msAllMonitors;
-    VclPtr<FixedText>          msMonitorExternal;
-    VclPtr<FixedText>          msExternal;
+    std::unique_ptr<weld::Label> m_xMonitor;
+    std::unique_ptr<weld::Label> m_xAllMonitors;
+    std::unique_ptr<weld::Label> m_xMonitorExternal;
+    std::unique_ptr<weld::Label> m_xExternal;
 
-                        DECL_LINK( ChangeRangeHdl, Button*, void );
-                        DECL_LINK( ClickWindowPresentationHdl, Button*, void );
-                        DECL_LINK( ChangePauseHdl, Edit&, void );
+    DECL_LINK(ChangeRangeHdl, weld::Button&, void);
+    DECL_LINK(ClickWindowPresentationHdl, weld::Button&, void);
+    void ChangePause();
+    DECL_LINK(ChangePauseHdl, weld::Entry&, void);
 
     void                InitMonitorSettings();
     enum DisplayType {
@@ -83,13 +79,11 @@ private:
     OUString            GetDisplayName( sal_Int32 nDisplay,
                                         DisplayType eType );
 public:
-                        SdStartPresentationDlg( vcl::Window* pWindow,
-                                const SfxItemSet& rInAttrs,
-                                const std::vector<OUString> &rPageNames,
-                                SdCustomShowList* pCSList );
+                        SdStartPresentationDlg(weld::Window* pWindow,
+                                               const SfxItemSet& rInAttrs,
+                                               const std::vector<OUString> &rPageNames,
+                                               SdCustomShowList* pCSList);
     virtual             ~SdStartPresentationDlg() override;
-    virtual void        dispose() override;
-
     void                GetAttr( SfxItemSet& rOutAttrs );
 };
 
diff --git a/sd/uiconfig/simpress/ui/presentationdialog.ui b/sd/uiconfig/simpress/ui/presentationdialog.ui
index 366f1957042e..d85e2f19edee 100644
--- a/sd/uiconfig/simpress/ui/presentationdialog.ui
+++ b/sd/uiconfig/simpress/ui/presentationdialog.ui
@@ -1,11 +1,19 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.18.3 -->
+<!-- Generated with glade 3.20.4 -->
 <interface domain="sd">
   <requires lib="gtk+" version="3.18"/>
+  <object class="GtkAdjustment" id="adjustment1">
+    <property name="upper">86400000</property>
+    <property name="step_increment">1000</property>
+    <property name="page_increment">60000</property>
+  </object>
   <object class="GtkDialog" id="PresentationDialog">
     <property name="can_focus">False</property>
     <property name="border_width">6</property>
     <property name="title" translatable="yes" context="presentationdialog|PresentationDialog">Slide Show Settings</property>
+    <property name="modal">True</property>
+    <property name="default_width">0</property>
+    <property name="default_height">0</property>
     <property name="type_hint">dialog</property>
     <child internal-child="vbox">
       <object class="GtkBox" id="dialog-vbox1">
@@ -13,6 +21,64 @@
         <property name="can_focus">False</property>
         <property name="orientation">vertical</property>
         <property name="spacing">12</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="ok">
+                <property name="label">gtk-ok</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="has_default">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="cancel">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="help">
+                <property name="label">gtk-help</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="receives_default">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+                <property name="secondary">True</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
         <child>
           <object class="GtkGrid" id="grid1">
             <property name="visible">True</property>
@@ -64,7 +130,7 @@
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkComboBox" id="from_cb">
+                              <object class="GtkComboBoxText" id="from_cb">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
                                 <property name="hexpand">True</property>
@@ -98,7 +164,6 @@
                             <property name="xalign">0</property>
                             <property name="active">True</property>
                             <property name="draw_indicator">True</property>
-                            <property name="group">from</property>
                           </object>
                           <packing>
                             <property name="left_attach">0</property>
@@ -114,7 +179,7 @@
                             <property name="use_underline">True</property>
                             <property name="xalign">0</property>
                             <property name="draw_indicator">True</property>
-                            <property name="group">from</property>
+                            <property name="group">allslides</property>
                             <accessibility>
                               <relation type="label-for" target="customslideshow_cb"/>
                             </accessibility>
@@ -125,7 +190,7 @@
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkComboBox" id="customslideshow_cb">
+                          <object class="GtkComboBoxText" id="customslideshow_cb">
                             <property name="visible">True</property>
                             <property name="can_focus">False</property>
                             <property name="margin_left">12</property>
@@ -187,7 +252,7 @@
                             <property name="vexpand">True</property>
                             <property name="column_spacing">12</property>
                             <child>
-                              <object class="GtkComboBox" id="presdisplay_cb">
+                              <object class="GtkComboBoxText" id="presdisplay_cb">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
                                 <property name="hexpand">True</property>
@@ -201,10 +266,10 @@
                               <object class="GtkLabel" id="presdisplay_label">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
                                 <property name="label" translatable="yes" context="presentationdialog|presdisplay_label">P_resentation display:</property>
                                 <property name="use_underline">True</property>
                                 <property name="mnemonic_widget">presdisplay_cb</property>
+                                <property name="xalign">0</property>
                               </object>
                               <packing>
                                 <property name="left_attach">0</property>
@@ -322,7 +387,6 @@
                                 <property name="xalign">0</property>
                                 <property name="active">True</property>
                                 <property name="draw_indicator">True</property>
-                                <property name="group">auto</property>
                               </object>
                               <packing>
                                 <property name="left_attach">0</property>
@@ -338,7 +402,7 @@
                                 <property name="use_underline">True</property>
                                 <property name="xalign">0</property>
                                 <property name="draw_indicator">True</property>
-                                <property name="group">auto</property>
+                                <property name="group">default</property>
                               </object>
                               <packing>
                                 <property name="left_attach">0</property>
@@ -354,9 +418,9 @@
                                 <property name="use_underline">True</property>
                                 <property name="xalign">0</property>
                                 <property name="draw_indicator">True</property>
-                                <property name="group">window</property>
+                                <property name="group">default</property>
                                 <accessibility>
-                                  <relation type="label-for" target="pauseduration:hh:mm"/>
+                                  <relation type="label-for" target="pauseduration"/>
                                 </accessibility>
                               </object>
                               <packing>
@@ -381,17 +445,19 @@
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkSpinButton" id="pauseduration:hh:mm">
+                              <object class="GtkSpinButton" id="pauseduration">
                                 <property name="visible">True</property>
                                 <property name="sensitive">False</property>
                                 <property name="can_focus">True</property>
                                 <property name="tooltip_text" translatable="yes" context="presentationdialog|pauseduration|tooltip_text">Duration of pause</property>
                                 <property name="margin_left">12</property>
+                                <property name="activates_default">True</property>
+                                <property name="adjustment">adjustment1</property>
                                 <accessibility>
                                   <relation type="labelled-by" target="auto"/>
                                 </accessibility>
                                 <child internal-child="accessible">
-                                  <object class="AtkObject" id="pauseduration:hh:mm-atkobject">
+                                  <object class="AtkObject" id="pauseduration-atkobject">
                                     <property name="AtkObject::accessible-name" translatable="yes" context="presentationdialog|pauseduration-atkobject">Pause Duration</property>
                                   </object>
                                 </child>
@@ -532,6 +598,9 @@
                                 <property name="top_attach">6</property>
                               </packing>
                             </child>
+                            <child>
+                              <placeholder/>
+                            </child>
                           </object>
                         </child>
                       </object>
@@ -565,64 +634,6 @@
             <property name="position">0</property>
           </packing>
         </child>
-        <child internal-child="action_area">
-          <object class="GtkButtonBox" id="dialog-action_area1">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="layout_style">end</property>
-            <child>
-              <object class="GtkButton" id="ok">
-                <property name="label">gtk-ok</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="has_default">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="cancel">
-                <property name="label">gtk-cancel</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="help">
-                <property name="label">gtk-help</property>
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="receives_default">False</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">2</property>
-                <property name="secondary">True</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="pack_type">end</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
       </object>
     </child>
     <action-widgets>
@@ -630,5 +641,8 @@
       <action-widget response="-6">cancel</action-widget>
       <action-widget response="-11">help</action-widget>
     </action-widgets>
+    <child>
+      <placeholder/>
+    </child>
   </object>
 </interface>
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 713e5acada9c..d5d613b892f1 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -1146,6 +1146,7 @@ private:
     VclPtr<Edit> m_xEntry;
 
     DECL_LINK(ChangeHdl, Edit&, void);
+    DECL_LINK(CursorListener, VclWindowEvent&, void);
 
     class WeldTextFilter : public TextFilter
     {
@@ -1237,8 +1238,17 @@ public:
         m_xEntry->SetFont(rFont);
     }
 
+    virtual void connect_cursor_position(const Link<Entry&, void>& rLink) override
+    {
+        assert(!m_aCursorPositionHdl.IsSet());
+        m_xEntry->AddEventListener(LINK(this, SalInstanceEntry, CursorListener));
+        weld::Entry::connect_cursor_position(rLink);
+    }
+
     virtual ~SalInstanceEntry() override
     {
+        if (m_aCursorPositionHdl.IsSet())
+            m_xEntry->RemoveEventListener(LINK(this, SalInstanceEntry, CursorListener));
         m_xEntry->SetTextFilter(nullptr);
         m_xEntry->SetModifyHdl(Link<Edit&, void>());
     }
@@ -1249,6 +1259,12 @@ IMPL_LINK_NOARG(SalInstanceEntry, ChangeHdl, Edit&, void)
     signal_changed();
 }
 
+IMPL_LINK(SalInstanceEntry, CursorListener, VclWindowEvent&, rEvent, void)
+{
+    if (rEvent.GetId() == VclEventId::EditSelectionChanged || rEvent.GetId() == VclEventId::EditCaretChanged)
+        signal_cursor_position();
+}
+
 class SalInstanceTreeView : public SalInstanceContainer, public virtual weld::TreeView
 {
 private:
@@ -1442,6 +1458,7 @@ private:
     DECL_LINK(UpDownHdl, SpinField&, void);
     DECL_LINK(LoseFocusHdl, Control&, void);
     DECL_LINK(OutputHdl, Edit&, bool);
+    DECL_LINK(InputHdl, sal_Int64*, TriState);
 
 public:
     SalInstanceSpinButton(NumericField* pButton, bool bTakeOwnership)
@@ -1452,6 +1469,7 @@ public:
         m_xButton->SetDownHdl(LINK(this, SalInstanceSpinButton, UpDownHdl));
         m_xButton->SetLoseFocusHdl(LINK(this, SalInstanceSpinButton, LoseFocusHdl));
         m_xButton->SetOutputHdl(LINK(this, SalInstanceSpinButton, OutputHdl));
+        m_xButton->SetInputHdl(LINK(this, SalInstanceSpinButton, InputHdl));
     }
 
     virtual int get_value() const override
@@ -1494,6 +1512,11 @@ public:
         m_xButton->SetDecimalDigits(digits);
     }
 
+    void DisableRemainderFactor()
+    {
+        m_xButton->DisableRemainderFactor();
+    }
+
     virtual unsigned int get_digits() const override
     {
         return m_xButton->GetDecimalDigits();
@@ -1501,6 +1524,7 @@ public:
 
     virtual ~SalInstanceSpinButton() override
     {
+        m_xButton->SetInputHdl(Link<sal_Int64*, TriState>());
         m_xButton->SetOutputHdl(Link<Edit&, bool>());
         m_xButton->SetLoseFocusHdl(Link<Control&, void>());
         m_xButton->SetDownHdl(Link<SpinField&, void>());
@@ -1523,6 +1547,15 @@ IMPL_LINK_NOARG(SalInstanceSpinButton, OutputHdl, Edit&, bool)
     return signal_output();
 }
 
+IMPL_LINK(SalInstanceSpinButton, InputHdl, sal_Int64*, pResult, TriState)
+{
+    int nResult;
+    TriState eRet = signal_input(&nResult);
+    if (eRet == TRISTATE_TRUE)
+        *pResult = nResult;
+    return eRet;
+}
+
 class SalInstanceLabel : public SalInstanceWidget, public virtual weld::Label
 {
 private:
@@ -2154,6 +2187,16 @@ public:
         return pSpinButton ? new SalInstanceSpinButton(pSpinButton, bTakeOwnership) : nullptr;
     }
 
+    virtual weld::TimeSpinButton* weld_time_spin_button(const OString& id, TimeFieldFormat eFormat,
+                                                        bool bTakeOwnership) override
+    {
+        weld::TimeSpinButton* pRet = new weld::TimeSpinButton(weld_spin_button(id, bTakeOwnership), eFormat);
+        SalInstanceSpinButton* pButton = dynamic_cast<SalInstanceSpinButton*>(pRet->get_widget());
+        assert(pButton);
+        pButton->DisableRemainderFactor(); //so with hh::mm::ss, incrementing mm will not reset ss
+        return pRet;
+    }
+
     virtual weld::ComboBoxText* weld_combo_box_text(const OString &id, bool bTakeOwnership) override
     {
         vcl::Window* pComboBoxText = m_xBuilder->get<vcl::Window>(id);
diff --git a/vcl/source/control/field.cxx b/vcl/source/control/field.cxx
index 6221a6f688fa..1ebcfe95e9ad 100644
--- a/vcl/source/control/field.cxx
+++ b/vcl/source/control/field.cxx
@@ -452,12 +452,6 @@ void FormatterBase::ImplSetText( const OUString& rText, Selection const * pNewSe
             aSel.Min() = aSel.Max();
             mpField->SetText(rText, aSel);
         }
-        if (maOutputHdl.IsSet())
-        {
-            OUString sText(mpField->GetText());
-            if (!maOutputHdl.Call(*mpField))
-                mpField->SetText(sText);
-        }
         MarkToBeReformatted( false );
     }
 }
@@ -474,13 +468,18 @@ bool FormatterBase::IsEmptyFieldValue() const
     return (!mpField || mpField->GetText().isEmpty());
 }
 
-void NumericFormatter::ImplNumericReformat(sal_Int64& rValue, OUString& rOutStr)
+void NumericFormatter::FormatValue(Selection const * pNewSelection)
 {
-    if (ImplNumericGetValue(GetField()->GetText(), rValue, GetDecimalDigits(), ImplGetLocaleDataWrapper()))
-    {
-        sal_Int64 nTempVal = ClipAgainstMinMax(rValue);
-        rOutStr = CreateFieldText( nTempVal );
-    }
+    mbFormatting = true;
+    if (!m_aOutputHdl.IsSet() || !m_aOutputHdl.Call(*GetField()))
+        ImplSetText(CreateFieldText(mnLastValue), pNewSelection);
+    mbFormatting = false;
+}
+
+void NumericFormatter::ImplNumericReformat()
+{
+    mnLastValue = GetValue();
+    FormatValue();
 }
 
 void NumericFormatter::ImplInit()
@@ -495,6 +494,8 @@ void NumericFormatter::ImplInit()
     mbThousandSep       = true;
     mbShowTrailingZeros = true;
     mbWrapOnLimits      = false;
+    mbFormatting       = false;
+    mbDisableRemainderFactor = false;
 
     // for fields
     mnSpinSize          = 1;
@@ -567,7 +568,7 @@ void NumericFormatter::ImplSetUserValue( sal_Int64 nNewValue, Selection const *
     mnLastValue = nNewValue;
 
     if ( GetField() )
-        ImplSetText( CreateFieldText( nNewValue ), pNewSelection );
+        FormatValue(pNewSelection);
 }
 
 void NumericFormatter::SetUserValue( sal_Int64 nNewValue )
@@ -590,6 +591,22 @@ sal_Int64 NumericFormatter::GetValueFromString(const OUString& rStr) const
 
 sal_Int64 NumericFormatter::GetValue() const
 {
+    if (mbFormatting) //don't parse the entry if we're currently formatting what to put in it
+        return mnLastValue;
+
+    if (m_aInputHdl.IsSet())
+    {
+        sal_Int64 nResult;
+        TriState eState = m_aInputHdl.Call(&nResult);
+        if (eState != TRISTATE_INDET)
+        {
+            if (eState == TRISTATE_TRUE)
+                return ClipAgainstMinMax(nResult);
+            else
+                return mnLastValue;
+        }
+    }
+
     return GetField() ? GetValueFromString(GetField()->GetText()) : 0;
 }
 
@@ -643,21 +660,18 @@ void NumericFormatter::Reformat()
     if ( GetField()->GetText().isEmpty() && ImplGetEmptyFieldValue() )
         return;
 
-    OUString aStr;
-    sal_Int64 nTemp = mnLastValue;
-    ImplNumericReformat(nTemp, aStr);
-    mnLastValue = nTemp;
+    ImplNumericReformat();
+}
 
-    if ( !aStr.isEmpty() )
-        ImplSetText( aStr );
-    else
-        SetValue( mnLastValue );
+void NumericFormatter::DisableRemainderFactor()
+{
+    mbDisableRemainderFactor = true;
 }
 
 void NumericFormatter::FieldUp()
 {
     sal_Int64 nValue = GetValue();
-    sal_Int64 nRemainder = nValue % mnSpinSize;
+    sal_Int64 nRemainder = mbDisableRemainderFactor ? 0 : (nValue % mnSpinSize);
     if (nValue >= 0)
         nValue = (nRemainder == 0) ? nValue + mnSpinSize : nValue + mnSpinSize - nRemainder;
     else
@@ -671,7 +685,7 @@ void NumericFormatter::FieldUp()
 void NumericFormatter::FieldDown()
 {
     sal_Int64 nValue = GetValue();
-    sal_Int64 nRemainder = nValue % mnSpinSize;
+    sal_Int64 nRemainder = mbDisableRemainderFactor ? 0 : (nValue % mnSpinSize);
     if (nValue >= 0)
         nValue = (nRemainder == 0) ? nValue - mnSpinSize : nValue - nRemainder;
     else
diff --git a/vcl/source/control/field2.cxx b/vcl/source/control/field2.cxx
index dff8cee200b5..12a4e7dc4ff9 100644
--- a/vcl/source/control/field2.cxx
+++ b/vcl/source/control/field2.cxx
@@ -1964,9 +1964,8 @@ static bool ImplCutTimePortion( OUStringBuffer& _rStr, sal_Int32 _nSepPos, bool
     return true;
 }
 
-static bool ImplTimeGetValue( const OUString& rStr, tools::Time& rTime,
-                              TimeFieldFormat eFormat, bool bDuration,
-                              const LocaleDataWrapper& rLocaleDataWrapper, bool _bSkipInvalidCharacters = true )
+bool TimeFormatter::TextToTime(const OUString& rStr, tools::Time& rTime, TimeFieldFormat eFormat,
+    bool bDuration, const LocaleDataWrapper& rLocaleDataWrapper, bool _bSkipInvalidCharacters)
 {
     OUStringBuffer    aStr    = rStr;
     short       nHour   = 0;
@@ -2161,7 +2160,7 @@ static bool ImplTimeGetValue( const OUString& rStr, tools::Time& rTime,
 bool TimeFormatter::ImplTimeReformat( const OUString& rStr, OUString& rOutStr )
 {
     tools::Time aTime( 0, 0, 0 );
-    if ( !ImplTimeGetValue( rStr, aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() ) )
+    if ( !TextToTime( rStr, aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() ) )
         return true;
 
     tools::Time aTempTime = aTime;
@@ -2211,81 +2210,102 @@ bool TimeFormatter::ImplTimeReformat( const OUString& rStr, OUString& rOutStr )
 
     return true;
 }
+
 bool TimeFormatter::ImplAllowMalformedInput() const
 {
     return !IsEnforceValidValue();
 }
 
-void TimeField::ImplTimeSpinArea( bool bUp )
+int TimeFormatter::GetTimeArea(TimeFieldFormat eFormat, const OUString& rText, int nCursor,
+                                     const LocaleDataWrapper& rLocaleDataWrapper)
 {
-    if ( GetField() )
-    {
-        sal_Int32 nTimeArea = 0;
-        tools::Time aTime( GetTime() );
-        OUString aText( GetText() );
-        Selection aSelection( GetField()->GetSelection() );
+    int nTimeArea = 0;
 
-        // Area search
-        if ( GetFormat() != TimeFieldFormat::F_SEC_CS )
+    // Area search
+    if (eFormat != TimeFieldFormat::F_SEC_CS)
+    {
+        //Which area is the cursor in of HH:MM:SS.TT
+        for ( sal_Int32 i = 1, nPos = 0; i <= 4; i++ )
         {
-            //Which area is the cursor in of HH:MM:SS.TT
-            for ( sal_Int32 i = 1, nPos = 0; i <= 4; i++ )
+            sal_Int32 nPos1 = rText.indexOf(rLocaleDataWrapper.getTimeSep(), nPos);
+            sal_Int32 nPos2 = rText.indexOf(rLocaleDataWrapper.getTime100SecSep(), nPos);
+            //which ever comes first, bearing in mind that one might not be there
+            if (nPos1 >= 0 && nPos2 >= 0)
+                nPos = std::min(nPos1, nPos2);
+            else if (nPos1 >= 0)
+                nPos = nPos1;
+            else
+                nPos = nPos2;
+            if (nPos < 0 || nPos >= nCursor)
             {
-                sal_Int32 nPos1 = aText.indexOf( ImplGetLocaleDataWrapper().getTimeSep(), nPos );
-                sal_Int32 nPos2 = aText.indexOf( ImplGetLocaleDataWrapper().getTime100SecSep(), nPos );
-                //which ever comes first, bearing in mind that one might not be there
-                if (nPos1 >= 0 && nPos2 >= 0)
-                    nPos = std::min(nPos1, nPos2);
-                else if (nPos1 >= 0)
-                    nPos = nPos1;
-                else
-                    nPos = nPos2;
-                if ( nPos < 0 || nPos >= aSelection.Max() )
-                {
-                    nTimeArea = i;
-                    break;
-                }
-                else
-                    nPos++;
+                nTimeArea = i;
+                break;
             }
+            else
+                nPos++;
         }
+    }
+    else
+    {
+        sal_Int32 nPos = rText.indexOf(rLocaleDataWrapper.getTime100SecSep());
+        if (nPos < 0 || nPos >= nCursor)
+            nTimeArea = 3;
         else
+            nTimeArea = 4;
+    }
+
+    return nTimeArea;
+}
+
+tools::Time TimeFormatter::SpinTime(bool bUp, const tools::Time& rTime, TimeFieldFormat eFormat,
+                                    bool bDuration, const OUString& rText, int nCursor,
+                                    const LocaleDataWrapper& rLocaleDataWrapper)
+{
+    tools::Time aTime(rTime);
+
+    int nTimeArea = GetTimeArea(eFormat, rText, nCursor, rLocaleDataWrapper);
+
+    if ( nTimeArea )
+    {
+        tools::Time aAddTime( 0, 0, 0 );
+        if ( nTimeArea == 1 )
+            aAddTime = tools::Time( 1, 0 );
+        else if ( nTimeArea == 2 )
+            aAddTime = tools::Time( 0, 1 );
+        else if ( nTimeArea == 3 )
+            aAddTime = tools::Time( 0, 0, 1 );
+        else if ( nTimeArea == 4 )
+            aAddTime = tools::Time( 0, 0, 0, 1 );
+
+        if ( !bUp )
+            aAddTime = -aAddTime;
+
+        aTime += aAddTime;
+        if (!bDuration)
         {
-            sal_Int32 nPos = aText.indexOf( ImplGetLocaleDataWrapper().getTime100SecSep() );
-            if ( nPos < 0 || nPos >= aSelection.Max() )
-                nTimeArea = 3;
-            else
-                nTimeArea = 4;
+            tools::Time aAbsMaxTime( 23, 59, 59, 999999999 );
+            if ( aTime > aAbsMaxTime )
+                aTime = aAbsMaxTime;
+            tools::Time aAbsMinTime( 0, 0 );
+            if ( aTime < aAbsMinTime )
+                aTime = aAbsMinTime;
         }
+    }
 
-        if ( nTimeArea )
-        {
-            tools::Time aAddTime( 0, 0, 0 );
-            if ( nTimeArea == 1 )
-                aAddTime = tools::Time( 1, 0 );
-            else if ( nTimeArea == 2 )
-                aAddTime = tools::Time( 0, 1 );
-            else if ( nTimeArea == 3 )
-                aAddTime = tools::Time( 0, 0, 1 );
-            else if ( nTimeArea == 4 )
-                aAddTime = tools::Time( 0, 0, 0, 1 );
+    return aTime;
+}
 
-            if ( !bUp )
-                aAddTime = -aAddTime;
+void TimeField::ImplTimeSpinArea( bool bUp )
+{
+    if ( GetField() )
+    {
+        tools::Time aTime( GetTime() );
+        OUString aText( GetText() );
+        Selection aSelection( GetField()->GetSelection() );
 
-            aTime += aAddTime;
-            if ( !IsDuration() )
-            {
-                tools::Time aAbsMaxTime( 23, 59, 59, 999999999 );
-                if ( aTime > aAbsMaxTime )
-                    aTime = aAbsMaxTime;
-                tools::Time aAbsMinTime( 0, 0 );
-                if ( aTime < aAbsMinTime )
-                    aTime = aAbsMinTime;
-            }
-            ImplNewFieldValue( aTime );
-        }
+        aTime = TimeFormatter::SpinTime(bUp, aTime, GetFormat(), IsDuration(), aText, aSelection.Max(), ImplGetLocaleDataWrapper());
 
+        ImplNewFieldValue( aTime );
     }
 }
 
@@ -2329,7 +2349,7 @@ void TimeFormatter::SetMax( const tools::Time& rNewMax )
         ReformatAll();
 }
 
-void TimeFormatter::SetTimeFormat( TimeFormatter::TimeFormat eNewFormat )
+void TimeFormatter::SetTimeFormat( TimeFormat eNewFormat )
 {
     mnTimeFormat = eNewFormat;
 }
@@ -2383,6 +2403,54 @@ void TimeFormatter::ImplNewFieldValue( const tools::Time& rTime )
     }
 }
 
+OUString TimeFormatter::FormatTime(const tools::Time& rNewTime, TimeFieldFormat eFormat, TimeFormat eHourFormat, bool bDuration, const LocaleDataWrapper& rLocaleData)
+{
+    OUString aStr;
+    bool bSec    = false;
+    bool b100Sec = false;
+    if ( eFormat != TimeFieldFormat::F_NONE )
+        bSec = true;
+    if ( eFormat == TimeFieldFormat::F_SEC_CS )
+        b100Sec = true;
+    if ( eFormat == TimeFieldFormat::F_SEC_CS )
+    {
+        sal_uLong n  = rNewTime.GetHour() * 3600L;
+        n       += rNewTime.GetMin()  * 60L;
+        n       += rNewTime.GetSec();
+        aStr     = OUString::number( n );
+        aStr    += rLocaleData.getTime100SecSep();
+        std::ostringstream ostr;
+        ostr.fill('0');
+        ostr.width(9);
+        ostr << rNewTime.GetNanoSec();
+        aStr += OUString::createFromAscii(ostr.str().c_str());
+    }
+    else if ( bDuration )
+    {
+        aStr = rLocaleData.getDuration( rNewTime, bSec, b100Sec );
+    }
+    else
+    {
+        aStr = rLocaleData.getTime( rNewTime, bSec, b100Sec );
+        if ( eHourFormat == TimeFormat::Hour12 )
+        {
+            if ( rNewTime.GetHour() > 12 )
+            {
+                tools::Time aT( rNewTime );
+                aT.SetHour( aT.GetHour() % 12 );
+                aStr = rLocaleData.getTime( aT, bSec, b100Sec );
+            }
+            // Don't use LocaleDataWrapper, we want AM/PM
+            if ( rNewTime.GetHour() < 12 )
+                aStr += "AM"; // rLocaleData.getTimeAM();
+            else
+                aStr += "PM"; // rLocaleData.getTimePM();
+        }
+    }
+
+    return aStr;
+}
+
 void TimeFormatter::ImplSetUserTime( const tools::Time& rNewTime, Selection const * pNewSelection )
 {
     tools::Time aNewTime = rNewTime;
@@ -2394,49 +2462,7 @@ void TimeFormatter::ImplSetUserTime( const tools::Time& rNewTime, Selection cons
 
     if ( GetField() )
     {
-        OUString aStr;
-        bool bSec    = false;
-        bool b100Sec = false;
-        if ( meFormat != TimeFieldFormat::F_NONE )
-            bSec = true;
-        if ( meFormat == TimeFieldFormat::F_SEC_CS )
-            b100Sec = true;
-        if ( meFormat == TimeFieldFormat::F_SEC_CS )
-        {
-            sal_uLong n  = aNewTime.GetHour() * 3600L;
-            n       += aNewTime.GetMin()  * 60L;
-            n       += aNewTime.GetSec();
-            aStr     = OUString::number( n );
-            aStr    += ImplGetLocaleDataWrapper().getTime100SecSep();
-            std::ostringstream ostr;
-            ostr.fill('0');
-            ostr.width(9);
-            ostr << aNewTime.GetNanoSec();
-            aStr += OUString::createFromAscii(ostr.str().c_str());
-        }
-        else if ( mbDuration )
-        {
-            aStr = ImplGetLocaleDataWrapper().getDuration( aNewTime, bSec, b100Sec );
-        }
-        else
-        {
-            aStr = ImplGetLocaleDataWrapper().getTime( aNewTime, bSec, b100Sec );
-            if ( GetTimeFormat() == TimeFormat::Hour12 )
-            {
-                if ( aNewTime.GetHour() > 12 )
-                {
-                    tools::Time aT( aNewTime );
-                    aT.SetHour( aT.GetHour() % 12 );
-                    aStr = ImplGetLocaleDataWrapper().getTime( aT, bSec, b100Sec );
-                }
-                // Don't use LocaleDataWrapper, we want AM/PM
-                if ( aNewTime.GetHour() < 12 )
-                    aStr += "AM"; // ImplGetLocaleDataWrapper().getTimeAM();
-                else
-                    aStr += "PM"; // ImplGetLocaleDataWrapper().getTimePM();
-            }
-        }
-
+        OUString aStr = TimeFormatter::FormatTime(aNewTime, meFormat, GetTimeFormat(), mbDuration, ImplGetLocaleDataWrapper());
         ImplSetText( aStr, pNewSelection );
     }
 }
@@ -2453,7 +2479,7 @@ tools::Time TimeFormatter::GetTime() const
     if ( GetField() )
     {
         bool bAllowMailformed = ImplAllowMalformedInput();
-        if ( ImplTimeGetValue( GetField()->GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), !bAllowMailformed ) )
+        if ( TextToTime( GetField()->GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), !bAllowMailformed ) )
         {
             if ( aTime > GetMax() )
                 aTime = GetMax();
@@ -2488,7 +2514,7 @@ void TimeFormatter::Reformat()
     if ( !aStr.isEmpty() )
     {
         ImplSetText( aStr );
-        ImplTimeGetValue( aStr, maLastTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() );
+        TextToTime( aStr, maLastTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() );
     }
     else
         SetTime( maLastTime );
@@ -2534,7 +2560,7 @@ bool TimeField::EventNotify( NotifyEvent& rNEvt )
             else
             {
                 tools::Time aTime( 0, 0, 0 );
-                if ( ImplTimeGetValue( GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), false ) )
+                if ( TextToTime( GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), false ) )
                     // even with strict text analysis, our text is a valid time -> do a complete
                     // reformat
                     Reformat();
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index 1b6b7726cf38..72f41efad638 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -242,6 +242,84 @@ namespace weld
     {
         return MetricField::ConvertValue(nValue, 0, m_xSpinButton->get_digits(), eInUnit, eOutUnit);
     }
+
+    IMPL_LINK_NOARG(TimeSpinButton, spin_button_cursor_position, Entry&, void)
+    {
+        int nStartPos, nEndPos;
+        m_xSpinButton->get_selection_bounds(nStartPos, nEndPos);
+
+        const SvtSysLocale aSysLocale;
+        const LocaleDataWrapper& rLocaleData = aSysLocale.GetLocaleData();
+        const int nTimeArea = TimeFormatter::GetTimeArea(m_eFormat, m_xSpinButton->get_text(), nEndPos,
+                                                         rLocaleData);
+
+        int nIncrements = 1;
+
+        if (nTimeArea == 1)
+            nIncrements = 1000 * 60 * 60;
+        else if (nTimeArea == 2)
+            nIncrements = 1000 * 60;
+        else if (nTimeArea == 3)
+            nIncrements = 1000;
+
+        m_xSpinButton->set_increments(nIncrements, nIncrements * 10);
+    }
+
+    IMPL_LINK_NOARG(TimeSpinButton, spin_button_value_changed, SpinButton&, void)
+    {
+        signal_value_changed();
+    }
+
+    IMPL_LINK(TimeSpinButton, spin_button_output, SpinButton&, rSpinButton, void)
+    {
+        int nStartPos, nEndPos;
+        rSpinButton.get_selection_bounds(nStartPos, nEndPos);
+        rSpinButton.set_text(format_number(rSpinButton.get_value()));
+        rSpinButton.set_position(nEndPos);
+    }
+
+    IMPL_LINK(TimeSpinButton, spin_button_input, int*, result, bool)
+    {
+        int nStartPos, nEndPos;
+        m_xSpinButton->get_selection_bounds(nStartPos, nEndPos);
+
+        const SvtSysLocale aSysLocale;
+        const LocaleDataWrapper& rLocaleData = aSysLocale.GetLocaleData();
+        tools::Time aResult(0);
+        bool bRet = TimeFormatter::TextToTime(m_xSpinButton->get_text(), aResult, m_eFormat, true, rLocaleData);
+        if (bRet)
+            *result = ConvertValue(aResult);
+        return bRet;
+    }
+
+    void TimeSpinButton::update_width_chars()
+    {
+        int min, max;
+        m_xSpinButton->get_range(min, max);
+        auto width = std::max(m_xSpinButton->get_pixel_size(format_number(min)).Width(),
+                              m_xSpinButton->get_pixel_size(format_number(max)).Width());
+        int chars = ceil(width / m_xSpinButton->get_approximate_digit_width());
+        m_xSpinButton->set_width_chars(chars);
+    }
+
+    tools::Time TimeSpinButton::ConvertValue(int nValue) const
+    {
+        tools::Time aTime(0);
+        aTime.MakeTimeFromMS(nValue);
+        return aTime;
+    }
+
+    int TimeSpinButton::ConvertValue(const tools::Time& rTime) const
+    {
+        return rTime.GetMSFromTime();
+    }
+
+    OUString TimeSpinButton::format_number(int nValue) const
+    {
+        const SvtSysLocale aSysLocale;
+        const LocaleDataWrapper& rLocaleData = aSysLocale.GetLocaleData();
+        return TimeFormatter::FormatTime(ConvertValue(nValue), m_eFormat, TimeFormat::Hour24, true, rLocaleData);
+    }
 }
 
 VclBuilder::VclBuilder(vcl::Window *pParent, const OUString& sUIDir, const OUString& sUIFile, const OString& sID,
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index d881155c7d40..f0cbf0ed97e4 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -2753,6 +2753,7 @@ private:
     GtkEntry* m_pEntry;
     gulong m_nChangedSignalId;
     gulong m_nInsertTextSignalId;
+    gulong m_nCursorPosSignalId;
 
     static void signalChanged(GtkEntry*, gpointer widget)
     {
@@ -2784,12 +2785,20 @@ private:
         }
         g_signal_stop_emission_by_name(pEntry, "insert-text");
     }
+
+    static void signalCursorPosition(GtkEntry*, GParamSpec*, gpointer widget)
+    {
+        GtkInstanceEntry* pThis = static_cast<GtkInstanceEntry*>(widget);
+        pThis->signal_cursor_position();
+    }
+
 public:
     GtkInstanceEntry(GtkEntry* pEntry, bool bTakeOwnership)
         : GtkInstanceWidget(GTK_WIDGET(pEntry), bTakeOwnership)
         , m_pEntry(pEntry)
         , m_nChangedSignalId(g_signal_connect(pEntry, "changed", G_CALLBACK(signalChanged), this))
         , m_nInsertTextSignalId(g_signal_connect(pEntry, "insert-text", G_CALLBACK(signalInsertText), this))
+        , m_nCursorPosSignalId(g_signal_connect(pEntry, "notify::cursor-position", G_CALLBACK(signalCursorPosition), this))
     {
     }
 
@@ -2941,6 +2950,7 @@ public:
 
     virtual ~GtkInstanceEntry() override
     {
+        g_signal_handler_disconnect(m_pEntry, m_nCursorPosSignalId);
         g_signal_handler_disconnect(m_pEntry, m_nInsertTextSignalId);
         g_signal_handler_disconnect(m_pEntry, m_nChangedSignalId);
     }
@@ -3279,6 +3289,7 @@ private:
     GtkSpinButton* m_pButton;
     gulong m_nValueChangedSignalId;
     gulong m_nOutputSignalId;
+    gulong m_nInputSignalId;
 
     static void signalValueChanged(GtkSpinButton*, gpointer widget)
     {
@@ -3294,6 +3305,22 @@ private:
         return pThis->signal_output();
     }
 
+    static gboolean signalInput(GtkSpinButton*, gdouble* new_value, gpointer widget)
+    {
+        GtkInstanceSpinButton* pThis = static_cast<GtkInstanceSpinButton*>(widget);
+        SolarMutexGuard aGuard;
+        int result;
+        TriState eHandled = pThis->signal_input(&result);
+        if (eHandled == TRISTATE_INDET)
+            return false;
+        if (eHandled == TRISTATE_TRUE)
+        {
+            *new_value = result;
+            return true;
+        }
+        return GTK_INPUT_ERROR;
+    }
+
     double toGtk(int nValue) const
     {
         return static_cast<double>(nValue) / Power10(get_digits());
@@ -3310,6 +3337,7 @@ public:
         , m_pButton(pButton)
         , m_nValueChangedSignalId(g_signal_connect(pButton, "value-changed", G_CALLBACK(signalValueChanged), this))
         , m_nOutputSignalId(g_signal_connect(pButton, "output", G_CALLBACK(signalOutput), this))
+        , m_nInputSignalId(g_signal_connect(pButton, "input", G_CALLBACK(signalInput), this))
     {
     }
 
@@ -3381,6 +3409,7 @@ public:
 
     virtual ~GtkInstanceSpinButton() override
     {
+        g_signal_handler_disconnect(m_pButton, m_nInputSignalId);
         g_signal_handler_disconnect(m_pButton, m_nOutputSignalId);
         g_signal_handler_disconnect(m_pButton, m_nValueChangedSignalId);
     }
@@ -4587,6 +4616,12 @@ public:
         return new GtkInstanceSpinButton(pSpinButton, bTakeOwnership);
     }
 
+    virtual weld::TimeSpinButton* weld_time_spin_button(const OString& id, TimeFieldFormat eFormat,
+                                                        bool bTakeOwnership) override
+    {
+        return new weld::TimeSpinButton(weld_spin_button(id, bTakeOwnership), eFormat);
+    }
+
     virtual weld::ComboBoxText* weld_combo_box_text(const OString &id, bool bTakeOwnership) override
     {
         GtkComboBoxText* pComboBoxText = GTK_COMBO_BOX_TEXT(gtk_builder_get_object(m_pBuilder, id.getStr()));


More information about the Libreoffice-commits mailing list