summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2018-04-04 14:33:16 +0100
committerCaolán McNamara <caolanm@redhat.com>2018-04-07 17:46:39 +0200
commitc4764345e0d326c7a9d443f5af06f06854806bdc (patch)
treefa2b95cb454e3db9a683061a6a3b2bdaef11fada
parent20a35c313496b1ca63d3bb79e0a88a3d862d8747 (diff)
weld ScLinkedAreaDlg
Change-Id: I427e5abd76f6edfa891c9186d5822173d3fa7f7e Reviewed-on: https://gerrit.libreoffice.org/52513 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r--include/svtools/inettbc.hxx61
-rw-r--r--include/vcl/combobox.hxx1
-rw-r--r--include/vcl/edit.hxx3
-rw-r--r--include/vcl/weld.hxx11
-rw-r--r--sc/inc/scabstdlg.hxx2
-rw-r--r--sc/source/ui/attrdlg/scdlgfact.cxx21
-rw-r--r--sc/source/ui/attrdlg/scdlgfact.hxx10
-rw-r--r--sc/source/ui/docshell/arealink.cxx5
-rw-r--r--sc/source/ui/inc/linkarea.hxx47
-rw-r--r--sc/source/ui/miscdlgs/linkarea.cxx181
-rw-r--r--sc/source/ui/view/cellsh1.cxx2
-rw-r--r--sc/uiconfig/scalc/ui/externaldata.ui51
-rw-r--r--starmath/source/dialog.cxx4
-rw-r--r--svtools/source/control/inettbc.cxx955
-rw-r--r--vcl/source/app/salvtables.cxx34
-rw-r--r--vcl/source/control/combobox.cxx3
-rw-r--r--vcl/source/control/edit.cxx8
-rw-r--r--vcl/unx/gtk3/gtk3gtkinst.cxx159
18 files changed, 1369 insertions, 189 deletions
diff --git a/include/svtools/inettbc.hxx b/include/svtools/inettbc.hxx
index d2b6707c0a5f..133978045054 100644
--- a/include/svtools/inettbc.hxx
+++ b/include/svtools/inettbc.hxx
@@ -26,7 +26,10 @@
#include <tools/urlobj.hxx>
#include <vcl/combobox.hxx>
+#include <vcl/idle.hxx>
+#include <vcl/weld.hxx>
+class MatchContext_Impl;
class SvtMatchContext_Impl;
class SvtURLBox_Impl;
class SVT_DLLPUBLIC SvtURLBox : public ComboBox
@@ -88,6 +91,64 @@ public:
{ return ( !aPlaceHolder.isEmpty() ) && ( aPlaceHolder == sToMatch ); }
};
+class SVT_DLLPUBLIC URLBox
+{
+ friend class MatchContext_Impl;
+ friend class SvtURLBox_Impl;
+
+ Idle aChangedIdle;
+ OUString aBaseURL;
+ OUString aPlaceHolder;
+ rtl::Reference< MatchContext_Impl > pCtx;
+ std::unique_ptr<SvtURLBox_Impl> pImpl;
+ INetProtocol eSmartProtocol;
+ bool bAutoCompleteMode : 1;
+ bool bOnlyDirectories : 1;
+ bool bHistoryDisabled : 1;
+
+ std::unique_ptr<weld::ComboBoxText> m_xWidget;
+
+ SVT_DLLPRIVATE bool ProcessKey( const vcl::KeyCode& rCode );
+ DECL_DLLPRIVATE_LINK( TryAutoComplete, Timer*, void);
+ SVT_DLLPRIVATE void UpdatePicklistForSmartProtocol_Impl();
+ DECL_DLLPRIVATE_LINK( ChangedHdl, weld::ComboBoxText&, void);
+ DECL_DLLPRIVATE_LINK( FocusInHdl, weld::Widget&, void);
+ DECL_DLLPRIVATE_LINK( FocusOutHdl, weld::Widget&, void);
+ SVT_DLLPRIVATE void Init();
+
+public:
+ URLBox(weld::ComboBoxText* pWidget);
+ ~URLBox();
+
+ void SetText(const OUString& rStr) { m_xWidget->set_entry_text(rStr); }
+ void Clear() { m_xWidget->clear(); }
+ void connect_entry_activate(const Link<weld::ComboBoxText&, void>& rLink) { m_xWidget->connect_entry_activate(rLink); }
+ void append_text(const OUString& rStr) { m_xWidget->append_text(rStr); }
+ OUString get_text(int nIndex) { return m_xWidget->get_text(nIndex); }
+ void select_entry_region(int nStartPos, int nEndPos) { m_xWidget->select_entry_region(nStartPos, nEndPos); }
+ void EnableAutocomplete() { m_xWidget->set_entry_completion(true); }
+
+ void SetBaseURL( const OUString& rURL );
+ const OUString& GetBaseURL() const { return aBaseURL; }
+ void SetOnlyDirectories( bool bDir );
+ INetProtocol GetSmartProtocol() const { return eSmartProtocol; }
+ void SetSmartProtocol( INetProtocol eProt );
+ OUString GetURL();
+ void DisableHistory();
+
+ void UpdatePickList( );
+
+ static OUString ParseSmart( const OUString& aText, const OUString& aBaseURL );
+
+ void SetFilter(const OUString& _sFilter);
+
+ void SetPlaceHolder( const OUString& sPlaceHolder )
+ { aPlaceHolder = sPlaceHolder; }
+ const OUString& GetPlaceHolder() { return aPlaceHolder; }
+ bool MatchesPlaceHolder( const OUString& sToMatch ) const
+ { return ( !aPlaceHolder.isEmpty() ) && ( aPlaceHolder == sToMatch ); }
+};
+
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/vcl/combobox.hxx b/include/vcl/combobox.hxx
index ddfe65186a18..2f7efd3e006e 100644
--- a/include/vcl/combobox.hxx
+++ b/include/vcl/combobox.hxx
@@ -121,6 +121,7 @@ public:
const Link<ComboBox&,void>& GetSelectHdl() const;
void SetDoubleClickHdl(const Link<ComboBox&,void>& rLink);
const Link<ComboBox&,void>& GetDoubleClickHdl() const;
+ void SetEntryActivateHdl(const Link<Edit&,void>& rLink);
Size CalcMinimumSize() const override;
virtual Size GetOptimalSize() const override;
diff --git a/include/vcl/edit.hxx b/include/vcl/edit.hxx
index d4a9b418c7ab..c55a19eb02c0 100644
--- a/include/vcl/edit.hxx
+++ b/include/vcl/edit.hxx
@@ -97,6 +97,7 @@ private:
Link<Edit&,void> maModifyHdl;
Link<Edit&,void> maUpdateDataHdl;
Link<Edit&,void> maAutocompleteHdl;
+ Link<Edit&,void> maActivateHdl;
std::unique_ptr<VclBuilder> mpUIBuilder;
css::uno::Reference<css::i18n::XExtendedInputSequenceChecker> mxISC;
@@ -237,6 +238,8 @@ public:
virtual const Link<Edit&,void>& GetModifyHdl() const { return maModifyHdl; }
virtual void SetUpdateDataHdl( const Link<Edit&,void>& rLink ) { maUpdateDataHdl = rLink; }
+ void SetActivateHdl(const Link<Edit&,void>& rLink) { maActivateHdl = rLink; }
+
void SetSubEdit( Edit* pEdit );
Edit* GetSubEdit() const { return mpSubEdit; }
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 52f247921289..33efcd3e0e41 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -197,6 +197,7 @@ private:
protected:
Link<ComboBoxText&, void> m_aChangeHdl;
+ Link<ComboBoxText&, void> m_aEntryActivateHdl;
void signal_changed() { m_aChangeHdl.Call(*this); }
@@ -227,8 +228,12 @@ public:
virtual void set_entry_text(const OUString& rStr) = 0;
virtual void select_entry_region(int nStartPos, int nEndPos) = 0;
virtual bool get_entry_selection_bounds(int& rStartPos, int& rEndPos) = 0;
+ virtual void set_entry_completion(bool bEnable) = 0;
- virtual void unset_entry_completion() = 0;
+ void connect_entry_activate(const Link<ComboBoxText&, void>& rLink)
+ {
+ m_aEntryActivateHdl = rLink;
+ }
void save_value() { m_sSavedValue = get_active_text(); }
@@ -262,6 +267,7 @@ public:
virtual void set_top_entry(int pos) = 0;
virtual void clear() = 0;
virtual OUString get_selected() const = 0;
+ virtual std::vector<OUString> get_selected_rows() const = 0;
OUString get_selected_id() const { return get_id(get_selected_index()); }
virtual int get_selected_index() const = 0;
virtual OUString get(int pos) const = 0;
@@ -271,6 +277,9 @@ public:
virtual void freeze() = 0;
virtual void thaw() = 0;
+ virtual void set_selection_mode(bool bMultiple) = 0;
+ virtual int count_selected_rows() const = 0;
+
void connect_changed(const Link<TreeView&, void>& rLink) { m_aChangeHdl = rLink; }
void connect_row_activated(const Link<TreeView&, void>& rLink) { m_aRowActivatedHdl = rLink; }
diff --git a/sc/inc/scabstdlg.hxx b/sc/inc/scabstdlg.hxx
index d90cc4ed9810..ccdd419f2a69 100644
--- a/sc/inc/scabstdlg.hxx
+++ b/sc/inc/scabstdlg.hxx
@@ -454,7 +454,7 @@ public:
virtual VclPtr<AbstractScSelEntryDlg > CreateScSelEntryDlg ( vcl::Window* pParent,
const std::vector<OUString> &rEntryList ) = 0;
- virtual VclPtr<AbstractScLinkedAreaDlg> CreateScLinkedAreaDlg(vcl::Window* pParent) = 0;
+ virtual VclPtr<AbstractScLinkedAreaDlg> CreateScLinkedAreaDlg(weld::Window* pParent) = 0;
virtual VclPtr<AbstractScMetricInputDlg> CreateScMetricInputDlg ( vcl::Window* pParent,
const OString& sDialogName,
diff --git a/sc/source/ui/attrdlg/scdlgfact.cxx b/sc/source/ui/attrdlg/scdlgfact.cxx
index b263ca09cc94..101ad4c56d96 100644
--- a/sc/source/ui/attrdlg/scdlgfact.cxx
+++ b/sc/source/ui/attrdlg/scdlgfact.cxx
@@ -115,7 +115,7 @@ AbstractScLinkedAreaDlg_Impl::~AbstractScLinkedAreaDlg_Impl()
}
short AbstractScLinkedAreaDlg_Impl::Execute()
{
- return pDlg->Execute();
+ return m_xDlg->run();
}
void ScAbstractTabDialog_Impl::SetCurPageId( sal_uInt16 nId )
@@ -393,32 +393,32 @@ void AbstractScLinkedAreaDlg_Impl::InitFromOldLink( const OUString& rFile, const
const OUString& rOptions, const OUString& rSource,
sal_uLong nRefresh )
{
- pDlg->InitFromOldLink( rFile, rFilter, rOptions, rSource, nRefresh);
+ m_xDlg->InitFromOldLink( rFile, rFilter, rOptions, rSource, nRefresh);
}
OUString AbstractScLinkedAreaDlg_Impl::GetURL()
{
- return pDlg->GetURL();
+ return m_xDlg->GetURL();
}
OUString AbstractScLinkedAreaDlg_Impl::GetFilter()
{
- return pDlg->GetFilter();
+ return m_xDlg->GetFilter();
}
OUString AbstractScLinkedAreaDlg_Impl::GetOptions()
{
- return pDlg->GetOptions();
+ return m_xDlg->GetOptions();
}
OUString AbstractScLinkedAreaDlg_Impl::GetSource()
{
- return pDlg->GetSource();
+ return m_xDlg->GetSource();
}
-sal_uLong AbstractScLinkedAreaDlg_Impl::GetRefresh()
+sal_uLong AbstractScLinkedAreaDlg_Impl::GetRefresh()
{
- return pDlg->GetRefresh();
+ return m_xDlg->GetRefresh();
}
ScConditionalFormatList* AbstractScCondFormatManagerDlg_Impl::GetConditionalFormatList()
@@ -742,10 +742,9 @@ VclPtr<AbstractScSelEntryDlg> ScAbstractDialogFactory_Impl::CreateScSelEntryDlg
return VclPtr<AbstractScSelEntryDlg_Impl>::Create( pDlg );
}
-VclPtr<AbstractScLinkedAreaDlg> ScAbstractDialogFactory_Impl::CreateScLinkedAreaDlg(vcl::Window* pParent)
+VclPtr<AbstractScLinkedAreaDlg> ScAbstractDialogFactory_Impl::CreateScLinkedAreaDlg(weld::Window* pParent)
{
- VclPtr<ScLinkedAreaDlg> pDlg = VclPtr<ScLinkedAreaDlg>::Create( pParent );
- return VclPtr<AbstractScLinkedAreaDlg_Impl>::Create( pDlg );
+ return VclPtr<AbstractScLinkedAreaDlg_Impl>::Create(new ScLinkedAreaDlg(pParent));
}
VclPtr<AbstractScMetricInputDlg> ScAbstractDialogFactory_Impl::CreateScMetricInputDlg ( vcl::Window* pParent,
diff --git a/sc/source/ui/attrdlg/scdlgfact.hxx b/sc/source/ui/attrdlg/scdlgfact.hxx
index 33d471fec7af..86cf786de353 100644
--- a/sc/source/ui/attrdlg/scdlgfact.hxx
+++ b/sc/source/ui/attrdlg/scdlgfact.hxx
@@ -240,10 +240,12 @@ class AbstractScSelEntryDlg_Impl : public AbstractScSelEntryDlg
class AbstractScLinkedAreaDlg_Impl : public AbstractScLinkedAreaDlg
{
- ScopedVclPtr<ScLinkedAreaDlg> pDlg;
+ std::unique_ptr<ScLinkedAreaDlg> m_xDlg;
public:
- explicit AbstractScLinkedAreaDlg_Impl( ScLinkedAreaDlg* p)
- : pDlg(p) {}
+ explicit AbstractScLinkedAreaDlg_Impl(ScLinkedAreaDlg* p)
+ : m_xDlg(p)
+ {
+ }
virtual ~AbstractScLinkedAreaDlg_Impl() override;
virtual short Execute() override;
virtual void InitFromOldLink( const OUString& rFile, const OUString& rFilter,
@@ -459,7 +461,7 @@ public:
virtual VclPtr<AbstractScSelEntryDlg> CreateScSelEntryDlg ( vcl::Window* pParent,
const std::vector<OUString> &rEntryList ) override;
- virtual VclPtr<AbstractScLinkedAreaDlg> CreateScLinkedAreaDlg(vcl::Window* pParent) override;
+ virtual VclPtr<AbstractScLinkedAreaDlg> CreateScLinkedAreaDlg(weld::Window* pParent) override;
virtual VclPtr<AbstractScMetricInputDlg> CreateScMetricInputDlg ( vcl::Window* pParent,
const OString& sDialogName,
diff --git a/sc/source/ui/docshell/arealink.cxx b/sc/source/ui/docshell/arealink.cxx
index 8a75234cc686..c1def55db4d3 100644
--- a/sc/source/ui/docshell/arealink.cxx
+++ b/sc/source/ui/docshell/arealink.cxx
@@ -73,14 +73,13 @@ ScAreaLink::~ScAreaLink()
StopRefreshTimer();
}
-void ScAreaLink::Edit(weld::Window*, const Link<SvBaseLink&,void>& /* rEndEditHdl */ )
+void ScAreaLink::Edit(weld::Window* pParent, const Link<SvBaseLink&,void>& /* rEndEditHdl */ )
{
// use own dialog instead of SvBaseLink::Edit...
ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
OSL_ENSURE(pFact, "ScAbstractFactory create fail!");
-//TODO ScopedVclPtr<AbstractScLinkedAreaDlg> pDlg(pFact->CreateScLinkedAreaDlg(pParent));
- ScopedVclPtr<AbstractScLinkedAreaDlg> pDlg(pFact->CreateScLinkedAreaDlg(nullptr));
+ ScopedVclPtr<AbstractScLinkedAreaDlg> pDlg(pFact->CreateScLinkedAreaDlg(pParent));
OSL_ENSURE(pDlg, "Dialog create fail!");
pDlg->InitFromOldLink( aFileName, aFilterName, aOptions, aSourceArea, GetRefreshDelay() );
if ( pDlg->Execute() == RET_OK )
diff --git a/sc/source/ui/inc/linkarea.hxx b/sc/source/ui/inc/linkarea.hxx
index e0fef1f20f9e..564568419d30 100644
--- a/sc/source/ui/inc/linkarea.hxx
+++ b/sc/source/ui/inc/linkarea.hxx
@@ -20,12 +20,7 @@
#ifndef INCLUDED_SC_SOURCE_UI_INC_LINKAREA_HXX
#define INCLUDED_SC_SOURCE_UI_INC_LINKAREA_HXX
-#include <vcl/dialog.hxx>
-
-#include <vcl/button.hxx>
-#include <vcl/field.hxx>
-#include <vcl/fixed.hxx>
-#include <vcl/lstbox.hxx>
+#include <vcl/weld.hxx>
#include <sfx2/objsh.hxx>
#include <svtools/inettbc.hxx>
@@ -34,27 +29,26 @@ namespace sfx2 { class FileDialogHelper; }
class ScDocShell;
-class ScLinkedAreaDlg : public ModalDialog
+class ScLinkedAreaDlg : public weld::GenericDialogController
{
private:
- VclPtr<SvtURLBox> m_pCbUrl;
- VclPtr<PushButton> m_pBtnBrowse;
- VclPtr<ListBox> m_pLbRanges;
- VclPtr<CheckBox> m_pBtnReload;
- VclPtr<NumericField> m_pNfDelay;
- VclPtr<FixedText> m_pFtSeconds;
- VclPtr<OKButton> m_pBtnOk;
-
- ScDocShell* pSourceShell;
- std::unique_ptr<sfx2::DocumentInserter> pDocInserter;
-
+ ScDocShell* m_pSourceShell;
+ std::unique_ptr<sfx2::DocumentInserter> m_xDocInserter;
SfxObjectShellRef aSourceRef;
- DECL_LINK(FileHdl, ComboBox&, void);
- DECL_LINK(BrowseHdl, Button*, void);
- DECL_LINK(RangeHdl, ListBox&, void);
- DECL_LINK(ReloadHdl, Button*, void);
- DECL_LINK( DialogClosedHdl, sfx2::FileDialogHelper*, void );
+ std::unique_ptr<URLBox> m_xCbUrl;
+ std::unique_ptr<weld::Button> m_xBtnBrowse;
+ std::unique_ptr<weld::TreeView> m_xLbRanges;
+ std::unique_ptr<weld::CheckButton> m_xBtnReload;
+ std::unique_ptr<weld::SpinButton> m_xNfDelay;
+ std::unique_ptr<weld::Label> m_xFtSeconds;
+ std::unique_ptr<weld::Button> m_xBtnOk;
+
+ DECL_LINK(FileHdl, weld::ComboBoxText&, void);
+ DECL_LINK(BrowseHdl, weld::Button&, void);
+ DECL_LINK(RangeHdl, weld::TreeView&, void);
+ DECL_LINK(ReloadHdl, weld::Button&, void);
+ DECL_LINK(DialogClosedHdl, sfx2::FileDialogHelper*, void);
void UpdateSourceRanges();
void UpdateEnable();
@@ -62,9 +56,8 @@ private:
const OUString& rOptions );
public:
- ScLinkedAreaDlg( vcl::Window* pParent );
- virtual ~ScLinkedAreaDlg() override;
- virtual void dispose() override;
+ ScLinkedAreaDlg(weld::Window* pParent);
+ virtual ~ScLinkedAreaDlg() override;
void InitFromOldLink( const OUString& rFile, const OUString& rFilter,
const OUString& rOptions, const OUString& rSource,
@@ -74,7 +67,7 @@ public:
OUString GetFilter(); // may be empty
OUString GetOptions(); // filter options
OUString GetSource(); // separated by ";"
- sal_uLong GetRefresh(); // 0 if disabled
+ sal_uLong GetRefresh(); // 0 if disabled
};
#endif
diff --git a/sc/source/ui/miscdlgs/linkarea.cxx b/sc/source/ui/miscdlgs/linkarea.cxx
index 257f07f24747..96cfee9ab2dc 100644
--- a/sc/source/ui/miscdlgs/linkarea.cxx
+++ b/sc/source/ui/miscdlgs/linkarea.cxx
@@ -37,62 +37,47 @@
#include <docsh.hxx>
#include <tablink.hxx>
-ScLinkedAreaDlg::ScLinkedAreaDlg(vcl::Window* pParent)
- : ModalDialog(pParent, "ExternalDataDialog", "modules/scalc/ui/externaldata.ui")
- , pSourceShell(nullptr)
- , pDocInserter(nullptr)
-
+ScLinkedAreaDlg::ScLinkedAreaDlg(weld::Window* pParent)
+ : GenericDialogController(pParent, "modules/scalc/ui/externaldata.ui", "ExternalDataDialog")
+ , m_pSourceShell(nullptr)
+ , m_xCbUrl(new URLBox(m_xBuilder->weld_combo_box_text("url")))
+ , m_xBtnBrowse(m_xBuilder->weld_button("browse"))
+ , m_xLbRanges(m_xBuilder->weld_tree_view("ranges"))
+ , m_xBtnReload(m_xBuilder->weld_check_button("reload"))
+ , m_xNfDelay(m_xBuilder->weld_spin_button("delay"))
+ , m_xFtSeconds(m_xBuilder->weld_label("secondsft"))
+ , m_xBtnOk(m_xBuilder->weld_button("ok"))
{
- get(m_pCbUrl, "url");
- get(m_pLbRanges, "ranges");
- m_pLbRanges->EnableMultiSelection(true);
- m_pLbRanges->SetDropDownLineCount(8);
- get(m_pBtnBrowse, "browse");
- get(m_pBtnReload, "reload");
- get(m_pNfDelay, "delay");
- get(m_pFtSeconds, "secondsft");
- get(m_pBtnOk, "ok");
-
- m_pCbUrl->SetSelectHdl( LINK( this, ScLinkedAreaDlg, FileHdl ) );
- m_pBtnBrowse->SetClickHdl( LINK( this, ScLinkedAreaDlg, BrowseHdl ) );
- m_pLbRanges->SetSelectHdl( LINK( this, ScLinkedAreaDlg, RangeHdl ) );
- m_pBtnReload->SetClickHdl( LINK( this, ScLinkedAreaDlg, ReloadHdl ) );
+ m_xLbRanges->set_selection_mode(true);
+
+ m_xCbUrl->connect_entry_activate(LINK( this, ScLinkedAreaDlg, FileHdl));
+ m_xBtnBrowse->connect_clicked(LINK( this, ScLinkedAreaDlg, BrowseHdl));
+ m_xLbRanges->connect_changed(LINK( this, ScLinkedAreaDlg, RangeHdl));
+ m_xLbRanges->set_size_request(m_xLbRanges->get_approximate_digit_width() * 54,
+ m_xLbRanges->get_height_rows(5));
+ m_xBtnReload->connect_clicked(LINK( this, ScLinkedAreaDlg, ReloadHdl));
UpdateEnable();
}
ScLinkedAreaDlg::~ScLinkedAreaDlg()
{
- disposeOnce();
-}
-
-void ScLinkedAreaDlg::dispose()
-{
- // pSourceShell is deleted by aSourceRef
- m_pCbUrl.clear();
- m_pBtnBrowse.clear();
- m_pLbRanges.clear();
- m_pBtnReload.clear();
- m_pNfDelay.clear();
- m_pFtSeconds.clear();
- m_pBtnOk.clear();
- ModalDialog::dispose();
}
#define FILTERNAME_HTML "HTML (StarCalc)"
#define FILTERNAME_QUERY "calc_HTML_WebQuery"
-IMPL_LINK_NOARG(ScLinkedAreaDlg, BrowseHdl, Button*, void)
+IMPL_LINK_NOARG(ScLinkedAreaDlg, BrowseHdl, weld::Button&, void)
{
- pDocInserter.reset( new sfx2::DocumentInserter(GetFrameWeld(), ScDocShell::Factory().GetFactoryName()) );
- pDocInserter->StartExecuteModal( LINK( this, ScLinkedAreaDlg, DialogClosedHdl ) );
+ m_xDocInserter.reset( new sfx2::DocumentInserter(m_xDialog.get(), ScDocShell::Factory().GetFactoryName()) );
+ m_xDocInserter->StartExecuteModal( LINK( this, ScLinkedAreaDlg, DialogClosedHdl ) );
}
-IMPL_LINK_NOARG(ScLinkedAreaDlg, FileHdl, ComboBox&, void)
+IMPL_LINK_NOARG(ScLinkedAreaDlg, FileHdl, weld::ComboBoxText&, void)
{
- OUString aEntered = m_pCbUrl->GetURL();
- if (pSourceShell)
+ OUString aEntered = m_xCbUrl->GetURL();
+ if (m_pSourceShell)
{
- SfxMedium* pMed = pSourceShell->GetMedium();
+ SfxMedium* pMed = m_pSourceShell->GetMedium();
if ( aEntered == pMed->GetName() )
{
// already loaded - nothing to do
@@ -104,7 +89,7 @@ IMPL_LINK_NOARG(ScLinkedAreaDlg, FileHdl, ComboBox&, void)
OUString aOptions;
// get filter name by looking at the file content (bWithContent = true)
// Break operation if any error occurred inside.
- if (!ScDocumentLoader::GetFilterName( aEntered, aFilter, aOptions, true, true ))
+ if (!ScDocumentLoader::GetFilterName( aEntered, aFilter, aOptions, true, false ))
return;
// #i53241# replace HTML filter with DataQuery filter
@@ -119,32 +104,32 @@ IMPL_LINK_NOARG(ScLinkedAreaDlg, FileHdl, ComboBox&, void)
void ScLinkedAreaDlg::LoadDocument( const OUString& rFile, const OUString& rFilter, const OUString& rOptions )
{
- if ( pSourceShell )
+ if (m_pSourceShell)
{
// unload old document
- pSourceShell->DoClose();
- pSourceShell = nullptr;
+ m_pSourceShell->DoClose();
+ m_pSourceShell = nullptr;
aSourceRef.clear();
}
if ( !rFile.isEmpty() )
{
- WaitObject aWait( this );
+ weld::WaitObject aWait(m_xDialog.get());
OUString aNewFilter = rFilter;
OUString aNewOptions = rOptions;
SfxErrorContext aEc( ERRCTX_SFX_OPENDOC, rFile );
- ScDocumentLoader aLoader( rFile, aNewFilter, aNewOptions, 0, GetFrameWeld() ); // with interaction
- pSourceShell = aLoader.GetDocShell();
- if ( pSourceShell )
+ ScDocumentLoader aLoader( rFile, aNewFilter, aNewOptions, 0, m_xDialog.get() ); // with interaction
+ m_pSourceShell = aLoader.GetDocShell();
+ if (m_pSourceShell)
{
- ErrCode nErr = pSourceShell->GetErrorCode();
+ ErrCode nErr = m_pSourceShell->GetErrorCode();
if (nErr)
ErrorHandler::HandleError( nErr ); // including warnings
- aSourceRef = pSourceShell;
+ aSourceRef = m_pSourceShell;
aLoader.ReleaseDocRef(); // don't call DoClose in DocLoader dtor
}
}
@@ -155,13 +140,13 @@ void ScLinkedAreaDlg::InitFromOldLink( const OUString& rFile, const OUString& rF
sal_uLong nRefresh )
{
LoadDocument( rFile, rFilter, rOptions );
- if (pSourceShell)
+ if (m_pSourceShell)
{
- SfxMedium* pMed = pSourceShell->GetMedium();
- m_pCbUrl->SetText( pMed->GetName() );
+ SfxMedium* pMed = m_pSourceShell->GetMedium();
+ m_xCbUrl->SetText(pMed->GetName());
}
else
- m_pCbUrl->SetText( EMPTY_OUSTRING );
+ m_xCbUrl->SetText(EMPTY_OUSTRING);
UpdateSourceRanges();
@@ -169,23 +154,23 @@ void ScLinkedAreaDlg::InitFromOldLink( const OUString& rFile, const OUString& rF
for ( sal_Int32 i=0; i<nRangeCount; i++ )
{
OUString aRange = rSource.getToken(i,';');
- m_pLbRanges->SelectEntry( aRange );
+ m_xLbRanges->select(aRange);
}
bool bDoRefresh = (nRefresh != 0);
- m_pBtnReload->Check( bDoRefresh );
+ m_xBtnReload->set_active(bDoRefresh);
if (bDoRefresh)
- m_pNfDelay->SetValue( nRefresh );
+ m_xNfDelay->set_value(nRefresh);
UpdateEnable();
}
-IMPL_LINK_NOARG(ScLinkedAreaDlg, RangeHdl, ListBox&, void)
+IMPL_LINK_NOARG(ScLinkedAreaDlg, RangeHdl, weld::TreeView&, void)
{
UpdateEnable();
}
-IMPL_LINK_NOARG(ScLinkedAreaDlg, ReloadHdl, Button*, void)
+IMPL_LINK_NOARG(ScLinkedAreaDlg, ReloadHdl, weld::Button&, void)
{
UpdateEnable();
}
@@ -195,10 +180,10 @@ IMPL_LINK( ScLinkedAreaDlg, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg,
if ( _pFileDlg->GetError() != ERRCODE_NONE )
return;
- SfxMedium* pMed = pDocInserter->CreateMedium();
+ SfxMedium* pMed = m_xDocInserter->CreateMedium();
if ( pMed )
{
- WaitObject aWait( this );
+ weld::WaitObject aWait(m_xDialog.get());
// replace HTML filter with DataQuery filter
const OUString aHTMLFilterName( FILTERNAME_HTML );
@@ -216,30 +201,30 @@ IMPL_LINK( ScLinkedAreaDlg, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg,
// ERRCTX_SFX_OPENDOC -> "Error loading document"
SfxErrorContext aEc( ERRCTX_SFX_OPENDOC, pMed->GetName() );
- if (pSourceShell)
- pSourceShell->DoClose(); // deleted when assigning aSourceRef
+ if (m_pSourceShell)
+ m_pSourceShell->DoClose(); // deleted when assigning aSourceRef
pMed->UseInteractionHandler( true ); // to enable the filter options dialog
- pSourceShell = new ScDocShell;
- aSourceRef = pSourceShell;
- pSourceShell->DoLoad( pMed );
+ m_pSourceShell = new ScDocShell;
+ aSourceRef = m_pSourceShell;
+ m_pSourceShell->DoLoad( pMed );
- ErrCode nErr = pSourceShell->GetErrorCode();
+ ErrCode nErr = m_pSourceShell->GetErrorCode();
if (nErr)
ErrorHandler::HandleError( nErr ); // including warnings
- if ( !pSourceShell->GetError() ) // only errors
+ if (!m_pSourceShell->GetError()) // only errors
{
- m_pCbUrl->SetText( pMed->GetName() );
+ m_xCbUrl->SetText(pMed->GetName());
}
else
{
- pSourceShell->DoClose();
- pSourceShell = nullptr;
+ m_pSourceShell->DoClose();
+ m_pSourceShell = nullptr;
aSourceRef.clear();
- m_pCbUrl->SetText( EMPTY_OUSTRING );
+ m_xCbUrl->SetText(EMPTY_OUSTRING);
}
}
@@ -252,46 +237,46 @@ IMPL_LINK( ScLinkedAreaDlg, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg,
void ScLinkedAreaDlg::UpdateSourceRanges()
{
- m_pLbRanges->SetUpdateMode(false);
+ m_xLbRanges->freeze();
- m_pLbRanges->Clear();
- if ( pSourceShell )
+ m_xLbRanges->clear();
+ if ( m_pSourceShell )
{
- std::shared_ptr<const SfxFilter> pFilter = pSourceShell->GetMedium()->GetFilter();
+ std::shared_ptr<const SfxFilter> pFilter = m_pSourceShell->GetMedium()->GetFilter();
if (pFilter && pFilter->GetFilterName() == SC_TEXT_CSV_FILTER_NAME)
{
// Insert dummy All range to have something selectable.
- m_pLbRanges->InsertEntry("CSV_all");
+ m_xLbRanges->append_text("CSV_all");
}
- ScAreaNameIterator aIter( &pSourceShell->GetDocument() );
+ ScAreaNameIterator aIter(&m_pSourceShell->GetDocument());
ScRange aDummy;
OUString aName;
while ( aIter.Next( aName, aDummy ) )
- m_pLbRanges->InsertEntry( aName );
+ m_xLbRanges->append_text(aName);
}
- m_pLbRanges->SetUpdateMode(true);
+ m_xLbRanges->thaw();
- if ( m_pLbRanges->GetEntryCount() == 1 )
- m_pLbRanges->SelectEntryPos(0);
+ if (m_xLbRanges->n_children() == 1)
+ m_xLbRanges->select(0);
}
void ScLinkedAreaDlg::UpdateEnable()
{
- bool bEnable = ( pSourceShell && m_pLbRanges->GetSelectedEntryCount() );
- m_pBtnOk->Enable( bEnable );
+ bool bEnable = ( m_pSourceShell && m_xLbRanges->count_selected_rows() );
+ m_xBtnOk->set_sensitive(bEnable);
- bool bReload = m_pBtnReload->IsChecked();
- m_pNfDelay->Enable( bReload );
- m_pFtSeconds->Enable( bReload );
+ bool bReload = m_xBtnReload->get_active();
+ m_xNfDelay->set_sensitive(bReload);
+ m_xFtSeconds->set_sensitive(bReload);
}
OUString ScLinkedAreaDlg::GetURL()
{
- if (pSourceShell)
+ if (m_pSourceShell)
{
- SfxMedium* pMed = pSourceShell->GetMedium();
+ SfxMedium* pMed = m_pSourceShell->GetMedium();
return pMed->GetName();
}
return EMPTY_OUSTRING;
@@ -299,9 +284,9 @@ OUString ScLinkedAreaDlg::GetURL()
OUString ScLinkedAreaDlg::GetFilter()
{
- if (pSourceShell)
+ if (m_pSourceShell)
{
- SfxMedium* pMed = pSourceShell->GetMedium();
+ SfxMedium* pMed = m_pSourceShell->GetMedium();
return pMed->GetFilter()->GetFilterName();
}
return OUString();
@@ -309,9 +294,9 @@ OUString ScLinkedAreaDlg::GetFilter()
OUString ScLinkedAreaDlg::GetOptions()
{
- if (pSourceShell)
+ if (m_pSourceShell)
{
- SfxMedium* pMed = pSourceShell->GetMedium();
+ SfxMedium* pMed = m_pSourceShell->GetMedium();
return ScDocumentLoader::GetOptions( *pMed );
}
return OUString();
@@ -320,20 +305,20 @@ OUString ScLinkedAreaDlg::GetOptions()
OUString ScLinkedAreaDlg::GetSource()
{
OUStringBuffer aBuf;
- const sal_Int32 nCount = m_pLbRanges->GetSelectedEntryCount();
- for (sal_Int32 i=0; i<nCount; ++i)
+ std::vector<OUString> aSelection = m_xLbRanges->get_selected_rows();
+ for (size_t i = 0; i < aSelection.size(); ++i)
{
if (i > 0)
aBuf.append(';');
- aBuf.append(m_pLbRanges->GetSelectedEntry(i));
+ aBuf.append(aSelection[i]);
}
return aBuf.makeStringAndClear();
}
sal_uLong ScLinkedAreaDlg::GetRefresh()
{
- if ( m_pBtnReload->IsChecked() )
- return sal::static_int_cast<sal_uLong>( m_pNfDelay->GetValue() );
+ if (m_xBtnReload->get_active())
+ return sal::static_int_cast<sal_uLong>(m_xNfDelay->get_value());
else
return 0; // disabled
}
diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx
index 80b3ccf6d888..97892de03912 100644
--- a/sc/source/ui/view/cellsh1.cxx
+++ b/sc/source/ui/view/cellsh1.cxx
@@ -2626,7 +2626,7 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )
pImpl->m_pLinkedDlg.disposeAndClear();
pImpl->m_pLinkedDlg =
- pFact->CreateScLinkedAreaDlg(pTabViewShell->GetDialogParent());
+ pFact->CreateScLinkedAreaDlg(pTabViewShell->GetFrameWeld());
OSL_ENSURE(pImpl->m_pLinkedDlg, "Dialog create fail!");
delete pImpl->m_pRequest;
pImpl->m_pRequest = new SfxRequest( rReq );
diff --git a/sc/uiconfig/scalc/ui/externaldata.ui b/sc/uiconfig/scalc/ui/externaldata.ui
index 040213842c3a..449cce77cd7e 100644
--- a/sc/uiconfig/scalc/ui/externaldata.ui
+++ b/sc/uiconfig/scalc/ui/externaldata.ui
@@ -1,8 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.18.3 -->
+<!-- Generated with glade 3.20.4 -->
<interface domain="sc">
<requires lib="gtk+" version="3.18"/>
- <requires lib="LibreOffice" version="1.0"/>
<object class="GtkAdjustment" id="adjustment1">
<property name="lower">1</property>
<property name="upper">99999</property>
@@ -10,10 +9,21 @@
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
+ <object class="GtkListStore" id="liststore1">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
<object class="GtkDialog" id="ExternalDataDialog">
<property name="can_focus">False</property>
<property name="border_width">6</property>
<property name="title" translatable="yes" context="externaldata|ExternalDataDialog">External Data</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">
@@ -82,6 +92,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
+ <property name="vexpand">True</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
@@ -112,21 +123,20 @@
<property name="hexpand">True</property>
<property name="spacing">12</property>
<child>
- <object class="svtlo-SvtURLBox" id="url">
+ <object class="GtkComboBoxText" id="url">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes" context="externaldata|url|tooltip_text">Enter the URL of the source document in the local file system or Internet here.</property>
- <property name="hexpand">True</property>
<property name="has_entry">True</property>
- <property name="max_width_chars">48</property>
<child internal-child="entry">
- <object class="GtkEntry" id="URLBox-entry2">
- <property name="can_focus">False</property>
+ <object class="GtkEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
</object>
</child>
</object>
<packing>
- <property name="expand">False</property>
+ <property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
@@ -199,21 +209,35 @@
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
- <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="shadow_type">in</property>
<child>
- <object class="GtkTreeView" id="ranges:border">
+ <object class="GtkTreeView" id="ranges">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="hexpand">True</property>
<property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="headers_visible">False</property>
+ <property name="headers_clickable">False</property>
+ <property name="search_column">0</property>
+ <property name="show_expanders">False</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection1"/>
</child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
</object>
</child>
</object>
@@ -302,9 +326,9 @@
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="xalign">0.47999998927116394</property>
<property name="label" translatable="yes" context="externaldata|label2">_Available Tables/Ranges</property>
<property name="use_underline">True</property>
+ <property name="xalign">0.47999998927116394</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
@@ -331,5 +355,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/starmath/source/dialog.cxx b/starmath/source/dialog.cxx
index 38a4415b652d..176ad2352804 100644
--- a/starmath/source/dialog.cxx
+++ b/starmath/source/dialog.cxx
@@ -1981,8 +1981,8 @@ SmSymDefineDialog::SmSymDefineDialog(weld::Window* pParent, OutputDevice *pFntLi
{
// auto completion is troublesome since that symbols character also gets automatically selected in the
// display and if the user previously selected a character to define/redefine that one this is bad
- m_xOldSymbols->unset_entry_completion();
- m_xSymbols->unset_entry_completion();
+ m_xOldSymbols->set_entry_completion(false);
+ m_xSymbols->set_entry_completion(false);
FillFonts();
if (m_xFonts->get_count() > 0)
diff --git a/svtools/source/control/inettbc.cxx b/svtools/source/control/inettbc.cxx
index 8dab51f2ba1f..a1b3d744748d 100644
--- a/svtools/source/control/inettbc.cxx
+++ b/svtools/source/control/inettbc.cxx
@@ -120,6 +120,39 @@ public:
void Stop();
};
+class MatchContext_Impl: public salhelper::Thread
+{
+ static ::osl::Mutex* pDirMutex;
+
+ std::vector<OUString> aPickList;
+ std::vector<OUString> aCompletions;
+ std::vector<OUString> aURLs;
+ svtools::AsynchronLink aLink;
+ OUString aBaseURL;
+ OUString aText;
+ URLBox* pBox;
+ bool bOnlyDirectories;
+
+ osl::Mutex mutex_;
+ bool stopped_;
+ css::uno::Reference< css::ucb::XCommandProcessor > processor_;
+ sal_Int32 commandId_;
+
+ DECL_LINK( Select_Impl, void*, void );
+
+ virtual ~MatchContext_Impl() override;
+ virtual void execute() override;
+ void doExecute();
+ void Insert( const OUString& rCompletion, const OUString& rURL, bool bForce = false);
+ void ReadFolder( const OUString& rURL, const OUString& rMatch, bool bSmart );
+ static void FillPicklist(std::vector<OUString>& rPickList);
+
+public:
+ MatchContext_Impl( URLBox* pBoxP, const OUString& rText );
+ void Stop();
+};
+
+
namespace
{
struct theSvtMatchContextMutex
@@ -456,6 +489,319 @@ void SvtMatchContext_Impl::ReadFolder( const OUString& rURL,
}
}
+MatchContext_Impl::MatchContext_Impl(URLBox* pBoxP, const OUString& rText)
+ : Thread( "MatchContext_Impl" )
+ , aLink( LINK( this, MatchContext_Impl, Select_Impl ) )
+ , aBaseURL( pBoxP->aBaseURL )
+ , aText( rText )
+ , pBox( pBoxP )
+ , bOnlyDirectories( pBoxP->bOnlyDirectories )
+ , stopped_(false)
+ , commandId_(0)
+{
+ aLink.CreateMutex();
+
+ FillPicklist( aPickList );
+}
+
+MatchContext_Impl::~MatchContext_Impl()
+{
+ aLink.ClearPendingCall();
+}
+
+void MatchContext_Impl::FillPicklist(std::vector<OUString>& rPickList)
+{
+ // Read the history of picks
+ Sequence< Sequence< PropertyValue > > seqPicklist = SvtHistoryOptions().GetList( ePICKLIST );
+ sal_uInt32 nCount = seqPicklist.getLength();
+
+ for( sal_uInt32 nItem=0; nItem < nCount; nItem++ )
+ {
+ Sequence< PropertyValue > seqPropertySet = seqPicklist[ nItem ];
+
+ OUString sTitle;
+ INetURLObject aURL;
+
+ sal_uInt32 nPropertyCount = seqPropertySet.getLength();
+
+ for( sal_uInt32 nProperty=0; nProperty < nPropertyCount; nProperty++ )
+ {
+ if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_TITLE )
+ {
+ seqPropertySet[nProperty].Value >>= sTitle;
+ aURL.SetURL( sTitle );
+ rPickList.insert(rPickList.begin() + nItem, aURL.GetMainURL(INetURLObject::DecodeMechanism::WithCharset));
+ break;
+ }
+ }
+ }
+}
+
+void MatchContext_Impl::Stop()
+{
+ css::uno::Reference< css::ucb::XCommandProcessor > proc;
+ sal_Int32 id(0);
+ {
+ osl::MutexGuard g(mutex_);
+ if (!stopped_) {
+ stopped_ = true;
+ proc = processor_;
+ id = commandId_;
+ }
+ }
+ if (proc.is()) {
+ proc->abort(id);
+ }
+ terminate();
+}
+
+void MatchContext_Impl::execute( )
+{
+ doExecute();
+ aLink.Call( this );
+}
+
+
+// This method is called via AsynchronLink, so it has the SolarMutex and
+// calling solar code ( VCL ... ) is safe. It is called when the thread is
+// terminated ( finished work or stopped ). Cancelling the thread via
+// Cancellable does not discard the information gained so far, it
+// inserts all collected completions into the listbox.
+
+IMPL_LINK_NOARG( MatchContext_Impl, Select_Impl, void*, void )
+{
+ // avoid recursion through cancel button
+ {
+ osl::MutexGuard g(mutex_);
+ if (stopped_) {
+ // Completion was stopped, no display:
+ return;
+ }
+ }
+
+ pBox->bAutoCompleteMode = true;
+
+ // insert all completed strings into the listbox
+ pBox->Clear();
+
+ for (auto const& completion : aCompletions)
+ {
+ // convert the file into an URL
+ OUString sURL;
+ osl::FileBase::getFileURLFromSystemPath(completion, sURL);
+ // note: if this doesn't work, we're not interested in: we're checking the
+ // untouched sCompletion then
+
+ if ( !sURL.isEmpty() && !sURL.endsWith("/") )
+ {
+ OUString sUpperURL( sURL.toAsciiUpperCase() );
+
+ if ( ::std::none_of( pBox->pImpl->m_aFilters.begin(),
+ pBox->pImpl->m_aFilters.end(),
+ FilterMatch( sUpperURL ) ) )
+ { // this URL is not allowed
+ continue;
+ }
+ }
+
+ pBox->append_text(completion);
+ }
+
+ pBox->EnableAutocomplete();
+
+ // transfer string lists to listbox and forget them
+ pBox->pImpl->aURLs = aURLs;
+ pBox->pImpl->aCompletions = aCompletions;
+ aURLs.clear();
+ aCompletions.clear();
+
+ // the box has this control as a member so we have to set that member
+ // to zero before deleting ourself.
+ pBox->pCtx.clear();
+}
+
+void MatchContext_Impl::Insert( const OUString& rCompletion,
+ const OUString& rURL,
+ bool bForce )
+{
+ if( !bForce )
+ {
+ // avoid doubles
+ if(find(aCompletions.begin(), aCompletions.end(), rCompletion) != aCompletions.end())
+ return;
+ }
+
+ aCompletions.push_back(rCompletion);
+ aURLs.push_back(rURL);
+}
+
+
+void MatchContext_Impl::ReadFolder( const OUString& rURL,
+ const OUString& rMatch,
+ bool bSmart )
+{
+ // check folder to scan
+ if( !UCBContentHelper::IsFolder( rURL ) )
+ return;
+
+ bool bPureHomePath = false;
+#ifdef UNX
+ bPureHomePath = aText.startsWith( "~" ) && aText.indexOf( '/' ) == -1;
+#endif
+
+ bool bExectMatch = bPureHomePath
+ || aText == "."
+ || aText.endsWith("/.")
+ || aText.endsWith("/..");
+
+ // for pure home paths ( ~username ) the '.' at the end of rMatch
+ // means that it points to root catalog
+ // this is done only for file contents since home paths parsing is useful only for them
+ if ( bPureHomePath && rMatch == "file:///." )
+ {
+ // a home that refers to /
+
+ OUString aNewText( aText );
+ aNewText += "/";
+ Insert( aNewText, rURL, true );
+
+ return;
+ }
+
+ // string to match with
+ INetURLObject aMatchObj( rMatch );
+ OUString aMatchName;
+
+ if ( rURL != aMatchObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) )
+ {
+ aMatchName = aMatchObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset );
+
+ // matching is always done case insensitive, but completion will be case sensitive and case preserving
+ aMatchName = aMatchName.toAsciiLowerCase();
+
+ // if the matchstring ends with a slash, we must search for this also
+ if ( rMatch.endsWith("/") )
+ aMatchName += "/";
+ }
+
+ sal_Int32 nMatchLen = aMatchName.getLength();
+
+ INetURLObject aFolderObj( rURL );
+ DBG_ASSERT( aFolderObj.GetProtocol() != INetProtocol::NotValid, "Invalid URL!" );
+
+ try
+ {
+ Content aCnt( aFolderObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
+ new ::ucbhelper::CommandEnvironment( uno::Reference< XInteractionHandler >(),
+ uno::Reference< XProgressHandler >() ),
+ comphelper::getProcessComponentContext() );
+ uno::Reference< XResultSet > xResultSet;
+ Sequence< OUString > aProps(2);
+ OUString* pProps = aProps.getArray();
+ pProps[0] = "Title";
+ pProps[1] = "IsFolder";
+
+ try
+ {
+ uno::Reference< XDynamicResultSet > xDynResultSet;
+ ResultSetInclude eInclude = INCLUDE_FOLDERS_AND_DOCUMENTS;
+ if ( bOnlyDirectories )
+ eInclude = INCLUDE_FOLDERS_ONLY;
+
+ xDynResultSet = aCnt.createDynamicCursor( aProps, eInclude );
+
+ uno::Reference < XAnyCompareFactory > xCompare;
+ uno::Reference < XSortedDynamicResultSetFactory > xSRSFac =
+ SortedDynamicResultSetFactory::create( ::comphelper::getProcessComponentContext() );
+
+ Sequence< NumberedSortingInfo > aSortInfo( 2 );
+ NumberedSortingInfo* pInfo = aSortInfo.getArray();
+ pInfo[ 0 ].ColumnIndex = 2;
+ pInfo[ 0 ].Ascending = false;
+ pInfo[ 1 ].ColumnIndex = 1;
+ pInfo[ 1 ].Ascending = true;
+
+ uno::Reference< XDynamicResultSet > xDynamicResultSet;
+ xDynamicResultSet =
+ xSRSFac->createSortedDynamicResultSet( xDynResultSet, aSortInfo, xCompare );
+
+ if ( xDynamicResultSet.is() )
+ {
+ xResultSet = xDynamicResultSet->getStaticResultSet();
+ }
+ }
+ catch( css::uno::Exception& ) {}
+
+ if ( xResultSet.is() )
+ {
+ uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
+ uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
+
+ try
+ {
+ while ( schedule() && xResultSet->next() )
+ {
+ OUString aURL = xContentAccess->queryContentIdentifierString();
+ OUString aTitle = xRow->getString(1);
+ bool bIsFolder = xRow->getBoolean(2);
+
+ // matching is always done case insensitive, but completion will be case sensitive and case preserving
+ aTitle = aTitle.toAsciiLowerCase();
+
+ if (
+ !nMatchLen ||
+ (bExectMatch && aMatchName == aTitle) ||
+ (!bExectMatch && aTitle.startsWith(aMatchName))
+ )
+ {
+ // all names fit if matchstring is empty
+ INetURLObject aObj( aURL );
+ sal_Unicode aDelimiter = '/';
+ if ( bSmart )
+ // when parsing is done "smart", the delimiter must be "guessed"
+ aObj.getFSysPath( static_cast<FSysStyle>(FSysStyle::Detect & ~FSysStyle::Vos), &aDelimiter );
+
+ if ( bIsFolder )
+ aObj.setFinalSlash();
+
+ // get the last name of the URL
+ OUString aMatch = aObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset );
+ OUString aInput( aText );
+ if ( nMatchLen )
+ {
+ if (aText.endsWith(".") || bPureHomePath)
+ {
+ // if a "special folder" URL was typed, don't touch the user input
+ aMatch = aMatch.copy( nMatchLen );
+ }
+ else
+ {
+ // make the user input case preserving
+ DBG_ASSERT( aInput.getLength() >= nMatchLen, "Suspicious Matching!" );
+ aInput = aInput.copy( 0, aInput.getLength() - nMatchLen );
+ }
+ }
+
+ aInput += aMatch;
+
+ // folders should get a final slash automatically
+ if ( bIsFolder )
+ aInput += OUStringLiteral1(aDelimiter);
+
+ Insert( aInput, aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ), true );
+ }
+ }
+ }
+ catch( css::uno::Exception& )
+ {
+ }
+ }
+ }
+ catch( css::uno::Exception& )
+ {
+ }
+}
+
OUString SvtURLBox::ParseSmart( const OUString& _aText, const OUString& _aBaseURL )
{
OUString aMatch;
@@ -584,9 +930,9 @@ void SvtMatchContext_Impl::doExecute()
OUString aMainURL( aURLObject.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
// Disable autocompletion for anything but the (local) file
// system (for which access is hopefully fast), as the logic of
- // how SvtMatchContext_Impl is used requires this code to run to
+ // how MatchContext_Impl is used requires this code to run to
// completion before further user input is processed, and even
- // SvtMatchContext_Impl::Stop does not guarantee a speedy
+ // MatchContext_Impl::Stop does not guarantee a speedy
// return:
if ( !aMainURL.isEmpty()
&& aURLObject.GetProtocol() == INetProtocol::File )
@@ -661,7 +1007,252 @@ void SvtMatchContext_Impl::doExecute()
}
}
if ( folder )
- Insert( aText, aMatch );
+ Insert( aText, aMatch );
+ else
+ // otherwise the parent folder will be taken
+ aURLObject.removeSegment();
+
+ // scan directory and insert all matches
+ ReadFolder( aURLObject.GetMainURL( INetURLObject::DecodeMechanism::NONE ), aMatch, eProt == INetProtocol::NotValid );
+ }
+ }
+ }
+ }
+
+ if ( bOnlyDirectories )
+ // don't scan history picklist if only directories are allowed, picklist contains only files
+ return;
+
+ bool bFull = false;
+
+ INetURLObject aCurObj;
+ OUString aCurString, aCurMainURL;
+ INetURLObject aObj;
+ aObj.SetSmartProtocol( eSmartProt == INetProtocol::NotValid ? INetProtocol::Http : eSmartProt );
+ for( ;; )
+ {
+ for(std::vector<OUString>::iterator i = aPickList.begin(); schedule() && i != aPickList.end(); ++i)
+ {
+ aCurObj.SetURL(*i);
+ aCurObj.SetSmartURL( aCurObj.GetURLNoPass());
+ aCurMainURL = aCurObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ if( eProt != INetProtocol::NotValid && aCurObj.GetProtocol() != eProt )
+ continue;
+
+ if( eSmartProt != INetProtocol::NotValid && aCurObj.GetProtocol() != eSmartProt )
+ continue;
+
+ switch( aCurObj.GetProtocol() )
+ {
+ case INetProtocol::Http:
+ case INetProtocol::Https:
+ case INetProtocol::Ftp:
+ {
+ if( eProt == INetProtocol::NotValid && !bFull )
+ {
+ aObj.SetSmartURL( aText );
+ if( aObj.GetURLPath().getLength() > 1 )
+ continue;
+ }
+
+ aCurString = aCurMainURL;
+ if( eProt == INetProtocol::NotValid )
+ {
+ // try if text matches the scheme
+ OUString aScheme( INetURLObject::GetScheme( aCurObj.GetProtocol() ) );
+ if ( aScheme.startsWithIgnoreAsciiCase( aText ) && aText.getLength() < aScheme.getLength() )
+ {
+ if( bFull )
+ aMatch = aCurObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ else
+ {
+ aCurObj.SetMark( "" );
+ aCurObj.SetParam( "" );
+ aCurObj.SetURLPath( "" );
+ aMatch = aCurObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ }
+
+ Insert( aMatch, aMatch );
+ }
+
+ // now try smart matching
+ aCurString = aCurString.copy( aScheme.getLength() );
+ }
+
+ if( aCurString.startsWithIgnoreAsciiCase( aText ) )
+ {
+ if( bFull )
+ aMatch = aCurObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ else
+ {
+ aCurObj.SetMark( "" );
+ aCurObj.SetParam( "" );
+ aCurObj.SetURLPath( "" );
+ aMatch = aCurObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ }
+
+ OUString aURL( aMatch );
+ if( eProt == INetProtocol::NotValid )
+ aMatch = aMatch.copy( INetURLObject::GetScheme( aCurObj.GetProtocol() ).getLength() );
+
+ if( aText.getLength() < aMatch.getLength() )
+ Insert( aMatch, aURL );
+
+ continue;
+ }
+ break;
+ }
+ default:
+ {
+ if( bFull )
+ continue;
+
+ if( aCurMainURL.startsWith(aText) )
+ {
+ if( aText.getLength() < aCurMainURL.getLength() )
+ Insert( aCurMainURL, aCurMainURL );
+
+ continue;
+ }
+ break;
+ }
+ }
+ }
+
+ if( !bFull )
+ bFull = true;
+ else
+ break;
+ }
+}
+
+void MatchContext_Impl::doExecute()
+{
+ ::osl::MutexGuard aGuard( theSvtMatchContextMutex::get() );
+ {
+ // have we been stopped while we were waiting for the mutex?
+ osl::MutexGuard g(mutex_);
+ if (stopped_) {
+ return;
+ }
+ }
+
+ // Reset match lists
+ aCompletions.clear();
+ aURLs.clear();
+
+ // check for input
+ if ( aText.isEmpty() )
+ return;
+
+ if( aText.indexOf( '*' ) != -1 || aText.indexOf( '?' ) != -1 )
+ // no autocompletion for wildcards
+ return;
+
+ OUString aMatch;
+ INetProtocol eProt = INetURLObject::CompareProtocolScheme( aText );
+ INetProtocol eBaseProt = INetURLObject::CompareProtocolScheme( aBaseURL );
+ if ( aBaseURL.isEmpty() )
+ eBaseProt = INetURLObject::CompareProtocolScheme( SvtPathOptions().GetWorkPath() );
+ INetProtocol eSmartProt = pBox->GetSmartProtocol();
+
+ // if the user input is a valid URL, go on with it
+ // otherwise it could be parsed smart with a predefined smart protocol
+ // ( or if this is not set with the protocol of a predefined base URL )
+ if( eProt == INetProtocol::NotValid || eProt == eSmartProt || (eSmartProt == INetProtocol::NotValid && eProt == eBaseProt) )
+ {
+ // not stopped yet ?
+ if( schedule() )
+ {
+ if ( eProt == INetProtocol::NotValid )
+ aMatch = SvtURLBox::ParseSmart( aText, aBaseURL );
+ else
+ aMatch = aText;
+ if ( !aMatch.isEmpty() )
+ {
+ INetURLObject aURLObject( aMatch );
+ OUString aMainURL( aURLObject.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
+ // Disable autocompletion for anything but the (local) file
+ // system (for which access is hopefully fast), as the logic of
+ // how MatchContext_Impl is used requires this code to run to
+ // completion before further user input is processed, and even
+ // MatchContext_Impl::Stop does not guarantee a speedy
+ // return:
+ if ( !aMainURL.isEmpty()
+ && aURLObject.GetProtocol() == INetProtocol::File )
+ {
+ // if text input is a directory, it must be part of the match list! Until then it is scanned
+ bool folder = false;
+ if (aURLObject.hasFinalSlash()) {
+ try {
+ css::uno::Reference< css::uno::XComponentContext >
+ ctx(comphelper::getProcessComponentContext());
+ css::uno::Reference<
+ css::ucb::XUniversalContentBroker > ucb(
+ css::ucb::UniversalContentBroker::create(
+ ctx));
+ css::uno::Sequence< css::beans::Property > prop(1);
+ prop[0].Name = "IsFolder";
+ prop[0].Handle = -1;
+ prop[0].Type = cppu::UnoType< bool >::get();
+ css::uno::Any res;
+ css::uno::Reference< css::ucb::XCommandProcessor >
+ proc(
+ ucb->queryContent(
+ ucb->createContentIdentifier(aMainURL)),
+ css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::ucb::XCommandProcessor2 >
+ proc2(proc, css::uno::UNO_QUERY);
+ sal_Int32 id = proc->createCommandIdentifier();
+ try {
+ {
+ osl::MutexGuard g(mutex_);
+ processor_ = proc;
+ commandId_ = id;
+ }
+ res = proc->execute(
+ css::ucb::Command(
+ "getPropertyValues", -1,
+ css::uno::makeAny(prop)),
+ id,
+ css::uno::Reference<
+ css::ucb::XCommandEnvironment >());
+ } catch (...) {
+ if (proc2.is()) {
+ try {
+ proc2->releaseCommandIdentifier(id);
+ } catch (css::uno::RuntimeException & e) {
+ SAL_WARN("svtools.control", "ignoring " << e);
+ }
+ }
+ throw;
+ }
+ if (proc2.is()) {
+ proc2->releaseCommandIdentifier(id);
+ }
+ {
+ osl::MutexGuard g(mutex_);
+ processor_.clear();
+ // At least the neon-based WebDAV UCP does not
+ // properly support aborting commands, so return
+ // anyway now if an abort request had been
+ // ignored and the command execution only
+ // returned "successfully" after some timeout:
+ if (stopped_) {
+ return;
+ }
+ }
+ css::uno::Reference< css::sdbc::XRow > row(
+ res, css::uno::UNO_QUERY_THROW);
+ folder = row->getBoolean(1) && !row->wasNull();
+ } catch (css::uno::Exception & e) {
+ SAL_WARN("svtools.control", "ignoring " << e);
+ return;
+ }
+ }
+ if (folder)
+ Insert( aText, aMatch );
else
// otherwise the parent folder will be taken
aURLObject.removeSegment();
@@ -1325,4 +1916,362 @@ void SvtURLBox::SetFilter(const OUString& _sFilter)
FilterMatch::createWildCardFilterList(_sFilter,pImpl->m_aFilters);
}
+//--
+
+OUString URLBox::ParseSmart( const OUString& _aText, const OUString& _aBaseURL )
+{
+ OUString aMatch;
+ OUString aText = _aText;
+ OUString aBaseURL = _aBaseURL;
+
+ // parse ~ for Unix systems
+ // does nothing for Windows
+ if( !SvtURLBox_Impl::TildeParsing( aText, aBaseURL ) )
+ return OUString();
+
+ if( !aBaseURL.isEmpty() )
+ {
+ INetProtocol eBaseProt = INetURLObject::CompareProtocolScheme( aBaseURL );
+
+ // if a base URL is set the string may be parsed relative
+ if( aText.startsWith( "/" ) )
+ {
+ // text starting with slashes means absolute file URLs
+ OUString aTemp = INetURLObject::GetScheme( eBaseProt );
+
+ // file URL must be correctly encoded!
+ OUString aTextURL = INetURLObject::encode( aText, INetURLObject::PART_FPATH,
+ INetURLObject::EncodeMechanism::All );
+ aTemp += aTextURL;
+
+ INetURLObject aTmp( aTemp );
+ if ( !aTmp.HasError() && aTmp.GetProtocol() != INetProtocol::NotValid )
+ aMatch = aTmp.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ }
+ else
+ {
+ OUString aSmart( aText );
+ INetURLObject aObj( aBaseURL );
+
+ // HRO: I suppose this hack should only be done for Windows !!!???
+#ifdef _WIN32
+ // HRO: INetURLObject::smatRel2Abs does not recognize '\\' as a relative path
+ // but in case of "\\\\" INetURLObject is right - this is an absolute path !
+
+ if( aText.startsWith("\\") && (aText.getLength() < 2 || aText[ 1 ] != '\\') )
+ {
+ // cut to first segment
+ OUString aTmp = INetURLObject::GetScheme( eBaseProt );
+ aTmp += "/";
+ aTmp += aObj.getName( 0, true, INetURLObject::DecodeMechanism::WithCharset );
+ aObj.SetURL( aTmp );
+
+ aSmart = aSmart.copy(1);
+ }
+#endif
+ // base URL must be a directory !
+ aObj.setFinalSlash();
+
+ // take base URL and append current input
+ bool bWasAbsolute = false;
+#ifdef UNX
+ // encode file URL correctly
+ aSmart = INetURLObject::encode( aSmart, INetURLObject::PART_FPATH, INetURLObject::EncodeMechanism::All );
+#endif
+ INetURLObject aTmp( aObj.smartRel2Abs( aSmart, bWasAbsolute ) );
+
+ if ( aText.endsWith(".") )
+ // INetURLObject appends a final slash for the directories "." and "..", this is a bug!
+ // Remove it as a workaround
+ aTmp.removeFinalSlash();
+ if ( !aTmp.HasError() && aTmp.GetProtocol() != INetProtocol::NotValid )
+ aMatch = aTmp.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ }
+ }
+ else
+ {
+ OUString aTmpMatch;
+ osl::FileBase::getFileURLFromSystemPath( aText, aTmpMatch );
+ aMatch = aTmpMatch;
+ }
+
+ return aMatch;
+}
+
+IMPL_LINK_NOARG(URLBox, TryAutoComplete, Timer *, void)
+{
+ OUString aCurText = m_xWidget->get_active_text();
+ int nStartPos, nEndPos;
+ m_xWidget->get_entry_selection_bounds(nStartPos, nEndPos);
+ if (nEndPos != aCurText.getLength())
+ return;
+ aCurText = aCurText.copy(0, nStartPos);
+ if (!aCurText.isEmpty())
+ {
+ if (pCtx.is())
+ {
+ pCtx->Stop();
+ pCtx->join();
+ pCtx.clear();
+ }
+ pCtx = new MatchContext_Impl(this, aCurText);
+ pCtx->launch();
+ }
+ else
+ m_xWidget->clear();
+}
+
+URLBox::URLBox(weld::ComboBoxText* pWidget)
+ : eSmartProtocol(INetProtocol::NotValid)
+ , bAutoCompleteMode(false)
+ , bOnlyDirectories(false)
+ , bHistoryDisabled(false)
+ , m_xWidget(pWidget)
+{
+ Init();
+
+ m_xWidget->connect_focus_in(LINK(this, URLBox, FocusInHdl));
+ m_xWidget->connect_focus_out(LINK(this, URLBox, FocusOutHdl));
+ m_xWidget->connect_changed(LINK(this, URLBox, ChangedHdl));
+
+ aChangedIdle.SetInvokeHandler(LINK(this, URLBox, TryAutoComplete));
+ aChangedIdle.SetDebugName("svtools::URLBox aChangedIdle");
+}
+
+void URLBox::Init()
+{
+ pImpl.reset( new SvtURLBox_Impl );
+
+ m_xWidget->set_entry_completion(false);
+
+ UpdatePicklistForSmartProtocol_Impl();
+}
+
+URLBox::~URLBox()
+{
+ if (pCtx.is())
+ {
+ pCtx->Stop();
+ pCtx->join();
+ }
+}
+
+void URLBox::UpdatePickList( )
+{
+ if (pCtx.is())
+ {
+ pCtx->Stop();
+ pCtx->join();
+ pCtx.clear();
+ }
+ OUString sText = m_xWidget->get_active_text();
+ if (!sText.isEmpty())
+ {
+ pCtx = new MatchContext_Impl( this, sText );
+ pCtx->launch();
+ }
+}
+
+void URLBox::SetSmartProtocol( INetProtocol eProt )
+{
+ if ( eSmartProtocol != eProt )
+ {
+ eSmartProtocol = eProt;
+ UpdatePicklistForSmartProtocol_Impl();
+ }
+}
+
+void URLBox::UpdatePicklistForSmartProtocol_Impl()
+{
+ m_xWidget->clear();
+ if ( bHistoryDisabled )
+ return;
+
+ // read history pick list
+ Sequence< Sequence< PropertyValue > > seqPicklist = SvtHistoryOptions().GetList( ePICKLIST );
+ sal_uInt32 nCount = seqPicklist.getLength();
+ INetURLObject aCurObj;
+
+ for( sal_uInt32 nItem=0; nItem < nCount; nItem++ )
+ {
+ Sequence< PropertyValue > seqPropertySet = seqPicklist[ nItem ];
+
+ OUString sURL;
+
+ sal_uInt32 nPropertyCount = seqPropertySet.getLength();
+
+ for( sal_uInt32 nProperty=0; nProperty < nPropertyCount; nProperty++ )
+ {
+ if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_URL )
+ {
+ seqPropertySet[nProperty].Value >>= sURL;
+ aCurObj.SetURL( sURL );
+
+ if ( !sURL.isEmpty() && ( eSmartProtocol != INetProtocol::NotValid ) )
+ {
+ if( aCurObj.GetProtocol() != eSmartProtocol )
+ break;
+ }
+
+ OUString aURL( aCurObj.GetMainURL( INetURLObject::DecodeMechanism::WithCharset ) );
+
+ if ( !aURL.isEmpty() )
+ {
+ bool bFound = aURL.endsWith("/");
+ if ( !bFound )
+ {
+ OUString aUpperURL( aURL );
+ aUpperURL = aUpperURL.toAsciiUpperCase();
+
+ bFound = ::std::any_of(pImpl->m_aFilters.begin(),
+ pImpl->m_aFilters.end(),
+ FilterMatch( aUpperURL ) );
+ }
+ if ( bFound )
+ {
+ OUString aFile;
+ if (osl::FileBase::getSystemPathFromFileURL(aURL, aFile) == osl::FileBase::E_None)
+ m_xWidget->append_text(aFile);
+ else
+ m_xWidget->append_text(aURL);
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+IMPL_LINK_NOARG(URLBox, ChangedHdl, weld::ComboBoxText&, void)
+{
+ aChangedIdle.Start(); //launch this to happen on idle after cursor position will have been set
+}
+
+IMPL_LINK_NOARG(URLBox, FocusInHdl, weld::Widget&, void)
+{
+#ifndef UNX
+ // pb: don't select automatically on unix #93251#
+ m_xWidget->select_entry_region(0, -1);
+#endif
+}
+
+IMPL_LINK_NOARG(URLBox, FocusOutHdl, weld::Widget&, void)
+{
+ if (pCtx.is())
+ {
+ pCtx->Stop();
+ pCtx->join();
+ pCtx.clear();
+ }
+}
+
+void URLBox::SetOnlyDirectories( bool bDir )
+{
+ bOnlyDirectories = bDir;
+ if (bOnlyDirectories)
+ m_xWidget->clear();
+}
+
+OUString URLBox::GetURL()
+{
+ // wait for end of autocompletion
+ ::osl::MutexGuard aGuard( theSvtMatchContextMutex::get() );
+
+ OUString aText(m_xWidget->get_active_text());
+ if ( MatchesPlaceHolder( aText ) )
+ return aPlaceHolder;
+
+ // try to get the right case preserving URL from the list of URLs
+ for(std::vector<OUString>::iterator i = pImpl->aCompletions.begin(), j = pImpl->aURLs.begin(); i != pImpl->aCompletions.end() && j != pImpl->aURLs.end(); ++i, ++j)
+ {
+ if((*i) == aText)
+ return *j;
+ }
+
+#ifdef _WIN32
+ // erase trailing spaces on Windows since thay are invalid on this OS and
+ // most of the time they are inserted by accident via copy / paste
+ aText = comphelper::string::stripEnd(aText, ' ');
+ if ( aText.isEmpty() )
+ return aText;
+ // #i9739#
+#endif
+
+ INetURLObject aObj( aText );
+ if( aText.indexOf( '*' ) != -1 || aText.indexOf( '?' ) != -1 )
+ {
+ // no autocompletion for wildcards
+ INetURLObject aTempObj;
+ if ( eSmartProtocol != INetProtocol::NotValid )
+ aTempObj.SetSmartProtocol( eSmartProtocol );
+ if ( aTempObj.SetSmartURL( aText ) )
+ return aTempObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ else
+ return aText;
+ }
+
+ if ( aObj.GetProtocol() == INetProtocol::NotValid )
+ {
+ OUString aName = ParseSmart( aText, aBaseURL );
+ aObj.SetURL(aName);
+ OUString aURL( aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
+ if ( aURL.isEmpty() )
+ // aText itself is invalid, and even together with aBaseURL, it could not
+ // made valid -> no chance
+ return aText;
+
+ bool bSlash = aObj.hasFinalSlash();
+ {
+ const OUString aPropName("CasePreservingURL");
+
+ OUString aFileURL;
+
+ Any aAny = UCBContentHelper::GetProperty(aURL, aPropName);
+ bool success = (aAny >>= aFileURL);
+ OUString aTitle;
+ if(success)
+ aTitle = INetURLObject(aFileURL).getName(
+ INetURLObject::LAST_SEGMENT,
+ true,
+ INetURLObject::DecodeMechanism::WithCharset );
+ else
+ success =
+ UCBContentHelper::GetTitle(aURL,&aTitle);
+
+ if( success && aTitle != "/" && aTitle != "." )
+ {
+ aObj.SetName( aTitle );
+ if ( bSlash )
+ aObj.setFinalSlash();
+ }
+ }
+ }
+
+ return aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+}
+
+void URLBox::DisableHistory()
+{
+ bHistoryDisabled = true;
+ UpdatePicklistForSmartProtocol_Impl();
+}
+
+void URLBox::SetBaseURL( const OUString& rURL )
+{
+ ::osl::MutexGuard aGuard( theSvtMatchContextMutex::get() );
+
+ // Reset match lists
+ pImpl->aCompletions.clear();
+ pImpl->aURLs.clear();
+
+ aBaseURL = rURL;
+}
+
+void URLBox::SetFilter(const OUString& _sFilter)
+{
+ pImpl->m_aFilters.clear();
+ FilterMatch::createWildCardFilterList(_sFilter,pImpl->m_aFilters);
+}
+
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 905e29f5b33d..637f5651d66b 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -1091,6 +1091,16 @@ public:
return m_xTreeView->GetSelectedEntry();
}
+ virtual std::vector<OUString> get_selected_rows() const override
+ {
+ std::vector<OUString> aRows;
+
+ for (sal_Int32 i = 0; i < m_xTreeView->GetSelectedEntryCount(); ++i)
+ aRows.push_back(m_xTreeView->GetSelectedEntry(i));
+
+ return aRows;
+ }
+
virtual OUString get(int pos) const override
{
return m_xTreeView->GetEntry(pos);
@@ -1127,6 +1137,16 @@ public:
m_xTreeView->SetUpdateMode(true);
}
+ virtual void set_selection_mode(bool bMultiple) override
+ {
+ m_xTreeView->EnableMultiSelection(bMultiple);
+ }
+
+ virtual int count_selected_rows() const override
+ {
+ return m_xTreeView->GetSelectedEntryCount();
+ }
+
virtual int get_height_rows(int nRows) const override
{
return m_xTreeView->CalcWindowSizePixel(nRows);
@@ -1597,7 +1617,7 @@ public:
return false;
}
- virtual void unset_entry_completion() override
+ virtual void set_entry_completion(bool) override
{
assert(false);
}
@@ -1617,11 +1637,13 @@ class SalInstanceComboBoxTextWithEdit : public SalInstanceComboBoxText<ComboBox>
{
private:
DECL_LINK(ChangeHdl, Edit&, void);
+ DECL_LINK(EntryActivateHdl, Edit&, void);
public:
SalInstanceComboBoxTextWithEdit(ComboBox* pComboBoxText, bool bTakeOwnership)
: SalInstanceComboBoxText<ComboBox>(pComboBoxText, bTakeOwnership)
{
m_xComboBoxText->SetModifyHdl(LINK(this, SalInstanceComboBoxTextWithEdit, ChangeHdl));
+ m_xComboBoxText->SetEntryActivateHdl(LINK(this, SalInstanceComboBoxTextWithEdit, EntryActivateHdl));
}
virtual void set_entry_error(bool bError) override
@@ -1642,9 +1664,9 @@ public:
m_xComboBoxText->SetText(rText);
}
- virtual void unset_entry_completion() override
+ virtual void set_entry_completion(bool bEnable) override
{
- m_xComboBoxText->EnableAutocomplete(false);
+ m_xComboBoxText->EnableAutocomplete(bEnable);
}
virtual void select_entry_region(int nStartPos, int nEndPos) override
@@ -1662,6 +1684,7 @@ public:
virtual ~SalInstanceComboBoxTextWithEdit() override
{
+ m_xComboBoxText->SetEntryActivateHdl(Link<Edit&, void>());
m_xComboBoxText->SetModifyHdl(Link<Edit&, void>());
}
};
@@ -1671,6 +1694,11 @@ IMPL_LINK_NOARG(SalInstanceComboBoxTextWithEdit, ChangeHdl, Edit&, void)
signal_changed();
}
+IMPL_LINK_NOARG(SalInstanceComboBoxTextWithEdit, EntryActivateHdl, Edit&, void)
+{
+ m_aEntryActivateHdl.Call(*this);
+}
+
class SalInstanceBuilder : public weld::Builder
{
private:
diff --git a/vcl/source/control/combobox.cxx b/vcl/source/control/combobox.cxx
index 7b14c8da64c2..1cb790dada78 100644
--- a/vcl/source/control/combobox.cxx
+++ b/vcl/source/control/combobox.cxx
@@ -58,6 +58,7 @@ struct ComboBox::Impl
sal_Int32 m_nMaxWidthChars;
Link<ComboBox&,void> m_SelectHdl;
Link<ComboBox&,void> m_DoubleClickHdl;
+ Link<ComboBox&,void> m_EntryActivateHdl;
explicit Impl(ComboBox & rThis)
: m_rThis(rThis)
@@ -986,6 +987,8 @@ void ComboBox::SetDoubleClickHdl(const Link<ComboBox&,void>& rLink) { m_pImpl->m
const Link<ComboBox&,void>& ComboBox::GetDoubleClickHdl() const { return m_pImpl->m_DoubleClickHdl; }
+void ComboBox::SetEntryActivateHdl(const Link<Edit&,void>& rLink) { m_pImpl->m_pSubEdit->SetActivateHdl(rLink); }
+
long ComboBox::CalcWindowSizePixel(sal_uInt16 nLines) const
{
return m_pImpl->m_pImplLB->GetEntryHeight() * nLines;
diff --git a/vcl/source/control/edit.cxx b/vcl/source/control/edit.cxx
index 42dd22296585..8d3bfa665596 100644
--- a/vcl/source/control/edit.cxx
+++ b/vcl/source/control/edit.cxx
@@ -1677,6 +1677,14 @@ bool Edit::ImplHandleKeyEvent( const KeyEvent& rKEvt )
}
break;
+ case KEY_RETURN:
+ if (maActivateHdl.IsSet())
+ {
+ maActivateHdl.Call(*this);
+ bDone = true;
+ }
+ break;
+
default:
{
if ( IsCharInput( rKEvt ) )
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 133406925d79..269a0741973f 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -1184,12 +1184,14 @@ private:
static void signalFocusIn(GtkWidget*, GdkEvent*, gpointer widget)
{
GtkInstanceWidget* pThis = static_cast<GtkInstanceWidget*>(widget);
+ SolarMutexGuard aGuard;
pThis->signal_focus_in();
}
static void signalFocusOut(GtkWidget*, GdkEvent*, gpointer widget)
{
GtkInstanceWidget* pThis = static_cast<GtkInstanceWidget*>(widget);
+ SolarMutexGuard aGuard;
pThis->signal_focus_out();
}
@@ -1446,6 +1448,7 @@ private:
static void signalActivate(GtkMenuItem* pItem, gpointer widget)
{
GtkInstanceMenu* pThis = static_cast<GtkInstanceMenu*>(widget);
+ SolarMutexGuard aGuard;
pThis->signal_activate(pItem);
}
@@ -2077,6 +2080,7 @@ private:
static void signalVAdjustValueChanged(GtkAdjustment*, gpointer widget)
{
GtkInstanceScrolledWindow* pThis = static_cast<GtkInstanceScrolledWindow*>(widget);
+ SolarMutexGuard aGuard;
pThis->signal_vadjustment_changed();
}
@@ -2181,6 +2185,7 @@ private:
static void signalSwitchPage(GtkNotebook*, GtkWidget*, guint nNewPage, gpointer widget)
{
GtkInstanceNotebook* pThis = static_cast<GtkInstanceNotebook*>(widget);
+ SolarMutexGuard aGuard;
pThis->signal_switch_page(nNewPage);
}
@@ -2278,6 +2283,7 @@ private:
static void signalClicked(GtkButton*, gpointer widget)
{
GtkInstanceButton* pThis = static_cast<GtkInstanceButton*>(widget);
+ SolarMutexGuard aGuard;
pThis->signal_clicked();
}
@@ -2360,6 +2366,7 @@ private:
static void signalToggled(GtkToggleButton*, gpointer widget)
{
GtkInstanceToggleButton* pThis = static_cast<GtkInstanceToggleButton*>(widget);
+ SolarMutexGuard aGuard;
pThis->signal_toggled();
}
public:
@@ -2438,6 +2445,7 @@ private:
static void signalChanged(GtkEntry*, gpointer widget)
{
GtkInstanceEntry* pThis = static_cast<GtkInstanceEntry*>(widget);
+ SolarMutexGuard aGuard;
pThis->signal_changed();
}
@@ -2445,6 +2453,7 @@ private:
gint* position, gpointer widget)
{
GtkInstanceEntry* pThis = static_cast<GtkInstanceEntry*>(widget);
+ SolarMutexGuard aGuard;
pThis->signal_insert_text(pEntry, pNewText, nNewTextLength, position);
}
@@ -2580,12 +2589,14 @@ private:
static void signalChanged(GtkTreeView*, gpointer widget)
{
GtkInstanceTreeView* pThis = static_cast<GtkInstanceTreeView*>(widget);
+ SolarMutexGuard aGuard;
pThis->signal_changed();
}
static void signalRowActivated(GtkTreeView*, GtkTreePath*, GtkTreeViewColumn*, gpointer widget)
{
GtkInstanceTreeView* pThis = static_cast<GtkInstanceTreeView*>(widget);
+ SolarMutexGuard aGuard;
pThis->signal_row_activated();
}
@@ -2721,6 +2732,8 @@ public:
virtual OUString get_selected() const override
{
+ assert(gtk_tree_selection_get_mode(gtk_tree_view_get_selection(m_pTreeView)) == GTK_SELECTION_SINGLE);
+
OUString sRet;
GtkTreeIter iter;
GtkTreeModel* pModel;
@@ -2734,6 +2747,23 @@ public:
return sRet;
}
+ virtual std::vector<OUString> get_selected_rows() const override
+ {
+ std::vector<OUString> aRows;
+
+ GtkTreeModel* pModel;
+ GList* pList = gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(m_pTreeView), &pModel);
+ for (GList* pItem = g_list_first(pList); pItem; pItem = g_list_next(pItem))
+ {
+ GtkTreePath* path = static_cast<GtkTreePath*>(pItem->data);
+ int nRow = gtk_tree_path_get_indices(path)[0];
+ aRows.push_back(get(nRow));
+ }
+ g_list_free_full(pList, reinterpret_cast<GDestroyNotify>(gtk_tree_path_free));
+
+ return aRows;
+ }
+
virtual OUString get(int pos) const override
{
return get(pos, 0);
@@ -2808,6 +2838,16 @@ public:
gtk_widget_set_size_request(m_pWidget, nWidth, nHeight);
}
+ virtual void set_selection_mode(bool bMultiple) override
+ {
+ gtk_tree_selection_set_mode(gtk_tree_view_get_selection(m_pTreeView), bMultiple ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE);
+ }
+
+ virtual int count_selected_rows() const override
+ {
+ return gtk_tree_selection_count_selected_rows(gtk_tree_view_get_selection(m_pTreeView));
+ }
+
virtual void disable_notify_events() override
{
g_signal_handler_block(gtk_tree_view_get_selection(m_pTreeView), m_nChangedSignalId);
@@ -2840,12 +2880,14 @@ private:
static void signalValueChanged(GtkSpinButton*, gpointer widget)
{
GtkInstanceSpinButton* pThis = static_cast<GtkInstanceSpinButton*>(widget);
+ SolarMutexGuard aGuard;
pThis->signal_value_changed();
}
static gboolean signalOutput(GtkSpinButton*, gpointer widget)
{
GtkInstanceSpinButton* pThis = static_cast<GtkInstanceSpinButton*>(widget);
+ SolarMutexGuard aGuard;
return pThis->signal_output();
}
@@ -3078,6 +3120,7 @@ private:
static gboolean signalDraw(GtkWidget*, cairo_t* cr, gpointer widget)
{
GtkInstanceDrawingArea* pThis = static_cast<GtkInstanceDrawingArea*>(widget);
+ SolarMutexGuard aGuard;
pThis->signal_draw(cr);
return false;
}
@@ -3097,6 +3140,7 @@ private:
static void signalSizeAllocate(GtkWidget*, GdkRectangle* allocation, gpointer widget)
{
GtkInstanceDrawingArea* pThis = static_cast<GtkInstanceDrawingArea*>(widget);
+ SolarMutexGuard aGuard;
pThis->signal_size_allocate(allocation->width, allocation->height);
}
void signal_size_allocate(guint nWidth, guint nHeight)
@@ -3119,6 +3163,7 @@ private:
static gboolean signalButton(GtkWidget*, GdkEventButton* pEvent, gpointer widget)
{
GtkInstanceDrawingArea* pThis = static_cast<GtkInstanceDrawingArea*>(widget);
+ SolarMutexGuard aGuard;
return pThis->signal_button(pEvent);
}
bool signal_button(GdkEventButton* pEvent)
@@ -3187,6 +3232,7 @@ private:
static gboolean signalMotion(GtkWidget*, GdkEventMotion* pEvent, gpointer widget)
{
GtkInstanceDrawingArea* pThis = static_cast<GtkInstanceDrawingArea*>(widget);
+ SolarMutexGuard aGuard;
return pThis->signal_motion(pEvent);
}
bool signal_motion(GdkEventMotion* pEvent)
@@ -3202,6 +3248,7 @@ private:
static gboolean signalKey(GtkWidget*, GdkEventKey* pEvent, gpointer widget)
{
GtkInstanceDrawingArea* pThis = static_cast<GtkInstanceDrawingArea*>(widget);
+ SolarMutexGuard aGuard;
return pThis->signal_key(pEvent);
}
gboolean signal_key(GdkEventKey* pEvent)
@@ -3312,14 +3359,53 @@ class GtkInstanceComboBoxText : public GtkInstanceContainer, public virtual weld
private:
GtkComboBoxText* m_pComboBoxText;
std::unique_ptr<comphelper::string::NaturalStringSorter> m_xSorter;
- gulong m_nSignalId;
+ gboolean m_bPopupActive;
+ gulong m_nChangedSignalId;
+ gulong m_nPopupShownSignalId;
+ gulong m_nEntryActivateSignalId;
static void signalChanged(GtkComboBox*, gpointer widget)
{
GtkInstanceComboBoxText* pThis = static_cast<GtkInstanceComboBoxText*>(widget);
+ SolarMutexGuard aGuard;
pThis->signal_changed();
}
+ static void signalPopupShown(GtkComboBox*, GParamSpec*, gpointer widget)
+ {
+ GtkInstanceComboBoxText* pThis = static_cast<GtkInstanceComboBoxText*>(widget);
+ pThis->signal_popup_shown();
+ }
+
+ void signal_popup_shown()
+ {
+ gboolean bIsShown(false);
+ g_object_get(m_pComboBoxText, "popup-shown", &bIsShown, nullptr);
+ if (m_bPopupActive != bIsShown)
+ {
+ m_bPopupActive = bIsShown;
+ //restore focus to the entry wieh the popup is gone, which
+ //is what the vcl case does, to ease the transition a little
+ gtk_widget_grab_focus(m_pWidget);
+ }
+ }
+
+ static void signalEntryActivate(GtkComboBox*, gpointer widget)
+ {
+ GtkInstanceComboBoxText* pThis = static_cast<GtkInstanceComboBoxText*>(widget);
+ pThis->signal_entry_activate();
+ }
+
+ void signal_entry_activate()
+ {
+ if (m_aEntryActivateHdl.IsSet())
+ {
+ SolarMutexGuard aGuard;
+ m_aEntryActivateHdl.Call(*this);
+ g_signal_stop_emission_by_name(get_entry(), "activate");
+ }
+ }
+
OUString get(int pos, int col) const
{
OUString sRet;
@@ -3358,28 +3444,43 @@ private:
return -1;
}
- void setup_completion()
+ GtkEntry* get_entry()
{
GtkWidget* pChild = gtk_bin_get_child(GTK_BIN(m_pComboBoxText));
- if (GTK_IS_ENTRY(pChild))
- {
- GtkEntry* pEntry = GTK_ENTRY(pChild);
- GtkEntryCompletion* pCompletion = gtk_entry_completion_new();
- gtk_entry_completion_set_model(pCompletion, gtk_combo_box_get_model(GTK_COMBO_BOX(m_pComboBoxText)));
- gtk_entry_completion_set_text_column(pCompletion, 0);
- gtk_entry_completion_set_inline_selection(pCompletion, true);
- gtk_entry_set_completion(pEntry, pCompletion);
- g_object_unref(pCompletion);
- }
+ if (!GTK_IS_ENTRY(pChild))
+ return nullptr;
+ return GTK_ENTRY(pChild);
+ }
+
+ void setup_completion(GtkEntry* pEntry)
+ {
+ if (gtk_entry_get_completion(pEntry))
+ return;
+ GtkEntryCompletion* pCompletion = gtk_entry_completion_new();
+ gtk_entry_completion_set_model(pCompletion, gtk_combo_box_get_model(GTK_COMBO_BOX(m_pComboBoxText)));
+ gtk_entry_completion_set_text_column(pCompletion, 0);
+ gtk_entry_completion_set_inline_selection(pCompletion, true);
+ gtk_entry_completion_set_inline_completion(pCompletion, true);
+ gtk_entry_completion_set_popup_completion(pCompletion, false);
+ gtk_entry_set_completion(pEntry, pCompletion);
+ g_object_unref(pCompletion);
}
public:
GtkInstanceComboBoxText(GtkComboBoxText* pComboBoxText, bool bTakeOwnership)
: GtkInstanceContainer(GTK_CONTAINER(pComboBoxText), bTakeOwnership)
, m_pComboBoxText(pComboBoxText)
- , m_nSignalId(g_signal_connect(m_pComboBoxText, "changed", G_CALLBACK(signalChanged), this))
+ , m_bPopupActive(false)
+ , m_nChangedSignalId(g_signal_connect(m_pComboBoxText, "changed", G_CALLBACK(signalChanged), this))
+ , m_nPopupShownSignalId(g_signal_connect(m_pComboBoxText, "notify::popup-shown", G_CALLBACK(signalPopupShown), this))
{
- setup_completion();
+ if (GtkEntry* pEntry = get_entry())
+ {
+ setup_completion(pEntry);
+ m_nEntryActivateSignalId = g_signal_connect(pEntry, "activate", G_CALLBACK(signalEntryActivate), this);
+ }
+ else
+ m_nEntryActivateSignalId = 0;
}
virtual int get_active() const override
@@ -3517,29 +3618,40 @@ public:
return gtk_editable_get_selection_bounds(GTK_EDITABLE(pEntry), &rStartPos, &rEndPos);
}
- virtual void unset_entry_completion() override
+ virtual void set_entry_completion(bool bEnable) override
{
- GtkWidget* pChild = gtk_bin_get_child(GTK_BIN(m_pComboBoxText));
- assert(pChild && GTK_IS_ENTRY(pChild));
- GtkEntry* pEntry = GTK_ENTRY(pChild);
- gtk_entry_set_completion(pEntry, nullptr);
+ GtkEntry* pEntry = get_entry();
+ assert(pEntry);
+ if (bEnable)
+ setup_completion(pEntry);
+ else
+ gtk_entry_set_completion(pEntry, nullptr);
}
virtual void disable_notify_events() override
{
- g_signal_handler_block(m_pComboBoxText, m_nSignalId);
+ if (GtkEntry* pEntry = get_entry())
+ g_signal_handler_block(pEntry, m_nEntryActivateSignalId);
+ g_signal_handler_block(m_pComboBoxText, m_nChangedSignalId);
+ g_signal_handler_block(m_pComboBoxText, m_nPopupShownSignalId);
GtkInstanceContainer::disable_notify_events();
}
virtual void enable_notify_events() override
{
GtkInstanceContainer::disable_notify_events();
- g_signal_handler_unblock(m_pComboBoxText, m_nSignalId);
+ g_signal_handler_unblock(m_pComboBoxText, m_nPopupShownSignalId);
+ g_signal_handler_unblock(m_pComboBoxText, m_nChangedSignalId);
+ if (GtkEntry* pEntry = get_entry())
+ g_signal_handler_unblock(pEntry, m_nEntryActivateSignalId);
}
virtual ~GtkInstanceComboBoxText() override
{
- g_signal_handler_disconnect(m_pComboBoxText, m_nSignalId);
+ if (GtkEntry* pEntry = get_entry())
+ g_signal_handler_disconnect(pEntry, m_nEntryActivateSignalId);
+ g_signal_handler_disconnect(m_pComboBoxText, m_nChangedSignalId);
+ g_signal_handler_disconnect(m_pComboBoxText, m_nPopupShownSignalId);
}
};
@@ -3549,9 +3661,10 @@ private:
GtkExpander* m_pExpander;
gulong m_nSignalId;
- static void signalExpanded(GtkExpander* pExpander, GParamSpec *, gpointer widget)
+ static void signalExpanded(GtkExpander* pExpander, GParamSpec*, gpointer widget)
{
GtkInstanceExpander* pThis = static_cast<GtkInstanceExpander*>(widget);
+ SolarMutexGuard aGuard;
pThis->signal_expanded();
GtkWidget *pToplevel = gtk_widget_get_toplevel(GTK_WIDGET(pExpander));