Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / dbaccess / source / ui / control / RelationControl.cxx
blob3ebaef041568554dae5940ae189491ab5adec438
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "RelationControl.hxx"
22 #include <svtools/editbrowsebox.hxx>
23 #include <com/sun/star/beans/XPropertySet.hpp>
24 #include <tools/diagnose_ex.h>
25 #include <vcl/builderfactory.hxx>
26 #include "TableConnectionData.hxx"
27 #include "TableConnection.hxx"
28 #include "TableWindow.hxx"
29 #include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
30 #include "UITools.hxx"
31 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
32 #include <com/sun/star/container/XNameAccess.hpp>
33 #include "RelControliFace.hxx"
34 #include "dbu_control.hrc"
35 #include "dbaccess_helpid.hrc"
36 #include <osl/diagnose.h>
38 #include <list>
39 using std::list;
40 #include <utility>
41 using std::pair;
42 using std::make_pair;
44 #define SOURCE_COLUMN 1
45 #define DEST_COLUMN 2
47 namespace dbaui
49 using namespace ::com::sun::star::uno;
50 using namespace ::com::sun::star::beans;
51 using namespace ::com::sun::star::sdbc;
52 using namespace ::com::sun::star::sdbcx;
53 using namespace ::com::sun::star::container;
54 using namespace svt;
56 typedef ::svt::EditBrowseBox ORelationControl_Base;
57 class ORelationControl : public ORelationControl_Base
59 friend class OTableListBoxControl;
61 VclPtr< ::svt::ListBoxControl> m_pListCell;
62 TTableConnectionData::value_type m_pConnData;
63 OTableListBoxControl* m_pBoxControl;
64 long m_nDataPos;
65 Reference< XPropertySet> m_xSourceDef;
66 Reference< XPropertySet> m_xDestDef;
67 enum opcode { DELETE, INSERT, MODIFY };
68 typedef list< pair < opcode, pair < OConnectionLineDataVec::size_type, OConnectionLineDataVec::size_type> > > ops_type;
69 ops_type m_ops;
71 void fillListBox(const Reference< XPropertySet>& _xDest,long nRow,sal_uInt16 nColumnId);
72 /** returns the column id for the editbrowsebox
73 @param _nColId
74 the column id SOURCE_COLUMN or DEST_COLUMN
76 @return the current column id either SOURCE_COLUMN or DEST_COLUMN depends on the connection data
78 sal_uInt16 getColumnIdent( sal_uInt16 _nColId ) const;
79 public:
80 explicit ORelationControl(vcl::Window *pParent);
81 void SetController(OTableListBoxControl* pController)
83 m_pBoxControl = pController;
86 /** searches for a connection between these two tables
87 @param _pSource
88 the left table
89 @param _pDest
90 the right window
92 void setWindowTables(const OTableWindow* _pSource,const OTableWindow* _pDest);
94 /** allows to access the connection data from outside
96 @return the connection data
98 const TTableConnectionData::value_type& getData() const { return m_pConnData; }
100 void lateInit();
102 protected:
103 virtual ~ORelationControl() { disposeOnce(); }
104 virtual void dispose() override { m_pListCell.disposeAndClear(); ORelationControl_Base::dispose(); }
105 virtual void Resize() override;
106 virtual Size GetOptimalSize() const override;
107 virtual bool PreNotify(NotifyEvent& rNEvt ) override;
109 virtual bool IsTabAllowed(bool bForward) const override;
111 void Init(const TTableConnectionData::value_type& _pConnData);
112 virtual void Init() override { ORelationControl_Base::Init(); }
113 virtual void InitController( ::svt::CellControllerRef& rController, long nRow, sal_uInt16 nCol ) override;
114 virtual ::svt::CellController* GetController( long nRow, sal_uInt16 nCol ) override;
115 virtual void PaintCell( OutputDevice& rDev, const Rectangle& rRect, sal_uInt16 nColId ) const override;
116 virtual bool SeekRow( long nRow ) override;
117 virtual bool SaveModified() override;
118 virtual OUString GetCellText( long nRow, sal_uInt16 nColId ) const override;
120 virtual void CellModified() override;
122 DECL_LINK_TYPED( AsynchDeactivate, void*, void );
123 private:
125 DECL_LINK_TYPED( AsynchActivate, void*, void );
129 // class ORelationControl
130 ORelationControl::ORelationControl(vcl::Window *pParent)
131 : EditBrowseBox(pParent,
132 EditBrowseBoxFlags::SMART_TAB_TRAVEL | EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT,
133 WB_TABSTOP | WB_BORDER,
134 BrowserMode::AUTOSIZE_LASTCOL)
135 , m_pBoxControl(nullptr)
136 , m_nDataPos(0)
137 , m_xSourceDef(nullptr)
138 , m_xDestDef(nullptr)
142 VCL_BUILDER_FACTORY(ORelationControl)
144 void ORelationControl::Init(const TTableConnectionData::value_type& _pConnData)
147 m_pConnData = _pConnData;
148 OSL_ENSURE(m_pConnData, "No data supplied!");
150 m_pConnData->normalizeLines();
153 void ORelationControl::lateInit()
155 if ( !m_pConnData.get() )
156 return;
157 m_xSourceDef = m_pConnData->getReferencingTable()->getTable();
158 m_xDestDef = m_pConnData->getReferencedTable()->getTable();
160 if ( ColCount() == 0 )
162 InsertDataColumn( SOURCE_COLUMN, m_pConnData->getReferencingTable()->GetWinName(), 100);
163 InsertDataColumn( DEST_COLUMN, m_pConnData->getReferencedTable()->GetWinName(), 100);
164 // If the Defs do not yet exits, we need to set them with SetSource-/-DestDef
166 m_pListCell.reset( VclPtr<ListBoxControl>::Create( &GetDataWindow() ) );
168 // set browse mode
169 SetMode( BrowserMode::COLUMNSELECTION |
170 BrowserMode::HLINES |
171 BrowserMode::VLINES |
172 BrowserMode::HIDECURSOR |
173 BrowserMode::HIDESELECT |
174 BrowserMode::AUTO_HSCROLL |
175 BrowserMode::AUTO_VSCROLL);
177 else
178 // not the first call
179 RowRemoved(0, GetRowCount());
181 RowInserted(0, m_pConnData->GetConnLineDataList().size() + 1); // add one extra row
184 void ORelationControl::Resize()
186 EditBrowseBox::Resize();
187 long nOutputWidth = GetOutputSizePixel().Width() - 1;
188 SetColumnWidth(1, (nOutputWidth / 2));
189 SetColumnWidth(2, (nOutputWidth / 2));
192 bool ORelationControl::PreNotify(NotifyEvent& rNEvt)
194 if (rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS && !HasChildPathFocus() )
195 PostUserEvent(LINK(this, ORelationControl, AsynchDeactivate), nullptr, true);
196 else if (rNEvt.GetType() == MouseNotifyEvent::GETFOCUS)
197 PostUserEvent(LINK(this, ORelationControl, AsynchActivate), nullptr, true);
199 return EditBrowseBox::PreNotify(rNEvt);
202 IMPL_LINK_NOARG_TYPED(ORelationControl, AsynchActivate, void*, void)
204 ActivateCell();
207 IMPL_LINK_NOARG_TYPED(ORelationControl, AsynchDeactivate, void*, void)
209 DeactivateCell();
212 bool ORelationControl::IsTabAllowed(bool bForward) const
214 long nRow = GetCurRow();
215 sal_uInt16 nCol = GetCurColumnId();
217 bool bRet = !(( ( bForward && (nCol == DEST_COLUMN) && (nRow == GetRowCount() - 1)))
218 || (!bForward && (nCol == SOURCE_COLUMN) && (nRow == 0)));
220 return bRet && EditBrowseBox::IsTabAllowed(bForward);
223 bool ORelationControl::SaveModified()
225 long nRow = GetCurRow();
226 if ( nRow != BROWSER_ENDOFSELECTION )
228 OUString sFieldName(m_pListCell->GetSelectEntry());
229 OConnectionLineDataVec& rLines = m_pConnData->GetConnLineDataList();
230 if ( rLines.size() <= static_cast<OConnectionLineDataVec::size_type>(nRow) )
232 rLines.push_back(new OConnectionLineData());
233 nRow = rLines.size() - 1;
234 // add new past-rLines row
235 m_ops.push_back(make_pair(INSERT, make_pair(nRow+1, nRow+2)));
238 OConnectionLineDataRef pConnLineData = rLines[nRow];
240 switch( getColumnIdent( GetCurColumnId() ) )
242 case SOURCE_COLUMN:
243 pConnLineData->SetSourceFieldName( sFieldName );
244 break;
245 case DEST_COLUMN:
246 pConnLineData->SetDestFieldName( sFieldName );
247 break;
249 // the modification we just did does *not* need to be registered in m_ops;
250 // it is already taken into account (by the codepath that called us)
251 //m_ops.push_back(make_pair(MODIFY, make_pair(nRow, nRow+1)));
254 const OConnectionLineDataVec::size_type oldSize = m_pConnData->GetConnLineDataList().size();
255 OConnectionLineDataVec::size_type line = m_pConnData->normalizeLines();
256 const OConnectionLineDataVec::size_type newSize = m_pConnData->GetConnLineDataList().size();
257 assert(newSize <= oldSize);
258 m_ops.push_back(make_pair(MODIFY, make_pair(line, newSize)));
259 m_ops.push_back(make_pair(DELETE, make_pair(newSize, oldSize)));
261 return true;
264 sal_uInt16 ORelationControl::getColumnIdent( sal_uInt16 _nColId ) const
266 sal_uInt16 nId = _nColId;
267 if ( m_pConnData->getReferencingTable() != m_pBoxControl->getReferencingTable() )
268 nId = ( _nColId == SOURCE_COLUMN) ? DEST_COLUMN : SOURCE_COLUMN;
269 return nId;
272 OUString ORelationControl::GetCellText( long nRow, sal_uInt16 nColId ) const
274 OUString sText;
275 if ( m_pConnData->GetConnLineDataList().size() > static_cast<size_t>(nRow) )
277 OConnectionLineDataRef pConnLineData = m_pConnData->GetConnLineDataList()[nRow];
278 switch( getColumnIdent( nColId ) )
280 case SOURCE_COLUMN:
281 sText = pConnLineData->GetSourceFieldName();
282 break;
283 case DEST_COLUMN:
284 sText = pConnLineData->GetDestFieldName();
285 break;
288 return sText;
291 void ORelationControl::InitController( CellControllerRef& /*rController*/, long nRow, sal_uInt16 nColumnId )
294 OString sHelpId( HID_RELATIONDIALOG_LEFTFIELDCELL );
296 Reference< XPropertySet> xDef;
297 switch ( getColumnIdent(nColumnId) )
299 case SOURCE_COLUMN:
300 xDef = m_xSourceDef;
301 sHelpId = HID_RELATIONDIALOG_LEFTFIELDCELL;
302 break;
303 case DEST_COLUMN:
304 xDef = m_xDestDef;
305 sHelpId = HID_RELATIONDIALOG_RIGHTFIELDCELL;
306 break;
307 default:
308 // ?????????
309 break;
312 if ( xDef.is() )
314 fillListBox(xDef,nRow,nColumnId);
315 OUString sName = GetCellText( nRow, nColumnId );
316 m_pListCell->SelectEntry( sName );
317 if ( m_pListCell->GetSelectEntry() != sName )
319 m_pListCell->InsertEntry( sName );
320 m_pListCell->SelectEntry( sName );
323 m_pListCell->SetHelpId(sHelpId);
327 CellController* ORelationControl::GetController( long /*nRow*/, sal_uInt16 /*nColumnId*/ )
329 return new ListBoxCellController( m_pListCell.get() );
332 bool ORelationControl::SeekRow( long nRow )
334 m_nDataPos = nRow;
335 return true;
338 void ORelationControl::PaintCell( OutputDevice& rDev, const Rectangle& rRect, sal_uInt16 nColumnId ) const
340 OUString aText = GetCellText( m_nDataPos, nColumnId );
342 Point aPos( rRect.TopLeft() );
343 Size aTextSize( GetDataWindow().GetTextWidth( aText ), GetDataWindow().GetTextHeight() );
345 if( aPos.X() < rRect.Left() || aPos.X() + aTextSize.Width() > rRect.Right() ||
346 aPos.Y() < rRect.Top() || aPos.Y() + aTextSize.Height() > rRect.Bottom() )
348 rDev.SetClipRegion(vcl::Region(rRect));
351 rDev.DrawText( aPos, aText );
353 if( rDev.IsClipRegion() )
354 rDev.SetClipRegion();
356 void ORelationControl::fillListBox(const Reference< XPropertySet>& _xDest,long /*_nRow*/,sal_uInt16 /*nColumnId*/)
358 m_pListCell->Clear();
361 if ( _xDest.is() )
363 //sal_Int32 nRows = GetRowCount();
364 Reference<XColumnsSupplier> xSup(_xDest,UNO_QUERY);
365 Reference<XNameAccess> xColumns = xSup->getColumns();
366 Sequence< OUString> aNames = xColumns->getElementNames();
367 const OUString* pIter = aNames.getConstArray();
368 const OUString* pEnd = pIter + aNames.getLength();
369 for(;pIter != pEnd;++pIter)
371 m_pListCell->InsertEntry( *pIter );
373 m_pListCell->InsertEntry(OUString(), 0);
376 catch( const Exception& )
378 DBG_UNHANDLED_EXCEPTION();
381 void ORelationControl::setWindowTables(const OTableWindow* _pSource,const OTableWindow* _pDest)
383 // If I edit here, hide
384 bool bWasEditing = IsEditing();
385 if ( bWasEditing )
386 DeactivateCell();
388 if ( _pSource && _pDest )
390 m_xSourceDef = _pSource->GetTable();
391 SetColumnTitle(1, _pSource->GetName());
393 m_xDestDef = _pDest->GetTable();
394 SetColumnTitle(2, _pDest->GetName());
396 const OJoinTableView* pView = _pSource->getTableView();
397 OTableConnection* pConn = pView->GetTabConn(_pSource,_pDest);
398 if ( pConn && !m_pConnData->GetConnLineDataList().empty() )
400 m_pConnData->CopyFrom(*pConn->GetData());
401 m_pBoxControl->getContainer()->notifyConnectionChange();
403 else
405 // no connection found so we clear our data
406 OConnectionLineDataVec& rLines = m_pConnData->GetConnLineDataList();
407 for( const auto& rLine : rLines )
409 rLine.get()->Reset();
412 m_pConnData->setReferencingTable(_pSource->GetData());
413 m_pConnData->setReferencedTable(_pDest->GetData());
415 m_pConnData->normalizeLines();
418 // Repaint
419 Invalidate();
421 if ( bWasEditing )
423 GoToRow(0);
424 ActivateCell();
428 void ORelationControl::CellModified()
430 EditBrowseBox::CellModified();
431 SaveModified();
432 assert(m_pBoxControl);
433 m_pBoxControl->NotifyCellChange();
436 Size ORelationControl::GetOptimalSize() const
438 return LogicToPixel(Size(140, 80), MAP_APPFONT);
441 // class OTableListBoxControl
442 OTableListBoxControl::OTableListBoxControl(VclBuilderContainer* _pParent,
443 const OJoinTableView::OTableWindowMap* _pTableMap,
444 IRelationControlInterface* _pParentDialog)
445 : m_pTableMap(_pTableMap)
446 , m_pParentDialog(_pParentDialog)
448 _pParent->get(m_pLeftTable, "table1");
449 _pParent->get(m_pRightTable, "table2");
451 _pParent->get(m_pRC_Tables, "relations");
452 m_pRC_Tables->SetController(this);
453 m_pRC_Tables->Init();
455 lateUIInit();
457 Link<ListBox&,void> aLink(LINK(this, OTableListBoxControl, OnTableChanged));
458 m_pLeftTable->SetSelectHdl(aLink);
459 m_pRightTable->SetSelectHdl(aLink);
462 OTableListBoxControl::~OTableListBoxControl()
466 void OTableListBoxControl::fillListBoxes()
468 OSL_ENSURE( !m_pTableMap->empty(), "OTableListBoxControl::fillListBoxes: no table window!");
469 OTableWindow* pInitialLeft = nullptr;
470 OTableWindow* pInitialRight = nullptr;
472 // Collect the names of all TabWins
473 OJoinTableView::OTableWindowMap::const_iterator aIter = m_pTableMap->begin();
474 OJoinTableView::OTableWindowMap::const_iterator aEnd = m_pTableMap->end();
475 for(;aIter != aEnd;++aIter)
477 m_pLeftTable->InsertEntry(aIter->first);
478 m_pRightTable->InsertEntry(aIter->first);
480 if (!pInitialLeft)
482 pInitialLeft = aIter->second;
483 m_strCurrentLeft = aIter->first;
485 else if (!pInitialRight)
487 pInitialRight = aIter->second;
488 m_strCurrentRight = aIter->first;
492 if ( !pInitialRight )
494 pInitialRight = pInitialLeft;
495 m_strCurrentRight = m_strCurrentLeft;
498 // The corresponding Defs for my Controls
499 m_pRC_Tables->setWindowTables(pInitialLeft,pInitialRight);
501 // The table selected in a ComboBox must not be available in the other
503 if ( m_pTableMap->size() > 2 )
505 m_pLeftTable->RemoveEntry(m_strCurrentRight);
506 m_pRightTable->RemoveEntry(m_strCurrentLeft);
509 // Select the first one on the left side and on the right side,
510 // select the second one
511 m_pLeftTable->SelectEntry(m_strCurrentLeft);
512 m_pRightTable->SelectEntry(m_strCurrentRight);
514 m_pLeftTable->GrabFocus();
517 IMPL_LINK_TYPED( OTableListBoxControl, OnTableChanged, ListBox&, rListBox, void )
519 OUString strSelected(rListBox.GetSelectEntry());
520 OTableWindow* pLeft = nullptr;
521 OTableWindow* pRight = nullptr;
523 // Special treatment: If there are only two tables, we need to switch the other one too when changing in a LB
524 if ( m_pTableMap->size() == 2 )
526 ListBox* pOther;
527 if (&rListBox == m_pLeftTable)
528 pOther = m_pRightTable;
529 else
530 pOther = m_pLeftTable;
531 pOther->SelectEntryPos(1 - pOther->GetSelectEntryPos());
533 OJoinTableView::OTableWindowMap::const_iterator aIter = m_pTableMap->begin();
534 OTableWindow* pFirst = aIter->second;
535 ++aIter;
536 OTableWindow* pSecond = aIter->second;
538 if ( m_pLeftTable->GetSelectEntry() == pFirst->GetName() )
540 pLeft = pFirst;
541 pRight = pSecond;
543 else
545 pLeft = pSecond;
546 pRight = pFirst;
549 else
551 // First we need the TableDef to the Table and with it the TabWin
552 OJoinTableView::OTableWindowMap::const_iterator aFind = m_pTableMap->find(strSelected);
553 OTableWindow* pLoop = nullptr;
554 if( aFind != m_pTableMap->end() )
555 pLoop = aFind->second;
556 OSL_ENSURE(pLoop != nullptr, "ORelationDialog::OnTableChanged: invalid ListBox entry!");
557 // We need to find strSelect, because we filled the ListBoxes with the table names with which we compare now
558 if (&rListBox == m_pLeftTable)
560 // Insert the previously selected Entry on the left side on the right side
561 m_pRightTable->InsertEntry(m_strCurrentLeft);
562 // Remove the currently selected Entry
563 m_pRightTable->RemoveEntry(strSelected);
564 m_strCurrentLeft = strSelected;
566 pLeft = pLoop;
568 OJoinTableView::OTableWindowMap::const_iterator aIter = m_pTableMap->find(m_pRightTable->GetSelectEntry());
569 OSL_ENSURE( aIter != m_pTableMap->end(), "Invalid name");
570 if ( aIter != m_pTableMap->end() )
571 pRight = aIter->second;
573 m_pLeftTable->GrabFocus();
575 else
577 // Insert the previously selected Entry on the right side on the left side
578 m_pLeftTable->InsertEntry(m_strCurrentRight);
579 // Remove the currently selected Entry
580 m_pLeftTable->RemoveEntry(strSelected);
581 m_strCurrentRight = strSelected;
583 pRight = pLoop;
584 OJoinTableView::OTableWindowMap::const_iterator aIter = m_pTableMap->find(m_pLeftTable->GetSelectEntry());
585 OSL_ENSURE( aIter != m_pTableMap->end(), "Invalid name");
586 if ( aIter != m_pTableMap->end() )
587 pLeft = aIter->second;
591 rListBox.GrabFocus();
593 m_pRC_Tables->setWindowTables(pLeft,pRight);
595 NotifyCellChange();
598 void OTableListBoxControl::NotifyCellChange()
600 // Enable/disable the OK button, depending on having a valid situation
601 TTableConnectionData::value_type pConnData = m_pRC_Tables->getData();
602 const OConnectionLineDataVec& rLines = pConnData->GetConnLineDataList();
603 bool bValid = !rLines.empty();
604 if (bValid)
606 OConnectionLineDataVec::const_iterator l(rLines.begin());
607 const OConnectionLineDataVec::const_iterator le(rLines.end());
608 for (; bValid && l!=le; ++l)
610 bValid = ! ((*l)->GetSourceFieldName().isEmpty() || (*l)->GetDestFieldName().isEmpty());
613 m_pParentDialog->setValid(bValid);
615 ORelationControl::ops_type::const_iterator i (m_pRC_Tables->m_ops.begin());
616 const ORelationControl::ops_type::const_iterator e (m_pRC_Tables->m_ops.end());
617 m_pRC_Tables->DeactivateCell();
618 for(; i != e; ++i)
620 switch(i->first)
622 case ORelationControl::DELETE:
623 m_pRC_Tables->RowRemoved(i->second.first, i->second.second - i->second.first);
624 break;
625 case ORelationControl::INSERT:
626 m_pRC_Tables->RowInserted(i->second.first, i->second.second - i->second.first);
627 break;
628 case ORelationControl::MODIFY:
629 for(OConnectionLineDataVec::size_type j = i->second.first; j < i->second.second; ++j)
630 m_pRC_Tables->RowModified(j);
631 break;
634 m_pRC_Tables->ActivateCell();
635 m_pRC_Tables->m_ops.clear();
638 void fillEntryAndDisable(ListBox& _rListBox,const OUString& _sEntry)
640 _rListBox.InsertEntry(_sEntry);
641 _rListBox.SelectEntryPos(0);
642 _rListBox.Disable();
645 void OTableListBoxControl::fillAndDisable(const TTableConnectionData::value_type& _pConnectionData)
647 fillEntryAndDisable(*m_pLeftTable, _pConnectionData->getReferencingTable()->GetWinName());
648 fillEntryAndDisable(*m_pRightTable, _pConnectionData->getReferencedTable()->GetWinName());
651 void OTableListBoxControl::Init(const TTableConnectionData::value_type& _pConnData)
653 m_pRC_Tables->Init(_pConnData);
656 void OTableListBoxControl::lateUIInit()
658 m_pRC_Tables->Show();
659 lateInit();
662 void OTableListBoxControl::lateInit()
664 m_pRC_Tables->lateInit();
667 void OTableListBoxControl::Disable()
669 m_pLeftTable->Disable();
670 m_pRightTable->Disable();
671 m_pRC_Tables->Disable();
674 void OTableListBoxControl::Invalidate()
676 m_pLeftTable->Invalidate();
677 m_pRightTable->Invalidate();
678 m_pRC_Tables->Invalidate();
681 void OTableListBoxControl::SaveModified()
683 m_pRC_Tables->SaveModified();
686 TTableWindowData::value_type OTableListBoxControl::getReferencingTable() const
688 return m_pRC_Tables->getData()->getReferencingTable();
691 void OTableListBoxControl::enableRelation(bool _bEnable)
693 if ( !_bEnable )
694 m_pRC_Tables->PostUserEvent(LINK(m_pRC_Tables, ORelationControl, AsynchDeactivate));
695 m_pRC_Tables->Enable(_bEnable);
700 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */