1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <sal/config.h>
22 #include <string_view>
24 #include "SelectionBrowseBox.hxx"
25 #include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
26 #include <com/sun/star/sdbc/DataType.hpp>
27 #include <JoinExchange.hxx>
28 #include <QueryDesignView.hxx>
29 #include <querycontroller.hxx>
30 #include <sqlbison.hxx>
31 #include <QueryTableView.hxx>
32 #include <browserids.hxx>
33 #include <comphelper/stl_types.hxx>
34 #include <comphelper/string.hxx>
35 #include "TableFieldInfo.hxx"
36 #include <core_resource.hxx>
37 #include <strings.hrc>
38 #include <strings.hxx>
40 #include "QTableWindow.hxx"
41 #include <vcl/weld.hxx>
42 #include <vcl/settings.hxx>
43 #include "QueryDesignFieldUndoAct.hxx"
44 #include <sqlmessage.hxx>
45 #include <UITools.hxx>
46 #include <o3tl/safeint.hxx>
47 #include <osl/diagnose.h>
48 #include <i18nlangtag/languagetag.hxx>
49 #include <vcl/commandevent.hxx>
50 #include <vcl/svapp.hxx>
51 #include <comphelper/diagnose_ex.hxx>
52 #include <o3tl/string_view.hxx>
54 using namespace ::svt
;
55 using namespace ::dbaui
;
56 using namespace ::connectivity
;
57 using namespace ::com::sun::star::uno
;
58 using namespace ::com::sun::star::sdbc
;
59 using namespace ::com::sun::star::beans
;
60 using namespace ::com::sun::star::accessibility
;
62 #define DEFAULT_QUERY_COLS 20
63 #define DEFAULT_SIZE GetTextWidth(u"0"_ustr) * 30
65 #define HANDLE_COLUMN_WIDTH 70
66 #define SORT_COLUMN_NONE 0xFFFFFFFF
70 bool isFieldNameAsterisk(std::u16string_view _sFieldName
)
72 bool bAsterisk
= _sFieldName
.empty() || _sFieldName
[0] == '*';
75 sal_Int32 nTokenCount
= comphelper::string::getTokenCount(_sFieldName
, '.');
76 if ( (nTokenCount
== 2 && o3tl::getToken(_sFieldName
,1,'.')[0] == '*' )
77 || (nTokenCount
== 3 && o3tl::getToken(_sFieldName
,2,'.')[0] == '*' ) )
84 bool lcl_SupportsCoreSQLGrammar(const Reference
< XConnection
>& _xConnection
)
86 bool bSupportsCoreGrammar
= false;
87 if ( _xConnection
.is() )
91 Reference
< XDatabaseMetaData
> xMetaData
= _xConnection
->getMetaData();
92 bSupportsCoreGrammar
= xMetaData
.is() && xMetaData
->supportsCoreSQLGrammar();
98 return bSupportsCoreGrammar
;
102 OSelectionBrowseBox::OSelectionBrowseBox( vcl::Window
* pParent
)
103 :EditBrowseBox( pParent
,EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT
, WB_3DLOOK
, BrowserMode::COLUMNSELECTION
| BrowserMode::KEEPHIGHLIGHT
| BrowserMode::HIDESELECT
|
104 BrowserMode::HIDECURSOR
| BrowserMode::HLINES
| BrowserMode::VLINES
)
105 ,m_timerInvalidate("dbaccess OSelectionBrowseBox m_timerInvalidate")
108 ,m_aFunctionStrings(DBA_RES(STR_QUERY_FUNCTIONS
))
110 ,m_nLastSortColumn(SORT_COLUMN_NONE
)
111 ,m_bOrderByUnRelated(true)
112 ,m_bGroupByUnRelated(true)
114 ,m_bWasEditing(false)
115 ,m_bDisableErrorBox(false)
116 ,m_bInUndoMode(false)
118 SetHelpId(HID_CTL_QRYDGNCRIT
);
120 m_nMode
= BrowserMode::COLUMNSELECTION
| BrowserMode::HIDESELECT
121 | BrowserMode::KEEPHIGHLIGHT
| BrowserMode::HIDECURSOR
122 | BrowserMode::HLINES
| BrowserMode::VLINES
123 | BrowserMode::HEADERBAR_NEW
;
125 m_pTextCell
= VclPtr
<EditControl
>::Create(&GetDataWindow());
126 m_pVisibleCell
= VclPtr
<CheckBoxControl
>::Create(&GetDataWindow());
127 m_pTableCell
= VclPtr
<ListBoxControl
>::Create(&GetDataWindow());
128 m_pFieldCell
= VclPtr
<ComboBoxControl
>::Create(&GetDataWindow());
129 m_pOrderCell
= VclPtr
<ListBoxControl
>::Create(&GetDataWindow());
130 m_pFunctionCell
= VclPtr
<ListBoxControl
>::Create(&GetDataWindow());
132 m_pVisibleCell
->SetHelpId(HID_QRYDGN_ROW_VISIBLE
);
133 m_pTableCell
->SetHelpId(HID_QRYDGN_ROW_TABLE
);
134 m_pFieldCell
->SetHelpId(HID_QRYDGN_ROW_FIELD
);
135 weld::ComboBox
& rOrderBox
= m_pOrderCell
->get_widget();
136 m_pOrderCell
->SetHelpId(HID_QRYDGN_ROW_ORDER
);
137 m_pFunctionCell
->SetHelpId(HID_QRYDGN_ROW_FUNCTION
);
139 // switch off triState of css::form::CheckBox
140 m_pVisibleCell
->EnableTriState( false );
142 vcl::Font aTitleFont
= OutputDevice::GetDefaultFont( DefaultFontType::SANS_UNICODE
,Window::GetSettings().GetLanguageTag().getLanguageType(),GetDefaultFontFlags::OnlyOne
);
143 aTitleFont
.SetFontSize(Size(0, 6));
144 SetTitleFont(aTitleFont
);
146 const OUString
aTxt(DBA_RES(STR_QUERY_SORTTEXT
));
147 for (sal_Int32 nIdx
{0}; nIdx
>=0;)
148 rOrderBox
.append_text(OUString(o3tl::getToken(aTxt
, 0, ';', nIdx
)));
150 m_bVisibleRow
.insert(m_bVisibleRow
.end(), BROW_ROW_CNT
, true);
152 m_bVisibleRow
[BROW_FUNCTION_ROW
] = false; // first hide
154 m_timerInvalidate
.SetTimeout(200);
155 m_timerInvalidate
.SetInvokeHandler(LINK(this, OSelectionBrowseBox
, OnInvalidateTimer
));
156 m_timerInvalidate
.Start();
159 OSelectionBrowseBox::~OSelectionBrowseBox()
164 void OSelectionBrowseBox::dispose()
166 m_pTextCell
.disposeAndClear();
167 m_pVisibleCell
.disposeAndClear();
168 m_pFieldCell
.disposeAndClear();
169 m_pTableCell
.disposeAndClear();
170 m_pOrderCell
.disposeAndClear();
171 m_pFunctionCell
.disposeAndClear();
172 ::svt::EditBrowseBox::dispose();
175 void OSelectionBrowseBox::initialize()
177 Reference
< XConnection
> xConnection
= static_cast<OQueryController
&>(getDesignView()->getController()).getConnection();
180 const IParseContext
& rContext
= static_cast<OQueryController
&>(getDesignView()->getController()).getParser().getContext();
181 const IParseContext::InternationalKeyCode eFunctions
[] = {
182 IParseContext::InternationalKeyCode::Avg
,IParseContext::InternationalKeyCode::Count
,IParseContext::InternationalKeyCode::Max
183 ,IParseContext::InternationalKeyCode::Min
,IParseContext::InternationalKeyCode::Sum
184 ,IParseContext::InternationalKeyCode::Every
185 ,IParseContext::InternationalKeyCode::Any
186 ,IParseContext::InternationalKeyCode::Some
187 ,IParseContext::InternationalKeyCode::StdDevPop
188 ,IParseContext::InternationalKeyCode::StdDevSamp
189 ,IParseContext::InternationalKeyCode::VarSamp
190 ,IParseContext::InternationalKeyCode::VarPop
191 ,IParseContext::InternationalKeyCode::Collect
192 ,IParseContext::InternationalKeyCode::Fusion
193 ,IParseContext::InternationalKeyCode::Intersection
196 OUString sGroup
= m_aFunctionStrings
.copy(m_aFunctionStrings
.lastIndexOf(';')+1);
197 m_aFunctionStrings
= m_aFunctionStrings
.getToken(0, ';');
199 for (IParseContext::InternationalKeyCode eFunction
: eFunctions
)
201 m_aFunctionStrings
+= ";" + OStringToOUString(rContext
.getIntlKeywordAscii(eFunction
), RTL_TEXTENCODING_UTF8
);
203 m_aFunctionStrings
+= ";" + sGroup
;
205 // Aggregate functions in general available only with Core SQL
206 // We slip in a few optionals one, too.
207 if ( lcl_SupportsCoreSQLGrammar(xConnection
) )
209 weld::ComboBox
& rComboBox
= m_pFunctionCell
->get_widget();
210 for (sal_Int32 nIdx
{0}; nIdx
>=0;)
211 rComboBox
.append_text(m_aFunctionStrings
.getToken(0, ';', nIdx
));
213 else // else only COUNT(*) and COUNT("table".*)
215 weld::ComboBox
& rComboBox
= m_pFunctionCell
->get_widget();
216 rComboBox
.append_text(m_aFunctionStrings
.getToken(0, ';'));
217 rComboBox
.append_text(m_aFunctionStrings
.getToken(2, ';')); // 2 -> COUNT
221 Reference
< XDatabaseMetaData
> xMetaData
= xConnection
->getMetaData();
222 if ( xMetaData
.is() )
224 m_bOrderByUnRelated
= xMetaData
->supportsOrderByUnrelated();
225 m_bGroupByUnRelated
= xMetaData
->supportsGroupByUnrelated();
236 OQueryDesignView
* OSelectionBrowseBox::getDesignView()
238 OSL_ENSURE(static_cast<const OQueryDesignView
*>(GetParent()),"Parent isn't an OQueryDesignView!");
239 return static_cast<OQueryDesignView
*>(GetParent());
242 OQueryDesignView
* OSelectionBrowseBox::getDesignView() const
244 OSL_ENSURE(static_cast<const OQueryDesignView
*>(GetParent()),"Parent isn't an OQueryDesignView!");
245 return static_cast<OQueryDesignView
*>(GetParent());
250 class OSelectionBrwBoxHeader
: public ::svt::EditBrowserHeader
252 VclPtr
<OSelectionBrowseBox
> m_pBrowseBox
;
254 virtual void Select() override
;
256 explicit OSelectionBrwBoxHeader(OSelectionBrowseBox
* pParent
);
257 virtual ~OSelectionBrwBoxHeader() override
{ disposeOnce(); }
258 virtual void dispose() override
{ m_pBrowseBox
.clear(); ::svt::EditBrowserHeader::dispose(); }
260 OSelectionBrwBoxHeader::OSelectionBrwBoxHeader(OSelectionBrowseBox
* pParent
)
261 : ::svt::EditBrowserHeader(pParent
,WB_BUTTONSTYLE
|WB_DRAG
)
262 ,m_pBrowseBox(pParent
)
266 void OSelectionBrwBoxHeader::Select()
268 EditBrowserHeader::Select();
269 m_pBrowseBox
->GrabFocus();
271 BrowserMode nMode
= m_pBrowseBox
->GetMode();
272 if ( 0 == m_pBrowseBox
->GetSelectColumnCount() )
274 m_pBrowseBox
->DeactivateCell();
275 // we are in the right mode if a row has been selected row
276 if ( nMode
& BrowserMode::HIDESELECT
)
278 nMode
&= ~BrowserMode::HIDESELECT
;
279 nMode
|= BrowserMode::MULTISELECTION
;
280 m_pBrowseBox
->SetMode( nMode
);
283 m_pBrowseBox
->SelectColumnId( GetCurItemId() );
284 m_pBrowseBox
->DeactivateCell();
288 VclPtr
<BrowserHeader
> OSelectionBrowseBox::imp_CreateHeaderBar(BrowseBox
* /*pParent*/)
290 return VclPtr
<OSelectionBrwBoxHeader
>::Create(this);
293 void OSelectionBrowseBox::ColumnMoved( sal_uInt16 nColId
, bool _bCreateUndo
)
295 EditBrowseBox::ColumnMoved( nColId
);
296 // swap the two columns
297 sal_uInt16 nNewPos
= GetColumnPos( nColId
);
298 OTableFields
& rFields
= getFields();
299 if ( rFields
.size() > o3tl::make_unsigned(nNewPos
-1) )
301 sal_uInt16 nOldPos
= 0;
302 bool bFoundElem
= false;
303 for (auto const& field
: rFields
)
305 if (field
->GetColumnId() == nColId
)
313 OSL_ENSURE( (nNewPos
-1) != nOldPos
&& nOldPos
< rFields
.size(),"Old and new position are equal!");
316 OTableFieldDescRef pOldEntry
= rFields
[nOldPos
];
317 rFields
.erase(rFields
.begin() + nOldPos
);
318 rFields
.insert(rFields
.begin() + nNewPos
- 1,pOldEntry
);
320 // create the undo action
321 if ( !m_bInUndoMode
&& _bCreateUndo
)
323 std::unique_ptr
<OTabFieldMovedUndoAct
> pUndoAct(new OTabFieldMovedUndoAct(this));
324 pUndoAct
->SetColumnPosition( nOldPos
+ 1);
325 pUndoAct
->SetTabFieldDescr(pOldEntry
);
327 getDesignView()->getController().addUndoActionAndInvalidate(std::move(pUndoAct
));
332 OSL_FAIL("Invalid column id!");
335 void OSelectionBrowseBox::Init()
338 EditBrowseBox::Init();
340 // set the header bar
341 VclPtr
<BrowserHeader
> pNewHeaderBar
= CreateHeaderBar(this);
342 pNewHeaderBar
->SetMouseTransparent(false);
344 SetHeaderBar(pNewHeaderBar
);
347 vcl::Font
aFont( GetDataWindow().GetFont() );
348 aFont
.SetWeight( WEIGHT_NORMAL
);
349 GetDataWindow().SetFont( aFont
);
352 const Control
* pControls
[] = { m_pTextCell
,m_pVisibleCell
,m_pTableCell
,m_pFieldCell
};
354 for (const Control
* pControl
: pControls
)
356 const Size
aTemp(pControl
->GetOptimalSize());
357 if ( aTemp
.Height() > aHeight
.Height() )
358 aHeight
.setHeight( aTemp
.Height() );
360 SetDataRowHeight(aHeight
.Height());
362 // get number of visible rows
363 for(tools::Long i
=0;i
<BROW_ROW_CNT
;i
++)
368 RowInserted(0, m_nVisibleCount
, false);
371 Reference
< XConnection
> xConnection
= static_cast<OQueryController
&>(getDesignView()->getController()).getConnection();
374 Reference
< XDatabaseMetaData
> xMetaData
= xConnection
->getMetaData();
375 m_nMaxColumns
= xMetaData
.is() ? xMetaData
->getMaxColumnsInSelect() : 0;
381 catch(const SQLException
&)
383 TOOLS_WARN_EXCEPTION( "dbaccess", "Caught Exception when asking for database metadata options!");
388 void OSelectionBrowseBox::PreFill()
390 SetUpdateMode(false);
392 if (GetCurRow() != 0)
395 static_cast< OQueryController
& >( getDesignView()->getController() ).clearFields();
400 InsertHandleColumn( HANDLE_COLUMN_WIDTH
);
404 void OSelectionBrowseBox::ClearAll()
406 SetUpdateMode(false);
408 OTableFields::const_reverse_iterator aIter
= getFields().rbegin();
409 for ( ;aIter
!= getFields().rend(); ++aIter
)
411 if ( !(*aIter
)->IsEmpty() )
413 RemoveField( (*aIter
)->GetColumnId() );
414 aIter
= getFields().rbegin();
417 m_nLastSortColumn
= SORT_COLUMN_NONE
;
421 void OSelectionBrowseBox::SetReadOnly(bool bRO
)
426 m_nMode
&= ~BrowserMode::HIDECURSOR
;
431 m_nMode
|= BrowserMode::HIDECURSOR
;
437 CellController
* OSelectionBrowseBox::GetController(sal_Int32 nRow
, sal_uInt16 nColId
)
439 if ( nColId
> getFields().size() )
441 OTableFieldDescRef pEntry
= getFields()[nColId
-1];
442 OSL_ENSURE(pEntry
.is(), "OSelectionBrowseBox::GetController : invalid FieldDescription !");
447 if (static_cast<OQueryController
&>(getDesignView()->getController()).isReadOnly())
450 sal_Int32 nCellIndex
= GetRealRow(nRow
);
454 return new ComboBoxCellController(m_pFieldCell
);
456 return new ListBoxCellController(m_pTableCell
);
458 return new CheckBoxCellController(m_pVisibleCell
);
460 return new ListBoxCellController(m_pOrderCell
);
461 case BROW_FUNCTION_ROW
:
462 return new ListBoxCellController(m_pFunctionCell
);
464 return new EditCellController(m_pTextCell
);
468 void OSelectionBrowseBox::InitController(CellControllerRef
& /*rController*/, sal_Int32 nRow
, sal_uInt16 nColId
)
470 OSL_ENSURE(nColId
!= BROWSER_INVALIDID
,"An Invalid Id was set!");
471 if ( nColId
== BROWSER_INVALIDID
)
473 sal_uInt16 nPos
= GetColumnPos(nColId
);
474 if ( nPos
== 0 || nPos
== BROWSER_INVALIDID
|| nPos
> getFields().size() )
476 OTableFieldDescRef pEntry
= getFields()[nPos
-1];
477 OSL_ENSURE(pEntry
.is(), "OSelectionBrowseBox::InitController : invalid FieldDescription !");
478 sal_Int32 nCellIndex
= GetRealRow(nRow
);
484 weld::ComboBox
& rComboBox
= m_pFieldCell
->get_widget();
486 rComboBox
.set_entry_text(OUString());
488 OUString
aField(pEntry
->GetField());
489 OUString
aTable(pEntry
->GetAlias());
491 getDesignView()->fillValidFields(aTable
, rComboBox
);
493 // replace with alias.*
494 if (o3tl::trim(aField
) == u
"*")
496 aField
= aTable
+ ".*";
498 rComboBox
.set_entry_text(aField
);
502 weld::ComboBox
& rComboBox
= m_pTableCell
->get_widget();
504 enableControl(pEntry
, m_pTableCell
);
505 if ( !pEntry
->isCondition() )
507 for (auto const& tabWin
: getDesignView()->getTableView()->GetTabWinMap())
508 rComboBox
.append_text(static_cast<OQueryTableWindow
*>(tabWin
.second
.get())->GetAliasName());
510 rComboBox
.insert_text(0, DBA_RES(STR_QUERY_NOTABLE
));
511 if (!pEntry
->GetAlias().isEmpty())
512 rComboBox
.set_active_text(pEntry
->GetAlias());
514 rComboBox
.set_active_text(DBA_RES(STR_QUERY_NOTABLE
));
519 m_pVisibleCell
->GetBox().set_active(pEntry
->IsVisible());
520 m_pVisibleCell
->GetBox().save_state();
522 enableControl(pEntry
,m_pTextCell
);
524 if(!pEntry
->IsVisible() && pEntry
->GetOrderDir() != ORDER_NONE
&& !m_bOrderByUnRelated
)
526 // a column has to visible in order to show up in ORDER BY
527 pEntry
->SetVisible();
528 m_pVisibleCell
->GetBox().set_active(pEntry
->IsVisible());
529 m_pVisibleCell
->GetBox().save_state();
530 m_pVisibleCell
->GetBox().set_sensitive(false);
531 OUString
aMessage(DBA_RES(STR_QRY_ORDERBY_UNRELATED
));
532 OQueryDesignView
* paDView
= getDesignView();
533 std::unique_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(paDView
? paDView
->GetFrameWeld() : nullptr,
534 VclMessageType::Info
, VclButtonsType::Ok
,
541 weld::ComboBox
& rComboBox
= m_pOrderCell
->get_widget();
542 rComboBox
.set_active(
543 sal::static_int_cast
< sal_uInt16
>(pEntry
->GetOrderDir()));
544 enableControl(pEntry
,m_pOrderCell
);
547 case BROW_COLUMNALIAS_ROW
:
548 setTextCellContext(pEntry
,pEntry
->GetFieldAlias(),HID_QRYDGN_ROW_ALIAS
);
550 case BROW_FUNCTION_ROW
:
551 setFunctionCell(pEntry
);
555 sal_uInt16 nIdx
= sal_uInt16(nCellIndex
- BROW_CRIT1_ROW
);
556 setTextCellContext(pEntry
,pEntry
->GetCriteria( nIdx
),HID_QRYDGN_ROW_CRIT
);
559 Controller()->SaveValue();
562 void OSelectionBrowseBox::notifyTableFieldChanged(const OUString
& _sOldAlias
, std::u16string_view _sAlias
, bool& _bListAction
, sal_uInt16 _nColumnId
)
564 appendUndoAction(_sOldAlias
,_sAlias
,BROW_TABLE_ROW
,_bListAction
);
565 if ( m_bVisibleRow
[BROW_TABLE_ROW
] )
566 RowModified(GetBrowseRow(BROW_TABLE_ROW
), _nColumnId
);
569 void OSelectionBrowseBox::notifyFunctionFieldChanged(const OUString
& _sOldFunctionName
, std::u16string_view _sFunctionName
, bool& _bListAction
, sal_uInt16 _nColumnId
)
571 appendUndoAction(_sOldFunctionName
,_sFunctionName
,BROW_FUNCTION_ROW
,_bListAction
);
572 if ( !m_bVisibleRow
[BROW_FUNCTION_ROW
] )
573 SetRowVisible(BROW_FUNCTION_ROW
, true);
574 RowModified(GetBrowseRow(BROW_FUNCTION_ROW
), _nColumnId
);
577 void OSelectionBrowseBox::clearEntryFunctionField(std::u16string_view _sFieldName
,OTableFieldDescRef
const & _pEntry
, bool& _bListAction
,sal_uInt16 _nColumnId
)
579 if ( !(isFieldNameAsterisk( _sFieldName
) && (!_pEntry
->isNoneFunction() || _pEntry
->IsGroupBy())) )
582 OUString sFunctionName
;
583 GetFunctionName(SQL_TOKEN_COUNT
,sFunctionName
);
584 OUString sOldLocalizedFunctionName
= _pEntry
->GetFunction();
585 if ( sOldLocalizedFunctionName
!= sFunctionName
|| _pEntry
->IsGroupBy() )
587 // append undo action for the function field
588 _pEntry
->SetFunctionType(FKT_NONE
);
589 _pEntry
->SetFunction(OUString());
590 _pEntry
->SetGroupBy(false);
591 notifyFunctionFieldChanged(sOldLocalizedFunctionName
,_pEntry
->GetFunction(),_bListAction
,_nColumnId
);
595 bool OSelectionBrowseBox::fillColumnRef(const OSQLParseNode
* _pColumnRef
, const Reference
< XConnection
>& _rxConnection
, OTableFieldDescRef
const & _pEntry
, bool& _bListAction
)
597 OSL_ENSURE(_pColumnRef
,"No valid parsenode!");
598 OUString sColumnName
,sTableRange
;
599 OSQLParseTreeIterator::getColumnRange(_pColumnRef
,_rxConnection
,sColumnName
,sTableRange
);
600 return fillColumnRef(sColumnName
,sTableRange
,_rxConnection
->getMetaData(),_pEntry
,_bListAction
);
603 bool OSelectionBrowseBox::fillColumnRef(const OUString
& _sColumnName
, std::u16string_view _sTableRange
, const Reference
<XDatabaseMetaData
>& _xMetaData
, OTableFieldDescRef
const & _pEntry
, bool& _bListAction
)
606 ::comphelper::UStringMixEqual
bCase(_xMetaData
->supportsMixedCaseQuotedIdentifiers());
607 // check if the table name is the same
608 if ( !_sTableRange
.empty() && (bCase(_pEntry
->GetTable(),_sTableRange
) || bCase(_pEntry
->GetAlias(),_sTableRange
)) )
609 { // a table was already inserted and the tables contains that column name
611 if ( !_pEntry
->GetTabWindow() )
613 OUString sOldAlias
= _pEntry
->GetAlias();
614 if ( !fillEntryTable(_pEntry
,_pEntry
->GetTable()) )
615 fillEntryTable(_pEntry
,_pEntry
->GetAlias()); // only when the first failed
616 if ( !bCase(sOldAlias
,_pEntry
->GetAlias()) )
617 notifyTableFieldChanged(sOldAlias
,_pEntry
->GetAlias(),_bListAction
,GetCurColumnId());
620 // check if the table window
621 OQueryTableWindow
* pEntryTab
= static_cast<OQueryTableWindow
*>(_pEntry
->GetTabWindow());
622 if ( !pEntryTab
) // no table found with this name so we have to travel through all tables
624 sal_uInt16 nTabCount
= 0;
625 if ( !static_cast<OQueryTableView
*>(getDesignView()->getTableView())->FindTableFromField(_sColumnName
,_pEntry
,nTabCount
) ) // error occurred: column not in table window
627 OUString
sErrorMsg(DBA_RES(RID_STR_FIELD_DOESNT_EXIST
));
628 sErrorMsg
= sErrorMsg
.replaceFirst("$name$",_sColumnName
);
629 OSQLErrorBox
aWarning(GetFrameWeld(), sErrorMsg
);
635 pEntryTab
= static_cast<OQueryTableWindow
*>(_pEntry
->GetTabWindow());
636 notifyTableFieldChanged(OUString(),_pEntry
->GetAlias(),_bListAction
,GetCurColumnId());
639 if ( pEntryTab
) // here we got a valid table
640 _pEntry
->SetField(_sColumnName
);
645 bool OSelectionBrowseBox::saveField(OUString
& _sFieldName
,OTableFieldDescRef
const & _pEntry
, bool& _bListAction
)
649 OQueryController
& rController
= static_cast<OQueryController
&>(getDesignView()->getController());
651 // first look if the name can be found in our tables
652 sal_uInt16 nTabCount
= 0;
653 OUString sOldAlias
= _pEntry
->GetAlias();
654 if ( static_cast<OQueryTableView
*>(getDesignView()->getTableView())->FindTableFromField(_sFieldName
,_pEntry
,nTabCount
) )
656 // append undo action for the alias name
657 _pEntry
->SetField(_sFieldName
);
658 notifyTableFieldChanged(sOldAlias
,_pEntry
->GetAlias(),_bListAction
,GetCurColumnId());
659 clearEntryFunctionField(_sFieldName
,_pEntry
,_bListAction
,_pEntry
->GetColumnId());
663 Reference
<XConnection
> xConnection( rController
.getConnection() );
664 Reference
< XDatabaseMetaData
> xMetaData
;
665 if ( xConnection
.is() )
666 xMetaData
= xConnection
->getMetaData();
667 OSL_ENSURE( xMetaData
.is(), "OSelectionBrowseBox::saveField: invalid connection/meta data!" );
668 if ( !xMetaData
.is() )
672 // second test if the name can be set as select columns in a pseudo statement
673 // we have to look which entries we should quote
675 const OUString sFieldAlias
= _pEntry
->GetFieldAlias();
676 ::connectivity::OSQLParser
& rParser( rController
.getParser() );
678 // automatically add parentheses around subqueries
680 std::unique_ptr
<OSQLParseNode
> pParseNode
= rParser
.parseTree( devnull
, _sFieldName
, true );
681 if (pParseNode
== nullptr)
682 pParseNode
= rParser
.parseTree( devnull
, _sFieldName
);
683 if (pParseNode
!= nullptr && SQL_ISRULE(pParseNode
, select_statement
))
684 _sFieldName
= "(" + _sFieldName
+ ")";
687 std::unique_ptr
<OSQLParseNode
> pParseNode
;
689 // 4 passes in trying to interpret the field name
690 // - don't quote the field name, parse internationally
691 // - don't quote the field name, parse en-US
692 // - quote the field name, parse internationally
693 // - quote the field name, parse en-US
695 OUString
sQuotedFullFieldName(::dbtools::quoteName( xMetaData
->getIdentifierQuoteString(), _sFieldName
));
696 OUString
sFullFieldName(_sFieldName
);
698 if ( _pEntry
->isAggregateFunction() )
700 OSL_ENSURE(!_pEntry
->GetFunction().isEmpty(),"No empty Function name allowed here! ;-(");
701 sQuotedFullFieldName
= _pEntry
->GetFunction() + "(" + sQuotedFullFieldName
+ ")";
702 sFullFieldName
= _pEntry
->GetFunction() + "(" + sFullFieldName
+ ")";
707 bool bQuote
= ( nPass
<= 2 );
708 bool bInternational
= ( nPass
% 2 ) == 0;
710 OUString sSql
{u
"SELECT "_ustr
};
712 sSql
+= sQuotedFullFieldName
;
714 sSql
+= sFullFieldName
;
716 if ( !sFieldAlias
.isEmpty() )
717 { // always quote the alias name: there cannot be a function in it
718 sSql
+= " " + ::dbtools::quoteName( xMetaData
->getIdentifierQuoteString(), sFieldAlias
);
722 pParseNode
= rParser
.parseTree( sErrorMsg
, sSql
, bInternational
);
724 while ( ( pParseNode
== nullptr ) && ( --nPass
> 0 ) );
727 if ( pParseNode
== nullptr )
729 // something different which we have to check
730 OUString
sErrorMessage( DBA_RES( STR_QRY_COLUMN_NOT_FOUND
) );
731 sErrorMessage
= sErrorMessage
.replaceFirst("$name$",_sFieldName
);
732 OSQLErrorBox
aWarning(GetFrameWeld(), sErrorMessage
);
738 // we got a valid select column
739 // find what type of column has be inserted
740 ::connectivity::OSQLParseNode
* pSelection
= pParseNode
->getChild(2);
741 if ( SQL_ISRULE(pSelection
,selection
) ) // we found the asterisk
743 _pEntry
->SetField(_sFieldName
);
744 clearEntryFunctionField(_sFieldName
,_pEntry
,_bListAction
,_pEntry
->GetColumnId());
746 else // travel through the select column parse node
748 OTableFieldDescRef aSelEntry
= _pEntry
;
749 sal_uInt16 nColumnId
= aSelEntry
->GetColumnId();
751 sal_uInt32 nCount
= pSelection
->count();
752 for (sal_uInt32 i
= 0; i
< nCount
; ++i
)
754 if ( i
> 0 ) // may we have to append more than one field
756 sal_uInt16 nColumnPosition
;
757 aSelEntry
= FindFirstFreeCol(nColumnPosition
);
758 if ( !aSelEntry
.is() )
761 aSelEntry
= FindFirstFreeCol(nColumnPosition
);
764 nColumnId
= GetColumnId(nColumnPosition
);
767 ::connectivity::OSQLParseNode
* pChild
= pSelection
->getChild( i
);
768 OSL_ENSURE(SQL_ISRULE(pChild
,derived_column
), "No derived column found!");
769 // get the column alias
770 OUString sColumnAlias
= OSQLParseTreeIterator::getColumnAlias(pChild
);
771 if ( !sColumnAlias
.isEmpty() ) // we found an as clause
773 OUString aSelectionAlias
= aSelEntry
->GetFieldAlias();
774 aSelEntry
->SetFieldAlias( sColumnAlias
);
776 appendUndoAction(aSelectionAlias
,aSelEntry
->GetFieldAlias(),BROW_COLUMNALIAS_ROW
,_bListAction
);
777 if ( m_bVisibleRow
[BROW_COLUMNALIAS_ROW
] )
778 RowModified(GetBrowseRow(BROW_COLUMNALIAS_ROW
), nColumnId
);
781 ::connectivity::OSQLParseNode
* pColumnRef
= pChild
->getChild(0);
783 pColumnRef
->getKnownRuleID() != OSQLParseNode::subquery
&&
784 pColumnRef
->count() == 3 &&
785 SQL_ISPUNCTUATION(pColumnRef
->getChild(0),"(") &&
786 SQL_ISPUNCTUATION(pColumnRef
->getChild(2),")")
788 pColumnRef
= pColumnRef
->getChild(1);
790 if ( SQL_ISRULE(pColumnRef
,column_ref
) ) // we found a valid column name or more column names
792 // look if we can find the corresponding table
793 bError
= fillColumnRef( pColumnRef
, xConnection
, aSelEntry
, _bListAction
);
795 // we found a simple column so we must clear the function fields but only when the column name is '*'
796 // and the function is different to count
797 clearEntryFunctionField(_sFieldName
,aSelEntry
,_bListAction
,nColumnId
);
799 // do we have an aggregate function and only a function?
800 else if ( SQL_ISRULE(pColumnRef
,general_set_fct
) )
802 OUString sLocalizedFunctionName
;
803 if ( GetFunctionName(pColumnRef
->getChild(0)->getTokenID(),sLocalizedFunctionName
) )
805 OUString sOldLocalizedFunctionName
= aSelEntry
->GetFunction();
806 aSelEntry
->SetFunction(sLocalizedFunctionName
);
807 sal_uInt32 nFunCount
= pColumnRef
->count() - 1;
808 sal_Int32 nFunctionType
= FKT_AGGREGATE
;
810 // may be there exists only one parameter which is a column, fill all information into our fields
811 if ( nFunCount
== 4 && SQL_ISRULE(pColumnRef
->getChild(3),column_ref
) )
812 bError
= fillColumnRef( pColumnRef
->getChild(3), xConnection
, aSelEntry
, _bListAction
);
813 else if ( nFunCount
== 3 ) // we have a COUNT(*) here, so take the first table
814 bError
= fillColumnRef( u
"*"_ustr
, std::u16string_view(), xMetaData
, aSelEntry
, _bListAction
);
817 nFunctionType
|= FKT_NUMERIC
;
819 aSelEntry
->SetDataType(DataType::DOUBLE
);
820 aSelEntry
->SetFieldType(TAB_NORMAL_FIELD
);
823 // now parse the parameters
824 OUString sParameters
;
825 for(sal_uInt32 function
= 2; function
< nFunCount
; ++function
) // we only want to parse the parameters of the function
826 pColumnRef
->getChild(function
)->parseNodeToStr( sParameters
, xConnection
, &rParser
.getContext(), true, bQuote
);
828 aSelEntry
->SetFunctionType(nFunctionType
);
829 aSelEntry
->SetField(sParameters
);
830 if ( aSelEntry
->IsGroupBy() )
832 sOldLocalizedFunctionName
= m_aFunctionStrings
.copy(m_aFunctionStrings
.lastIndexOf(';')+1);
833 aSelEntry
->SetGroupBy(false);
836 // append undo action
837 notifyFunctionFieldChanged(sOldLocalizedFunctionName
,sLocalizedFunctionName
,_bListAction
, nColumnId
);
840 OSL_FAIL("Unsupported function inserted!");
845 // so we first clear the function field
846 clearEntryFunctionField(_sFieldName
,aSelEntry
,_bListAction
,nColumnId
);
848 pColumnRef
->parseNodeToStr( sFunction
,
850 &rController
.getParser().getContext(),
851 true); // quote is to true because we need quoted elements inside the function
853 getDesignView()->fillFunctionInfo(pColumnRef
,sFunction
,aSelEntry
);
855 if( SQL_ISRULEOR3(pColumnRef
, position_exp
, extract_exp
, fold
) ||
856 SQL_ISRULEOR3(pColumnRef
, char_substring_fct
, length_exp
, char_value_fct
) )
857 // a calculation has been found ( can be calc and function )
859 // now parse the whole statement
860 sal_uInt32 nFunCount
= pColumnRef
->count();
861 OUString sParameters
;
862 for(sal_uInt32 function
= 0; function
< nFunCount
; ++function
)
863 pColumnRef
->getChild(function
)->parseNodeToStr( sParameters
, xConnection
, &rParser
.getContext(), true );
865 sOldAlias
= aSelEntry
->GetAlias();
866 sal_Int32 nNewFunctionType
= aSelEntry
->GetFunctionType() | FKT_NUMERIC
| FKT_OTHER
;
867 aSelEntry
->SetFunctionType(nNewFunctionType
);
868 aSelEntry
->SetField(sParameters
);
872 aSelEntry
->SetFieldAlias(sColumnAlias
);
873 if ( SQL_ISRULE(pColumnRef
,set_fct_spec
) )
874 aSelEntry
->SetFunctionType(/*FKT_NUMERIC | */FKT_OTHER
);
876 aSelEntry
->SetFunctionType(FKT_NUMERIC
| FKT_OTHER
);
879 aSelEntry
->SetAlias(OUString());
880 notifyTableFieldChanged(sOldAlias
,aSelEntry
->GetAlias(),_bListAction
, nColumnId
);
883 if ( i
> 0 && !InsertField(aSelEntry
,BROWSER_INVALIDID
,true,false).is() ) // may we have to append more than one field
884 { // the field could not be inserted
885 OUString
sErrorMessage( DBA_RES( RID_STR_FIELD_DOESNT_EXIST
) );
886 sErrorMessage
= sErrorMessage
.replaceFirst("$name$",aSelEntry
->GetField());
887 OSQLErrorBox
aWarning(GetFrameWeld(), sErrorMessage
);
897 bool OSelectionBrowseBox::SaveModified()
899 OQueryController
& rController
= static_cast<OQueryController
&>(getDesignView()->getController());
900 OTableFieldDescRef pEntry
;
901 sal_uInt16 nCurrentColumnPos
= GetColumnPos(GetCurColumnId());
902 if(getFields().size() > o3tl::make_unsigned(nCurrentColumnPos
- 1))
903 pEntry
= getEntry(nCurrentColumnPos
- 1);
905 bool bWasEmpty
= pEntry
.is() && pEntry
->IsEmpty();
907 bool bListAction
= false;
909 if (pEntry
.is() && Controller().is() && Controller()->IsValueChangedFromSaved())
911 // for the Undo-action
912 OUString strOldCellContents
,sNewValue
;
913 sal_Int32 nRow
= GetRealRow(GetCurRow());
914 bool bAppendRow
= false;
919 bool bOldValue
= m_pVisibleCell
->GetBox().get_saved_state() != TRISTATE_FALSE
;
921 = bOldValue
? std::u16string_view(u
"1") : std::u16string_view(u
"0");
923 = !bOldValue
? std::u16string_view(u
"1") : std::u16string_view(u
"0");
925 if((m_bOrderByUnRelated
|| pEntry
->GetOrderDir() == ORDER_NONE
) &&
926 (m_bGroupByUnRelated
|| !pEntry
->IsGroupBy()))
928 pEntry
->SetVisible(m_pVisibleCell
->GetBox().get_active());
932 pEntry
->SetVisible();
933 m_pVisibleCell
->GetBox().set_active(true);
939 weld::ComboBox
& rComboBox
= m_pFieldCell
->get_widget();
940 OUString
aFieldName(rComboBox
.get_active_text());
943 if (aFieldName
.isEmpty())
945 OTableFieldDescRef pNewEntry
= new OTableFieldDesc();
946 pNewEntry
->SetColumnId( pEntry
->GetColumnId() );
947 std::replace(getFields().begin(),getFields().end(),pEntry
,pNewEntry
);
948 sal_uInt16 nCol
= GetCurColumnId();
949 for (int i
= 0; i
< m_nVisibleCount
; i
++) // redraw column
954 strOldCellContents
= pEntry
->GetField();
956 if ( !m_bInUndoMode
)
957 rController
.GetUndoManager().EnterListAction(OUString(),OUString(),0,ViewShellId(-1));
959 sal_Int32 nPos
= rComboBox
.find_text(aFieldName
);
960 OUString aAliasName
= pEntry
->GetAlias();
961 if ( nPos
!= -1 && aAliasName
.isEmpty() && aFieldName
.indexOf('.') >= 0 )
962 { // special case, we have a table field so we must cut the table name
963 OUString sTableAlias
= aFieldName
.getToken(0,'.');
964 pEntry
->SetAlias(sTableAlias
);
965 OUString sColumnName
= aFieldName
.copy(sTableAlias
.getLength()+1);
966 const Reference
<XConnection
>& xConnection
= rController
.getConnection();
967 if ( !xConnection
.is() )
969 bError
= fillColumnRef( sColumnName
, sTableAlias
, xConnection
->getMetaData(), pEntry
, bListAction
);
975 bError
= saveField(aFieldName
,pEntry
,bListAction
);
984 sNewValue
= aFieldName
;
985 if ( !m_bInUndoMode
)
986 static_cast<OQueryController
&>(getDesignView()->getController()).GetUndoManager().LeaveListAction();
990 sNewValue
= pEntry
->GetField();
991 rController
.InvalidateFeature( ID_BROWSER_QUERY_EXECUTE
);
997 weld::ComboBox
& rComboBox
= m_pTableCell
->get_widget();
998 OUString aAliasName
= rComboBox
.get_active_text();
999 strOldCellContents
= pEntry
->GetAlias();
1000 if (rComboBox
.get_active() != 0)
1002 pEntry
->SetAlias(aAliasName
);
1003 // we have to set the table name as well as the table window
1004 OJoinTableView::OTableWindowMap
& rTabWinList
= getDesignView()->getTableView()->GetTabWinMap();
1005 OJoinTableView::OTableWindowMap::const_iterator aIter
= rTabWinList
.find(aAliasName
);
1006 if(aIter
!= rTabWinList
.end())
1008 OQueryTableWindow
* pEntryTab
= static_cast<OQueryTableWindow
*>(aIter
->second
.get());
1011 pEntry
->SetTable(pEntryTab
->GetTableName());
1012 pEntry
->SetTabWindow(pEntryTab
);
1018 pEntry
->SetAlias(OUString());
1019 pEntry
->SetTable(OUString());
1020 pEntry
->SetTabWindow(nullptr);
1022 sNewValue
= pEntry
->GetAlias();
1026 case BROW_ORDER_ROW
:
1028 strOldCellContents
= OUString::number(static_cast<sal_uInt16
>(pEntry
->GetOrderDir()));
1029 weld::ComboBox
& rComboBox
= m_pOrderCell
->get_widget();
1030 sal_Int32 nIdx
= rComboBox
.get_active();
1033 pEntry
->SetOrderDir(EOrderDir(nIdx
));
1034 if(!m_bOrderByUnRelated
)
1036 pEntry
->SetVisible();
1037 m_pVisibleCell
->GetBox().set_active(true);
1038 RowModified(GetBrowseRow(BROW_VIS_ROW
), GetCurColumnId());
1040 sNewValue
= OUString::number(static_cast<sal_uInt16
>(pEntry
->GetOrderDir()));
1043 case BROW_COLUMNALIAS_ROW
:
1044 strOldCellContents
= pEntry
->GetFieldAlias();
1045 pEntry
->SetFieldAlias(m_pTextCell
->get_widget().get_text());
1046 sNewValue
= pEntry
->GetFieldAlias();
1048 case BROW_FUNCTION_ROW
:
1050 strOldCellContents
= pEntry
->GetFunction();
1051 weld::ComboBox
& rComboBox
= m_pFunctionCell
->get_widget();
1052 sal_Int32 nPos
= rComboBox
.get_active();
1053 // these functions are only available in CORE
1054 OUString sFunctionName
= rComboBox
.get_text(nPos
);
1055 std::u16string_view sGroupFunctionName
= m_aFunctionStrings
.subView(m_aFunctionStrings
.lastIndexOf(';')+1);
1056 bool bGroupBy
= false;
1057 if ( sGroupFunctionName
== sFunctionName
) // check if the function name is GROUP
1061 if ( !m_bGroupByUnRelated
&& !pEntry
->IsVisible() )
1063 // we have to change the visible flag, so we must append also an undo action
1064 pEntry
->SetVisible();
1065 m_pVisibleCell
->GetBox().set_active(true);
1066 appendUndoAction(u
"0"_ustr
,u
"1",BROW_VIS_ROW
,bListAction
);
1067 RowModified(GetBrowseRow(BROW_VIS_ROW
), GetCurColumnId());
1070 pEntry
->SetFunction(OUString());
1071 pEntry
->SetFunctionType(pEntry
->GetFunctionType() & ~FKT_AGGREGATE
);
1073 else if ( nPos
) // we found an aggregate function
1075 pEntry
->SetFunctionType(pEntry
->GetFunctionType() | FKT_AGGREGATE
);
1076 pEntry
->SetFunction(sFunctionName
);
1080 sFunctionName
.clear();
1081 pEntry
->SetFunction(OUString());
1082 pEntry
->SetFunctionType(pEntry
->GetFunctionType() & ~FKT_AGGREGATE
);
1085 pEntry
->SetGroupBy(bGroupBy
);
1087 sNewValue
= sFunctionName
;
1092 Reference
< XConnection
> xConnection
= static_cast<OQueryController
&>(getDesignView()->getController()).getConnection();
1093 if(!xConnection
.is())
1096 sal_uInt16 nIdx
= sal_uInt16(nRow
- BROW_CRIT1_ROW
);
1097 OUString aText
= comphelper::string::stripStart(m_pTextCell
->get_widget().get_text(), ' ');
1100 if(!aText
.isEmpty())
1103 Reference
<XPropertySet
> xColumn
;
1104 std::unique_ptr
<OSQLParseNode
> pParseNode
= getDesignView()->getPredicateTreeFromEntry(pEntry
,aText
,aErrorMsg
,xColumn
);
1108 pParseNode
->parseNodeToPredicateStr(aCrit
,
1110 static_cast<OQueryController
&>(getDesignView()->getController()).getNumberFormatter(),
1113 getDesignView()->getLocale(),
1114 getDesignView()->getDecimalSeparator(),
1115 &(static_cast<OQueryController
&>(getDesignView()->getController()).getParser().getContext()));
1121 sal_Int32 nType
= 0;
1122 xColumn
->getPropertyValue(PROPERTY_TYPE
) >>= nType
;
1125 case DataType::CHAR
:
1126 case DataType::VARCHAR
:
1127 case DataType::LONGVARCHAR
:
1128 case DataType::CLOB
:
1129 if(!aText
.startsWith("'") || !aText
.endsWith("'"))
1131 aText
= aText
.replaceAll("'", "''");
1132 aText
= "'" + aText
+ "'";
1138 ::connectivity::OSQLParser
& rParser
= static_cast<OQueryController
&>(getDesignView()->getController()).getParser();
1139 pParseNode
= rParser
.predicateTree(aErrorMsg
,
1141 static_cast<OQueryController
&>(getDesignView()->getController()).getNumberFormatter(),
1145 pParseNode
->parseNodeToPredicateStr(aCrit
,
1147 static_cast<OQueryController
&>(getDesignView()->getController()).getNumberFormatter(),
1150 getDesignView()->getLocale(),
1151 getDesignView()->getDecimalSeparator(),
1152 &(static_cast<OQueryController
&>(getDesignView()->getController()).getParser().getContext()));
1156 if ( !m_bDisableErrorBox
)
1158 OSQLWarningBox
aWarning(GetFrameWeld(), aErrorMsg
);
1166 if ( !m_bDisableErrorBox
)
1168 OSQLWarningBox
aWarning(GetFrameWeld(), aErrorMsg
);
1175 strOldCellContents
= pEntry
->GetCriteria(nIdx
);
1176 pEntry
->SetCriteria(nIdx
, aCrit
);
1177 sNewValue
= pEntry
->GetCriteria(nIdx
);
1178 if(!aCrit
.isEmpty() && nRow
>= (GetRowCount()-1))
1182 if( !bError
&& Controller().is() )
1183 Controller()->SaveValue();
1185 RowModified(GetCurRow(), GetCurColumnId());
1189 RowInserted( GetRowCount()-1 );
1190 m_bVisibleRow
.push_back(true);
1196 // and now the undo-action for the total
1197 appendUndoAction(strOldCellContents
,sNewValue
,nRow
);
1202 // did I store data in a FieldDescription which was empty before and which is not empty anymore after the changes?
1203 if ( pEntry
.is() && bWasEmpty
&& !pEntry
->IsEmpty() && !bError
)
1205 // Default to visible
1206 pEntry
->SetVisible();
1207 appendUndoAction(u
"0"_ustr
,u
"1",BROW_VIS_ROW
,bListAction
);
1208 RowModified(BROW_VIS_ROW
, GetCurColumnId());
1210 // if required add empty columns
1212 CheckFreeColumns(nDummy
);
1215 if ( bListAction
&& !m_bInUndoMode
)
1216 static_cast<OQueryController
&>(getDesignView()->getController()).GetUndoManager().LeaveListAction();
1218 return pEntry
!= nullptr && !bError
;
1221 bool OSelectionBrowseBox::SeekRow(sal_Int32 nRow
)
1224 return nRow
< m_nVisibleCount
;
1227 void OSelectionBrowseBox::PaintCell(OutputDevice
& rDev
, const tools::Rectangle
& rRect
, sal_uInt16 nColumnId
) const
1229 rDev
.SetClipRegion(vcl::Region(rRect
));
1231 OTableFieldDescRef pEntry
;
1232 sal_uInt16 nPos
= GetColumnPos(nColumnId
);
1233 if(getFields().size() > o3tl::make_unsigned(nPos
- 1))
1234 pEntry
= getFields()[nPos
- 1];
1239 sal_Int32 nRow
= GetRealRow(m_nSeekRow
);
1240 if (nRow
== BROW_VIS_ROW
)
1241 PaintTristate(rRect
, pEntry
->IsVisible() ? TRISTATE_TRUE
: TRISTATE_FALSE
);
1243 rDev
.DrawText(rRect
, GetCellText(nRow
, nColumnId
),DrawTextFlags::VCenter
);
1245 rDev
.SetClipRegion( );
1248 void OSelectionBrowseBox::PaintStatusCell(OutputDevice
& rDev
, const tools::Rectangle
& rRect
) const
1250 tools::Rectangle
aRect(rRect
);
1251 aRect
.TopLeft().AdjustY( -2 );
1252 OUString
aLabel(DBA_RES(STR_QUERY_HANDLETEXT
));
1254 // from BROW_CRIT2_ROW onwards all rows are shown "or"
1255 sal_Int32 nToken
= (m_nSeekRow
>= GetBrowseRow(BROW_CRIT2_ROW
))
1256 ? BROW_CRIT2_ROW
: GetRealRow(m_nSeekRow
);
1257 rDev
.DrawText(aRect
, aLabel
.getToken(nToken
, ';'),DrawTextFlags::VCenter
);
1260 void OSelectionBrowseBox::RemoveColumn(sal_uInt16 _nColumnId
)
1262 OQueryController
& rController
= static_cast<OQueryController
&>(getDesignView()->getController());
1264 sal_uInt16 nPos
= GetColumnPos(_nColumnId
);
1265 // the control should always have exactly one more column: the HandleColumn
1266 OSL_ENSURE((nPos
== 0) || (nPos
<= getFields().size()), "OSelectionBrowseBox::RemoveColumn : invalid parameter nColId");
1267 // ColId is synonymous to Position, and the condition should be valid
1269 sal_uInt16 nCurCol
= GetCurColumnId();
1270 sal_Int32 nCurrentRow
= GetCurRow();
1274 getFields().erase( getFields().begin() + (nPos
- 1) );
1275 OTableFieldDescRef pEntry
= new OTableFieldDesc();
1276 pEntry
->SetColumnId(_nColumnId
);
1277 getFields().push_back(pEntry
);
1279 EditBrowseBox::RemoveColumn( _nColumnId
);
1280 InsertDataColumn( _nColumnId
, OUString(), DEFAULT_SIZE
);
1283 tools::Rectangle aInvalidRect
= GetInvalidRect( _nColumnId
);
1284 Invalidate( aInvalidRect
);
1286 ActivateCell( nCurrentRow
, nCurCol
);
1288 rController
.setModified( true );
1290 invalidateUndoRedo();
1293 void OSelectionBrowseBox::RemoveField(sal_uInt16 nColumnId
)
1295 OQueryController
& rController
= static_cast<OQueryController
&>(getDesignView()->getController());
1297 sal_uInt16 nPos
= GetColumnPos(nColumnId
);
1298 OSL_ENSURE(getFields().size() > o3tl::make_unsigned(nPos
-1),"ID is to great!");
1300 OTableFieldDescRef pDesc
= getEntry(static_cast<sal_uInt32
>(nPos
- 1)) ;
1301 pDesc
->SetColWidth( static_cast<sal_uInt16
>(GetColumnWidth(nColumnId
)) ); // was not stored this before
1303 // trigger UndoAction
1304 if ( !m_bInUndoMode
)
1306 std::unique_ptr
<OTabFieldDelUndoAct
> pUndoAction(new OTabFieldDelUndoAct( this ));
1307 pUndoAction
->SetTabFieldDescr(pDesc
);
1308 pUndoAction
->SetColumnPosition(nPos
);
1309 rController
.addUndoActionAndInvalidate( std::move(pUndoAction
) );
1312 RemoveColumn(nColumnId
);
1314 invalidateUndoRedo();
1317 void OSelectionBrowseBox::adjustSelectionMode( bool _bClickedOntoHeader
, bool _bClickedOntoHandleCol
)
1319 // if a Header has been selected it should be shown otherwise not
1320 if ( _bClickedOntoHeader
)
1322 if (0 == GetSelectColumnCount() )
1323 // I am in the correct mode if a selected column exists
1324 if ( BrowserMode::HIDESELECT
== ( m_nMode
& BrowserMode::HIDESELECT
) )
1326 m_nMode
&= ~BrowserMode::HIDESELECT
;
1327 m_nMode
|= BrowserMode::MULTISELECTION
;
1331 else if ( BrowserMode::HIDESELECT
!= ( m_nMode
& BrowserMode::HIDESELECT
) )
1333 if ( GetSelectColumnCount() != 0 )
1336 if ( _bClickedOntoHandleCol
)
1338 m_nMode
|= BrowserMode::HIDESELECT
;
1339 m_nMode
&= ~BrowserMode::MULTISELECTION
;
1345 void OSelectionBrowseBox::MouseButtonDown(const BrowserMouseEvent
& rEvt
)
1349 bool bOnHandle
= HANDLE_ID
== rEvt
.GetColumnId();
1350 bool bOnHeader
= ( rEvt
.GetRow() < 0 ) && !bOnHandle
;
1351 adjustSelectionMode( bOnHeader
, bOnHandle
);
1353 EditBrowseBox::MouseButtonDown(rEvt
);
1356 void OSelectionBrowseBox::MouseButtonUp(const BrowserMouseEvent
& rEvt
)
1358 EditBrowseBox::MouseButtonUp( rEvt
);
1359 static_cast<OQueryController
&>(getDesignView()->getController()).InvalidateFeature( ID_BROWSER_QUERY_EXECUTE
);
1362 void OSelectionBrowseBox::KeyInput( const KeyEvent
& rEvt
)
1364 if (IsColumnSelected(GetCurColumnId()))
1366 if (rEvt
.GetKeyCode().GetCode() == KEY_DELETE
&& // Delete rows
1367 !rEvt
.GetKeyCode().IsShift() &&
1368 !rEvt
.GetKeyCode().IsMod1())
1370 RemoveField(GetCurColumnId());
1374 EditBrowseBox::KeyInput(rEvt
);
1377 sal_Int8
OSelectionBrowseBox::AcceptDrop( const BrowserAcceptDropEvent
& rEvt
)
1379 sal_Int8 nDropAction
= DND_ACTION_NONE
;
1380 if ( rEvt
.GetRow() >= -1 )
1384 // allow the asterisk again
1385 m_bDisableErrorBox
= true;
1387 m_bDisableErrorBox
= false;
1390 // check if the format is already supported, if not deactivate the current cell and try again
1391 if ( OJoinExchObj::isFormatAvailable(GetDataFlavors()) )
1392 nDropAction
= DND_ACTION_LINK
;
1398 sal_Int8
OSelectionBrowseBox::ExecuteDrop( const BrowserExecuteDropEvent
& _rEvt
)
1401 TransferableDataHelper
aDropped(_rEvt
.maDropEvent
.Transferable
);
1402 if (!OJoinExchObj::isFormatAvailable(aDropped
.GetDataFlavorExVector()))
1404 OSL_FAIL("OSelectionBrowseBox::ExecuteDrop: this should never have passed AcceptDrop!");
1405 return DND_ACTION_NONE
;
1408 // insert the field at the selected position
1409 OJoinExchangeData jxdSource
= OJoinExchObj::GetSourceDescription(_rEvt
.maDropEvent
.Transferable
);
1410 InsertField(jxdSource
);
1412 return DND_ACTION_LINK
;
1415 OTableFieldDescRef
const & OSelectionBrowseBox::AppendNewCol( sal_uInt16 nCnt
)
1417 // one or more can be created, but the first one will is not returned
1418 sal_uInt32 nCount
= getFields().size();
1419 for (sal_uInt16 i
=0 ; i
<nCnt
; i
++)
1421 OTableFieldDescRef pEmptyEntry
= new OTableFieldDesc();
1422 getFields().push_back(pEmptyEntry
);
1423 sal_uInt16 nColumnId
= sal::static_int_cast
< sal_uInt16
>(getFields().size());
1424 pEmptyEntry
->SetColumnId( nColumnId
);
1426 InsertDataColumn( nColumnId
, OUString(), DEFAULT_SIZE
);
1429 return getFields()[nCount
];
1432 void OSelectionBrowseBox::DeleteFields(const OUString
& rAliasName
)
1434 if (getFields().empty())
1437 sal_uInt16 nColId
= GetCurColumnId();
1438 sal_uInt32 nRow
= GetCurRow();
1440 bool bWasEditing
= IsEditing();
1444 auto aIter
= std::find_if(getFields().rbegin(), getFields().rend(),
1445 [&rAliasName
](const OTableFieldDescRef pEntry
) { return pEntry
->GetAlias() == rAliasName
; });
1446 if (aIter
!= getFields().rend())
1448 sal_uInt16 nPos
= sal::static_int_cast
<sal_uInt16
>(std::distance(aIter
, getFields().rend()));
1449 RemoveField( GetColumnId( nPos
) );
1453 ActivateCell(nRow
, nColId
);
1456 void OSelectionBrowseBox::SetColWidth(sal_uInt16 nColId
, tools::Long nNewWidth
)
1458 bool bWasEditing
= IsEditing();
1462 // create the BaseClass
1463 SetColumnWidth(nColId
, nNewWidth
);
1465 // tell it the FieldDescription
1466 OTableFieldDescRef pEntry
= getEntry(GetColumnPos(nColId
) - 1);
1468 pEntry
->SetColWidth(sal_uInt16(GetColumnWidth(nColId
)));
1471 ActivateCell(GetCurRow(), GetCurColumnId());
1474 tools::Rectangle
OSelectionBrowseBox::GetInvalidRect( sal_uInt16 nColId
)
1476 // The rectangle is the full output area of the window
1477 tools::Rectangle
aInvalidRect( Point(0,0), GetOutputSizePixel() );
1479 // now update the left side
1480 tools::Rectangle
aFieldRect(GetCellRect( 0, nColId
)); // used instead of GetFieldRectPixel
1481 aInvalidRect
.SetLeft( aFieldRect
.Left() );
1483 return aInvalidRect
;
1486 void OSelectionBrowseBox::InsertColumn(const OTableFieldDescRef
& pEntry
, sal_uInt16
& _nColumnPosition
)
1488 // the control should have exactly one more column: the HandleColumn
1489 OSL_ENSURE(_nColumnPosition
== BROWSER_INVALIDID
|| (_nColumnPosition
<= static_cast<tools::Long
>(getFields().size())), "OSelectionBrowseBox::InsertColumn : invalid parameter nColId.");
1490 // -1 means at the end. Count means at the end, others denotes a correct position
1492 sal_uInt16 nCurCol
= GetCurColumnId();
1493 sal_Int32 nCurrentRow
= GetCurRow();
1497 // remember the column id of the current position
1498 sal_uInt16 nColumnId
= GetColumnId(_nColumnPosition
);
1499 // put at the end of the list if too small or too big,
1500 if ((_nColumnPosition
== BROWSER_INVALIDID
) || (_nColumnPosition
>= getFields().size())) // append the field
1502 if (FindFirstFreeCol(_nColumnPosition
) == nullptr) // no more free columns
1505 _nColumnPosition
= sal::static_int_cast
< sal_uInt16
>(
1506 getFields().size());
1510 _nColumnPosition
= static_cast<sal_uInt16
>(_nColumnPosition
+ 1); // within the list
1512 nColumnId
= GetColumnId(_nColumnPosition
);
1513 pEntry
->SetColumnId( nColumnId
);
1514 getFields()[ _nColumnPosition
- 1] = pEntry
;
1517 // check if the column ids are identical, if not we have to move
1518 if ( pEntry
->GetColumnId() != nColumnId
)
1520 sal_uInt16 nOldPosition
= GetColumnPos(pEntry
->GetColumnId());
1521 OSL_ENSURE( nOldPosition
!= 0,"Old position was 0. Not possible!");
1522 SetColumnPos(pEntry
->GetColumnId(),_nColumnPosition
);
1523 // we have to delete an empty field for the fields list, because the columns must have equal length
1524 if ( nOldPosition
> 0 && nOldPosition
<= getFields().size() )
1525 getFields()[nOldPosition
- 1] = pEntry
;
1527 ColumnMoved(pEntry
->GetColumnId(),false);
1530 if ( pEntry
->GetFunctionType() & FKT_AGGREGATE
)
1532 OUString sFunctionName
= pEntry
->GetFunction();
1533 if ( GetFunctionName(sal_uInt32(-1),sFunctionName
) )
1534 pEntry
->SetFunction(sFunctionName
);
1537 nColumnId
= pEntry
->GetColumnId();
1539 SetColWidth(nColumnId
,getDesignView()->getColWidth(GetColumnPos(nColumnId
)-1));
1541 tools::Rectangle aInvalidRect
= GetInvalidRect( nColumnId
);
1542 Invalidate( aInvalidRect
);
1544 ActivateCell( nCurrentRow
, nCurCol
);
1545 static_cast<OQueryController
&>(getDesignView()->getController()).setModified( true );
1547 invalidateUndoRedo();
1550 OTableFieldDescRef
OSelectionBrowseBox::InsertField(const OJoinExchangeData
& jxdSource
)
1552 OQueryTableWindow
* pSourceWin
= static_cast<OQueryTableWindow
*>(jxdSource
.pListBox
->GetTabWin());
1556 // name and position of the selected field
1557 weld::TreeView
& rTreeView
= jxdSource
.pListBox
->get_widget();
1558 OUString aFieldName
= rTreeView
.get_text(jxdSource
.nEntry
);
1559 sal_uInt32 nFieldIndex
= jxdSource
.nEntry
;
1560 OTableFieldInfo
* pInf
= weld::fromId
<OTableFieldInfo
*>(rTreeView
.get_id(jxdSource
.nEntry
));
1562 // construct DragInfo, such that I use the other InsertField
1563 OTableFieldDescRef aInfo
= new OTableFieldDesc(pSourceWin
->GetTableName(),aFieldName
);
1564 aInfo
->SetTabWindow(pSourceWin
);
1565 aInfo
->SetFieldIndex(nFieldIndex
);
1566 aInfo
->SetFieldType(pInf
->GetKeyType());
1567 aInfo
->SetAlias(pSourceWin
->GetAliasName());
1569 aInfo
->SetDataType(pInf
->GetDataType());
1570 aInfo
->SetVisible();
1572 return InsertField(aInfo
);
1575 OTableFieldDescRef
OSelectionBrowseBox::InsertField(const OTableFieldDescRef
& _rInfo
, sal_uInt16 _nColumnPosition
, bool bVis
, bool bActivate
)
1578 if(m_nMaxColumns
&& m_nMaxColumns
<= FieldsCount())
1583 // new column description
1584 OTableFieldDescRef pEntry
= _rInfo
;
1585 pEntry
->SetVisible(bVis
);
1588 InsertColumn( pEntry
, _nColumnPosition
);
1590 if ( !m_bInUndoMode
)
1592 // trigger UndoAction
1593 std::unique_ptr
<OTabFieldCreateUndoAct
> pUndoAction(new OTabFieldCreateUndoAct( this ));
1594 pUndoAction
->SetTabFieldDescr( pEntry
);
1595 pUndoAction
->SetColumnPosition(_nColumnPosition
);
1596 getDesignView()->getController().addUndoActionAndInvalidate( std::move(pUndoAction
) );
1602 sal_uInt16
OSelectionBrowseBox::FieldsCount()
1604 sal_uInt16 nCount
= 0;
1605 for (auto const& field
: getFields())
1607 if (field
.is() && !field
->IsEmpty())
1614 OTableFieldDescRef
OSelectionBrowseBox::FindFirstFreeCol(sal_uInt16
& _rColumnPosition
)
1617 _rColumnPosition
= BROWSER_INVALIDID
;
1619 for (auto const& field
: getFields())
1621 _rColumnPosition
= static_cast<sal_uInt16
>(_rColumnPosition
+ 1);
1622 OTableFieldDescRef pEntry
= field
;
1623 if ( pEntry
.is() && pEntry
->IsEmpty() )
1630 void OSelectionBrowseBox::CheckFreeColumns(sal_uInt16
& _rColumnPosition
)
1632 if (FindFirstFreeCol(_rColumnPosition
) == nullptr)
1634 // it is full, so append a pack of columns
1635 AppendNewCol(DEFAULT_QUERY_COLS
);
1636 OSL_VERIFY(FindFirstFreeCol(_rColumnPosition
).is());
1640 void OSelectionBrowseBox::AddGroupBy( const OTableFieldDescRef
& rInfo
)
1642 Reference
< XConnection
> xConnection
= static_cast<OQueryController
&>(getDesignView()->getController()).getConnection();
1643 if(!xConnection
.is())
1645 OSL_ENSURE(!rInfo
->IsEmpty(),"AddGroupBy:: OTableFieldDescRef should not be empty!");
1646 OTableFieldDescRef pEntry
;
1647 const Reference
<XDatabaseMetaData
> xMeta
= xConnection
->getMetaData();
1648 const ::comphelper::UStringMixEqual
bCase(xMeta
.is() && xMeta
->supportsMixedCaseQuotedIdentifiers());
1649 //sal_Bool bAppend = sal_False;
1651 bool bAllFieldsSearched
= true;
1652 for (auto const& field
: getFields())
1655 OSL_ENSURE(pEntry
.is(),"OTableFieldDescRef was null!");
1657 const OUString aField
= pEntry
->GetField();
1658 const OUString aAlias
= pEntry
->GetAlias();
1660 if (bCase(aField
,rInfo
->GetField()) &&
1661 bCase(aAlias
,rInfo
->GetAlias()) &&
1662 pEntry
->GetFunctionType() == rInfo
->GetFunctionType() &&
1663 pEntry
->GetFunction() == rInfo
->GetFunction())
1665 if ( pEntry
->isNumericOrAggregateFunction() && rInfo
->IsGroupBy() )
1667 pEntry
->SetGroupBy(false);
1668 // we do want to consider that bAllFieldsSearched still true here
1669 // bAllFieldsSearched = false;
1674 if ( !pEntry
->IsGroupBy() && !pEntry
->HasCriteria() ) // here we have a where condition which is no having clause
1676 pEntry
->SetGroupBy(rInfo
->IsGroupBy());
1677 if(!m_bGroupByUnRelated
&& pEntry
->IsGroupBy())
1678 pEntry
->SetVisible();
1679 bAllFieldsSearched
= false;
1687 if (bAllFieldsSearched
)
1689 OTableFieldDescRef pTmp
= InsertField(rInfo
, BROWSER_INVALIDID
, false, false );
1690 if ( pTmp
->isNumericOrAggregateFunction() && rInfo
->IsGroupBy() ) // the GroupBy is inherited from rInfo
1691 pTmp
->SetGroupBy(false);
1695 void OSelectionBrowseBox::DuplicateConditionLevel( const sal_uInt16 nLevel
)
1697 const sal_uInt16 nNewLevel
= nLevel
+1;
1698 for (auto const& field
: getFields())
1700 const OTableFieldDescRef
& pEntry
= field
;
1701 OUString sValue
= pEntry
->GetCriteria(nLevel
);
1702 if ( !sValue
.isEmpty() )
1704 pEntry
->SetCriteria( nNewLevel
, sValue
);
1705 if ( nNewLevel
== (m_nVisibleCount
-BROW_CRIT1_ROW
-1) )
1707 RowInserted( GetRowCount()-1 );
1708 m_bVisibleRow
.push_back(true);
1711 m_bVisibleRow
[BROW_CRIT1_ROW
+ nNewLevel
] = true;
1716 void OSelectionBrowseBox::AddCondition( const OTableFieldDescRef
& rInfo
, const OUString
& rValue
, const sal_uInt16 nLevel
,bool _bAddOrOnOneLine
)
1718 Reference
< XConnection
> xConnection
= static_cast<OQueryController
&>(getDesignView()->getController()).getConnection();
1719 if(!xConnection
.is())
1721 OSL_ENSURE(rInfo
.is() && !rInfo
->IsEmpty(),"AddCondition:: OTableFieldDescRef should not be Empty!");
1723 OTableFieldDescRef pLastEntry
;
1724 Reference
<XDatabaseMetaData
> xMeta
= xConnection
->getMetaData();
1725 ::comphelper::UStringMixEqual
bCase(xMeta
.is() && xMeta
->supportsMixedCaseQuotedIdentifiers());
1727 bool bAllFieldsSearched
= true;
1728 for (auto const& field
: getFields())
1730 const OTableFieldDescRef
& pEntry
= field
;
1731 const OUString aField
= pEntry
->GetField();
1732 const OUString aAlias
= pEntry
->GetAlias();
1734 if (bCase(aField
,rInfo
->GetField()) &&
1735 bCase(aAlias
,rInfo
->GetAlias()) &&
1736 pEntry
->GetFunctionType() == rInfo
->GetFunctionType() &&
1737 pEntry
->GetFunction() == rInfo
->GetFunction() &&
1738 pEntry
->IsGroupBy() == rInfo
->IsGroupBy() )
1740 if ( pEntry
->isNumericOrAggregateFunction() && rInfo
->IsGroupBy() )
1741 pEntry
->SetGroupBy(false);
1744 if(!m_bGroupByUnRelated
&& pEntry
->IsGroupBy())
1745 pEntry
->SetVisible();
1747 if (pEntry
->GetCriteria(nLevel
).isEmpty() )
1749 pEntry
->SetCriteria( nLevel
, rValue
);
1750 if(nLevel
== (m_nVisibleCount
-BROW_CRIT1_ROW
-1))
1752 RowInserted( GetRowCount()-1 );
1753 m_bVisibleRow
.push_back(true);
1756 m_bVisibleRow
[BROW_CRIT1_ROW
+ nLevel
] = true;
1757 bAllFieldsSearched
= false;
1760 if ( _bAddOrOnOneLine
)
1762 pLastEntry
= pEntry
;
1766 if ( pLastEntry
.is() )
1768 OUString sCriteria
= rValue
;
1769 OUString sOldCriteria
= pLastEntry
->GetCriteria( nLevel
);
1770 if ( !sOldCriteria
.isEmpty() )
1772 sCriteria
= "( " + sOldCriteria
+ " OR " + rValue
+ " )";
1774 pLastEntry
->SetCriteria( nLevel
, sCriteria
);
1775 if(nLevel
== (m_nVisibleCount
-BROW_CRIT1_ROW
-1))
1777 RowInserted( GetRowCount()-1 );
1778 m_bVisibleRow
.push_back(true);
1781 m_bVisibleRow
[BROW_CRIT1_ROW
+ nLevel
] = true;
1783 else if (bAllFieldsSearched
)
1785 OTableFieldDescRef pTmp
= InsertField(rInfo
, BROWSER_INVALIDID
, false, false );
1786 if ( pTmp
->isNumericOrAggregateFunction() && rInfo
->IsGroupBy() ) // the GroupBy was inherited from rInfo
1787 pTmp
->SetGroupBy(false);
1790 pTmp
->SetCriteria( nLevel
, rValue
);
1791 if(nLevel
== (m_nVisibleCount
-BROW_CRIT1_ROW
-1))
1793 RowInserted( GetRowCount()-1 );
1794 m_bVisibleRow
.push_back(true);
1801 void OSelectionBrowseBox::AddOrder( const OTableFieldDescRef
& rInfo
, const EOrderDir eDir
, sal_uInt32 _nCurrentPos
)
1803 if (_nCurrentPos
== 0)
1804 m_nLastSortColumn
= SORT_COLUMN_NONE
;
1806 Reference
< XConnection
> xConnection
= static_cast<OQueryController
&>(getDesignView()->getController()).getConnection();
1807 if(!xConnection
.is())
1809 OSL_ENSURE(!rInfo
->IsEmpty(),"AddOrder:: OTableFieldDescRef should not be Empty!");
1810 OTableFieldDescRef pEntry
;
1811 Reference
<XDatabaseMetaData
> xMeta
= xConnection
->getMetaData();
1812 ::comphelper::UStringMixEqual
bCase(xMeta
.is() && xMeta
->supportsMixedCaseQuotedIdentifiers());
1814 bool bAppend
= false;
1815 sal_uInt32 nPos
= 0;
1816 bool bAllFieldsSearched
= true;
1817 for (auto const& field
: getFields())
1820 OUString aField
= pEntry
->GetField();
1821 OUString aAlias
= pEntry
->GetAlias();
1823 if (bCase(aField
,rInfo
->GetField()) &&
1824 bCase(aAlias
,rInfo
->GetAlias()))
1826 bAppend
= (m_nLastSortColumn
!= SORT_COLUMN_NONE
) && (nPos
<= m_nLastSortColumn
);
1829 // we do want to consider that bAllFieldsSearched still true here
1830 // bAllFieldsSearched = false;
1835 if ( !m_bOrderByUnRelated
)
1836 pEntry
->SetVisible();
1837 pEntry
->SetOrderDir( eDir
);
1838 m_nLastSortColumn
= nPos
;
1840 bAllFieldsSearched
= false;
1846 if (bAllFieldsSearched
)
1848 OTableFieldDescRef pTmp
= InsertField(rInfo
, BROWSER_INVALIDID
, false, false );
1851 m_nLastSortColumn
= pTmp
->GetColumnId() - 1;
1852 if ( !m_bOrderByUnRelated
&& !bAppend
)
1854 pTmp
->SetOrderDir( eDir
);
1859 bool OSelectionBrowseBox::Save()
1863 bRet
= SaveModified();
1867 void OSelectionBrowseBox::CellModified()
1869 sal_Int32 nRow
= GetRealRow(GetCurRow());
1874 OTableFieldDescRef pEntry
= getEntry(GetColumnPos(GetCurColumnId()) - 1);
1876 weld::ComboBox
& rComboBox
= m_pOrderCell
->get_widget();
1877 sal_Int32 nIdx
= rComboBox
.get_active();
1878 if(!m_bOrderByUnRelated
&& nIdx
> 0 &&
1880 !pEntry
->IsEmpty() &&
1881 pEntry
->GetOrderDir() != ORDER_NONE
)
1883 m_pVisibleCell
->GetBox().set_active(true);
1884 pEntry
->SetVisible();
1887 pEntry
->SetVisible(m_pVisibleCell
->GetBox().get_active());
1891 static_cast<OQueryController
&>(getDesignView()->getController()).setModified( true );
1894 void OSelectionBrowseBox::Fill()
1896 OSL_ENSURE(ColCount() >= 1, "OSelectionBrowseBox::Fill : please call only after inserting the handle column !");
1898 sal_uInt16 nColCount
= ColCount() - 1;
1899 if (nColCount
< DEFAULT_QUERY_COLS
)
1900 AppendNewCol(DEFAULT_QUERY_COLS
- nColCount
);
1903 Size
OSelectionBrowseBox::CalcOptimalSize( const Size
& _rAvailable
)
1905 Size
aReturn( _rAvailable
.Width(), GetTitleHeight() );
1907 aReturn
.AdjustHeight(( m_nVisibleCount
? m_nVisibleCount
: 15 ) * GetDataRowHeight() );
1908 aReturn
.AdjustHeight(40 ); // just some space
1913 void OSelectionBrowseBox::Command(const CommandEvent
& rEvt
)
1915 switch (rEvt
.GetCommand())
1917 case CommandEventId::ContextMenu
:
1919 Point
aMenuPos( rEvt
.GetMousePosPixel() );
1921 if (!rEvt
.IsMouseEvent())
1923 if ( 1 == GetSelectColumnCount() )
1925 sal_uInt16 nSelId
= GetColumnId(
1926 sal::static_int_cast
< sal_uInt16
>(
1927 FirstSelectedColumn() ) );
1928 ::tools::Rectangle
aColRect( GetFieldRectPixel( 0, nSelId
, false ) );
1930 aMenuPos
= aColRect
.TopCenter();
1934 EditBrowseBox::Command(rEvt
);
1939 sal_uInt16 nColId
= GetColumnId(GetColumnAtXPosPixel( aMenuPos
.X() ));
1940 sal_Int32 nRow
= GetRowAtYPosPixel( aMenuPos
.Y() );
1942 if (nRow
< 0 && nColId
> HANDLE_ID
)
1944 if ( !IsColumnSelected( nColId
) )
1946 adjustSelectionMode( true /* clicked onto a header */ , false /* not onto the handle col */ );
1947 SelectColumnId( nColId
);
1950 if (!static_cast<OQueryController
&>(getDesignView()->getController()).isReadOnly())
1952 ::tools::Rectangle
aRect(aMenuPos
, Size(1, 1));
1953 weld::Window
* pPopupParent
= weld::GetPopupParent(*this, aRect
);
1954 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(pPopupParent
, u
"dbaccess/ui/querycolmenu.ui"_ustr
));
1955 std::unique_ptr
<weld::Menu
> xContextMenu(xBuilder
->weld_menu(u
"menu"_ustr
));
1956 OUString sIdent
= xContextMenu
->popup_at_rect(pPopupParent
, aRect
);
1957 if (sIdent
== "delete")
1958 RemoveField(nColId
);
1959 else if (sIdent
== "width")
1960 adjustBrowseBoxColumnWidth( this, nColId
);
1963 else if(nRow
>= 0 && nColId
<= HANDLE_ID
)
1965 if (!static_cast<OQueryController
&>(getDesignView()->getController()).isReadOnly())
1967 ::tools::Rectangle
aRect(aMenuPos
, Size(1, 1));
1968 weld::Window
* pPopupParent
= weld::GetPopupParent(*this, aRect
);
1969 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(pPopupParent
, u
"dbaccess/ui/queryfuncmenu.ui"_ustr
));
1970 std::unique_ptr
<weld::Menu
> xContextMenu(xBuilder
->weld_menu(u
"menu"_ustr
));
1971 xContextMenu
->set_active(u
"functions"_ustr
, m_bVisibleRow
[BROW_FUNCTION_ROW
]);
1972 xContextMenu
->set_active(u
"tablename"_ustr
, m_bVisibleRow
[BROW_TABLE_ROW
]);
1973 xContextMenu
->set_active(u
"alias"_ustr
, m_bVisibleRow
[BROW_COLUMNALIAS_ROW
]);
1974 xContextMenu
->set_active(u
"distinct"_ustr
, static_cast<OQueryController
&>(getDesignView()->getController()).isDistinct());
1976 OUString sIdent
= xContextMenu
->popup_at_rect(pPopupParent
, aRect
);
1977 if (sIdent
== "functions")
1979 SetRowVisible(BROW_FUNCTION_ROW
, !IsRowVisible(BROW_FUNCTION_ROW
));
1980 static_cast<OQueryController
&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_FUNCTIONS
);
1982 else if (sIdent
== "tablename")
1984 SetRowVisible(BROW_TABLE_ROW
, !IsRowVisible(BROW_TABLE_ROW
));
1985 static_cast<OQueryController
&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_TABLES
);
1987 else if (sIdent
== "alias")
1989 SetRowVisible(BROW_COLUMNALIAS_ROW
, !IsRowVisible(BROW_COLUMNALIAS_ROW
));
1990 static_cast<OQueryController
&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_ALIASES
);
1992 else if (sIdent
== "distinct")
1994 static_cast<OQueryController
&>(getDesignView()->getController()).setDistinct(!static_cast<OQueryController
&>(getDesignView()->getController()).isDistinct());
1995 static_cast<OQueryController
&>(getDesignView()->getController()).setModified( true );
1996 static_cast<OQueryController
&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_DISTINCT_VALUES
);
1999 static_cast<OQueryController
&>(getDesignView()->getController()).setModified( true );
2004 EditBrowseBox::Command(rEvt
);
2011 EditBrowseBox::Command(rEvt
);
2015 bool OSelectionBrowseBox::IsRowVisible(sal_uInt16 _nWhich
) const
2017 OSL_ENSURE(_nWhich
<(m_bVisibleRow
.size()), "OSelectionBrowseBox::IsRowVisible : invalid parameter !");
2018 return m_bVisibleRow
[_nWhich
];
2021 void OSelectionBrowseBox::SetRowVisible(sal_uInt16 _nWhich
, bool _bVis
)
2023 OSL_ENSURE(_nWhich
<m_bVisibleRow
.size(), "OSelectionBrowseBox::SetRowVisible : invalid parameter !");
2025 bool bWasEditing
= IsEditing();
2029 // do this before removing or inserting rows, as this triggers ActivateCell-calls, which rely on m_bVisibleRow
2030 m_bVisibleRow
[_nWhich
] = !m_bVisibleRow
[_nWhich
];
2032 tools::Long nId
= GetBrowseRow(_nWhich
);
2048 sal_Int32
OSelectionBrowseBox::GetBrowseRow(sal_Int32 nRowId
) const
2050 sal_Int32
nCount(0);
2051 for(sal_Int32 i
= 0 ; i
< nRowId
; ++i
)
2053 if ( m_bVisibleRow
[i
] )
2059 sal_Int32
OSelectionBrowseBox::GetRealRow(sal_Int32 nRowId
) const
2062 const sal_Int32 nCount
= m_bVisibleRow
.size();
2063 for(i
=0;i
< nCount
; ++i
)
2065 if(m_bVisibleRow
[i
] && nErg
++ == nRowId
)
2068 OSL_ENSURE(nErg
<= tools::Long(m_bVisibleRow
.size()),"nErg cannot be greater than BROW_ROW_CNT!");
2072 const tools::Long nVisibleRowMask
[] =
2087 sal_Int32
OSelectionBrowseBox::GetNoneVisibleRows() const
2090 // only the first 11 rows are interesting
2091 std::size_t const nSize
= std::size(nVisibleRowMask
);
2092 for(std::size_t i
=0;i
<nSize
;i
++)
2094 if(!m_bVisibleRow
[i
])
2095 nErg
|= nVisibleRowMask
[i
];
2100 void OSelectionBrowseBox::SetNoneVisibleRow(sal_Int32 nRows
)
2102 // only the first 11 rows are interesting
2103 std::size_t const nSize
= std::size(nVisibleRowMask
);
2104 for(std::size_t i
=0;i
< nSize
;i
++)
2105 m_bVisibleRow
[i
] = !(nRows
& nVisibleRowMask
[i
]);
2108 OUString
OSelectionBrowseBox::GetCellText(sal_Int32 nRow
, sal_uInt16 nColId
) const
2111 sal_uInt16 nPos
= GetColumnPos(nColId
);
2112 if ( nPos
== 0 || nPos
== BROWSER_INVALIDID
|| nPos
> getFields().size() )
2115 OTableFieldDescRef pEntry
= getFields()[nPos
-1];
2116 OSL_ENSURE(pEntry
!= nullptr, "OSelectionBrowseBox::GetCellText : invalid column id, prepare for GPF ... ");
2117 if ( pEntry
->IsEmpty() )
2123 case BROW_TABLE_ROW
:
2124 aText
= pEntry
->GetAlias();
2126 case BROW_FIELD_ROW
:
2128 OUString aField
= pEntry
->GetField();
2129 if (!aField
.isEmpty() && aField
[0] == '*') // * replace with alias.*
2131 aField
= pEntry
->GetAlias();
2132 if(!aField
.isEmpty())
2138 case BROW_ORDER_ROW
:
2139 if (pEntry
->GetOrderDir() != ORDER_NONE
)
2140 aText
= DBA_RES(STR_QUERY_SORTTEXT
).getToken(sal::static_int_cast
< sal_uInt16
>(pEntry
->GetOrderDir()), ';');
2144 case BROW_COLUMNALIAS_ROW
:
2145 aText
= pEntry
->GetFieldAlias();
2147 case BROW_FUNCTION_ROW
:
2148 // we always show the group function at first
2149 if ( pEntry
->IsGroupBy() )
2150 aText
= m_aFunctionStrings
.copy(m_aFunctionStrings
.lastIndexOf(';')+1);
2151 else if ( pEntry
->isNumericOrAggregateFunction() )
2152 aText
= pEntry
->GetFunction();
2155 aText
= pEntry
->GetCriteria(sal_uInt16(nRow
- BROW_CRIT1_ROW
));
2160 bool OSelectionBrowseBox::GetFunctionName(sal_uInt32 _nFunctionTokenId
, OUString
& rFkt
)
2162 weld::ComboBox
& rComboBox
= m_pFunctionCell
->get_widget();
2163 switch(_nFunctionTokenId
)
2165 case SQL_TOKEN_COUNT
:
2166 rFkt
= (rComboBox
.get_count() < 3) ? rComboBox
.get_text(1) : rComboBox
.get_text(2);
2169 rFkt
= rComboBox
.get_text(1);
2172 rFkt
= rComboBox
.get_text(3);
2175 rFkt
= rComboBox
.get_text(4);
2178 rFkt
= rComboBox
.get_text(5);
2180 case SQL_TOKEN_EVERY
:
2181 rFkt
= rComboBox
.get_text(6);
2184 rFkt
= rComboBox
.get_text(7);
2186 case SQL_TOKEN_SOME
:
2187 rFkt
= rComboBox
.get_text(8);
2189 case SQL_TOKEN_STDDEV_POP
:
2190 rFkt
= rComboBox
.get_text(9);
2192 case SQL_TOKEN_STDDEV_SAMP
:
2193 rFkt
= rComboBox
.get_text(10);
2195 case SQL_TOKEN_VAR_SAMP
:
2196 rFkt
= rComboBox
.get_text(11);
2198 case SQL_TOKEN_VAR_POP
:
2199 rFkt
= rComboBox
.get_text(12);
2201 case SQL_TOKEN_COLLECT
:
2202 rFkt
= rComboBox
.get_text(13);
2204 case SQL_TOKEN_FUSION
:
2205 rFkt
= rComboBox
.get_text(14);
2207 case SQL_TOKEN_INTERSECTION
:
2208 rFkt
= rComboBox
.get_text(15);
2212 const sal_Int32 nStopIdx
= m_aFunctionStrings
.lastIndexOf(';'); // grouping is not counted
2213 for (sal_Int32 nIdx
{0}; nIdx
<nStopIdx
;)
2215 const OUString sFunc
{m_aFunctionStrings
.getToken(0, ';', nIdx
)};
2216 if (rFkt
.equalsIgnoreAsciiCase(sFunc
))
2229 OUString
OSelectionBrowseBox::GetCellContents(sal_Int32 nCellIndex
, sal_uInt16 nColId
)
2231 if ( GetCurColumnId() == nColId
&& !m_bInUndoMode
)
2234 sal_uInt16 nPos
= GetColumnPos(nColId
);
2235 OTableFieldDescRef pEntry
= getFields()[nPos
- 1];
2236 OSL_ENSURE(pEntry
!= nullptr, "OSelectionBrowseBox::GetCellContents : invalid column id, prepare for GPF ... ");
2241 return OUString(pEntry
->IsVisible() ? std::u16string_view(u
"1") : std::u16string_view(u
"0"));
2242 case BROW_ORDER_ROW
:
2244 sal_Int32 nIdx
= m_pOrderCell
->get_widget().get_active();
2247 return OUString::number(nIdx
);
2250 return GetCellText(nCellIndex
, nColId
);
2254 void OSelectionBrowseBox::SetCellContents(sal_Int32 nRow
, sal_uInt16 nColId
, const OUString
& strNewText
)
2256 bool bWasEditing
= IsEditing() && (GetCurColumnId() == nColId
) && IsRowVisible(static_cast<sal_uInt16
>(nRow
)) && (GetCurRow() == static_cast<sal_uInt16
>(GetBrowseRow(nRow
)));
2260 sal_uInt16 nPos
= GetColumnPos(nColId
);
2261 OTableFieldDescRef pEntry
= getEntry(nPos
- 1);
2262 OSL_ENSURE(pEntry
!= nullptr, "OSelectionBrowseBox::SetCellContents : invalid column id, prepare for GPF ... ");
2267 pEntry
->SetVisible(strNewText
== "1");
2269 case BROW_FIELD_ROW
:
2270 pEntry
->SetField(strNewText
);
2272 case BROW_TABLE_ROW
:
2273 pEntry
->SetAlias(strNewText
);
2275 case BROW_ORDER_ROW
:
2277 sal_uInt16 nIdx
= static_cast<sal_uInt16
>(strNewText
.toInt32());
2278 pEntry
->SetOrderDir(EOrderDir(nIdx
));
2280 case BROW_COLUMNALIAS_ROW
:
2281 pEntry
->SetFieldAlias(strNewText
);
2283 case BROW_FUNCTION_ROW
:
2285 std::u16string_view sGroupFunctionName
= m_aFunctionStrings
.subView(m_aFunctionStrings
.lastIndexOf(';')+1);
2286 pEntry
->SetFunction(strNewText
);
2287 // first reset this two member
2288 sal_Int32 nFunctionType
= pEntry
->GetFunctionType();
2289 nFunctionType
&= ~FKT_AGGREGATE
;
2290 pEntry
->SetFunctionType(nFunctionType
);
2291 if ( pEntry
->IsGroupBy() && !o3tl::equalsIgnoreAsciiCase(sGroupFunctionName
, strNewText
) )
2292 pEntry
->SetGroupBy(false);
2294 if ( o3tl::equalsIgnoreAsciiCase(sGroupFunctionName
, strNewText
) )
2295 pEntry
->SetGroupBy(true);
2296 else if ( !strNewText
.isEmpty() )
2298 nFunctionType
|= FKT_AGGREGATE
;
2299 pEntry
->SetFunctionType(nFunctionType
);
2303 pEntry
->SetCriteria(sal_uInt16(nRow
- BROW_CRIT1_ROW
), strNewText
);
2306 tools::Long nCellIndex
= GetRealRow(nRow
);
2307 if(IsRowVisible(static_cast<sal_uInt16
>(nRow
)))
2308 RowModified(nCellIndex
, nColId
);
2310 // the appropriate field-description is now empty -> set Visible to sal_False (now it is consistent to normal empty rows)
2311 if (pEntry
->IsEmpty())
2312 pEntry
->SetVisible(false);
2315 ActivateCell(nCellIndex
, nColId
);
2317 static_cast<OQueryController
&>(getDesignView()->getController()).setModified( true );
2320 void OSelectionBrowseBox::ColumnResized(sal_uInt16 nColId
)
2322 if (static_cast<OQueryController
&>(getDesignView()->getController()).isReadOnly())
2324 // The resizing of columns can't be suppressed (BrowseBox doesn't support that) so we have to do this
2325 // fake. It's not _that_ bad : the user may change column widths while in read-only mode to see all details
2326 // but the changes aren't permanent ...
2328 sal_uInt16 nPos
= GetColumnPos(nColId
);
2329 OSL_ENSURE(nPos
<= getFields().size(),"ColumnResized:: nColId should not be greater than List::count!");
2330 OTableFieldDescRef pEntry
= getEntry(nPos
-1);
2331 OSL_ENSURE(pEntry
.is(), "OSelectionBrowseBox::ColumnResized : invalid FieldDescription !");
2332 static_cast<OQueryController
&>(getDesignView()->getController()).setModified( true );
2333 EditBrowseBox::ColumnResized(nColId
);
2337 if ( !m_bInUndoMode
)
2339 // create the undo action
2340 std::unique_ptr
<OTabFieldSizedUndoAct
> pUndo(new OTabFieldSizedUndoAct(this));
2341 pUndo
->SetColumnPosition( nPos
);
2342 pUndo
->SetOriginalWidth(pEntry
->GetColWidth());
2343 getDesignView()->getController().addUndoActionAndInvalidate(std::move(pUndo
));
2345 pEntry
->SetColWidth(sal_uInt16(GetColumnWidth(nColId
)));
2349 sal_uInt32
OSelectionBrowseBox::GetTotalCellWidth(sal_Int32 nRowId
, sal_uInt16 nColId
)
2351 sal_uInt16 nPos
= GetColumnPos(nColId
);
2352 OSL_ENSURE((nPos
== 0) || (nPos
<= getFields().size()), "OSelectionBrowseBox::GetTotalCellWidth : invalid parameter nColId");
2354 OTableFieldDescRef pEntry
= getFields()[nPos
-1];
2355 OSL_ENSURE(pEntry
.is(), "OSelectionBrowseBox::GetTotalCellWidth : invalid FieldDescription !");
2357 sal_Int32 nRow
= GetRealRow(nRowId
);
2358 OUString
strText(GetCellText(nRow
, nColId
));
2359 return GetDataWindow().LogicToPixel(Size(GetDataWindow().GetTextWidth(strText
),0)).Width();
2362 bool OSelectionBrowseBox::isCutAllowed() const
2364 bool bCutAllowed
= false;
2365 sal_Int32 nRow
= GetRealRow(GetCurRow());
2369 case BROW_ORDER_ROW
:
2370 case BROW_TABLE_ROW
:
2371 case BROW_FUNCTION_ROW
:
2373 case BROW_FIELD_ROW
:
2375 weld::ComboBox
& rComboBox
= m_pFieldCell
->get_widget();
2376 int nStartPos
, nEndPos
;
2377 bCutAllowed
= rComboBox
.get_entry_selection_bounds(nStartPos
, nEndPos
);
2382 weld::Entry
& rEntry
= m_pTextCell
->get_widget();
2383 int nStartPos
, nEndPos
;
2384 bCutAllowed
= rEntry
.get_selection_bounds(nStartPos
, nEndPos
);
2391 void OSelectionBrowseBox::cut()
2393 sal_Int32 nRow
= GetRealRow(GetCurRow());
2396 case BROW_FIELD_ROW
:
2398 weld::ComboBox
& rComboBox
= m_pFieldCell
->get_widget();
2399 rComboBox
.cut_entry_clipboard();
2404 weld::Entry
& rEntry
= m_pTextCell
->get_widget();
2405 rEntry
.cut_clipboard();
2409 RowModified(GetBrowseRow(nRow
), GetCurColumnId());
2411 invalidateUndoRedo();
2414 void OSelectionBrowseBox::paste()
2416 sal_Int32 nRow
= GetRealRow(GetCurRow());
2419 case BROW_FIELD_ROW
:
2421 weld::ComboBox
& rComboBox
= m_pFieldCell
->get_widget();
2422 rComboBox
.paste_entry_clipboard();
2427 weld::Entry
& rEntry
= m_pTextCell
->get_widget();
2428 rEntry
.paste_clipboard();
2432 RowModified(GetBrowseRow(nRow
), GetCurColumnId());
2433 invalidateUndoRedo();
2436 bool OSelectionBrowseBox::isPasteAllowed() const
2438 bool bPasteAllowed
= true;
2439 sal_Int32 nRow
= GetRealRow(GetCurRow());
2443 case BROW_ORDER_ROW
:
2444 case BROW_TABLE_ROW
:
2445 case BROW_FUNCTION_ROW
:
2446 bPasteAllowed
= false;
2449 return bPasteAllowed
;
2452 bool OSelectionBrowseBox::isCopyAllowed() const
2454 return isCutAllowed();
2457 void OSelectionBrowseBox::copy()
2459 sal_Int32 nRow
= GetRealRow(GetCurRow());
2462 case BROW_FIELD_ROW
:
2464 weld::ComboBox
& rComboBox
= m_pFieldCell
->get_widget();
2465 rComboBox
.copy_entry_clipboard();
2470 weld::Entry
& rEntry
= m_pTextCell
->get_widget();
2471 rEntry
.copy_clipboard();
2477 void OSelectionBrowseBox::appendUndoAction(const OUString
& _rOldValue
, std::u16string_view _rNewValue
, sal_Int32 _nRow
, bool& _bListAction
)
2479 if ( !m_bInUndoMode
&& _rNewValue
!= _rOldValue
)
2481 if ( !_bListAction
)
2483 _bListAction
= true;
2484 static_cast<OQueryController
&>(getDesignView()->getController()).GetUndoManager().EnterListAction(OUString(),OUString(),0,ViewShellId(-1));
2486 appendUndoAction(_rOldValue
,_rNewValue
,_nRow
);
2490 void OSelectionBrowseBox::appendUndoAction(const OUString
& _rOldValue
,std::u16string_view _rNewValue
,sal_Int32 _nRow
)
2492 if ( !m_bInUndoMode
&& _rNewValue
!= _rOldValue
)
2494 std::unique_ptr
<OTabFieldCellModifiedUndoAct
> pUndoAct(new OTabFieldCellModifiedUndoAct(this));
2495 pUndoAct
->SetCellIndex(_nRow
);
2496 OSL_ENSURE(GetColumnPos(GetCurColumnId()) != BROWSER_INVALIDID
,"Current position isn't valid!");
2497 pUndoAct
->SetColumnPosition( GetColumnPos(GetCurColumnId()) );
2498 pUndoAct
->SetCellContents(_rOldValue
);
2499 getDesignView()->getController().addUndoActionAndInvalidate(std::move(pUndoAct
));
2503 IMPL_LINK_NOARG(OSelectionBrowseBox
, OnInvalidateTimer
, Timer
*, void)
2505 static_cast<OQueryController
&>(getDesignView()->getController()).InvalidateFeature(SID_CUT
);
2506 static_cast<OQueryController
&>(getDesignView()->getController()).InvalidateFeature(SID_COPY
);
2507 static_cast<OQueryController
&>(getDesignView()->getController()).InvalidateFeature(SID_PASTE
);
2509 m_timerInvalidate
.Start();
2512 void OSelectionBrowseBox::stopTimer()
2514 m_bStopTimer
= true;
2515 if (m_timerInvalidate
.IsActive())
2516 m_timerInvalidate
.Stop();
2519 void OSelectionBrowseBox::startTimer()
2521 m_bStopTimer
= false;
2522 if (!m_timerInvalidate
.IsActive())
2523 m_timerInvalidate
.Start();
2526 OTableFields
& OSelectionBrowseBox::getFields() const
2528 OQueryController
& rController
= static_cast<OQueryController
&>(getDesignView()->getController());
2529 return rController
.getTableFieldDesc();
2532 void OSelectionBrowseBox::enableControl(const OTableFieldDescRef
& _rEntry
,Window
* _pControl
)
2534 bool bEnable
= !_rEntry
->isCondition();
2535 _pControl
->Enable(bEnable
);
2536 _pControl
->EnableInput(bEnable
);
2539 void OSelectionBrowseBox::setTextCellContext(const OTableFieldDescRef
& _rEntry
,const OUString
& _sText
,const OUString
& _sHelpId
)
2541 weld::Entry
& rEntry
= m_pTextCell
->get_widget();
2542 rEntry
.set_text(_sText
);
2543 rEntry
.save_value();
2544 if (!m_pTextCell
->HasFocus())
2545 m_pTextCell
->GrabFocus();
2547 enableControl(_rEntry
,m_pTextCell
);
2549 if (m_pTextCell
->GetHelpId() != _sHelpId
)
2550 // as TextCell is used in various contexts I will delete the cached HelpText
2551 m_pTextCell
->SetHelpText(OUString());
2552 m_pTextCell
->SetHelpId(_sHelpId
);
2555 void OSelectionBrowseBox::invalidateUndoRedo()
2557 OQueryController
& rController
= static_cast<OQueryController
&>(getDesignView()->getController());
2558 rController
.InvalidateFeature( ID_BROWSER_UNDO
);
2559 rController
.InvalidateFeature( ID_BROWSER_REDO
);
2560 rController
.InvalidateFeature( ID_BROWSER_QUERY_EXECUTE
);
2563 OTableFieldDescRef
OSelectionBrowseBox::getEntry(OTableFields::size_type _nPos
)
2565 // we have to check if we need a new entry at this position
2566 OTableFields
& aFields
= getFields();
2567 OSL_ENSURE(aFields
.size() > _nPos
,"ColID is to great!");
2569 OTableFieldDescRef pEntry
= aFields
[_nPos
];
2570 OSL_ENSURE(pEntry
.is(),"Invalid entry!");
2573 pEntry
= new OTableFieldDesc();
2574 pEntry
->SetColumnId(
2575 GetColumnId(sal::static_int_cast
< sal_uInt16
>(_nPos
+1)));
2576 aFields
[_nPos
] = pEntry
;
2581 void OSelectionBrowseBox::GetFocus()
2583 if(!IsEditing() && !m_bWasEditing
)
2585 EditBrowseBox::GetFocus();
2588 void OSelectionBrowseBox::DeactivateCell(bool _bUpdate
)
2590 m_bWasEditing
= true;
2591 EditBrowseBox::DeactivateCell(_bUpdate
);
2592 m_bWasEditing
= false;
2595 OUString
OSelectionBrowseBox::GetRowDescription( sal_Int32 _nRow
) const
2597 OUString
aLabel(DBA_RES(STR_QUERY_HANDLETEXT
));
2599 // from BROW_CRIT2_ROW onwards all rows are shown as "or"
2600 sal_Int32 nToken
= (_nRow
>= GetBrowseRow(BROW_CRIT2_ROW
))
2601 ? BROW_CRIT2_ROW
: GetRealRow(_nRow
);
2602 return aLabel
.getToken(nToken
, ';');
2605 OUString
OSelectionBrowseBox::GetAccessibleObjectName( AccessibleBrowseBoxObjType _eObjType
,sal_Int32 _nPosition
) const
2610 case AccessibleBrowseBoxObjType::RowHeaderCell
:
2611 sRetText
= GetRowDescription(_nPosition
);
2614 sRetText
= EditBrowseBox::GetAccessibleObjectDescription(_eObjType
,_nPosition
);
2619 bool OSelectionBrowseBox::fillEntryTable(OTableFieldDescRef
const & _pEntry
,const OUString
& _sTableName
)
2622 OJoinTableView::OTableWindowMap
& rTabWinList
= getDesignView()->getTableView()->GetTabWinMap();
2623 OJoinTableView::OTableWindowMap::const_iterator aIter
= rTabWinList
.find(_sTableName
);
2624 if(aIter
!= rTabWinList
.end())
2626 OQueryTableWindow
* pEntryTab
= static_cast<OQueryTableWindow
*>(aIter
->second
.get());
2629 _pEntry
->SetTable(pEntryTab
->GetTableName());
2630 _pEntry
->SetTabWindow(pEntryTab
);
2637 void OSelectionBrowseBox::setFunctionCell(OTableFieldDescRef
const & _pEntry
)
2639 Reference
< XConnection
> xConnection
= static_cast<OQueryController
&>(getDesignView()->getController()).getConnection();
2640 if ( !xConnection
.is() )
2643 // Aggregate functions in general only available with Core SQL
2644 if ( lcl_SupportsCoreSQLGrammar(xConnection
) )
2647 // if we have an asterisk, no other function than count is allowed
2648 weld::ComboBox
& rComboBox
= m_pFunctionCell
->get_widget();
2650 rComboBox
.append_text(m_aFunctionStrings
.getToken(0, ';', nIdx
));
2651 if ( isFieldNameAsterisk(_pEntry
->GetField()) )
2652 rComboBox
.append_text(m_aFunctionStrings
.getToken(1, ';', nIdx
)); // 2nd token: COUNT
2655 const bool bSkipLastToken
{_pEntry
->isNumeric()};
2658 const OUString sTok
{m_aFunctionStrings
.getToken(0, ';', nIdx
)};
2659 if (bSkipLastToken
&& nIdx
<0)
2661 rComboBox
.append_text(sTok
);
2665 if ( _pEntry
->IsGroupBy() )
2667 OSL_ENSURE(!_pEntry
->isNumeric(),"Not allowed to combine group by and numeric values!");
2668 rComboBox
.set_active_text(rComboBox
.get_text(rComboBox
.get_count() - 1));
2670 else if (rComboBox
.find_text(_pEntry
->GetFunction()) != -1)
2671 rComboBox
.set_active_text(_pEntry
->GetFunction());
2673 rComboBox
.set_active(0);
2675 enableControl(_pEntry
, m_pFunctionCell
);
2679 // only COUNT(*) and COUNT("table".*) allowed
2680 bool bCountRemoved
= !isFieldNameAsterisk(_pEntry
->GetField());
2681 weld::ComboBox
& rComboBox
= m_pFunctionCell
->get_widget();
2682 if ( bCountRemoved
)
2683 rComboBox
.remove(1);
2685 if ( !bCountRemoved
&& rComboBox
.get_count() < 2)
2686 rComboBox
.append_text(m_aFunctionStrings
.getToken(2, ';')); // 2 -> COUNT
2688 if (rComboBox
.find_text(_pEntry
->GetFunction()) != -1)
2689 rComboBox
.set_active_text(_pEntry
->GetFunction());
2691 rComboBox
.set_active(0);
2695 Reference
< XAccessible
> OSelectionBrowseBox::CreateAccessibleCell( sal_Int32 _nRow
, sal_uInt16 _nColumnPos
)
2697 OTableFieldDescRef pEntry
;
2698 if ( _nColumnPos
!= 0 && _nColumnPos
!= BROWSER_INVALIDID
&& _nColumnPos
<= getFields().size() )
2699 pEntry
= getFields()[_nColumnPos
- 1];
2701 if ( _nRow
== BROW_VIS_ROW
&& pEntry
.is() )
2702 return EditBrowseBox::CreateAccessibleCheckBoxCell( _nRow
, _nColumnPos
,pEntry
->IsVisible() ? TRISTATE_TRUE
: TRISTATE_FALSE
);
2704 return EditBrowseBox::CreateAccessibleCell( _nRow
, _nColumnPos
);
2707 bool OSelectionBrowseBox::HasFieldByAliasName(std::u16string_view rFieldName
, OTableFieldDescRef
const & rInfo
) const
2709 for (auto const& field
: getFields())
2711 if ( field
->GetFieldAlias() == rFieldName
)
2720 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */