weld FmFieldWin

needs drag source support

fixes a leak of ColumnInfo data as well

Change-Id: I671834726aed3fd4de096b56baaa592f51a9e73e
Reviewed-on: https://gerrit.libreoffice.org/84147
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
This commit is contained in:
Caolán McNamara
2019-12-01 20:51:12 +01:00
parent b1f9e704cb
commit 19d17a739c
15 changed files with 380 additions and 247 deletions
+6 -6
View File
@@ -51,15 +51,17 @@ namespace svx
//= OColumnTransferable
class SAL_WARN_UNUSED SVX_DLLPUBLIC OColumnTransferable final : public TransferableHelper
class SAL_WARN_UNUSED SVX_DLLPUBLIC OColumnTransferable final : public TransferDataContainer
{
public:
OColumnTransferable(ColumnTransferFormatFlags nFormats);
/** construct the transferable from a data access descriptor
Note that some of the aspects, in particular all which cannot be represented
as string, can only be transported via the CTF_COLUMN_DESCRIPTOR format.
@param _rDescriptor
@param rDescriptor
The descriptor for the column. It must contain at least
<ul><li>information sufficient to create a connection, that is, either one of DataSource, DatabaseLocation,
ConnectionResource, and DataAccessDescriptorProperty::Connection</li>
@@ -68,10 +70,8 @@ namespace svx
<li>a ColumnName or ColumnObject</li>
</ul>
*/
OColumnTransferable(
const ODataAccessDescriptor& _rDescriptor,
ColumnTransferFormatFlags _nFormats
);
void setDescriptor(const ODataAccessDescriptor& rDescriptor);
/** construct the transferable from a DatabaseForm component and a field name
+1 -1
View File
@@ -483,7 +483,7 @@ public:
struct TransferDataContainer_Impl;
class VCL_DLLPUBLIC TransferDataContainer final : public TransferableHelper
class VCL_DLLPUBLIC TransferDataContainer : public TransferableHelper
{
std::unique_ptr<TransferDataContainer_Impl> pImpl;
+6
View File
@@ -225,9 +225,13 @@ class VCL_DLLPUBLIC SvTreeListBox
SelectionMode eSelMode;
sal_Int32 nMinWidthInChars;
sal_Int8 mnDragAction;
SvTreeListEntry* pEdEntry;
SvLBoxItem* pEdItem;
rtl::Reference<TransferDataContainer> m_xTransferHelper;
protected:
std::unique_ptr<SvImpLBox> pImpl;
short nColumns;
@@ -726,6 +730,8 @@ public:
void SetForceMakeVisible(bool bEnable);
virtual FactoryFunction GetUITestFactory() const override;
void SetDragHelper(rtl::Reference<TransferDataContainer>& rHelper, sal_uInt8 eDNDConstants);
};
class SvInplaceEdit2
+10
View File
@@ -63,6 +63,7 @@ enum class PointerStyle;
class SvNumberFormatter;
class KeyEvent;
class MouseEvent;
class TransferDataContainer;
class OutputDevice;
class VirtualDevice;
struct SystemEnvData;
@@ -686,7 +687,10 @@ protected:
Link<const TreeIter&, bool> m_aExpandingHdl;
Link<TreeView&, void> m_aVisibleRangeChangedHdl;
Link<TreeView&, void> m_aModelChangedHdl;
// if handler returns true, then menu has been show and event is consumed
Link<const CommandEvent&, bool> m_aPopupMenuHdl;
// if handler returns true, drag is disallowed
Link<TreeView&, bool> m_aDragBeginHdl;
std::function<int(const weld::TreeIter&, const weld::TreeIter&)> m_aCustomSort;
std::vector<int> m_aRadioIndexes;
@@ -937,6 +941,12 @@ public:
m_aPopupMenuHdl = rLink;
}
virtual void enable_drag_source(rtl::Reference<TransferDataContainer>& rTransferrable,
sal_uInt8 eDNDConstants)
= 0;
void connect_drag_begin(const Link<TreeView&, bool>& rLink) { m_aDragBeginHdl = rLink; }
//all of them
void select_all() { unselect(-1); }
void unselect_all() { select(-1); }
+1
View File
@@ -49,6 +49,7 @@ $(eval $(call gb_UIConfig_add_uifiles,svx,\
svx/uiconfig/ui/fontworkgallerydialog \
svx/uiconfig/ui/fontworkspacingdialog \
svx/uiconfig/ui/formdatamenu \
svx/uiconfig/ui/formfielddialog \
svx/uiconfig/ui/formlinkwarndialog \
svx/uiconfig/ui/formnavimenu \
svx/uiconfig/ui/functionmenu \
+16 -13
View File
@@ -42,18 +42,22 @@ namespace svx
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::datatransfer;
OColumnTransferable::OColumnTransferable(const ODataAccessDescriptor& _rDescriptor, ColumnTransferFormatFlags _nFormats )
:m_nFormatFlags(_nFormats)
OColumnTransferable::OColumnTransferable(ColumnTransferFormatFlags nFormats)
: m_nFormatFlags(nFormats)
{
}
void OColumnTransferable::setDescriptor(const ODataAccessDescriptor& rDescriptor)
{
OUString sDataSource, sDatabaseLocation, sConnectionResource, sCommand, sFieldName;
if ( _rDescriptor.has( DataAccessDescriptorProperty::DataSource ) ) _rDescriptor[ DataAccessDescriptorProperty::DataSource ] >>= sDataSource;
if ( _rDescriptor.has( DataAccessDescriptorProperty::DatabaseLocation ) ) _rDescriptor[ DataAccessDescriptorProperty::DatabaseLocation ] >>= sDatabaseLocation;
if ( _rDescriptor.has( DataAccessDescriptorProperty::ConnectionResource ) ) _rDescriptor[ DataAccessDescriptorProperty::ConnectionResource ] >>= sConnectionResource;
if ( _rDescriptor.has( DataAccessDescriptorProperty::Command ) ) _rDescriptor[ DataAccessDescriptorProperty::Command ] >>= sCommand;
if ( _rDescriptor.has( DataAccessDescriptorProperty::ColumnName ) ) _rDescriptor[ DataAccessDescriptorProperty::ColumnName ] >>= sFieldName;
if ( rDescriptor.has( DataAccessDescriptorProperty::DataSource ) ) rDescriptor[ DataAccessDescriptorProperty::DataSource ] >>= sDataSource;
if ( rDescriptor.has( DataAccessDescriptorProperty::DatabaseLocation ) ) rDescriptor[ DataAccessDescriptorProperty::DatabaseLocation ] >>= sDatabaseLocation;
if ( rDescriptor.has( DataAccessDescriptorProperty::ConnectionResource ) ) rDescriptor[ DataAccessDescriptorProperty::ConnectionResource ] >>= sConnectionResource;
if ( rDescriptor.has( DataAccessDescriptorProperty::Command ) ) rDescriptor[ DataAccessDescriptorProperty::Command ] >>= sCommand;
if ( rDescriptor.has( DataAccessDescriptorProperty::ColumnName ) ) rDescriptor[ DataAccessDescriptorProperty::ColumnName ] >>= sFieldName;
sal_Int32 nCommandType = CommandType::TABLE;
OSL_VERIFY( _rDescriptor[ DataAccessDescriptorProperty::CommandType ] >>= nCommandType );
OSL_VERIFY( rDescriptor[ DataAccessDescriptorProperty::CommandType ] >>= nCommandType );
implConstruct(
@@ -62,14 +66,13 @@ namespace svx
if ( m_nFormatFlags & ColumnTransferFormatFlags::COLUMN_DESCRIPTOR )
{
if ( _rDescriptor.has( DataAccessDescriptorProperty::Connection ) )
m_aDescriptor[ DataAccessDescriptorProperty::Connection ] = _rDescriptor[ DataAccessDescriptorProperty::Connection ];
if ( _rDescriptor.has( DataAccessDescriptorProperty::ColumnObject ) )
m_aDescriptor[ DataAccessDescriptorProperty::ColumnObject ] = _rDescriptor[ DataAccessDescriptorProperty::ColumnObject ];
if ( rDescriptor.has( DataAccessDescriptorProperty::Connection ) )
m_aDescriptor[ DataAccessDescriptorProperty::Connection ] = rDescriptor[ DataAccessDescriptorProperty::Connection ];
if ( rDescriptor.has( DataAccessDescriptorProperty::ColumnObject ) )
m_aDescriptor[ DataAccessDescriptorProperty::ColumnObject ] = rDescriptor[ DataAccessDescriptorProperty::ColumnObject ];
}
}
OColumnTransferable::OColumnTransferable(const Reference< XPropertySet >& _rxForm,
const OUString& _rFieldName, const Reference< XPropertySet >& _rxColumn,
const Reference< XConnection >& _rxConnection, ColumnTransferFormatFlags _nFormats)
+62 -156
View File
@@ -24,7 +24,6 @@
#include <svx/strings.hrc>
#include <svx/svxids.hrc>
#include <svx/dbaexchange.hxx>
#include <com/sun/star/sdb/CommandType.hpp>
#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
#include <com/sun/star/sdb/XQueriesSupplier.hpp>
@@ -59,8 +58,6 @@
const long STD_WIN_SIZE_X = 120;
const long STD_WIN_SIZE_Y = 150;
const long LISTBOX_BORDER = 2;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::sdb;
using namespace ::com::sun::star::uno;
@@ -74,8 +71,6 @@ using namespace ::svxform;
using namespace ::svx;
using namespace ::dbtools;
namespace {
struct ColumnInfo
{
OUString const sColumnName;
@@ -85,9 +80,7 @@ struct ColumnInfo
}
};
}
static void lcl_addToList( SvTreeListBox& _rListBox, const uno::Reference< container::XNameAccess>& i_xColumns )
void FmFieldWin::addToList(const uno::Reference< container::XNameAccess>& i_xColumns )
{
const uno::Sequence< OUString > aEntries = i_xColumns->getElementNames();
for ( const OUString& rEntry : aEntries )
@@ -96,124 +89,77 @@ static void lcl_addToList( SvTreeListBox& _rListBox, const uno::Reference< conta
OUString sLabel;
if ( xColumn->getPropertySetInfo()->hasPropertyByName(FM_PROP_LABEL) )
xColumn->getPropertyValue(FM_PROP_LABEL) >>= sLabel;
m_aListBoxData.emplace_back(new ColumnInfo(rEntry));
OUString sId(OUString::number(reinterpret_cast<sal_Int64>(m_aListBoxData.back().get())));
if ( !sLabel.isEmpty() )
_rListBox.InsertEntry( sLabel, nullptr, false, TREELIST_APPEND, new ColumnInfo(rEntry) );
m_xListBox->append(sId, sLabel);
else
_rListBox.InsertEntry( rEntry, nullptr, false, TREELIST_APPEND, new ColumnInfo(rEntry) );
m_xListBox->append(sId, rEntry);
}
}
FmFieldWinListBox::FmFieldWinListBox( FmFieldWin* pParent )
:SvTreeListBox( pParent, WB_HASBUTTONS|WB_BORDER )
,pTabWin( pParent )
IMPL_LINK_NOARG(FmFieldWin, DragBeginHdl, weld::TreeView&, bool)
{
SetHelpId( HID_FIELD_SEL );
SetHighlightRange( );
}
FmFieldWinListBox::~FmFieldWinListBox()
{
disposeOnce();
}
void FmFieldWinListBox::dispose()
{
pTabWin.clear();
SvTreeListBox::dispose();
}
sal_Int8 FmFieldWinListBox::AcceptDrop( const AcceptDropEvent& /*rEvt*/ )
{
return DND_ACTION_NONE;
}
sal_Int8 FmFieldWinListBox::ExecuteDrop( const ExecuteDropEvent& /*rEvt*/ )
{
return DND_ACTION_NONE;
}
bool FmFieldWinListBox::DoubleClickHdl()
{
if ( pTabWin->createSelectionControls() )
return true;
return SvTreeListBox::DoubleClickHdl();
}
void FmFieldWinListBox::StartDrag( sal_Int8 /*_nAction*/, const Point& /*_rPosPixel*/ )
{
SvTreeListEntry* pSelected = FirstSelected();
ColumnInfo* pSelected = reinterpret_cast<ColumnInfo*>(m_xListBox->get_selected_id().toInt64());
if (!pSelected)
{
// no drag without a field
return;
return true;
}
svx::ODataAccessDescriptor aDescriptor;
aDescriptor[ DataAccessDescriptorProperty::DataSource ] <<= pTabWin->GetDatabaseName();
aDescriptor[ DataAccessDescriptorProperty::Connection ] <<= pTabWin->GetConnection().getTyped();
aDescriptor[ DataAccessDescriptorProperty::Command ] <<= pTabWin->GetObjectName();
aDescriptor[ DataAccessDescriptorProperty::CommandType ]<<= pTabWin->GetObjectType();
ColumnInfo* pInfo = static_cast<ColumnInfo*>(pSelected->GetUserData());
aDescriptor[ DataAccessDescriptorProperty::ColumnName ] <<= pInfo->sColumnName;
aDescriptor[ DataAccessDescriptorProperty::DataSource ] <<= GetDatabaseName();
aDescriptor[ DataAccessDescriptorProperty::Connection ] <<= GetConnection().getTyped();
aDescriptor[ DataAccessDescriptorProperty::Command ] <<= GetObjectName();
aDescriptor[ DataAccessDescriptorProperty::CommandType ]<<= GetObjectType();
aDescriptor[ DataAccessDescriptorProperty::ColumnName ] <<= pSelected->sColumnName;
rtl::Reference<OColumnTransferable> pTransferColumn = new OColumnTransferable(
aDescriptor, ColumnTransferFormatFlags::FIELD_DESCRIPTOR | ColumnTransferFormatFlags::CONTROL_EXCHANGE | ColumnTransferFormatFlags::COLUMN_DESCRIPTOR
);
EndSelection();
pTransferColumn->StartDrag( this, DND_ACTION_COPY );
m_xHelper->setDescriptor(aDescriptor);
return false;
}
FmFieldWin::FmFieldWin(SfxBindings* _pBindings, SfxChildWindow* _pMgr, vcl::Window* _pParent)
:SfxFloatingWindow(_pBindings, _pMgr, _pParent, WinBits(WB_STDMODELESS|WB_SIZEABLE))
,SfxControllerItem(SID_FM_FIELDS_CONTROL, *_pBindings)
,::comphelper::OPropertyChangeListener(m_aMutex)
,m_nObjectType(0)
FmFieldWin::FmFieldWin(SfxBindings* _pBindings, SfxChildWindow* _pMgr, weld::Window* _pParent)
: SfxModelessDialogController(_pBindings, _pMgr, _pParent, "svx/ui/formfielddialog.ui", "FormFieldDialog")
, SfxControllerItem(SID_FM_FIELDS_CONTROL, *_pBindings)
, comphelper::OPropertyChangeListener(m_aMutex)
, m_xListBox(m_xBuilder->weld_tree_view("treeview"))
, m_nObjectType(0)
{
SetHelpId( HID_FIELD_SEL_WIN );
m_xDialog->set_help_id(HID_FIELD_SEL_WIN);
m_xListBox->set_help_id(HID_FIELD_SEL);
m_xListBox->connect_row_activated(LINK(this, FmFieldWin, RowActivatedHdl));
m_xHelper.set(new OColumnTransferable(
ColumnTransferFormatFlags::FIELD_DESCRIPTOR | ColumnTransferFormatFlags::CONTROL_EXCHANGE | ColumnTransferFormatFlags::COLUMN_DESCRIPTOR
));
rtl::Reference<TransferDataContainer> xHelper(m_xHelper.get());
m_xListBox->enable_drag_source(xHelper, DND_ACTION_COPY);
m_xListBox->connect_drag_begin(LINK(this, FmFieldWin, DragBeginHdl));
SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetFaceColor()) );
pListBox = VclPtr<FmFieldWinListBox>::Create( this );
pListBox->Show();
UpdateContent(nullptr);
SetSizePixel(Size(STD_WIN_SIZE_X,STD_WIN_SIZE_Y));
m_xDialog->set_size_request(STD_WIN_SIZE_X, STD_WIN_SIZE_Y);
}
FmFieldWin::~FmFieldWin()
{
disposeOnce();
}
void FmFieldWin::dispose()
{
if (m_pChangeListener.is())
if (m_xChangeListener.is())
{
m_pChangeListener->dispose();
m_pChangeListener.clear();
m_xChangeListener->dispose();
m_xChangeListener.clear();
}
pListBox.disposeAndClear();
::SfxControllerItem::dispose();
SfxFloatingWindow::dispose();
}
void FmFieldWin::GetFocus()
IMPL_LINK_NOARG(FmFieldWin, RowActivatedHdl, weld::TreeView&, bool)
{
if ( pListBox )
pListBox->GrabFocus();
else
SfxFloatingWindow::GetFocus();
return createSelectionControls();
}
bool FmFieldWin::createSelectionControls( )
bool FmFieldWin::createSelectionControls()
{
SvTreeListEntry* pSelected = pListBox->FirstSelected();
if ( pSelected )
ColumnInfo* pSelected = reinterpret_cast<ColumnInfo*>(m_xListBox->get_selected_id().toInt64());
if (pSelected)
{
// build a descriptor for the currently selected field
ODataAccessDescriptor aDescr;
@@ -223,8 +169,7 @@ bool FmFieldWin::createSelectionControls( )
aDescr[ DataAccessDescriptorProperty::Command ] <<= GetObjectName();
aDescr[ DataAccessDescriptorProperty::CommandType ] <<= GetObjectType();
ColumnInfo* pInfo = static_cast<ColumnInfo*>(pSelected->GetUserData());
aDescr[ DataAccessDescriptorProperty::ColumnName ] <<= pInfo->sColumnName;//OUString( pListBox->GetEntryText( pSelected) );
aDescr[ DataAccessDescriptorProperty::ColumnName ] <<= pSelected->sColumnName;
// transfer this to the SFX world
SfxUnoAnyItem aDescriptorItem( SID_FM_DATACCESS_DESCRIPTOR, makeAny( aDescr.createPropertyValueSequence() ) );
@@ -240,30 +185,12 @@ bool FmFieldWin::createSelectionControls( )
return nullptr != pSelected;
}
bool FmFieldWin::PreNotify( NotifyEvent& _rNEvt )
{
if ( MouseNotifyEvent::KEYINPUT == _rNEvt.GetType() )
{
const vcl::KeyCode& rKeyCode = _rNEvt.GetKeyEvent()->GetKeyCode();
if ( ( 0 == rKeyCode.GetModifier() ) && ( KEY_RETURN == rKeyCode.GetCode() ) )
{
if ( createSelectionControls() )
return true;
}
}
return SfxFloatingWindow::PreNotify( _rNEvt );
}
void FmFieldWin::_propertyChanged(const css::beans::PropertyChangeEvent& evt)
{
css::uno::Reference< css::form::XForm > xForm(evt.Source, css::uno::UNO_QUERY);
UpdateContent(xForm);
}
void FmFieldWin::StateChanged(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState)
{
if (!pState || SID_FM_FIELDS_CONTROL != nSID)
@@ -278,12 +205,12 @@ void FmFieldWin::StateChanged(sal_uInt16 nSID, SfxItemState eState, const SfxPoo
UpdateContent(nullptr);
}
void FmFieldWin::UpdateContent(FmFormShell const * pShell)
{
pListBox->Clear();
m_xListBox->clear();
m_aListBoxData.clear();
OUString aTitle(SvxResId(RID_STR_FIELDSELECTION));
SetText( aTitle );
m_xDialog->set_title(aTitle);
if (!pShell || !pShell->GetImpl())
return;
@@ -293,15 +220,15 @@ void FmFieldWin::UpdateContent(FmFormShell const * pShell)
UpdateContent( xForm );
}
void FmFieldWin::UpdateContent(const css::uno::Reference< css::form::XForm > & xForm)
{
try
{
// delete ListBox
pListBox->Clear();
m_xListBox->clear();
m_aListBoxData.clear();
OUString aTitle(SvxResId(RID_STR_FIELDSELECTION));
SetText(aTitle);
m_xDialog->set_title(aTitle);
if (!xForm.is())
return;
@@ -328,7 +255,7 @@ void FmFieldWin::UpdateContent(const css::uno::Reference< css::form::XForm > & x
Reference< XComponent > xKeepFieldsAlive;
Reference< XNameAccess > xColumns = getFieldsByCommandDescriptor( m_aConnection, m_nObjectType, m_aObjectName,xKeepFieldsAlive );
if ( xColumns.is() )
lcl_addToList(*pListBox,xColumns);
addToList(xColumns);
}
// set prefix
@@ -348,19 +275,19 @@ void FmFieldWin::UpdateContent(const css::uno::Reference< css::form::XForm > & x
}
// listen for changes at ControlSource in PropertySet
if (m_pChangeListener.is())
if (m_xChangeListener.is())
{
m_pChangeListener->dispose();
m_pChangeListener.clear();
m_xChangeListener->dispose();
m_xChangeListener.clear();
}
m_pChangeListener = new ::comphelper::OPropertyChangeMultiplexer(this, xSet);
m_pChangeListener->addProperty(FM_PROP_DATASOURCE);
m_pChangeListener->addProperty(FM_PROP_COMMAND);
m_pChangeListener->addProperty(FM_PROP_COMMANDTYPE);
m_xChangeListener = new ::comphelper::OPropertyChangeMultiplexer(this, xSet);
m_xChangeListener->addProperty(FM_PROP_DATASOURCE);
m_xChangeListener->addProperty(FM_PROP_COMMAND);
m_xChangeListener->addProperty(FM_PROP_COMMANDTYPE);
// set title
aTitle += " " + aPrefix + " " + m_aObjectName;
SetText( aTitle );
m_xDialog->set_title(aTitle);
}
catch( const Exception& )
{
@@ -368,41 +295,20 @@ void FmFieldWin::UpdateContent(const css::uno::Reference< css::form::XForm > & x
}
}
void FmFieldWin::Resize()
{
SfxFloatingWindow::Resize();
Size aOutputSize( GetOutputSizePixel() );
// adapt size of css::form::ListBox
Point aLBPos( LISTBOX_BORDER, LISTBOX_BORDER );
Size aLBSize( aOutputSize );
aLBSize.AdjustWidth( -(2*LISTBOX_BORDER) );
aLBSize.AdjustHeight( -(2*LISTBOX_BORDER) );
pListBox->SetPosSizePixel( aLBPos, aLBSize );
}
void FmFieldWin::FillInfo( SfxChildWinInfo& rInfo ) const
{
rInfo.bVisible = false;
}
SFX_IMPL_FLOATINGWINDOW(FmFieldWinMgr, SID_FM_ADD_FIELD)
SFX_IMPL_MODELESSDIALOGCONTOLLER(FmFieldWinMgr, SID_FM_ADD_FIELD)
FmFieldWinMgr::FmFieldWinMgr(vcl::Window* _pParent, sal_uInt16 _nId,
SfxBindings* _pBindings, SfxChildWinInfo const * _pInfo)
:SfxChildWindow(_pParent, _nId)
{
SetWindow( VclPtr<FmFieldWin>::Create(_pBindings, this, _pParent) );
SetController(std::make_shared<FmFieldWin>(_pBindings, this, _pParent->GetFrameWeld()));
SetHideNotDelete(true);
static_cast<SfxFloatingWindow*>(GetWindow())->Initialize( _pInfo );
static_cast<FmFieldWin*>(GetController().get())->Initialize(_pInfo);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+18 -45
View File
@@ -23,6 +23,7 @@
#include <sfx2/basedlgs.hxx>
#include <sfx2/childwin.hxx>
#include <sfx2/ctrlitem.hxx>
#include <svx/dbaexchange.hxx>
#include <com/sun/star/form/XForm.hpp>
#include <comphelper/propmultiplex.hxx>
@@ -30,61 +31,34 @@
#include <connectivity/dbtools.hxx>
class FmFieldWin;
class FmFieldWinListBox
:public SvTreeListBox
{
VclPtr<FmFieldWin> pTabWin;
protected:
// virtual void Command( const CommandEvent& rEvt );
public:
FmFieldWinListBox( FmFieldWin* pParent );
virtual ~FmFieldWinListBox() override;
virtual void dispose() override;
sal_Int8 AcceptDrop( const AcceptDropEvent& rEvt ) override;
sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt ) override;
protected:
// DragSourceHelper
virtual void StartDrag( sal_Int8 nAction, const Point& rPosPixel ) override;
// SvTreeListBox
virtual bool DoubleClickHdl() override;
using SvTreeListBox::ExecuteDrop;
};
class FmFormShell;
struct ColumnInfo;
class FmFieldWin :public SfxFloatingWindow
,public SfxControllerItem
,public ::comphelper::OPropertyChangeListener
class FmFieldWin : public SfxModelessDialogController
, public SfxControllerItem
, public ::comphelper::OPropertyChangeListener
{
::osl::Mutex m_aMutex;
VclPtr<FmFieldWinListBox> pListBox;
std::unique_ptr<weld::TreeView> m_xListBox;
std::vector<std::unique_ptr<ColumnInfo>> m_aListBoxData;
::dbtools::SharedConnection
m_aConnection;
OUString m_aDatabaseName,
m_aObjectName;
sal_Int32 m_nObjectType;
rtl::Reference<::comphelper::OPropertyChangeMultiplexer> m_pChangeListener;
rtl::Reference<comphelper::OPropertyChangeMultiplexer> m_xChangeListener;
rtl::Reference<svx::OColumnTransferable> m_xHelper;
void addToList(const css::uno::Reference<css::container::XNameAccess>& i_xColumns);
DECL_LINK(RowActivatedHdl, weld::TreeView&, bool);
DECL_LINK(DragBeginHdl, weld::TreeView&, bool);
public:
FmFieldWin(SfxBindings *pBindings,
SfxChildWindow *pMgr, vcl::Window* pParent);
FmFieldWin(SfxBindings *pBindings, SfxChildWindow *pMgr, weld::Window* pParent);
virtual ~FmFieldWin() override;
virtual void dispose() override;
virtual void Resize() override;
using SfxFloatingWindow::Close;
virtual void GetFocus() override;
virtual bool PreNotify( NotifyEvent& _rNEvt ) override;
virtual void StateChanged(sal_uInt16 nSID, SfxItemState eState,
const SfxPoolItem* pState) override;
@@ -92,10 +66,10 @@ public:
void UpdateContent(const css::uno::Reference< css::form::XForm > &);
void FillInfo( SfxChildWinInfo& rInfo ) const override;
const OUString& GetDatabaseName() const { return m_aDatabaseName; }
const OUString& GetDatabaseName() const { return m_aDatabaseName; }
const ::dbtools::SharedConnection& GetConnection() const { return m_aConnection; }
const OUString& GetObjectName() const { return m_aObjectName; }
sal_Int32 GetObjectType() const { return m_nObjectType; }
const OUString& GetObjectName() const { return m_aObjectName; }
sal_Int32 GetObjectType() const { return m_nObjectType; }
bool createSelectionControls( );
@@ -105,7 +79,6 @@ protected:
protected:
using SfxControllerItem::GetBindings;
using SfxFloatingWindow::StateChanged;
};
+99
View File
@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface domain="svx">
<requires lib="gtk+" version="3.18"/>
<object class="GtkTreeStore" id="liststore1">
<columns>
<!-- column-name text -->
<column type="gchararray"/>
<!-- column-name id -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkDialog" id="FormFieldDialog">
<property name="can_focus">False</property>
<property name="border_width">6</property>
<property name="default_width">0</property>
<property name="default_height">0</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>
<property name="orientation">vertical</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area1">
<property name="can_focus">False</property>
<property name="no_show_all">True</property>
<property name="layout_style">end</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="container">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<child>
<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="treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">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="reorderable">True</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="treeviewcolumn3">
<property name="resizable">True</property>
<child>
<object class="GtkCellRendererText" id="cellrenderer1"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
+4 -3
View File
@@ -56,7 +56,7 @@ public:
class LclTabListBox final : public SvTabListBox
{
Link<SvTreeListBox*, void> m_aModelChangedHdl;
Link<SvTreeListBox*, void> m_aStartDragHdl;
Link<SvTreeListBox*, bool> m_aStartDragHdl;
Link<SvTreeListBox*, void> m_aEndDragHdl;
Link<SvTreeListEntry*, bool> m_aEditingEntryHdl;
Link<std::pair<SvTreeListEntry*, OUString>, bool> m_aEditedEntryHdl;
@@ -68,7 +68,7 @@ public:
}
void SetModelChangedHdl(const Link<SvTreeListBox*, void>& rLink) { m_aModelChangedHdl = rLink; }
void SetStartDragHdl(const Link<SvTreeListBox*, void>& rLink) { m_aStartDragHdl = rLink; }
void SetStartDragHdl(const Link<SvTreeListBox*, bool>& rLink) { m_aStartDragHdl = rLink; }
void SetEndDragHdl(const Link<SvTreeListBox*, void>& rLink) { m_aEndDragHdl = rLink; }
void SetEditingEntryHdl(const Link<SvTreeListEntry*, bool>& rLink)
{
@@ -86,7 +86,8 @@ public:
virtual void StartDrag(sal_Int8 nAction, const Point& rPosPixel) override
{
m_aStartDragHdl.Call(this);
if (m_aStartDragHdl.Call(this))
return;
SvTabListBox::StartDrag(nAction, rPosPixel);
}
+7
View File
@@ -150,6 +150,13 @@ public:
{
}
void set_datatransfer(const css::uno::Reference<css::datatransfer::XTransferable>& rTrans,
const css::uno::Reference<css::datatransfer::dnd::XDragSourceListener>& rListener);
std::vector<GtkTargetEntry> FormatsToGtk(const css::uno::Sequence<css::datatransfer::DataFlavor> &rFormats);
void setActiveDragSource();
virtual ~GtkDragSource() override;
// XDragSource
+11 -3
View File
@@ -3438,7 +3438,7 @@ private:
DECL_LINK(HeaderBarClickedHdl, HeaderBar*, void);
DECL_LINK(ToggleHdl, SvLBoxButtonData*, void);
DECL_LINK(ModelChangedHdl, SvTreeListBox*, void);
DECL_LINK(StartDragHdl, SvTreeListBox*, void);
DECL_LINK(StartDragHdl, SvTreeListBox*, bool);
DECL_STATIC_LINK(SalInstanceTreeView, FinishDragHdl, SvTreeListBox*, void);
DECL_LINK(EditingEntryHdl, SvTreeListEntry*, bool);
typedef std::pair<SvTreeListEntry*, OUString> IterString;
@@ -4350,6 +4350,11 @@ public:
set_id(rVclIter.iter, rId);
}
virtual void enable_drag_source(rtl::Reference<TransferDataContainer>& rHelper, sal_uInt8 eDNDConstants) override
{
m_xTreeView->SetDragHelper(rHelper, eDNDConstants);
}
virtual void set_selection_mode(SelectionMode eMode) override
{
m_xTreeView->SetSelectionMode(eMode);
@@ -4582,7 +4587,7 @@ public:
else
{
static_cast<LclTabListBox&>(*m_xTreeView).SetEndDragHdl(Link<SvTreeListBox*, void>());
static_cast<LclTabListBox&>(*m_xTreeView).SetStartDragHdl(Link<SvTreeListBox*, void>());
static_cast<LclTabListBox&>(*m_xTreeView).SetStartDragHdl(Link<SvTreeListBox*, bool>());
static_cast<LclTabListBox&>(*m_xTreeView).SetModelChangedHdl(Link<SvTreeListBox*, void>());
}
m_xTreeView->SetPopupMenuHdl(Link<const CommandEvent&, bool>());
@@ -4651,9 +4656,12 @@ IMPL_LINK_NOARG(SalInstanceTreeView, ModelChangedHdl, SvTreeListBox*, void)
signal_model_changed();
}
IMPL_LINK_NOARG(SalInstanceTreeView, StartDragHdl, SvTreeListBox*, void)
IMPL_LINK_NOARG(SalInstanceTreeView, StartDragHdl, SvTreeListBox*, bool)
{
if (m_aDragBeginHdl.Call(*this))
return true;
g_DragSource = this;
return false;
}
IMPL_STATIC_LINK_NOARG(SalInstanceTreeView, FinishDragHdl, SvTreeListBox*, void)
+19 -8
View File
@@ -373,6 +373,7 @@ SvTreeListBox::SvTreeListBox(vcl::Window* pParent, WinBits nWinStyle) :
mbQuickSearch(false),
eSelMode(SelectionMode::NONE),
nMinWidthInChars(0),
mnDragAction(DND_ACTION_COPYMOVE | DND_ACTION_LINK),
mbCenterAndClipText(false)
{
nImpFlags = SvTreeListBoxFlags::NONE;
@@ -1152,7 +1153,6 @@ void SvTreeListBox::SetupDragOrigin()
void SvTreeListBox::StartDrag( sal_Int8, const Point& rPosPixel )
{
Point aEventPos( rPosPixel );
MouseEvent aMouseEvt( aEventPos, 1, MouseEventModifiers::SELECT, MOUSE_LEFT );
MouseButtonUp( aMouseEvt );
@@ -1170,8 +1170,17 @@ void SvTreeListBox::StartDrag( sal_Int8, const Point& rPosPixel )
return;
}
rtl::Reference<TransferDataContainer> pContainer = new TransferDataContainer;
nDragDropMode = NotifyStartDrag( *pContainer, pEntry );
rtl::Reference<TransferDataContainer> xContainer = m_xTransferHelper;
if (!xContainer)
{
xContainer.set(new TransferDataContainer);
// apparently some (unused) content is needed
xContainer->CopyAnyData( SotClipboardFormatId::TREELISTBOX,
"unused", SAL_N_ELEMENTS("unused") );
}
nDragDropMode = NotifyStartDrag( *xContainer, pEntry );
if( nDragDropMode == DragDropMode::NONE || 0 == GetSelectionCount() )
{
nDragDropMode = nOldDragMode;
@@ -1181,10 +1190,6 @@ void SvTreeListBox::StartDrag( sal_Int8, const Point& rPosPixel )
SetupDragOrigin();
// apparently some (unused) content is needed
pContainer->CopyAnyData( SotClipboardFormatId::TREELISTBOX,
"unused", SAL_N_ELEMENTS("unused") );
bool bOldUpdateMode = Control::IsUpdateMode();
Control::SetUpdateMode( true );
Update();
@@ -1196,7 +1201,13 @@ void SvTreeListBox::StartDrag( sal_Int8, const Point& rPosPixel )
// (GetSourceListBox()->EnableSelectionAsDropTarget( true, true );)
EnableSelectionAsDropTarget( false );
pContainer->StartDrag( this, DND_ACTION_COPYMOVE | DND_ACTION_LINK, GetDragFinishedHdl() );
xContainer->StartDrag(this, mnDragAction, GetDragFinishedHdl());
}
void SvTreeListBox::SetDragHelper(rtl::Reference<TransferDataContainer>& rHelper, sal_uInt8 eDNDConstants)
{
m_xTransferHelper = rHelper;
mnDragAction = eDNDConstants;
}
void SvTreeListBox::DragFinished( sal_Int8
+25 -9
View File
@@ -4231,18 +4231,38 @@ sal_uIntPtr GtkSalFrame::GetNativeWindowHandle()
return GetNativeWindowHandle(m_pWindow);
}
void GtkDragSource::set_datatransfer(const css::uno::Reference<css::datatransfer::XTransferable>& rTrans,
const css::uno::Reference<css::datatransfer::dnd::XDragSourceListener>& rListener)
{
m_xListener = rListener;
m_xTrans = rTrans;
}
void GtkDragSource::setActiveDragSource()
{
// For LibreOffice internal D&D we provide the Transferable without Gtk
// intermediaries as a shortcut, see tdf#100097 for how dbaccess depends on this
g_ActiveDragSource = this;
g_DropSuccessSet = false;
g_DropSuccess = false;
}
std::vector<GtkTargetEntry> GtkDragSource::FormatsToGtk(const css::uno::Sequence<css::datatransfer::DataFlavor> &rFormats)
{
return m_aConversionHelper.FormatsToGtk(rFormats);
}
void GtkDragSource::startDrag(const datatransfer::dnd::DragGestureEvent& rEvent,
sal_Int8 sourceActions, sal_Int32 /*cursor*/, sal_Int32 /*image*/,
const css::uno::Reference<css::datatransfer::XTransferable>& rTrans,
const css::uno::Reference<css::datatransfer::dnd::XDragSourceListener>& rListener)
{
m_xListener = rListener;
m_xTrans = rTrans;
set_datatransfer(rTrans, rListener);
if (m_pFrame)
{
css::uno::Sequence<css::datatransfer::DataFlavor> aFormats = rTrans->getTransferDataFlavors();
std::vector<GtkTargetEntry> aGtkTargets(m_aConversionHelper.FormatsToGtk(aFormats));
auto aFormats = m_xTrans->getTransferDataFlavors();
std::vector<GtkTargetEntry> aGtkTargets(FormatsToGtk(aFormats));
GtkTargetList *pTargetList = gtk_target_list_new(aGtkTargets.data(), aGtkTargets.size());
gint nDragButton = 1; // default to left button
@@ -4257,11 +4277,7 @@ void GtkDragSource::startDrag(const datatransfer::dnd::DragGestureEvent& rEvent,
nDragButton = 2;
}
// For LibreOffice internal D&D we provide the Transferable without Gtk
// intermediaries as a shortcut, see tdf#100097 for how dbaccess depends on this
g_ActiveDragSource = this;
g_DropSuccessSet = false;
g_DropSuccess = false;
setActiveDragSource();
m_pFrame->startDrag(nDragButton, rEvent.DragOriginX, rEvent.DragOriginY,
VclToGdk(sourceActions), pTargetList);
+95 -3
View File
@@ -22,6 +22,7 @@
#include <headless/svpvd.hxx>
#include <headless/svpbmp.hxx>
#include <vcl/inputtypes.hxx>
#include <vcl/transfer.hxx>
#include <unx/genpspgraphics.h>
#include <rtl/strbuf.hxx>
#include <sal/log.hxx>
@@ -7945,6 +7946,18 @@ namespace
return -1;
}
GdkDragAction VclToGdk(sal_Int8 dragOperation)
{
GdkDragAction eRet(static_cast<GdkDragAction>(0));
if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_COPY)
eRet = static_cast<GdkDragAction>(eRet | GDK_ACTION_COPY);
if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_MOVE)
eRet = static_cast<GdkDragAction>(eRet | GDK_ACTION_MOVE);
if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_LINK)
eRet = static_cast<GdkDragAction>(eRet | GDK_ACTION_LINK);
return eRet;
}
struct GtkInstanceTreeIter : public weld::TreeIter
{
GtkInstanceTreeIter(const GtkInstanceTreeIter* pOrig)
@@ -7993,6 +8006,7 @@ private:
std::vector<int> m_aSavedSortColumns;
std::vector<int> m_aViewColToModelCol;
std::vector<int> m_aModelColToViewCol;
rtl::Reference<GtkDragSource> m_xDragSource;
bool m_bWorkAroundBadDragRegion;
bool m_bInDrag;
gint m_nTextCol;
@@ -8008,6 +8022,9 @@ private:
gulong m_nPopupMenuSignalId;
gulong m_nDragBeginSignalId;
gulong m_nDragEndSignalId;
gulong m_nDragFailedSignalId;
gulong m_nDragDataDeleteignalId;
gulong m_nDragGetSignalId;
gulong m_nKeyPressSignalId;
ImplSVEvent* m_pChangeEvent;
@@ -8392,15 +8409,63 @@ private:
return default_sort_func(pModel, a, b, m_xSorter.get());
}
static void signalDragBegin(GtkWidget*, GdkDragContext*, gpointer widget)
static void signalDragBegin(GtkWidget*, GdkDragContext* context, gpointer widget)
{
GtkInstanceTreeView* pThis = static_cast<GtkInstanceTreeView*>(widget);
g_DragSource = pThis;
pThis->signal_drag_begin(context);
}
static void signalDragEnd(GtkWidget*, GdkDragContext*, gpointer)
void ensure_drag_source()
{
if (!m_xDragSource)
{
m_xDragSource.set(new GtkDragSource);
m_nDragFailedSignalId = g_signal_connect(m_pWidget, "drag-failed", G_CALLBACK(signalDragFailed), this);
m_nDragDataDeleteignalId = g_signal_connect(m_pWidget, "drag-data-delete", G_CALLBACK(signalDragDelete), this);
m_nDragGetSignalId = g_signal_connect(m_pWidget, "drag-data-get", G_CALLBACK(signalDragDataGet), this);
}
}
void signal_drag_begin(GdkDragContext* context)
{
if (m_aDragBeginHdl.Call(*this))
{
gtk_drag_cancel(context);
return;
}
g_DragSource = this;
if (!m_xDragSource)
return;
m_xDragSource->setActiveDragSource();
}
static void signalDragEnd(GtkWidget* /*widget*/, GdkDragContext* context, gpointer widget)
{
g_DragSource = nullptr;
GtkInstanceTreeView* pThis = static_cast<GtkInstanceTreeView*>(widget);
if (pThis->m_xDragSource.is())
pThis->m_xDragSource->dragEnd(context);
}
static gboolean signalDragFailed(GtkWidget* /*widget*/, GdkDragContext* /*context*/, GtkDragResult /*result*/, gpointer widget)
{
GtkInstanceTreeView* pThis = static_cast<GtkInstanceTreeView*>(widget);
pThis->m_xDragSource->dragFailed();
return false;
}
static void signalDragDelete(GtkWidget* /*widget*/, GdkDragContext* /*context*/, gpointer widget)
{
GtkInstanceTreeView* pThis = static_cast<GtkInstanceTreeView*>(widget);
pThis->m_xDragSource->dragDelete();
}
static void signalDragDataGet(GtkWidget* /*widget*/, GdkDragContext* /*context*/, GtkSelectionData *data, guint info,
guint /*time*/, gpointer widget)
{
GtkInstanceTreeView* pThis = static_cast<GtkInstanceTreeView*>(widget);
pThis->m_xDragSource->dragDataGet(data, info);
}
bool signal_key_press(GdkEventKey* pEvent)
@@ -8463,6 +8528,9 @@ public:
, m_nPopupMenuSignalId(g_signal_connect(pTreeView, "popup-menu", G_CALLBACK(signalPopupMenu), this))
, m_nDragBeginSignalId(g_signal_connect(pTreeView, "drag-begin", G_CALLBACK(signalDragBegin), this))
, m_nDragEndSignalId(g_signal_connect(pTreeView, "drag-end", G_CALLBACK(signalDragEnd), this))
, m_nDragFailedSignalId(0)
, m_nDragDataDeleteignalId(0)
, m_nDragGetSignalId(0)
, m_nKeyPressSignalId(g_signal_connect(pTreeView, "key-press-event", G_CALLBACK(signalKeyPress), this))
, m_pChangeEvent(nullptr)
{
@@ -9649,6 +9717,24 @@ public:
gtk_widget_hide(m_pWidget);
}
virtual void enable_drag_source(rtl::Reference<TransferDataContainer>& rHelper, sal_uInt8 eDNDConstants) override
{
css::uno::Reference<css::datatransfer::XTransferable> xTrans(rHelper.get());
css::uno::Reference<css::datatransfer::dnd::XDragSourceListener> xListener(rHelper.get());
ensure_drag_source();
auto aFormats = xTrans->getTransferDataFlavors();
std::vector<GtkTargetEntry> aGtkTargets(m_xDragSource->FormatsToGtk(aFormats));
gtk_tree_view_enable_model_drag_source(m_pTreeView, GDK_BUTTON1_MASK, aGtkTargets.data(), aGtkTargets.size(), VclToGdk(eDNDConstants));
for (auto &a : aGtkTargets)
g_free(a.target);
m_xDragSource->set_datatransfer(xTrans, xListener);
}
virtual void set_selection_mode(SelectionMode eMode) override
{
disable_notify_events();
@@ -9876,6 +9962,12 @@ public:
g_signal_handler_disconnect(m_pTreeView, m_nKeyPressSignalId);
g_signal_handler_disconnect(m_pTreeView, m_nDragEndSignalId);
g_signal_handler_disconnect(m_pTreeView, m_nDragBeginSignalId);
if (m_nDragFailedSignalId)
g_signal_handler_disconnect(m_pTreeView, m_nDragFailedSignalId);
if (m_nDragDataDeleteignalId)
g_signal_handler_disconnect(m_pTreeView, m_nDragDataDeleteignalId);
if (m_nDragGetSignalId)
g_signal_handler_disconnect(m_pTreeView, m_nDragGetSignalId);
g_signal_handler_disconnect(m_pTreeView, m_nPopupMenuSignalId);
GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore);
g_signal_handler_disconnect(pModel, m_nRowDeletedSignalId);