summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cui/source/options/optinet2.cxx4
-rw-r--r--cui/source/options/webconninfo.cxx189
-rw-r--r--cui/source/options/webconninfo.hxx44
-rw-r--r--cui/uiconfig/ui/storedwebconnectiondialog.ui100
-rw-r--r--include/vcl/weld.hxx5
-rw-r--r--vcl/source/app/salvtables.cxx42
-rw-r--r--vcl/source/window/builder.cxx32
-rw-r--r--vcl/unx/gtk3/gtk3gtkinst.cxx85
8 files changed, 270 insertions, 231 deletions
diff --git a/cui/source/options/optinet2.cxx b/cui/source/options/optinet2.cxx
index c269d87fdda5..bee5e2d64d14 100644
--- a/cui/source/options/optinet2.cxx
+++ b/cui/source/options/optinet2.cxx
@@ -784,8 +784,8 @@ IMPL_LINK_NOARG(SvxSecurityTabPage, ShowPasswordsHdl, Button*, void)
if ( xMasterPasswd->isPersistentStoringAllowed() && xMasterPasswd->authorizateWithMasterPassword(xTmpHandler) )
{
- ScopedVclPtrInstance< svx::WebConnectionInfoDialog > aDlg(this);
- aDlg->Execute();
+ svx::WebConnectionInfoDialog aDlg(GetDialogFrameWeld());
+ aDlg.run();
}
}
catch (const Exception&)
diff --git a/cui/source/options/webconninfo.cxx b/cui/source/options/webconninfo.cxx
index 18a2cd7fbca9..5bb56294cfc3 100644
--- a/cui/source/options/webconninfo.cxx
+++ b/cui/source/options/webconninfo.cxx
@@ -35,125 +35,49 @@ using namespace ::com::sun::star;
namespace svx
{
-
-// class PasswordTable ---------------------------------------------------
-
-PasswordTable::PasswordTable(SvSimpleTableContainer& rParent, WinBits nBits)
- : SvSimpleTable(rParent, nBits | WB_NOINITIALSELECTION)
-{
-}
-
-void PasswordTable::InsertHeaderItem(sal_uInt16 nColumn, const OUString& rText, HeaderBarItemBits nBits)
-{
- GetTheHeaderBar().InsertItem( nColumn, rText, 0, nBits );
-}
-
-void PasswordTable::Resort( bool bForced )
-{
- sal_uInt16 nColumn = GetSelectedCol();
- if ( 0 == nColumn || bForced ) // only the first column is sorted
- {
- HeaderBarItemBits nBits = GetTheHeaderBar().GetItemBits(1);
- bool bUp = ( ( nBits & HeaderBarItemBits::UPARROW ) == HeaderBarItemBits::UPARROW );
- SvSortMode eMode = SortAscending;
-
- if ( bUp )
- {
- nBits &= ~HeaderBarItemBits::UPARROW;
- nBits |= HeaderBarItemBits::DOWNARROW;
- eMode = SortDescending;
- }
- else
- {
- nBits &= ~HeaderBarItemBits::DOWNARROW;
- nBits |= HeaderBarItemBits::UPARROW;
- }
- GetTheHeaderBar().SetItemBits( 1, nBits );
- SvTreeList* pListModel = GetModel();
- pListModel->SetSortMode( eMode );
- pListModel->Resort();
- }
-}
-
-void PasswordTable::Resize()
-{
- SvSimpleTable::Resize();
- if (isInitialLayout(this))
- setColWidths();
-}
-
-void PasswordTable::setColWidths()
-{
- HeaderBar &rBar = GetTheHeaderBar();
- if (rBar.GetItemCount() < 2)
- return;
- long nUserNameWidth = 12 +
- std::max(rBar.GetTextWidth(rBar.GetItemText(2)),
- GetTextWidth("XXXXXXXXXXXX"));
- long nWebSiteWidth = std::max(
- 12 + rBar.GetTextWidth(rBar.GetItemText(1)),
- GetSizePixel().Width() - nUserNameWidth);
- long aStaticTabs[]= { 0, nWebSiteWidth };
- SvSimpleTable::SetTabs(SAL_N_ELEMENTS(aStaticTabs), aStaticTabs, MapUnit::MapPixel);
-}
-
// class WebConnectionInfoDialog -----------------------------------------
-
-WebConnectionInfoDialog::WebConnectionInfoDialog(vcl::Window* pParent)
- : ModalDialog(pParent, "StoredWebConnectionDialog", "cui/ui/storedwebconnectiondialog.ui")
+WebConnectionInfoDialog::WebConnectionInfoDialog(weld::Window* pParent)
+ : GenericDialogController(pParent, "cui/ui/storedwebconnectiondialog.ui", "StoredWebConnectionDialog")
, m_nPos( -1 )
+ , m_xRemoveBtn(m_xBuilder->weld_button("remove"))
+ , m_xRemoveAllBtn(m_xBuilder->weld_button("removeall"))
+ , m_xChangeBtn(m_xBuilder->weld_button("change"))
+ , m_xPasswordsLB(m_xBuilder->weld_tree_view("logins"))
{
- get(m_pRemoveBtn, "remove");
- get(m_pRemoveAllBtn, "removeall");
- get(m_pChangeBtn, "change");
-
- SvSimpleTableContainer *pPasswordsLBContainer = get<SvSimpleTableContainer>("logins");
- m_pPasswordsLB = VclPtr<PasswordTable>::Create(*pPasswordsLBContainer, 0);
-
- long const aStaticTabs[]= { 0, 0 };
- m_pPasswordsLB->SetTabs( SAL_N_ELEMENTS(aStaticTabs), aStaticTabs );
- m_pPasswordsLB->InsertHeaderItem( 1, get<FixedText>("website")->GetText(),
- HeaderBarItemBits::LEFT | HeaderBarItemBits::FIXEDPOS | HeaderBarItemBits::CLICKABLE | HeaderBarItemBits::UPARROW );
- m_pPasswordsLB->InsertHeaderItem( 2, get<FixedText>("username")->GetText(),
- HeaderBarItemBits::LEFT | HeaderBarItemBits::FIXEDPOS );
- pPasswordsLBContainer->set_height_request(m_pPasswordsLB->GetTextHeight()*8);
+ std::vector<int> aWidths;
+ aWidths.push_back(m_xPasswordsLB->get_approximate_digit_width() * 50);
+ m_xPasswordsLB->set_column_fixed_widths(aWidths);
+ m_xPasswordsLB->set_size_request(m_xPasswordsLB->get_approximate_digit_width() * 70,
+ m_xPasswordsLB->get_height_rows(8));
- m_pPasswordsLB->SetHeaderBarClickHdl( LINK( this, WebConnectionInfoDialog, HeaderBarClickedHdl ) );
+ m_xPasswordsLB->connect_column_clicked(LINK(this, WebConnectionInfoDialog, HeaderBarClickedHdl));
FillPasswordList();
- m_pRemoveBtn->SetClickHdl( LINK( this, WebConnectionInfoDialog, RemovePasswordHdl ) );
- m_pRemoveAllBtn->SetClickHdl( LINK( this, WebConnectionInfoDialog, RemoveAllPasswordsHdl ) );
- m_pChangeBtn->SetClickHdl( LINK( this, WebConnectionInfoDialog, ChangePasswordHdl ) );
- m_pPasswordsLB->SetSelectHdl( LINK( this, WebConnectionInfoDialog, EntrySelectedHdl ) );
+ m_xRemoveBtn->connect_clicked( LINK( this, WebConnectionInfoDialog, RemovePasswordHdl ) );
+ m_xRemoveAllBtn->connect_clicked( LINK( this, WebConnectionInfoDialog, RemoveAllPasswordsHdl ) );
+ m_xChangeBtn->connect_clicked( LINK( this, WebConnectionInfoDialog, ChangePasswordHdl ) );
+ m_xPasswordsLB->connect_changed( LINK( this, WebConnectionInfoDialog, EntrySelectedHdl ) );
- m_pRemoveBtn->Enable( false );
- m_pChangeBtn->Enable( false );
+ m_xRemoveBtn->set_sensitive( false );
+ m_xChangeBtn->set_sensitive( false );
- HeaderBarClickedHdl( nullptr );
+ m_xPasswordsLB->make_sorted();
}
WebConnectionInfoDialog::~WebConnectionInfoDialog()
{
- disposeOnce();
}
-void WebConnectionInfoDialog::dispose()
+IMPL_LINK(WebConnectionInfoDialog, HeaderBarClickedHdl, int, nColumn, void)
{
- m_pPasswordsLB.disposeAndClear();
- m_pRemoveBtn.clear();
- m_pRemoveAllBtn.clear();
- m_pChangeBtn.clear();
- ModalDialog::dispose();
-}
-
-IMPL_LINK( WebConnectionInfoDialog, HeaderBarClickedHdl, SvSimpleTable*, pTable, void )
-{
- m_pPasswordsLB->Resort( nullptr == pTable );
+ if (nColumn == 0) // only the first column is sorted
+ {
+ m_xPasswordsLB->set_sort_order(!m_xPasswordsLB->get_sort_order());
+ }
}
-
void WebConnectionInfoDialog::FillPasswordList()
{
try
@@ -173,10 +97,9 @@ void WebConnectionInfoDialog::FillPasswordList()
{
for ( sal_Int32 nUserInd = 0; nUserInd < aURLEntries[nURLInd].UserList.getLength(); nUserInd++ )
{
- SvTreeListEntry* pEntry = m_pPasswordsLB->InsertEntry(
- aURLEntries[nURLInd].Url + "\t" +
- aURLEntries[nURLInd].UserList[nUserInd].UserName);
- pEntry->SetUserData( reinterpret_cast<void*>(nCount++) );
+ m_xPasswordsLB->append(OUString::number(nCount), aURLEntries[nURLInd].Url);
+ m_xPasswordsLB->set_text(nCount, aURLEntries[nURLInd].UserList[nUserInd].UserName, 1);
+ ++nCount;
}
}
@@ -188,9 +111,9 @@ void WebConnectionInfoDialog::FillPasswordList()
for ( sal_Int32 nURLIdx = 0; nURLIdx < aUrls.getLength(); nURLIdx++ )
{
- SvTreeListEntry* pEntry = m_pPasswordsLB->InsertEntry(
- aUrls[nURLIdx] + "\t*");
- pEntry->SetUserData( reinterpret_cast<void*>(nCount++) );
+ m_xPasswordsLB->append(OUString::number(nCount), aUrls[nURLIdx]);
+ m_xPasswordsLB->set_text(nCount, "*");
+ ++nCount;
}
}
}
@@ -199,20 +122,20 @@ void WebConnectionInfoDialog::FillPasswordList()
}
-IMPL_LINK_NOARG(WebConnectionInfoDialog, RemovePasswordHdl, Button*, void)
+IMPL_LINK_NOARG(WebConnectionInfoDialog, RemovePasswordHdl, weld::Button&, void)
{
try
{
- SvTreeListEntry* pEntry = m_pPasswordsLB->GetCurEntry();
- if ( pEntry )
+ int nEntry = m_xPasswordsLB->get_selected_index();
+ if (nEntry != -1)
{
- OUString aURL = SvTabListBox::GetEntryText( pEntry, 0 );
- OUString aUserName = SvTabListBox::GetEntryText( pEntry, 1 );
+ OUString aURL = m_xPasswordsLB->get_text(nEntry, 0);
+ OUString aUserName = m_xPasswordsLB->get_text(nEntry, 1);
uno::Reference< task::XPasswordContainer2 > xPasswdContainer(
task::PasswordContainer::create(comphelper::getProcessComponentContext()));
- sal_Int32 nPos = static_cast<sal_Int32>(reinterpret_cast<sal_IntPtr>(pEntry->GetUserData()));
+ int nPos = m_xPasswordsLB->get_id(nEntry).toInt32();
if ( nPos < m_nPos )
{
xPasswdContainer->removePersistent( aURL, aUserName );
@@ -221,15 +144,15 @@ IMPL_LINK_NOARG(WebConnectionInfoDialog, RemovePasswordHdl, Button*, void)
{
xPasswdContainer->removeUrl( aURL );
}
- m_pPasswordsLB->RemoveEntry( pEntry );
+
+ m_xPasswordsLB->remove(nEntry);
}
}
catch( uno::Exception& )
{}
}
-
-IMPL_LINK_NOARG(WebConnectionInfoDialog, RemoveAllPasswordsHdl, Button*, void)
+IMPL_LINK_NOARG(WebConnectionInfoDialog, RemoveAllPasswordsHdl, weld::Button&, void)
{
try
{
@@ -244,30 +167,28 @@ IMPL_LINK_NOARG(WebConnectionInfoDialog, RemoveAllPasswordsHdl, Button*, void)
for ( sal_Int32 nURLIdx = 0; nURLIdx < aUrls.getLength(); nURLIdx++ )
xPasswdContainer->removeUrl( aUrls[ nURLIdx ] );
- m_pPasswordsLB->Clear();
+ m_xPasswordsLB->clear();
}
catch( uno::Exception& )
{}
}
-
-IMPL_LINK_NOARG(WebConnectionInfoDialog, ChangePasswordHdl, Button*, void)
+IMPL_LINK_NOARG(WebConnectionInfoDialog, ChangePasswordHdl, weld::Button&, void)
{
try
{
- SvTreeListEntry* pEntry = m_pPasswordsLB->GetCurEntry();
- if ( pEntry )
+ int nEntry = m_xPasswordsLB->get_selected_index();
+ if (nEntry != -1)
{
- OUString aURL = SvTabListBox::GetEntryText( pEntry, 0 );
- OUString aUserName = SvTabListBox::GetEntryText( pEntry, 1 );
+ OUString aURL = m_xPasswordsLB->get_text(nEntry, 0);
+ OUString aUserName = m_xPasswordsLB->get_text(nEntry, 1);
::comphelper::SimplePasswordRequest* pPasswordRequest
= new ::comphelper::SimplePasswordRequest;
uno::Reference< task::XInteractionRequest > rRequest( pPasswordRequest );
- auto xWindow = VCLUnoHelper::GetInterface(this);
uno::Reference< task::XInteractionHandler > xInteractionHandler(
- task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(), xWindow),
+ task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(), m_xDialog->GetXWindow()),
uno::UNO_QUERY );
xInteractionHandler->handle( rRequest );
@@ -288,27 +209,25 @@ IMPL_LINK_NOARG(WebConnectionInfoDialog, ChangePasswordHdl, Button*, void)
}
-IMPL_LINK_NOARG(WebConnectionInfoDialog, EntrySelectedHdl, SvTreeListBox*, void)
+IMPL_LINK_NOARG(WebConnectionInfoDialog, EntrySelectedHdl, weld::TreeView&, void)
{
- SvTreeListEntry* pEntry = m_pPasswordsLB->GetCurEntry();
- if ( !pEntry )
+ int nEntry = m_xPasswordsLB->get_selected_index();
+ if (nEntry == -1)
{
- m_pRemoveBtn->Enable( false );
- m_pChangeBtn->Enable( false );
+ m_xRemoveBtn->set_sensitive(false);
+ m_xChangeBtn->set_sensitive(false);
}
else
{
- m_pRemoveBtn->Enable();
+ m_xRemoveBtn->set_sensitive(true);
// url container entries (-> use system credentials) have
// no password
- sal_Int32 nPos = static_cast<sal_Int32>(reinterpret_cast<sal_IntPtr>(pEntry->GetUserData()));
- m_pChangeBtn->Enable( nPos < m_nPos );
+ int nPos = m_xPasswordsLB->get_id(nEntry).toInt32();
+ m_xChangeBtn->set_sensitive(nPos < m_nPos);
}
}
-
}
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cui/source/options/webconninfo.hxx b/cui/source/options/webconninfo.hxx
index 792d66cb2a1c..95d524c8a3bc 100644
--- a/cui/source/options/webconninfo.hxx
+++ b/cui/source/options/webconninfo.hxx
@@ -18,47 +18,31 @@
#ifndef INCLUDED_CUI_SOURCE_OPTIONS_WEBCONNINFO_HXX
#define INCLUDED_CUI_SOURCE_OPTIONS_WEBCONNINFO_HXX
-#include <vcl/button.hxx>
-#include <vcl/dialog.hxx>
-#include <vcl/fixed.hxx>
-#include <svtools/simptabl.hxx>
+#include <vcl/weld.hxx>
namespace svx
{
-
-
- class PasswordTable : public SvSimpleTable
- {
- public:
- PasswordTable(SvSimpleTableContainer& rParent, WinBits nBits);
-
- void InsertHeaderItem(sal_uInt16 nColumn, const OUString& rText, HeaderBarItemBits nBits);
- void setColWidths();
- void Resort( bool bForced );
- virtual void Resize() override;
- };
-
- class WebConnectionInfoDialog : public ModalDialog
+ class WebConnectionInfoDialog : public weld::GenericDialogController
{
private:
- VclPtr<PasswordTable> m_pPasswordsLB;
- VclPtr<PushButton> m_pRemoveBtn;
- VclPtr<PushButton> m_pRemoveAllBtn;
- VclPtr<PushButton> m_pChangeBtn;
- sal_Int32 m_nPos;
+ sal_Int32 m_nPos;
+
+ std::unique_ptr<weld::Button> m_xRemoveBtn;
+ std::unique_ptr<weld::Button> m_xRemoveAllBtn;
+ std::unique_ptr<weld::Button> m_xChangeBtn;
+ std::unique_ptr<weld::TreeView> m_xPasswordsLB;
- DECL_LINK( HeaderBarClickedHdl, SvSimpleTable*, void );
- DECL_LINK( RemovePasswordHdl, Button*, void );
- DECL_LINK( RemoveAllPasswordsHdl, Button*, void );
- DECL_LINK( ChangePasswordHdl, Button*, void );
- DECL_LINK( EntrySelectedHdl, SvTreeListBox*, void );
+ DECL_LINK( HeaderBarClickedHdl, int, void );
+ DECL_LINK( RemovePasswordHdl, weld::Button&, void );
+ DECL_LINK( RemoveAllPasswordsHdl, weld::Button&, void );
+ DECL_LINK( ChangePasswordHdl, weld::Button&, void );
+ DECL_LINK( EntrySelectedHdl, weld::TreeView&, void );
void FillPasswordList();
public:
- explicit WebConnectionInfoDialog( vcl::Window* pParent );
+ explicit WebConnectionInfoDialog(weld::Window* pParent);
virtual ~WebConnectionInfoDialog() override;
- virtual void dispose() override;
};
diff --git a/cui/uiconfig/ui/storedwebconnectiondialog.ui b/cui/uiconfig/ui/storedwebconnectiondialog.ui
index 685df0e160a4..69f2c30b9b79 100644
--- a/cui/uiconfig/ui/storedwebconnectiondialog.ui
+++ b/cui/uiconfig/ui/storedwebconnectiondialog.ui
@@ -1,14 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.18.3 -->
+<!-- Generated with glade 3.22.1 -->
<interface domain="cui">
<requires lib="gtk+" version="3.18"/>
- <requires lib="LibreOffice" version="1.0"/>
+ <object class="GtkTreeStore" id="liststore1">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name text2 -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
<object class="GtkDialog" id="StoredWebConnectionDialog">
<property name="can_focus">False</property>
<property name="border_width">6</property>
<property name="title" translatable="yes" context="storedwebconnectiondialog|StoredWebConnectionDialog">Stored Web Connection Information</property>
<property name="resizable">False</property>
<property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox1">
<property name="can_focus">False</property>
@@ -66,8 +78,8 @@
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="xalign">0</property>
<property name="label" translatable="yes" context="storedwebconnectiondialog|label1">Web login information (passwords are never shown)</property>
+ <property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
@@ -75,32 +87,53 @@
</packing>
</child>
<child>
- <object class="GtkGrid" id="grid3">
- <property name="can_focus">False</property>
- <property name="no_show_all">True</property>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
<property name="hexpand">True</property>
- <property name="column_spacing">12</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
<child>
- <object class="GtkLabel" id="website">
+ <object class="GtkTreeView" id="logins">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes" context="storedwebconnectiondialog|website">Website</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="search_column">0</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn5">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="storedwebconnectiondialog|website">Website</property>
+ <property name="clickable">True</property>
+ <property name="sort_indicator">True</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer4"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="storedwebconnectiondialog|username">User name</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer1"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="username">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes" context="storedwebconnectiondialog|username">User name</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- </packing>
</child>
</object>
<packing>
@@ -109,21 +142,6 @@
</packing>
</child>
<child>
- <object class="svtlo-SvSimpleTableContainer" id="logins">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- <child internal-child="selection">
- <object class="GtkTreeSelection" id="Simple Table Container-selection1"/>
- </child>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">2</property>
- </packing>
- </child>
- <child>
<object class="GtkButtonBox" id="buttonbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -175,7 +193,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">3</property>
+ <property name="top_attach">2</property>
</packing>
</child>
</object>
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 2649e551921a..bcb6a898105a 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -455,6 +455,7 @@ class VCL_DLLPUBLIC TreeView : virtual public Container
protected:
Link<TreeView&, void> m_aChangeHdl;
Link<TreeView&, void> m_aRowActivatedHdl;
+ Link<int, void> m_aColumnClickedHdl;
Link<const std::pair<int, int>&, void> m_aRadioToggleHdl;
// if handler returns false, the expansion of the row is refused
Link<TreeIter&, bool> m_aExpandingHdl;
@@ -463,6 +464,7 @@ protected:
void signal_changed() { m_aChangeHdl.Call(*this); }
void signal_row_activated() { m_aRowActivatedHdl.Call(*this); }
+ void signal_column_clicked(int nColumn) { m_aColumnClickedHdl.Call(nColumn); }
bool signal_expanding(TreeIter& rIter)
{
return !m_aExpandingHdl.IsSet() || m_aExpandingHdl.Call(rIter);
@@ -515,6 +517,7 @@ public:
{
m_aRadioToggleHdl = rLink;
}
+ void connect_column_clicked(const Link<int, void>& rLink) { m_aColumnClickedHdl = rLink; }
//by index
virtual int get_selected_index() const = 0;
@@ -599,6 +602,8 @@ public:
virtual int n_children() const = 0;
virtual void make_sorted() = 0;
+ virtual bool get_sort_order() const = 0;
+ virtual void set_sort_order(bool bAscending) = 0;
virtual void clear() = 0;
virtual int get_height_rows(int nRows) const = 0;
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 823c4bb2a666..f55c6fc3b43d 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -1936,6 +1936,7 @@ private:
DECL_LINK(DoubleClickHdl, SvTreeListBox*, bool);
DECL_LINK(ExpandingHdl, SvTreeListBox*, bool);
DECL_LINK(EndDragHdl, HeaderBar*, void);
+ DECL_LINK(HeaderBarClickedHdl, HeaderBar*, void);
DECL_LINK(ToggleHdl, SvLBoxButtonData*, void);
public:
SalInstanceTreeView(SvTabListBox* pTreeView, bool bTakeOwnership)
@@ -1956,6 +1957,7 @@ public:
//make the last entry fill available space
pHeaderBar->SetItemSize(pHeaderBar->GetItemId(pHeaderBar->GetItemCount() - 1 ), HEADERBAR_FULLSIZE);
pHeaderBar->SetEndDragHdl(LINK(this, SalInstanceTreeView, EndDragHdl));
+ pHeaderBar->SetSelectHdl(LINK(this, SalInstanceTreeView, HeaderBarClickedHdl));
}
m_aCheckButtonData.SetLink(LINK(this, SalInstanceTreeView, ToggleHdl));
m_aRadioButtonData.SetLink(LINK(this, SalInstanceTreeView, ToggleHdl));
@@ -2487,7 +2489,36 @@ public:
virtual void make_sorted() override
{
m_xTreeView->SetStyle(m_xTreeView->GetStyle() | WB_SORT);
- m_xTreeView->GetModel()->Resort();
+ set_sort_order(true);
+ }
+
+ virtual void set_sort_order(bool bAscending) override
+ {
+ SvHeaderTabListBox* pHeaderBox = dynamic_cast<SvHeaderTabListBox*>(m_xTreeView.get());
+ if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
+ {
+ sal_uInt16 nTextId = pHeaderBar->GetItemId(0);
+ HeaderBarItemBits nBits = pHeaderBar->GetItemBits(nTextId);
+ if (nBits & HeaderBarItemBits::CLICKABLE)
+ {
+ nBits &= ~HeaderBarItemBits::UPARROW;
+ nBits &= ~HeaderBarItemBits::DOWNARROW;
+ if (bAscending)
+ nBits |= HeaderBarItemBits::DOWNARROW;
+ else
+ nBits |= HeaderBarItemBits::UPARROW;
+ pHeaderBar->SetItemBits(nTextId, nBits);
+ }
+ }
+
+ SvTreeList* pListModel = m_xTreeView->GetModel();
+ pListModel->SetSortMode(bAscending ? SortAscending : SortDescending);
+ pListModel->Resort();
+ }
+
+ virtual bool get_sort_order() const override
+ {
+ return m_xTreeView->GetModel()->GetSortMode() == SortAscending;
}
SvTabListBox& getTreeView()
@@ -2500,6 +2531,7 @@ public:
SvHeaderTabListBox* pHeaderBox = dynamic_cast<SvHeaderTabListBox*>(m_xTreeView.get());
if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
{
+ pHeaderBar->SetSelectHdl(Link<HeaderBar*, void>());
pHeaderBar->SetEndDragHdl(Link<HeaderBar*, void>());
}
m_xTreeView->SetExpandingHdl(Link<SvTreeListBox*, bool>());
@@ -2554,6 +2586,14 @@ IMPL_LINK(SalInstanceTreeView, EndDragHdl, HeaderBar*, pHeaderBar, void)
m_xTreeView->SetTabs(aTabPositions.size(), aTabPositions.data(), MapUnit::MapPixel);
}
+IMPL_LINK(SalInstanceTreeView, HeaderBarClickedHdl, HeaderBar*, pHeaderBar, void)
+{
+ sal_uInt16 nId = pHeaderBar->GetCurItemId();
+ if (!(pHeaderBar->GetItemBits(nId) & HeaderBarItemBits::CLICKABLE))
+ return;
+ signal_column_clicked(pHeaderBar->GetItemPos(nId));
+}
+
IMPL_LINK_NOARG(SalInstanceTreeView, ExpandingHdl, SvTreeListBox*, bool)
{
SvTreeListEntry* pEntry = m_xTreeView->GetHdlEntry();
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index fe406ed94b6f..c95ed2800193 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -1123,6 +1123,30 @@ namespace
return bHeadersVisible;
}
+ bool extractSortIndicator(VclBuilder::stringmap &rMap)
+ {
+ bool bSortIndicator = false;
+ VclBuilder::stringmap::iterator aFind = rMap.find(OString("sort-indicator"));
+ if (aFind != rMap.end())
+ {
+ bSortIndicator = toBool(aFind->second);
+ rMap.erase(aFind);
+ }
+ return bSortIndicator;
+ }
+
+ bool extractClickable(VclBuilder::stringmap &rMap)
+ {
+ bool bClickable = false;
+ VclBuilder::stringmap::iterator aFind = rMap.find(OString("clickable"));
+ if (aFind != rMap.end())
+ {
+ bClickable = toBool(aFind->second);
+ rMap.erase(aFind);
+ }
+ return bClickable;
+ }
+
void setupFromActionName(Button *pButton, VclBuilder::stringmap &rMap, const css::uno::Reference<css::frame::XFrame>& rFrame)
{
if (!rFrame.is())
@@ -1950,8 +1974,11 @@ VclPtr<vcl::Window> VclBuilder::makeObject(vcl::Window *pParent, const OString &
SvHeaderTabListBox* pTreeView = dynamic_cast<SvHeaderTabListBox*>(pParent);
if (HeaderBar* pHeaderBar = pTreeView ? pTreeView->GetHeaderBar() : nullptr)
{
- OUString sTitle(extractTitle(rMap));
- HeaderBarItemBits nBits = HeaderBarItemBits::LEFTIMAGE | HeaderBarItemBits::CLICKABLE;
+ HeaderBarItemBits nBits = HeaderBarItemBits::LEFTIMAGE;
+ if (extractClickable(rMap))
+ nBits |= HeaderBarItemBits::CLICKABLE;
+ if (extractSortIndicator(rMap))
+ nBits |= HeaderBarItemBits::DOWNARROW;
float fAlign = extractAlignment(rMap);
if (fAlign == 0.0)
nBits |= HeaderBarItemBits::LEFT;
@@ -1960,6 +1987,7 @@ VclPtr<vcl::Window> VclBuilder::makeObject(vcl::Window *pParent, const OString &
else if (fAlign == 0.5)
nBits |= HeaderBarItemBits::CENTER;
auto nItemId = pHeaderBar->GetItemCount() + 1;
+ OUString sTitle(extractTitle(rMap));
pHeaderBar->InsertItem(nItemId, sTitle, 100, nBits);
}
}
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index b64cb1933a73..ca35d447fbb1 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -4956,15 +4956,19 @@ private:
GtkTreeView* m_pTreeView;
GtkTreeStore* m_pTreeStore;
std::unique_ptr<comphelper::string::NaturalStringSorter> m_xSorter;
+ GList *m_pColumns;
+ std::vector<gulong> m_aColumnSignalIds;
// map from toggle column to toggle visibility column
std::map<int, int> m_aToggleVisMap;
gint m_nTextCol;
+ gint m_nTextColHeader;
gint m_nImageCol;
gint m_nExpanderImageCol;
gint m_nIdCol;
gulong m_nChangedSignalId;
gulong m_nRowActivatedSignalId;
gulong m_nTestExpandRowSignalId;
+ GtkSortType m_eSortType;
DECL_LINK(async_signal_changed, void*, void);
@@ -5142,30 +5146,57 @@ private:
gtk_tree_path_free(tree_path);
}
+ void signal_column_clicked(GtkTreeViewColumn* pClickedColumn)
+ {
+ int nIndex(0);
+ for (GList* pEntry = g_list_first(m_pColumns); pEntry; pEntry = g_list_next(pEntry))
+ {
+ GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(pEntry->data);
+ if (pColumn == pClickedColumn)
+ {
+ TreeView::signal_column_clicked(nIndex);
+ break;
+ }
+ ++nIndex;
+ }
+ }
+
+ static void signalColumnClicked(GtkTreeViewColumn* pColumn, gpointer widget)
+ {
+ GtkInstanceTreeView* pThis = static_cast<GtkInstanceTreeView*>(widget);
+ pThis->signal_column_clicked(pColumn);
+ }
+
public:
GtkInstanceTreeView(GtkTreeView* pTreeView, bool bTakeOwnership)
: GtkInstanceContainer(GTK_CONTAINER(pTreeView), bTakeOwnership)
, m_pTreeView(pTreeView)
, m_pTreeStore(GTK_TREE_STORE(gtk_tree_view_get_model(m_pTreeView)))
, m_nTextCol(-1)
+ , m_nTextColHeader(-1)
, m_nImageCol(-1)
, m_nExpanderImageCol(-1)
, m_nChangedSignalId(g_signal_connect(gtk_tree_view_get_selection(pTreeView), "changed",
G_CALLBACK(signalChanged), this))
, m_nRowActivatedSignalId(g_signal_connect(pTreeView, "row-activated", G_CALLBACK(signalRowActivated), this))
, m_nTestExpandRowSignalId(g_signal_connect(pTreeView, "test-expand-row", G_CALLBACK(signalTestExpandRow), this))
+ , m_eSortType(GTK_SORT_ASCENDING)
{
- GList *pColumns = gtk_tree_view_get_columns(m_pTreeView);
- int nIndex(0);
- for (GList* pEntry = g_list_first(pColumns); pEntry; pEntry = g_list_next(pEntry))
+ m_pColumns = gtk_tree_view_get_columns(m_pTreeView);
+ int nIndex(0), nHeader(0);
+ for (GList* pEntry = g_list_first(m_pColumns); pEntry; pEntry = g_list_next(pEntry))
{
GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(pEntry->data);
+ m_aColumnSignalIds.push_back(g_signal_connect(pColumn, "clicked", G_CALLBACK(signalColumnClicked), this));
GList *pRenderers = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(pColumn));
for (GList* pRenderer = g_list_first(pRenderers); pRenderer; pRenderer = g_list_next(pRenderer))
{
GtkCellRenderer* pCellRenderer = GTK_CELL_RENDERER(pRenderer->data);
if (m_nTextCol == -1 && GTK_IS_CELL_RENDERER_TEXT(pCellRenderer))
+ {
m_nTextCol = nIndex;
+ m_nTextColHeader = nHeader;
+ }
else if (GTK_IS_CELL_RENDERER_TOGGLE(pCellRenderer))
{
g_object_set_data(G_OBJECT(pCellRenderer), "g-lo-CellIndex", reinterpret_cast<gpointer>(nIndex));
@@ -5183,8 +5214,8 @@ public:
++nIndex;
}
g_list_free(pRenderers);
+ ++nHeader;
}
- g_list_free(pColumns);
m_nIdCol = nIndex++;
for (auto& a : m_aToggleVisMap)
{
@@ -5194,8 +5225,7 @@ public:
virtual void set_column_fixed_widths(const std::vector<int>& rWidths) override
{
- GList *pColumns = gtk_tree_view_get_columns(m_pTreeView);
- GList* pEntry = g_list_first(pColumns);
+ GList* pEntry = g_list_first(m_pColumns);
for (auto nWidth : rWidths)
{
assert(pEntry && "wrong count");
@@ -5203,27 +5233,22 @@ public:
gtk_tree_view_column_set_fixed_width(pColumn, nWidth);
pEntry = g_list_next(pEntry);
}
- g_list_free(pColumns);
}
virtual OUString get_column_title(int nColumn) const override
{
- GList *pColumns = gtk_tree_view_get_columns(m_pTreeView);
- GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(g_list_nth_data(pColumns, nColumn));
+ GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(g_list_nth_data(m_pColumns, nColumn));
assert(pColumn && "wrong count");
const gchar* pTitle = gtk_tree_view_column_get_title(pColumn);
OUString sRet = OUString(pTitle, pTitle ? strlen(pTitle) : 0, RTL_TEXTENCODING_UTF8);
- g_list_free(pColumns);
return sRet;
}
virtual void set_column_title(int nColumn, const OUString& rTitle) override
{
- GList *pColumns = gtk_tree_view_get_columns(m_pTreeView);
- GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(g_list_nth_data(pColumns, nColumn));
+ GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(g_list_nth_data(m_pColumns, nColumn));
assert(pColumn && "wrong count");
gtk_tree_view_column_set_title(pColumn, OUStringToOString(rTitle, RTL_TEXTENCODING_UTF8).getStr());
- g_list_free(pColumns);
}
virtual void insert(weld::TreeIter* pParent, int pos, const OUString* pText, const OUString* pId, const OUString* pIconName,
@@ -5310,9 +5335,23 @@ public:
m_xSorter.reset(new comphelper::string::NaturalStringSorter(
::comphelper::getProcessComponentContext(),
Application::GetSettings().GetUILanguageTag().getLocale()));
+ set_sort_order(true);
+ }
+
+ virtual void set_sort_order(bool bAscending) override
+ {
+ m_eSortType = bAscending ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING;
GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore);
- gtk_tree_sortable_set_sort_column_id(pSortable, m_nTextCol, GTK_SORT_ASCENDING);
- gtk_tree_sortable_set_sort_func(pSortable, m_nTextCol, sort_func, m_xSorter.get(), nullptr);
+ gtk_tree_sortable_set_sort_column_id(pSortable, m_nTextCol, m_eSortType);
+ GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(g_list_nth_data(m_pColumns, m_nTextColHeader));
+ assert(pColumn && "wrong count");
+ if (gtk_tree_view_column_get_sort_indicator(pColumn))
+ gtk_tree_view_column_set_sort_order(pColumn, m_eSortType);
+ }
+
+ virtual bool get_sort_order() const override
+ {
+ return m_eSortType == GTK_SORT_ASCENDING;
}
virtual int n_children() const override
@@ -5681,7 +5720,7 @@ public:
if (m_xSorter)
{
GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore);
- gtk_tree_sortable_set_sort_column_id(pSortable, GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, GTK_SORT_ASCENDING);
+ gtk_tree_sortable_set_sort_column_id(pSortable, GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, m_eSortType);
}
enable_notify_events();
}
@@ -5692,7 +5731,7 @@ public:
if (m_xSorter)
{
GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore);
- gtk_tree_sortable_set_sort_column_id(pSortable, m_nTextCol, GTK_SORT_ASCENDING);
+ gtk_tree_sortable_set_sort_column_id(pSortable, m_nTextCol, m_eSortType);
}
gtk_tree_view_set_model(m_pTreeView, GTK_TREE_MODEL(m_pTreeStore));
GtkInstanceContainer::thaw();
@@ -5703,8 +5742,7 @@ public:
virtual int get_height_rows(int nRows) const override
{
gint nMaxRowHeight = 0;
- GList *pColumns = gtk_tree_view_get_columns(m_pTreeView);
- for (GList* pEntry = g_list_first(pColumns); pEntry; pEntry = g_list_next(pEntry))
+ for (GList* pEntry = g_list_first(m_pColumns); pEntry; pEntry = g_list_next(pEntry))
{
GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(pEntry->data);
GList *pRenderers = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(pColumn));
@@ -5714,7 +5752,6 @@ public:
nMaxRowHeight = std::max(nMaxRowHeight, nRowHeight);
g_list_free(pRenderers);
}
- g_list_free(pColumns);
gint nVerticalSeparator;
gtk_widget_style_get(GTK_WIDGET(m_pTreeView), "vertical-separator", &nVerticalSeparator, nullptr);
@@ -5807,6 +5844,14 @@ public:
g_signal_handler_disconnect(m_pTreeView, m_nTestExpandRowSignalId);
g_signal_handler_disconnect(m_pTreeView, m_nRowActivatedSignalId);
g_signal_handler_disconnect(gtk_tree_view_get_selection(m_pTreeView), m_nChangedSignalId);
+
+ for (GList* pEntry = g_list_last(m_pColumns); pEntry; pEntry = g_list_previous(pEntry))
+ {
+ GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(pEntry->data);
+ g_signal_handler_disconnect(pColumn, m_aColumnSignalIds.back());
+ m_aColumnSignalIds.pop_back();
+ }
+ g_list_free(m_pColumns);
}
};