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@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/include/vcl/field.hxx b/include/vcl/field.hxx
index 3af20ff..8f4bf5b 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 e31c7cc..8697465 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 448a592..b7f53ab 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 4b1e402..65cfb1a 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 8683881..a306432 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 4bb21bc..ea97037 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"    );
    Link<weld::Button&,void> aLink( LINK( this, SdStartPresentationDlg, ChangeRangeHdl ) );

    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 );
    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() ) );
    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() ) );

    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)))) );
    int nPos = m_xLBMonitor->get_active();
    if (nPos != -1)
        rAttr.Put(SfxInt32Item(ATTR_PRESENT_DISPLAY, m_xLBMonitor->get_id(nPos).toInt32()));

    nPos = aLbCustomshow->GetSelectedEntryPos();
    if( nPos != LISTBOX_ENTRY_NOTFOUND )
    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)
{
    aCbxAutoLogo->Enable( aRbtAuto->IsChecked() && ( aTmfPause->GetTime().GetMSFromTime() > 0 ) );
    ChangePause();
}

void SdStartPresentationDlg::ChangePause()
{
    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 2c6131f..af5f634 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 d8bb343..66ba0a9 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 13da0d2..1a5ee50 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 f627bcf4..d81b2918 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:

    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;

    VclPtr<CheckBox>           aCbxManuel;
    VclPtr<CheckBox>           aCbxMousepointer;
    VclPtr<CheckBox>           aCbxPen;
    VclPtr<CheckBox>           aCbxAnimationAllowed;
    VclPtr<CheckBox>           aCbxChangePage;
    VclPtr<CheckBox>           aCbxAlwaysOnTop;

    VclPtr<FixedText>          maFtMonitor;
    VclPtr<ListBox>            maLBMonitor;

    SdCustomShowList*   pCustomShowList;
    const SfxItemSet&   rOutAttrs;
    sal_Int32           mnMonitors;

    VclPtr<FixedText>          msMonitor;
    VclPtr<FixedText>          msAllMonitors;
    VclPtr<FixedText>          msMonitorExternal;
    VclPtr<FixedText>          msExternal;
    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;

                        DECL_LINK( ChangeRangeHdl, Button*, void );
                        DECL_LINK( ClickWindowPresentationHdl, Button*, void );
                        DECL_LINK( ChangePauseHdl, Edit&, void );
    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;

    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;

    std::unique_ptr<weld::Label> m_xFtMonitor;
    std::unique_ptr<weld::ComboBoxText> m_xLBMonitor;

    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, 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 366f195..d85e2f1 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 713e5ac..d5d613b 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 6221a6f..1ebcfe9 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 dff8cee..12a4e7d 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();
}

int TimeFormatter::GetTimeArea(TimeFieldFormat eFormat, const OUString& rText, int nCursor,
                                     const LocaleDataWrapper& rLocaleDataWrapper)
{
    int nTimeArea = 0;

    // 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++ )
        {
            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)
            {
                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)
        {
            tools::Time aAbsMaxTime( 23, 59, 59, 999999999 );
            if ( aTime > aAbsMaxTime )
                aTime = aAbsMaxTime;
            tools::Time aAbsMinTime( 0, 0 );
            if ( aTime < aAbsMinTime )
                aTime = aAbsMinTime;
        }
    }

    return aTime;
}

void TimeField::ImplTimeSpinArea( bool bUp )
{
    if ( GetField() )
    {
        sal_Int32 nTimeArea = 0;
        tools::Time aTime( GetTime() );
        OUString aText( GetText() );
        Selection aSelection( GetField()->GetSelection() );

        // Area search
        if ( GetFormat() != 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++ )
            {
                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++;
            }
        }
        else
        {
            sal_Int32 nPos = aText.indexOf( ImplGetLocaleDataWrapper().getTime100SecSep() );
            if ( nPos < 0 || nPos >= aSelection.Max() )
                nTimeArea = 3;
            else
                nTimeArea = 4;
        }
        aTime = TimeFormatter::SpinTime(bUp, aTime, GetFormat(), IsDuration(), aText, aSelection.Max(), ImplGetLocaleDataWrapper());

        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 ( !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 );
        }

        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 1b6b772..72f41ef 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 d881155..f0cbf0e 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()));