Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / dbaccess / source / ui / querydesign / SelectionBrowseBox.cxx
blobfb900b9d530ba4558e25f28096c58ce9794be0f5
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 "SelectionBrowseBox.hxx"
21 #include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
22 #include <com/sun/star/sdbc/DataType.hpp>
23 #include "QueryDesignView.hxx"
24 #include "querycontroller.hxx"
25 #include "sqlbison.hxx"
26 #include "QueryTableView.hxx"
27 #include "browserids.hxx"
28 #include <comphelper/extract.hxx>
29 #include <comphelper/stl_types.hxx>
30 #include <comphelper/string.hxx>
31 #include <comphelper/types.hxx>
32 #include "TableFieldInfo.hxx"
33 #include "dbu_qry.hrc"
34 #include "dbaccess_helpid.hrc"
35 #include <com/sun/star/container/XNameAccess.hpp>
36 #include "dbustrings.hrc"
37 #include "QTableWindow.hxx"
38 #include <vcl/msgbox.hxx>
39 #include <vcl/settings.hxx>
40 #include "QueryDesignFieldUndoAct.hxx"
41 #include "sqlmessage.hxx"
42 #include "UITools.hxx"
43 #include <osl/diagnose.h>
44 #include "svtools/treelistentry.hxx"
46 using namespace ::svt;
47 using namespace ::dbaui;
48 using namespace ::connectivity;
49 using namespace ::com::sun::star::uno;
50 using namespace ::com::sun::star::sdbc;
51 using namespace ::com::sun::star::beans;
52 using namespace ::com::sun::star::container;
53 using namespace ::com::sun::star::util;
54 using namespace ::com::sun::star::accessibility;
56 #define DEFAULT_QUERY_COLS 20
57 #define DEFAULT_SIZE GetTextWidth("0") * 30
58 #define HANDLE_ID 0
59 #define HANDLE_COLUMN_WITDH 70
60 #define SORT_COLUMN_NONE 0xFFFFFFFF
62 namespace
64 bool isFieldNameAsterisk(const OUString& _sFieldName )
66 bool bAsterisk = !(!_sFieldName.isEmpty() && _sFieldName.toChar() != '*');
67 if ( !bAsterisk )
69 sal_Int32 nTokenCount = comphelper::string::getTokenCount(_sFieldName, '.');
70 if ( (nTokenCount == 2 && _sFieldName.getToken(1,'.')[0] == '*' )
71 || (nTokenCount == 3 && _sFieldName.getToken(2,'.')[0] == '*' ) )
73 bAsterisk = true;
76 return bAsterisk;
78 bool lcl_SupportsCoreSQLGrammar(const Reference< XConnection>& _xConnection)
80 bool bSupportsCoreGrammar = false;
81 if ( _xConnection.is() )
83 try
85 Reference< XDatabaseMetaData > xMetaData = _xConnection->getMetaData();
86 bSupportsCoreGrammar = xMetaData.is() && xMetaData->supportsCoreSQLGrammar();
88 catch(Exception&)
92 return bSupportsCoreGrammar;
96 OSelectionBrowseBox::OSelectionBrowseBox( vcl::Window* pParent )
97 :EditBrowseBox( pParent,EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT, WB_3DLOOK, BrowserMode::COLUMNSELECTION | BrowserMode::KEEPHIGHLIGHT | BrowserMode::HIDESELECT |
98 BrowserMode::HIDECURSOR | BrowserMode::HLINES | BrowserMode::VLINES )
99 ,m_nSeekRow(0)
100 ,m_nMaxColumns(0)
101 ,m_aFunctionStrings(ModuleRes(STR_QUERY_FUNCTIONS))
102 ,m_nVisibleCount(0)
103 ,m_nLastSortColumn(SORT_COLUMN_NONE)
104 ,m_bOrderByUnRelated(true)
105 ,m_bGroupByUnRelated(true)
106 ,m_bStopTimer(false)
107 ,m_bWasEditing(false)
108 ,m_bDisableErrorBox(false)
109 ,m_bInUndoMode(false)
111 SetHelpId(HID_CTL_QRYDGNCRIT);
113 m_nMode = BrowserMode::COLUMNSELECTION | BrowserMode::HIDESELECT
114 | BrowserMode::KEEPHIGHLIGHT | BrowserMode::HIDECURSOR
115 | BrowserMode::HLINES | BrowserMode::VLINES
116 | BrowserMode::HEADERBAR_NEW ;
118 m_pTextCell = VclPtr<Edit>::Create(&GetDataWindow(), 0);
119 m_pVisibleCell = VclPtr<CheckBoxControl>::Create(&GetDataWindow());
120 m_pTableCell = VclPtr<ListBoxControl>::Create(&GetDataWindow()); m_pTableCell->SetDropDownLineCount( 20 );
121 m_pFieldCell = VclPtr<ComboBoxControl>::Create(&GetDataWindow()); m_pFieldCell->SetDropDownLineCount( 20 );
122 m_pOrderCell = VclPtr<ListBoxControl>::Create(&GetDataWindow());
123 m_pFunctionCell = VclPtr<ListBoxControl>::Create(&GetDataWindow()); m_pFunctionCell->SetDropDownLineCount( 20 );
125 m_pVisibleCell->SetHelpId(HID_QRYDGN_ROW_VISIBLE);
126 m_pTableCell->SetHelpId(HID_QRYDGN_ROW_TABLE);
127 m_pFieldCell->SetHelpId(HID_QRYDGN_ROW_FIELD);
128 m_pOrderCell->SetHelpId(HID_QRYDGN_ROW_ORDER);
129 m_pFunctionCell->SetHelpId(HID_QRYDGN_ROW_FUNCTION);
131 // switch off triState of css::form::CheckBox
132 m_pVisibleCell->GetBox().EnableTriState( false );
134 vcl::Font aTitleFont = OutputDevice::GetDefaultFont( DefaultFontType::SANS_UNICODE,Window::GetSettings().GetLanguageTag().getLanguageType(),GetDefaultFontFlags::OnlyOne);
135 aTitleFont.SetFontSize(Size(0, 6));
136 SetTitleFont(aTitleFont);
138 OUString aTxt(ModuleRes(STR_QUERY_SORTTEXT));
139 sal_Int32 nCount = comphelper::string::getTokenCount(aTxt, ';');
140 for (sal_Int32 nIdx = 0; nIdx < nCount; nIdx++)
141 m_pOrderCell->InsertEntry(aTxt.getToken(nIdx, ';'));
143 for(long i=0;i < BROW_ROW_CNT;i++)
144 m_bVisibleRow.push_back(true);
146 m_bVisibleRow[BROW_FUNCTION_ROW] = false; // first hide
148 m_timerInvalidate.SetTimeout(200);
149 m_timerInvalidate.SetTimeoutHdl(LINK(this, OSelectionBrowseBox, OnInvalidateTimer));
150 m_timerInvalidate.Start();
153 OSelectionBrowseBox::~OSelectionBrowseBox()
155 disposeOnce();
158 void OSelectionBrowseBox::dispose()
160 m_pTextCell.disposeAndClear();
161 m_pVisibleCell.disposeAndClear();
162 m_pFieldCell.disposeAndClear();
163 m_pTableCell.disposeAndClear();
164 m_pOrderCell.disposeAndClear();
165 m_pFunctionCell.disposeAndClear();
166 ::svt::EditBrowseBox::dispose();
169 void OSelectionBrowseBox::initialize()
171 Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
172 if(xConnection.is())
174 const IParseContext& rContext = static_cast<OQueryController&>(getDesignView()->getController()).getParser().getContext();
175 const IParseContext::InternationalKeyCode eFunctions[] = {
176 IParseContext::InternationalKeyCode::Avg,IParseContext::InternationalKeyCode::Count,IParseContext::InternationalKeyCode::Max
177 ,IParseContext::InternationalKeyCode::Min,IParseContext::InternationalKeyCode::Sum
178 ,IParseContext::InternationalKeyCode::Every
179 ,IParseContext::InternationalKeyCode::Any
180 ,IParseContext::InternationalKeyCode::Some
181 ,IParseContext::InternationalKeyCode::StdDevPop
182 ,IParseContext::InternationalKeyCode::StdDevSamp
183 ,IParseContext::InternationalKeyCode::VarSamp
184 ,IParseContext::InternationalKeyCode::VarPop
185 ,IParseContext::InternationalKeyCode::Collect
186 ,IParseContext::InternationalKeyCode::Fusion
187 ,IParseContext::InternationalKeyCode::Intersection
190 OUString sGroup = m_aFunctionStrings.getToken(comphelper::string::getTokenCount(m_aFunctionStrings, ';') - 1, ';');
191 m_aFunctionStrings = m_aFunctionStrings.getToken(0, ';');
193 for (IParseContext::InternationalKeyCode eFunction : eFunctions)
195 m_aFunctionStrings += ";";
196 m_aFunctionStrings += OStringToOUString(rContext.getIntlKeywordAscii(eFunction),
197 RTL_TEXTENCODING_UTF8);
199 m_aFunctionStrings += ";";
200 m_aFunctionStrings += sGroup;
202 // Aggregate functions in general available only with Core SQL
203 // We slip in a few optionals one, too.
204 if ( lcl_SupportsCoreSQLGrammar(xConnection) )
206 sal_Int32 nCount = comphelper::string::getTokenCount(m_aFunctionStrings, ';');
207 for( sal_Int32 nIdx = 0; nIdx < nCount; nIdx++ )
208 m_pFunctionCell->InsertEntry(m_aFunctionStrings.getToken(nIdx, ';'));
210 else // else only COUNT(*) and COUNT("table".*)
212 m_pFunctionCell->InsertEntry(m_aFunctionStrings.getToken(0, ';'));
213 m_pFunctionCell->InsertEntry(m_aFunctionStrings.getToken(2, ';')); // 2 -> COUNT
217 Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
218 if ( xMetaData.is() )
220 m_bOrderByUnRelated = xMetaData->supportsOrderByUnrelated();
221 m_bGroupByUnRelated = xMetaData->supportsGroupByUnrelated();
224 catch(Exception&)
229 Init();
232 OQueryDesignView* OSelectionBrowseBox::getDesignView()
234 OSL_ENSURE(static_cast<const OQueryDesignView*>(GetParent()),"Parent isn't an OQueryDesignView!");
235 return static_cast<OQueryDesignView*>(GetParent());
238 OQueryDesignView* OSelectionBrowseBox::getDesignView() const
240 OSL_ENSURE(static_cast<const OQueryDesignView*>(GetParent()),"Parent isn't an OQueryDesignView!");
241 return static_cast<OQueryDesignView*>(GetParent());
244 namespace
246 class OSelectionBrwBoxHeader : public ::svt::EditBrowserHeader
248 VclPtr<OSelectionBrowseBox> m_pBrowseBox;
249 protected:
250 virtual void Select() override;
251 public:
252 explicit OSelectionBrwBoxHeader(OSelectionBrowseBox* pParent);
253 virtual ~OSelectionBrwBoxHeader() { disposeOnce(); }
254 virtual void dispose() override { m_pBrowseBox.clear(); ::svt::EditBrowserHeader::dispose(); }
256 OSelectionBrwBoxHeader::OSelectionBrwBoxHeader(OSelectionBrowseBox* pParent)
257 : ::svt::EditBrowserHeader(pParent,WB_BUTTONSTYLE|WB_DRAG)
258 ,m_pBrowseBox(pParent)
262 void OSelectionBrwBoxHeader::Select()
264 EditBrowserHeader::Select();
265 m_pBrowseBox->GrabFocus();
267 BrowserMode nMode = m_pBrowseBox->GetMode();
268 if ( 0 == m_pBrowseBox->GetSelectColumnCount() )
270 m_pBrowseBox->DeactivateCell();
271 // we are in the right mode if a row hase been selected row
272 if ( nMode & BrowserMode::HIDESELECT )
274 nMode &= ~BrowserMode::HIDESELECT;
275 nMode |= BrowserMode::MULTISELECTION;
276 m_pBrowseBox->SetMode( nMode );
279 m_pBrowseBox->SelectColumnId( GetCurItemId() );
280 m_pBrowseBox->DeactivateCell();
284 VclPtr<BrowserHeader> OSelectionBrowseBox::imp_CreateHeaderBar(BrowseBox* /*pParent*/)
286 return VclPtr<OSelectionBrwBoxHeader>::Create(this);
289 void OSelectionBrowseBox::ColumnMoved( sal_uInt16 nColId, bool _bCreateUndo )
291 EditBrowseBox::ColumnMoved( nColId );
292 // swap the two columns
293 sal_uInt16 nNewPos = GetColumnPos( nColId );
294 OTableFields& rFields = getFields();
295 if ( rFields.size() > sal_uInt16(nNewPos-1) )
297 sal_uInt16 nOldPos = 0;
298 OTableFields::const_iterator aEnd = rFields.end();
299 OTableFields::const_iterator aIter = rFields.begin();
300 for (; aIter != aEnd && ( (*aIter)->GetColumnId() != nColId ); ++aIter,++nOldPos)
303 OSL_ENSURE( (nNewPos-1) != nOldPos && nOldPos < rFields.size(),"Old and new position are equal!");
304 if ( aIter != aEnd )
306 OTableFieldDescRef pOldEntry = rFields[nOldPos];
307 rFields.erase(rFields.begin() + nOldPos);
308 rFields.insert(rFields.begin() + nNewPos - 1,pOldEntry);
310 // create the undo action
311 if ( !m_bInUndoMode && _bCreateUndo )
313 OTabFieldMovedUndoAct* pUndoAct = new OTabFieldMovedUndoAct(this);
314 pUndoAct->SetColumnPosition( nOldPos + 1);
315 pUndoAct->SetTabFieldDescr(pOldEntry);
317 getDesignView()->getController().addUndoActionAndInvalidate(pUndoAct);
321 else
322 OSL_FAIL("Invalid column id!");
325 void OSelectionBrowseBox::Init()
328 EditBrowseBox::Init();
330 // set the header bar
331 BrowserHeader* pNewHeaderBar = CreateHeaderBar(this);
332 pNewHeaderBar->SetMouseTransparent(false);
334 SetHeaderBar(pNewHeaderBar);
335 SetMode(m_nMode);
337 vcl::Font aFont( GetDataWindow().GetFont() );
338 aFont.SetWeight( WEIGHT_NORMAL );
339 GetDataWindow().SetFont( aFont );
341 Size aHeight;
342 const Control* pControls[] = { m_pTextCell,m_pVisibleCell,m_pTableCell,m_pFieldCell };
344 for (const Control* pControl : pControls)
346 const Size aTemp(pControl->GetOptimalSize());
347 if ( aTemp.Height() > aHeight.Height() )
348 aHeight.Height() = aTemp.Height();
350 SetDataRowHeight(aHeight.Height());
351 SetTitleLines(1);
352 // get number of visible rows
353 for(long i=0;i<BROW_ROW_CNT;i++)
355 if(m_bVisibleRow[i])
356 m_nVisibleCount++;
358 RowInserted(0, m_nVisibleCount, false);
361 Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
362 if(xConnection.is())
364 Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
365 m_nMaxColumns = xMetaData.is() ? xMetaData->getMaxColumnsInSelect() : 0;
368 else
369 m_nMaxColumns = 0;
371 catch(const SQLException&)
373 OSL_FAIL("Catched Exception when asking for database metadata options!");
374 m_nMaxColumns = 0;
378 void OSelectionBrowseBox::PreFill()
380 SetUpdateMode(false);
382 if (GetCurRow() != 0)
383 GoToRow(0);
385 static_cast< OQueryController& >( getDesignView()->getController() ).clearFields();
387 DeactivateCell();
389 RemoveColumns();
390 InsertHandleColumn( HANDLE_COLUMN_WITDH );
391 SetUpdateMode(true);
394 void OSelectionBrowseBox::ClearAll()
396 SetUpdateMode(false);
398 OTableFields::const_reverse_iterator aIter = getFields().rbegin();
399 for ( ;aIter != getFields().rend(); ++aIter )
401 if ( !(*aIter)->IsEmpty() )
403 RemoveField( (*aIter)->GetColumnId() );
404 aIter = getFields().rbegin();
407 m_nLastSortColumn = SORT_COLUMN_NONE;
408 SetUpdateMode(true);
411 void OSelectionBrowseBox::SetReadOnly(bool bRO)
413 if (bRO)
415 DeactivateCell();
416 m_nMode &= ~BrowserMode::HIDECURSOR;
417 SetMode(m_nMode);
419 else
421 m_nMode |= BrowserMode::HIDECURSOR;
422 SetMode(m_nMode);
423 ActivateCell();
427 CellController* OSelectionBrowseBox::GetController(long nRow, sal_uInt16 nColId)
429 if ( nColId > getFields().size() )
430 return nullptr;
431 OTableFieldDescRef pEntry = getFields()[nColId-1];
432 OSL_ENSURE(pEntry.is(), "OSelectionBrowseBox::GetController : keine FieldDescription !");
434 if (!pEntry.is())
435 return nullptr;
437 if (static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly())
438 return nullptr;
440 long nCellIndex = GetRealRow(nRow);
441 switch (nCellIndex)
443 case BROW_FIELD_ROW:
444 return new ComboBoxCellController(m_pFieldCell);
445 case BROW_TABLE_ROW:
446 return new ListBoxCellController(m_pTableCell);
447 case BROW_VIS_ROW:
448 return new CheckBoxCellController(m_pVisibleCell);
449 case BROW_ORDER_ROW:
450 return new ListBoxCellController(m_pOrderCell);
451 case BROW_FUNCTION_ROW:
452 return new ListBoxCellController(m_pFunctionCell);
453 default:
454 return new EditCellController(m_pTextCell);
458 void OSelectionBrowseBox::InitController(CellControllerRef& /*rController*/, long nRow, sal_uInt16 nColId)
460 OSL_ENSURE(nColId != BROWSER_INVALIDID,"An Invalid Id was set!");
461 if ( nColId == BROWSER_INVALIDID )
462 return;
463 sal_uInt16 nPos = GetColumnPos(nColId);
464 if ( nPos == 0 || nPos == BROWSER_INVALIDID || nPos > getFields().size() )
465 return;
466 OTableFieldDescRef pEntry = getFields()[nPos-1];
467 OSL_ENSURE(pEntry.is(), "OSelectionBrowseBox::InitController : keine FieldDescription !");
468 long nCellIndex = GetRealRow(nRow);
470 switch (nCellIndex)
472 case BROW_FIELD_ROW:
474 m_pFieldCell->Clear();
475 m_pFieldCell->SetText(OUString());
477 OUString aField(pEntry->GetField());
478 OUString aTable(pEntry->GetAlias());
480 getDesignView()->fillValidFields(aTable, m_pFieldCell);
482 // replace with alias.*
483 if (aField.trim() == "*")
485 aField = aTable + ".*";
487 m_pFieldCell->SetText(aField);
488 } break;
489 case BROW_TABLE_ROW:
491 m_pTableCell->Clear();
492 enableControl(pEntry,m_pTableCell);
493 if ( !pEntry->isCondition() )
495 OJoinTableView::OTableWindowMap& rTabWinList = getDesignView()->getTableView()->GetTabWinMap();
496 OJoinTableView::OTableWindowMap::const_iterator aIter = rTabWinList.begin();
497 OJoinTableView::OTableWindowMap::const_iterator aEnd = rTabWinList.end();
499 for(;aIter != aEnd;++aIter)
500 m_pTableCell->InsertEntry(static_cast<OQueryTableWindow*>(aIter->second.get())->GetAliasName());
502 m_pTableCell->InsertEntry(OUString(ModuleRes(STR_QUERY_NOTABLE)), 0);
503 if (!pEntry->GetAlias().isEmpty())
504 m_pTableCell->SelectEntry(pEntry->GetAlias());
505 else
506 m_pTableCell->SelectEntry(OUString(ModuleRes(STR_QUERY_NOTABLE)));
508 } break;
509 case BROW_VIS_ROW:
511 m_pVisibleCell->GetBox().Check(pEntry->IsVisible());
512 m_pVisibleCell->GetBox().SaveValue();
514 enableControl(pEntry,m_pTextCell);
516 if(!pEntry->IsVisible() && pEntry->GetOrderDir() != ORDER_NONE && !m_bOrderByUnRelated)
518 // a column has to visible in order to show up in ORDER BY
519 pEntry->SetVisible();
520 m_pVisibleCell->GetBox().Check(pEntry->IsVisible());
521 m_pVisibleCell->GetBox().SaveValue();
522 m_pVisibleCell->GetBox().Disable();
523 m_pVisibleCell->GetBox().EnableInput(false);
524 OUString aMessage(ModuleRes(STR_QRY_ORDERBY_UNRELATED));
525 OQueryDesignView* paDView = getDesignView();
526 ScopedVclPtrInstance<InfoBox>(paDView, aMessage)->Execute();
528 } break;
529 case BROW_ORDER_ROW:
530 m_pOrderCell->SelectEntryPos(
531 sal::static_int_cast< sal_uInt16 >(pEntry->GetOrderDir()));
532 enableControl(pEntry,m_pOrderCell);
533 break;
534 case BROW_COLUMNALIAS_ROW:
535 setTextCellContext(pEntry,pEntry->GetFieldAlias(),HID_QRYDGN_ROW_ALIAS);
536 break;
537 case BROW_FUNCTION_ROW:
538 setFunctionCell(pEntry);
539 break;
540 default:
542 sal_uInt16 nIdx = sal_uInt16(nCellIndex - BROW_CRIT1_ROW);
543 setTextCellContext(pEntry,pEntry->GetCriteria( nIdx ),HID_QRYDGN_ROW_CRIT);
546 Controller()->ClearModified();
549 void OSelectionBrowseBox::notifyTableFieldChanged(const OUString& _sOldAlias, const OUString& _sAlias, bool& _bListAction, sal_uInt16 _nColumnId)
551 appendUndoAction(_sOldAlias,_sAlias,BROW_TABLE_ROW,_bListAction);
552 if ( m_bVisibleRow[BROW_TABLE_ROW] )
553 RowModified(GetBrowseRow(BROW_TABLE_ROW), _nColumnId);
556 void OSelectionBrowseBox::notifyFunctionFieldChanged(const OUString& _sOldFunctionName, const OUString& _sFunctionName, bool& _bListAction, sal_uInt16 _nColumnId)
558 appendUndoAction(_sOldFunctionName,_sFunctionName,BROW_FUNCTION_ROW,_bListAction);
559 if ( !m_bVisibleRow[BROW_FUNCTION_ROW] )
560 SetRowVisible(BROW_FUNCTION_ROW, true);
561 RowModified(GetBrowseRow(BROW_FUNCTION_ROW), _nColumnId);
564 void OSelectionBrowseBox::clearEntryFunctionField(const OUString& _sFieldName,OTableFieldDescRef& _pEntry, bool& _bListAction,sal_uInt16 _nColumnId)
566 if ( isFieldNameAsterisk( _sFieldName ) && (!_pEntry->isNoneFunction() || _pEntry->IsGroupBy()) )
568 OUString sFunctionName;
569 GetFunctionName(SQL_TOKEN_COUNT,sFunctionName);
570 OUString sOldLocalizedFunctionName = _pEntry->GetFunction();
571 if ( sOldLocalizedFunctionName != sFunctionName || _pEntry->IsGroupBy() )
573 // append undo action for the function field
574 _pEntry->SetFunctionType(FKT_NONE);
575 _pEntry->SetFunction(OUString());
576 _pEntry->SetGroupBy(false);
577 notifyFunctionFieldChanged(sOldLocalizedFunctionName,_pEntry->GetFunction(),_bListAction,_nColumnId);
582 bool OSelectionBrowseBox::fillColumnRef(const OSQLParseNode* _pColumnRef, const Reference< XConnection >& _rxConnection, OTableFieldDescRef& _pEntry, bool& _bListAction )
584 OSL_ENSURE(_pColumnRef,"No valid parsenode!");
585 OUString sColumnName,sTableRange;
586 OSQLParseTreeIterator::getColumnRange(_pColumnRef,_rxConnection,sColumnName,sTableRange);
587 return fillColumnRef(sColumnName,sTableRange,_rxConnection->getMetaData(),_pEntry,_bListAction);
590 bool OSelectionBrowseBox::fillColumnRef(const OUString& _sColumnName, const OUString& _sTableRange, const Reference<XDatabaseMetaData>& _xMetaData, OTableFieldDescRef& _pEntry, bool& _bListAction)
592 bool bError = false;
593 ::comphelper::UStringMixEqual bCase(_xMetaData->supportsMixedCaseQuotedIdentifiers());
594 // check if the table name is the same
595 if ( !_sTableRange.isEmpty() && (bCase(_pEntry->GetTable(),_sTableRange) || bCase(_pEntry->GetAlias(),_sTableRange)) )
596 { // a table was already inserted and the tables contains that column name
598 if ( !_pEntry->GetTabWindow() )
599 { // fill tab window
600 OUString sOldAlias = _pEntry->GetAlias();
601 if ( !fillEntryTable(_pEntry,_pEntry->GetTable()) )
602 fillEntryTable(_pEntry,_pEntry->GetAlias()); // only when the first failed
603 if ( !bCase(sOldAlias,_pEntry->GetAlias()) )
604 notifyTableFieldChanged(sOldAlias,_pEntry->GetAlias(),_bListAction,GetCurColumnId());
607 // check if the table window
608 OQueryTableWindow* pEntryTab = static_cast<OQueryTableWindow*>(_pEntry->GetTabWindow());
609 if ( !pEntryTab ) // no table found with this name so we have to travel through all tables
611 sal_uInt16 nTabCount = 0;
612 if ( !static_cast<OQueryTableView*>(getDesignView()->getTableView())->FindTableFromField(_sColumnName,_pEntry,nTabCount) ) // error occurred: column not in table window
614 OUString sErrorMsg(ModuleRes(RID_STR_FIELD_DOESNT_EXIST));
615 sErrorMsg = sErrorMsg.replaceFirst("$name$",_sColumnName);
616 ScopedVclPtrInstance<OSQLErrorBox>(this, sErrorMsg)->Execute();
617 bError = true;
619 else
621 pEntryTab = static_cast<OQueryTableWindow*>(_pEntry->GetTabWindow());
622 notifyTableFieldChanged(OUString(),_pEntry->GetAlias(),_bListAction,GetCurColumnId());
625 if ( pEntryTab ) // here we got a valid table
626 _pEntry->SetField(_sColumnName);
628 return bError;
631 bool OSelectionBrowseBox::saveField(OUString& _sFieldName ,OTableFieldDescRef& _pEntry, bool& _bListAction)
633 bool bError = false;
635 OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
637 // first look if the name can be found in our tables
638 sal_uInt16 nTabCount = 0;
639 OUString sOldAlias = _pEntry->GetAlias();
640 if ( static_cast<OQueryTableView*>(getDesignView()->getTableView())->FindTableFromField(_sFieldName,_pEntry,nTabCount) )
642 // append undo action for the alias name
643 _pEntry->SetField(_sFieldName);
644 notifyTableFieldChanged(sOldAlias,_pEntry->GetAlias(),_bListAction,GetCurColumnId());
645 clearEntryFunctionField(_sFieldName,_pEntry,_bListAction,_pEntry->GetColumnId());
646 return bError;
649 Reference<XConnection> xConnection( rController.getConnection() );
650 Reference< XDatabaseMetaData > xMetaData;
651 if ( xConnection.is() )
652 xMetaData = xConnection->getMetaData();
653 OSL_ENSURE( xMetaData.is(), "OSelectionBrowseBox::saveField: invalid connection/meta data!" );
654 if ( !xMetaData.is() )
655 return true;
657 OUString sErrorMsg;
658 // second test if the name can be set as select columns in a pseudo statement
659 // we have to look which entries we should quote
661 const OUString sFieldAlias = _pEntry->GetFieldAlias();
662 ::connectivity::OSQLParser& rParser( rController.getParser() );
664 // automatically add parentheses around subqueries
665 OSQLParseNode *pParseNode = nullptr;
666 OUString devnull;
667 pParseNode = rParser.parseTree( devnull, _sFieldName, true );
668 if (pParseNode == nullptr)
669 pParseNode = rParser.parseTree( devnull, _sFieldName );
670 if (pParseNode != nullptr && SQL_ISRULE(pParseNode, select_statement))
671 _sFieldName = "(" + _sFieldName + ")";
674 OSQLParseNode* pParseNode = nullptr;
676 // 4 passes in trying to interprete the field name
677 // - don't quote the field name, parse internationally
678 // - don't quote the field name, parse en-US
679 // - quote the field name, parse internationally
680 // - quote the field name, parse en-US
681 size_t nPass = 4;
682 OUString sQuotedFullFieldName(::dbtools::quoteName( xMetaData->getIdentifierQuoteString(), _sFieldName ));
683 OUString sFullFieldName(_sFieldName);
685 if ( _pEntry->isAggreateFunction() )
687 OSL_ENSURE(!_pEntry->GetFunction().isEmpty(),"Functionname darf hier nicht leer sein! ;-(");
688 sQuotedFullFieldName = _pEntry->GetFunction() + "(" + sQuotedFullFieldName + ")";
689 sFullFieldName = _pEntry->GetFunction() + "(" + sFullFieldName + ")";
694 bool bQuote = ( nPass <= 2 );
695 bool bInternational = ( nPass % 2 ) == 0;
697 OUString sSql;
698 if ( bQuote )
699 sSql += sQuotedFullFieldName;
700 else
701 sSql += sFullFieldName;
703 sSql = "SELECT " + sSql;
704 if ( !sFieldAlias.isEmpty() )
705 { // always quote the alias name: there cannot be a function in it
706 sSql += " ";
707 sSql += ::dbtools::quoteName( xMetaData->getIdentifierQuoteString(), sFieldAlias );
709 sSql += " FROM x";
711 pParseNode = rParser.parseTree( sErrorMsg, sSql, bInternational );
713 while ( ( pParseNode == nullptr ) && ( --nPass > 0 ) );
716 if ( pParseNode == nullptr )
718 // something different which we have to check
719 OUString sErrorMessage( ModuleRes( STR_QRY_COLUMN_NOT_FOUND ) );
720 sErrorMessage = sErrorMessage.replaceFirst("$name$",_sFieldName);
721 ScopedVclPtrInstance<OSQLErrorBox>(this, sErrorMessage)->Execute();
723 return true;
726 // we got a valid select column
727 // find what type of column has be inserted
728 ::connectivity::OSQLParseNode* pSelection = pParseNode->getChild(2);
729 if ( SQL_ISRULE(pSelection,selection) ) // we found the asterisk
731 _pEntry->SetField(_sFieldName);
732 clearEntryFunctionField(_sFieldName,_pEntry,_bListAction,_pEntry->GetColumnId());
734 else // travel through the select column parse node
736 ::comphelper::UStringMixEqual bCase(xMetaData->supportsMixedCaseQuotedIdentifiers());
738 OTableFieldDescRef aSelEntry = _pEntry;
739 sal_uInt16 nColumnId = aSelEntry->GetColumnId();
741 sal_uInt32 nCount = pSelection->count();
742 for (sal_uInt32 i = 0; i < nCount; ++i)
744 if ( i > 0 ) // may we have to append more than one field
746 sal_uInt16 nColumnPostion;
747 aSelEntry = FindFirstFreeCol(nColumnPostion);
748 if ( !aSelEntry.is() )
750 AppendNewCol();
751 aSelEntry = FindFirstFreeCol(nColumnPostion);
753 ++nColumnPostion;
754 nColumnId = GetColumnId(nColumnPostion);
757 ::connectivity::OSQLParseNode* pChild = pSelection->getChild( i );
758 OSL_ENSURE(SQL_ISRULE(pChild,derived_column), "No derived column found!");
759 // get the column alias
760 OUString sColumnAlias = OSQLParseTreeIterator::getColumnAlias(pChild);
761 if ( !sColumnAlias.isEmpty() ) // we found an as clause
763 OUString aSelectionAlias = aSelEntry->GetFieldAlias();
764 aSelEntry->SetFieldAlias( sColumnAlias );
765 // append undo
766 appendUndoAction(aSelectionAlias,aSelEntry->GetFieldAlias(),BROW_COLUMNALIAS_ROW,_bListAction);
767 if ( m_bVisibleRow[BROW_COLUMNALIAS_ROW] )
768 RowModified(GetBrowseRow(BROW_COLUMNALIAS_ROW), nColumnId);
771 ::connectivity::OSQLParseNode* pColumnRef = pChild->getChild(0);
772 if (
773 pColumnRef->getKnownRuleID() != OSQLParseNode::subquery &&
774 pColumnRef->count() == 3 &&
775 SQL_ISPUNCTUATION(pColumnRef->getChild(0),"(") &&
776 SQL_ISPUNCTUATION(pColumnRef->getChild(2),")")
778 pColumnRef = pColumnRef->getChild(1);
780 if ( SQL_ISRULE(pColumnRef,column_ref) ) // we found a valid column name or more column names
782 // look if we can find the corresponding table
783 bError = fillColumnRef( pColumnRef, xConnection, aSelEntry, _bListAction );
785 // we found a simple column so we must clear the function fields but only when the column name is '*'
786 // and the function is different to count
787 clearEntryFunctionField(_sFieldName,aSelEntry,_bListAction,nColumnId);
789 // do we have a aggregate function and only a function?
790 else if ( SQL_ISRULE(pColumnRef,general_set_fct) )
792 OUString sLocalizedFunctionName;
793 if ( GetFunctionName(pColumnRef->getChild(0)->getTokenID(),sLocalizedFunctionName) )
795 OUString sOldLocalizedFunctionName = aSelEntry->GetFunction();
796 aSelEntry->SetFunction(sLocalizedFunctionName);
797 sal_uInt32 nFunCount = pColumnRef->count() - 1;
798 sal_Int32 nFunctionType = FKT_AGGREGATE;
799 bool bQuote = false;
800 // may be there exists only one parameter which is a column, fill all information into our fields
801 if ( nFunCount == 4 && SQL_ISRULE(pColumnRef->getChild(3),column_ref) )
802 bError = fillColumnRef( pColumnRef->getChild(3), xConnection, aSelEntry, _bListAction );
803 else if ( nFunCount == 3 ) // we have a COUNT(*) here, so take the first table
804 bError = fillColumnRef( "*", OUString(), xMetaData, aSelEntry, _bListAction );
805 else
807 nFunctionType |= FKT_NUMERIC;
808 bQuote = true;
809 aSelEntry->SetDataType(DataType::DOUBLE);
810 aSelEntry->SetFieldType(TAB_NORMAL_FIELD);
813 // now parse the parameters
814 OUString sParameters;
815 for(sal_uInt32 function = 2; function < nFunCount; ++function) // we only want to parse the parameters of the function
816 pColumnRef->getChild(function)->parseNodeToStr( sParameters, xConnection, &rParser.getContext(), true, bQuote );
818 aSelEntry->SetFunctionType(nFunctionType);
819 aSelEntry->SetField(sParameters);
820 if ( aSelEntry->IsGroupBy() )
822 sOldLocalizedFunctionName = m_aFunctionStrings.getToken(comphelper::string::getTokenCount(m_aFunctionStrings, ';')-1, ';');
823 aSelEntry->SetGroupBy(false);
826 // append undo action
827 notifyFunctionFieldChanged(sOldLocalizedFunctionName,sLocalizedFunctionName,_bListAction, nColumnId);
829 else
830 OSL_FAIL("Unsupported function inserted!");
833 else
835 // so we first clear the function field
836 clearEntryFunctionField(_sFieldName,aSelEntry,_bListAction,nColumnId);
837 OUString sFunction;
838 pColumnRef->parseNodeToStr( sFunction,
839 xConnection,
840 &rController.getParser().getContext(),
841 true); // quote is to true because we need quoted elements inside the function
843 getDesignView()->fillFunctionInfo(pColumnRef,sFunction,aSelEntry);
845 if( SQL_ISRULEOR3(pColumnRef, position_exp, extract_exp, fold) ||
846 SQL_ISRULEOR3(pColumnRef, char_substring_fct, length_exp, char_value_fct) )
847 // a calculation has been found ( can be calc and function )
849 // now parse the whole statement
850 sal_uInt32 nFunCount = pColumnRef->count();
851 OUString sParameters;
852 for(sal_uInt32 function = 0; function < nFunCount; ++function)
853 pColumnRef->getChild(function)->parseNodeToStr( sParameters, xConnection, &rParser.getContext(), true );
855 sOldAlias = aSelEntry->GetAlias();
856 sal_Int32 nNewFunctionType = aSelEntry->GetFunctionType() | FKT_NUMERIC | FKT_OTHER;
857 aSelEntry->SetFunctionType(nNewFunctionType);
858 aSelEntry->SetField(sParameters);
860 else
862 aSelEntry->SetFieldAlias(sColumnAlias);
863 if ( SQL_ISRULE(pColumnRef,set_fct_spec) )
864 aSelEntry->SetFunctionType(/*FKT_NUMERIC | */FKT_OTHER);
865 else
866 aSelEntry->SetFunctionType(FKT_NUMERIC | FKT_OTHER);
869 aSelEntry->SetAlias(OUString());
870 notifyTableFieldChanged(sOldAlias,aSelEntry->GetAlias(),_bListAction, nColumnId);
873 if ( i > 0 && !InsertField(aSelEntry,BROWSER_INVALIDID,true,false).is() ) // may we have to append more than one field
874 { // the field could not be inserted
875 OUString sErrorMessage( ModuleRes( RID_STR_FIELD_DOESNT_EXIST ) );
876 sErrorMessage = sErrorMessage.replaceFirst("$name$",aSelEntry->GetField());
877 ScopedVclPtrInstance<OSQLErrorBox>(this, sErrorMessage)->Execute();
878 bError = true;
882 delete pParseNode;
884 return bError;
887 bool OSelectionBrowseBox::SaveModified()
889 OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
890 OTableFieldDescRef pEntry = nullptr;
891 sal_uInt16 nCurrentColumnPos = GetColumnPos(GetCurColumnId());
892 if(getFields().size() > static_cast<sal_uInt16>(nCurrentColumnPos - 1))
893 pEntry = getEntry(nCurrentColumnPos - 1);
895 bool bWasEmpty = pEntry.is() && pEntry->IsEmpty();
896 bool bError = false;
897 bool bListAction = false;
899 if (pEntry.is() && Controller().Is() && Controller()->IsModified())
901 // for the Undo-action
902 OUString strOldCellContents,sNewValue;
903 long nRow = GetRealRow(GetCurRow());
904 bool bAppendRow = false;
905 switch (nRow)
907 case BROW_VIS_ROW:
909 bool bOldValue = m_pVisibleCell->GetBox().GetSavedValue() != TRISTATE_FALSE;
910 strOldCellContents = bOldValue ? OUStringLiteral("1") : OUStringLiteral("0");
911 sNewValue = !bOldValue ? OUStringLiteral("1") : OUStringLiteral("0");
913 if((m_bOrderByUnRelated || pEntry->GetOrderDir() == ORDER_NONE) &&
914 (m_bGroupByUnRelated || !pEntry->IsGroupBy()))
916 pEntry->SetVisible(m_pVisibleCell->GetBox().IsChecked());
918 else
920 pEntry->SetVisible();
921 m_pVisibleCell->GetBox().Check();
923 break;
925 case BROW_FIELD_ROW:
927 OUString aFieldName(m_pFieldCell->GetText());
930 if (aFieldName.isEmpty())
932 OTableFieldDescRef pNewEntry = new OTableFieldDesc();
933 pNewEntry->SetColumnId( pEntry->GetColumnId() );
934 ::std::replace(getFields().begin(),getFields().end(),pEntry,pNewEntry);
935 sal_uInt16 nCol = GetCurColumnId();
936 for (int i = 0; i < m_nVisibleCount; i++) // redraw column
937 RowModified(i,nCol);
939 else
941 strOldCellContents = pEntry->GetField();
942 bListAction = true;
943 if ( !m_bInUndoMode )
944 rController.GetUndoManager().EnterListAction(OUString(),OUString());
946 sal_Int32 nPos = m_pFieldCell->GetEntryPos(aFieldName);
947 OUString aAliasName = pEntry->GetAlias();
948 if ( nPos != COMBOBOX_ENTRY_NOTFOUND && aAliasName.isEmpty() && comphelper::string::getTokenCount(aFieldName, '.') > 1 )
949 { // special case, we have a table field so we must cut the table name
950 OUString sTableAlias = aFieldName.getToken(0,'.');
951 pEntry->SetAlias(sTableAlias);
952 OUString sColumnName = aFieldName.copy(sTableAlias.getLength()+1,aFieldName.getLength() - sTableAlias.getLength() -1);
953 Reference<XConnection> xConnection = rController.getConnection();
954 if ( !xConnection.is() )
955 return false;
956 bError = fillColumnRef( sColumnName, sTableAlias, xConnection->getMetaData(), pEntry, bListAction );
958 else
959 bError = true;
961 if ( bError )
962 bError = saveField(aFieldName,pEntry,bListAction);
965 catch(Exception&)
967 bError = true;
969 if ( bError )
971 sNewValue = aFieldName;
972 if ( !m_bInUndoMode )
973 static_cast<OQueryController&>(getDesignView()->getController()).GetUndoManager().LeaveListAction();
974 bListAction = false;
976 else
977 sNewValue = pEntry->GetField();
978 rController.InvalidateFeature( ID_BROWSER_QUERY_EXECUTE );
980 break;
982 case BROW_TABLE_ROW:
984 OUString aAliasName = m_pTableCell->GetSelectEntry();
985 strOldCellContents = pEntry->GetAlias();
986 if ( m_pTableCell->GetSelectEntryPos() != 0 )
988 pEntry->SetAlias(aAliasName);
989 // we have to set the table name as well as the table window
990 OJoinTableView::OTableWindowMap& rTabWinList = getDesignView()->getTableView()->GetTabWinMap();
991 OJoinTableView::OTableWindowMap::const_iterator aIter = rTabWinList.find(aAliasName);
992 if(aIter != rTabWinList.end())
994 OQueryTableWindow* pEntryTab = static_cast<OQueryTableWindow*>(aIter->second.get());
995 if (pEntryTab)
997 pEntry->SetTable(pEntryTab->GetTableName());
998 pEntry->SetTabWindow(pEntryTab);
1002 else
1004 pEntry->SetAlias(OUString());
1005 pEntry->SetTable(OUString());
1006 pEntry->SetTabWindow(nullptr);
1008 sNewValue = pEntry->GetAlias();
1010 } break;
1012 case BROW_ORDER_ROW:
1014 strOldCellContents = OUString::number((sal_uInt16)pEntry->GetOrderDir());
1015 sal_Int32 nIdx = m_pOrderCell->GetSelectEntryPos();
1016 if (nIdx == LISTBOX_ENTRY_NOTFOUND)
1017 nIdx = 0;
1018 pEntry->SetOrderDir(EOrderDir(nIdx));
1019 if(!m_bOrderByUnRelated)
1021 pEntry->SetVisible();
1022 m_pVisibleCell->GetBox().Check();
1023 RowModified(GetBrowseRow(BROW_VIS_ROW), GetCurColumnId());
1025 sNewValue = OUString::number((sal_uInt16)pEntry->GetOrderDir());
1026 } break;
1028 case BROW_COLUMNALIAS_ROW:
1029 strOldCellContents = pEntry->GetFieldAlias();
1030 pEntry->SetFieldAlias(m_pTextCell->GetText());
1031 sNewValue = pEntry->GetFieldAlias();
1032 break;
1033 case BROW_FUNCTION_ROW:
1035 strOldCellContents = pEntry->GetFunction();
1036 sal_Int32 nPos = m_pFunctionCell->GetSelectEntryPos();
1037 // these functions are only available in CORE
1038 OUString sFunctionName = m_pFunctionCell->GetEntry(nPos);
1039 OUString sGroupFunctionName = m_aFunctionStrings.getToken(comphelper::string::getTokenCount(m_aFunctionStrings, ';')-1, ';');
1040 bool bGroupBy = false;
1041 if ( sGroupFunctionName.equals(sFunctionName) ) // check if the function name is GROUP
1043 bGroupBy = true;
1045 if ( !m_bGroupByUnRelated && !pEntry->IsVisible() )
1047 // we have to change the visible flag, so we must append also an undo action
1048 pEntry->SetVisible();
1049 m_pVisibleCell->GetBox().Check();
1050 appendUndoAction("0","1",BROW_VIS_ROW,bListAction);
1051 RowModified(GetBrowseRow(BROW_VIS_ROW), GetCurColumnId());
1054 pEntry->SetFunction(OUString());
1055 pEntry->SetFunctionType(pEntry->GetFunctionType() & ~FKT_AGGREGATE );
1057 else if ( nPos ) // we found an aggregate function
1059 pEntry->SetFunctionType(pEntry->GetFunctionType() | FKT_AGGREGATE );
1060 pEntry->SetFunction(sFunctionName);
1062 else
1064 sFunctionName.clear();
1065 pEntry->SetFunction(OUString());
1066 pEntry->SetFunctionType(pEntry->GetFunctionType() & ~FKT_AGGREGATE );
1069 pEntry->SetGroupBy(bGroupBy);
1071 sNewValue = sFunctionName;
1073 break;
1074 default:
1076 Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
1077 if(!xConnection.is())
1078 break;
1080 sal_uInt16 nIdx = sal_uInt16(nRow - BROW_CRIT1_ROW);
1081 OUString aText = comphelper::string::stripStart(m_pTextCell->GetText(), ' ');
1083 OUString aCrit;
1084 if(!aText.isEmpty())
1086 OUString aErrorMsg;
1087 Reference<XPropertySet> xColumn;
1088 OSQLParseNode* pParseNode = getDesignView()->getPredicateTreeFromEntry(pEntry,aText,aErrorMsg,xColumn);
1090 if (pParseNode)
1092 pParseNode->parseNodeToPredicateStr(aCrit,
1093 xConnection,
1094 static_cast<OQueryController&>(getDesignView()->getController()).getNumberFormatter(),
1095 xColumn,
1096 pEntry->GetAlias(),
1097 getDesignView()->getLocale(),
1098 static_cast<sal_Char>(getDesignView()->getDecimalSeparator().toChar()),
1099 &(static_cast<OQueryController&>(getDesignView()->getController()).getParser().getContext()));
1100 delete pParseNode;
1102 else
1104 if(xColumn.is())
1106 sal_Int32 nType = 0;
1107 xColumn->getPropertyValue(PROPERTY_TYPE) >>= nType;
1108 switch(nType)
1110 case DataType::CHAR:
1111 case DataType::VARCHAR:
1112 case DataType::LONGVARCHAR:
1113 case DataType::CLOB:
1114 if(!aText.startsWith("'") || !aText.endsWith("'"))
1116 aText = aText.replaceAll("'", "''");
1117 aText = "'" + aText + "'";
1119 break;
1120 default:
1123 ::connectivity::OSQLParser& rParser = static_cast<OQueryController&>(getDesignView()->getController()).getParser();
1124 pParseNode = rParser.predicateTree(aErrorMsg,
1125 aText,
1126 static_cast<OQueryController&>(getDesignView()->getController()).getNumberFormatter(),
1127 xColumn);
1128 if (pParseNode)
1130 pParseNode->parseNodeToPredicateStr(aCrit,
1131 xConnection,
1132 static_cast<OQueryController&>(getDesignView()->getController()).getNumberFormatter(),
1133 xColumn,
1134 pEntry->GetAlias(),
1135 getDesignView()->getLocale(),
1136 static_cast<sal_Char>(getDesignView()->getDecimalSeparator().toChar()),
1137 &(static_cast<OQueryController&>(getDesignView()->getController()).getParser().getContext()));
1138 delete pParseNode;
1140 else
1142 if ( !m_bDisableErrorBox )
1144 ScopedVclPtrInstance<OSQLWarningBox>(this, aErrorMsg)->Execute();
1146 bError = true;
1149 else
1151 if ( !m_bDisableErrorBox )
1153 ScopedVclPtrInstance<OSQLWarningBox>(this, aErrorMsg)->Execute();
1155 bError = true;
1159 strOldCellContents = pEntry->GetCriteria(nIdx);
1160 pEntry->SetCriteria(nIdx, aCrit);
1161 sNewValue = pEntry->GetCriteria(nIdx);
1162 if(!aCrit.isEmpty() && nRow >= (GetRowCount()-1))
1163 bAppendRow = true;
1166 if(!bError && Controller())
1167 Controller()->ClearModified();
1169 RowModified(GetCurRow(), GetCurColumnId());
1171 if ( bAppendRow )
1173 RowInserted( GetRowCount()-1 );
1174 m_bVisibleRow.push_back(true);
1175 ++m_nVisibleCount;
1178 if(!bError)
1180 // and now the undo-action for the total
1181 appendUndoAction(strOldCellContents,sNewValue,nRow);
1186 // did I store data in a FieldDescription which was empty before and which is not empty anymore after the changes?
1187 if ( pEntry.is() && bWasEmpty && !pEntry->IsEmpty() && !bError )
1189 // Default to visible
1190 pEntry->SetVisible();
1191 appendUndoAction("0","1",BROW_VIS_ROW,bListAction);
1192 RowModified(BROW_VIS_ROW, GetCurColumnId());
1194 // if required add empty columns
1195 sal_uInt16 nDummy;
1196 CheckFreeColumns(nDummy);
1199 if ( bListAction && !m_bInUndoMode )
1200 static_cast<OQueryController&>(getDesignView()->getController()).GetUndoManager().LeaveListAction();
1202 return pEntry != nullptr && !bError;
1205 bool OSelectionBrowseBox::SeekRow(long nRow)
1207 m_nSeekRow = nRow;
1208 return nRow < m_nVisibleCount;
1211 void OSelectionBrowseBox::PaintCell(OutputDevice& rDev, const Rectangle& rRect, sal_uInt16 nColumnId) const
1213 rDev.SetClipRegion(vcl::Region(rRect));
1215 OTableFieldDescRef pEntry = nullptr;
1216 sal_uInt16 nPos = GetColumnPos(nColumnId);
1217 if(getFields().size() > sal_uInt16(nPos - 1))
1218 pEntry = getFields()[nPos - 1];
1220 if (!pEntry.is())
1221 return;
1223 long nRow = GetRealRow(m_nSeekRow);
1224 if (nRow == BROW_VIS_ROW)
1225 PaintTristate(rDev, rRect, pEntry->IsVisible() ? TRISTATE_TRUE : TRISTATE_FALSE);
1226 else
1227 rDev.DrawText(rRect, GetCellText(nRow, nColumnId),DrawTextFlags::VCenter);
1229 rDev.SetClipRegion( );
1232 void OSelectionBrowseBox::PaintStatusCell(OutputDevice& rDev, const Rectangle& rRect) const
1234 Rectangle aRect(rRect);
1235 aRect.TopLeft().Y() -= 2;
1236 OUString aLabel(ModuleRes(STR_QUERY_HANDLETEXT));
1238 // from BROW_CRIT2_ROW onwards all rows are shown "or"
1239 sal_Int32 nToken = (m_nSeekRow >= GetBrowseRow(BROW_CRIT2_ROW))
1240 ? BROW_CRIT2_ROW : GetRealRow(m_nSeekRow);
1241 rDev.DrawText(aRect, aLabel.getToken(nToken, ';'),DrawTextFlags::VCenter);
1244 void OSelectionBrowseBox::RemoveColumn(sal_uInt16 _nColumnId)
1246 OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
1248 sal_uInt16 nPos = GetColumnPos(_nColumnId);
1249 // the control should always have exactly one more column: the HandleColumn
1250 OSL_ENSURE((nPos == 0) || (nPos <= getFields().size()), "OSelectionBrowseBox::RemoveColumn : invalid parameter nColId");
1251 // ColId is synonymous to Position, and the condition should be valid
1253 sal_uInt16 nCurCol = GetCurColumnId();
1254 long nCurrentRow = GetCurRow();
1256 DeactivateCell();
1258 getFields().erase( getFields().begin() + (nPos - 1) );
1259 OTableFieldDescRef pEntry = new OTableFieldDesc();
1260 pEntry->SetColumnId(_nColumnId);
1261 getFields().push_back(pEntry);
1263 EditBrowseBox::RemoveColumn( _nColumnId );
1264 InsertDataColumn( _nColumnId , OUString(), DEFAULT_SIZE );
1266 // Neuzeichnen
1267 Rectangle aInvalidRect = GetInvalidRect( _nColumnId );
1268 Invalidate( aInvalidRect );
1270 ActivateCell( nCurrentRow, nCurCol );
1272 rController.setModified( true );
1274 invalidateUndoRedo();
1277 void OSelectionBrowseBox::RemoveField(sal_uInt16 nColumnId )
1279 OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
1281 sal_uInt16 nPos = GetColumnPos(nColumnId);
1282 OSL_ENSURE(getFields().size() > sal_uInt16(nPos-1),"ID is to great!");
1284 OTableFieldDescRef pDesc = getEntry((sal_uInt32)(nPos - 1)) ;
1285 pDesc->SetColWidth( (sal_uInt16)GetColumnWidth(nColumnId) ); // was not stored this before
1287 // trigger UndoAction
1288 if ( !m_bInUndoMode )
1290 OTabFieldDelUndoAct* pUndoAction = new OTabFieldDelUndoAct( this );
1291 pUndoAction->SetTabFieldDescr(pDesc);
1292 pUndoAction->SetColumnPosition(nPos);
1293 rController.addUndoActionAndInvalidate( pUndoAction );
1296 RemoveColumn(nColumnId);
1298 invalidateUndoRedo();
1301 void OSelectionBrowseBox::adjustSelectionMode( bool _bClickedOntoHeader, bool _bClickedOntoHandleCol )
1303 // if a Header has been selected it should be shown otherwise not
1304 if ( _bClickedOntoHeader )
1306 if (0 == GetSelectColumnCount() )
1307 // I am in the correct mode if a selected column exists
1308 if ( BrowserMode::HIDESELECT == ( m_nMode & BrowserMode::HIDESELECT ) )
1310 m_nMode &= ~BrowserMode::HIDESELECT;
1311 m_nMode |= BrowserMode::MULTISELECTION;
1312 SetMode( m_nMode );
1315 else if ( BrowserMode::HIDESELECT != ( m_nMode & BrowserMode::HIDESELECT ) )
1317 if ( GetSelectColumnCount() != 0 )
1318 SetNoSelection();
1320 if ( _bClickedOntoHandleCol )
1322 m_nMode |= BrowserMode::HIDESELECT;
1323 m_nMode &= ~BrowserMode::MULTISELECTION;
1324 SetMode( m_nMode );
1329 void OSelectionBrowseBox::MouseButtonDown(const BrowserMouseEvent& rEvt)
1331 if( rEvt.IsLeft() )
1333 bool bOnHandle = HANDLE_ID == rEvt.GetColumnId();
1334 bool bOnHeader = ( rEvt.GetRow() < 0 ) && !bOnHandle;
1335 adjustSelectionMode( bOnHeader, bOnHandle );
1337 EditBrowseBox::MouseButtonDown(rEvt);
1340 void OSelectionBrowseBox::MouseButtonUp(const BrowserMouseEvent& rEvt)
1342 EditBrowseBox::MouseButtonUp( rEvt );
1343 static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( ID_BROWSER_QUERY_EXECUTE );
1346 void OSelectionBrowseBox::KeyInput( const KeyEvent& rEvt )
1348 if (IsColumnSelected(GetCurColumnId()))
1350 if (rEvt.GetKeyCode().GetCode() == KEY_DELETE && // Delete rows
1351 !rEvt.GetKeyCode().IsShift() &&
1352 !rEvt.GetKeyCode().IsMod1())
1354 RemoveField(GetCurColumnId());
1355 return;
1358 EditBrowseBox::KeyInput(rEvt);
1361 sal_Int8 OSelectionBrowseBox::AcceptDrop( const BrowserAcceptDropEvent& rEvt )
1363 sal_Int8 nDropAction = DND_ACTION_NONE;
1364 if ( rEvt.GetRow() >= -1 )
1366 if ( IsEditing() )
1368 // allow the asterisk again
1369 m_bDisableErrorBox = true;
1370 SaveModified();
1371 m_bDisableErrorBox = false;
1372 DeactivateCell();
1374 // check if the format is already supported, if not deactivate the current cell and try again
1375 if ( OJoinExchObj::isFormatAvailable(GetDataFlavors()) )
1376 nDropAction = DND_ACTION_LINK;
1379 return nDropAction;
1382 sal_Int8 OSelectionBrowseBox::ExecuteDrop( const BrowserExecuteDropEvent& _rEvt )
1385 TransferableDataHelper aDropped(_rEvt.maDropEvent.Transferable);
1386 if (!OJoinExchObj::isFormatAvailable(aDropped.GetDataFlavorExVector()))
1388 OSL_FAIL("OSelectionBrowseBox::ExecuteDrop: this should never have passed AcceptDrop!");
1389 return DND_ACTION_NONE;
1392 rtl::Reference<OTableFieldDesc> aInfo;
1393 // insert the field at the selected position
1394 OJoinExchangeData jxdSource = OJoinExchObj::GetSourceDescription(_rEvt.maDropEvent.Transferable);
1395 InsertField(jxdSource);
1397 return DND_ACTION_LINK;
1400 OTableFieldDescRef OSelectionBrowseBox::AppendNewCol( sal_uInt16 nCnt)
1402 // one or more can be created, but the first one will is not returned
1403 sal_uInt32 nCount = getFields().size();
1404 for (sal_uInt16 i=0 ; i<nCnt ; i++)
1406 OTableFieldDescRef pEmptyEntry = new OTableFieldDesc();
1407 getFields().push_back(pEmptyEntry);
1408 sal_uInt16 nColumnId = sal::static_int_cast< sal_uInt16 >(getFields().size());
1409 pEmptyEntry->SetColumnId( nColumnId );
1411 InsertDataColumn( nColumnId , OUString(), DEFAULT_SIZE );
1414 return getFields()[nCount];
1417 void OSelectionBrowseBox::DeleteFields(const OUString& rAliasName)
1419 if (!getFields().empty())
1421 sal_uInt16 nColId = GetCurColumnId();
1422 sal_uInt32 nRow = GetCurRow();
1424 bool bWasEditing = IsEditing();
1425 if (bWasEditing)
1426 DeactivateCell();
1428 OTableFields::const_reverse_iterator aIter = getFields().rbegin();
1429 OTableFieldDescRef pEntry = nullptr;
1430 for(sal_uInt16 nPos=sal::static_int_cast< sal_uInt16 >(getFields().size());aIter != getFields().rend();++aIter,--nPos)
1432 pEntry = *aIter;
1433 if ( pEntry->GetAlias().equals( rAliasName ) )
1435 RemoveField( GetColumnId( nPos ) );
1436 break;
1440 if (bWasEditing)
1441 ActivateCell(nRow , nColId);
1445 void OSelectionBrowseBox::SetColWidth(sal_uInt16 nColId, long nNewWidth)
1447 bool bWasEditing = IsEditing();
1448 if (bWasEditing)
1449 DeactivateCell();
1451 // create the BaseClass
1452 SetColumnWidth(nColId, nNewWidth);
1454 // tell it the FieldDescription
1455 OTableFieldDescRef pEntry = getEntry(GetColumnPos(nColId) - 1);
1456 if (pEntry.is())
1457 pEntry->SetColWidth(sal_uInt16(GetColumnWidth(nColId)));
1459 if (bWasEditing)
1460 ActivateCell(GetCurRow(), GetCurColumnId());
1463 Rectangle OSelectionBrowseBox::GetInvalidRect( sal_uInt16 nColId )
1465 // The rectangle is the full output area of the window
1466 Rectangle aInvalidRect( Point(0,0), GetOutputSizePixel() );
1468 // now update the left side
1469 Rectangle aFieldRect(GetCellRect( 0, nColId )); // used instead of GetFieldRectPixel
1470 aInvalidRect.Left() = aFieldRect.Left();
1472 return aInvalidRect;
1475 void OSelectionBrowseBox::InsertColumn(const OTableFieldDescRef& pEntry, sal_uInt16& _nColumnPosition)
1477 // the control should have exactly one more column: the HandleColumn
1478 OSL_ENSURE(_nColumnPosition == BROWSER_INVALIDID || (_nColumnPosition <= (long)getFields().size()), "OSelectionBrowseBox::InsertColumn : invalid parameter nColId.");
1479 // -1 means at the end. Count means at the end, others denotes a correct position
1481 sal_uInt16 nCurCol = GetCurColumnId();
1482 long nCurrentRow = GetCurRow();
1484 DeactivateCell();
1486 // remember the column id of the current position
1487 sal_uInt16 nColumnId = GetColumnId(_nColumnPosition);
1488 // put at the end of the list if to small or to big,
1489 if ((_nColumnPosition == BROWSER_INVALIDID) || (_nColumnPosition >= getFields().size())) // append the field
1491 if (FindFirstFreeCol(_nColumnPosition) == nullptr) // no more free columns
1493 AppendNewCol();
1494 _nColumnPosition = sal::static_int_cast< sal_uInt16 >(
1495 getFields().size());
1497 else
1498 ++_nColumnPosition; // within the list
1499 nColumnId = GetColumnId(_nColumnPosition);
1500 pEntry->SetColumnId( nColumnId );
1501 getFields()[ _nColumnPosition - 1] = pEntry;
1504 // check if the column ids are identical, if not we have to move
1505 if ( pEntry->GetColumnId() != nColumnId )
1507 sal_uInt16 nOldPosition = GetColumnPos(pEntry->GetColumnId());
1508 OSL_ENSURE( nOldPosition != 0,"Old position was 0. Not possible!");
1509 SetColumnPos(pEntry->GetColumnId(),_nColumnPosition);
1510 // we have to delete an empty field for the fields list, because the columns must have equal length
1511 if ( nOldPosition > 0 && nOldPosition <= getFields().size() )
1512 getFields()[nOldPosition - 1] = pEntry;
1514 ColumnMoved(pEntry->GetColumnId(),false);
1517 if ( pEntry->GetFunctionType() & (FKT_AGGREGATE) )
1519 OUString sFunctionName = pEntry->GetFunction();
1520 if ( GetFunctionName(sal_uInt32(-1),sFunctionName) )
1521 pEntry->SetFunction(sFunctionName);
1524 nColumnId = pEntry->GetColumnId();
1526 SetColWidth(nColumnId,getDesignView()->getColWidth(GetColumnPos(nColumnId)-1));
1527 // redraw
1528 Rectangle aInvalidRect = GetInvalidRect( nColumnId );
1529 Invalidate( aInvalidRect );
1531 ActivateCell( nCurrentRow, nCurCol );
1532 static_cast<OQueryController&>(getDesignView()->getController()).setModified( true );
1534 invalidateUndoRedo();
1537 OTableFieldDescRef OSelectionBrowseBox::InsertField(const OJoinExchangeData& jxdSource)
1539 OQueryTableWindow* pSourceWin = static_cast<OQueryTableWindow*>(jxdSource.pListBox->GetTabWin());
1540 if (!pSourceWin)
1541 return nullptr;
1543 // name and position of the selected field
1544 OUString aFieldName = jxdSource.pListBox->GetEntryText(jxdSource.pEntry);
1545 sal_uInt32 nFieldIndex = jxdSource.pListBox->GetModel()->GetAbsPos(jxdSource.pEntry);
1546 OTableFieldInfo* pInf = static_cast<OTableFieldInfo*>(jxdSource.pEntry->GetUserData());
1548 // construct DragInfo, such that I use the other InsertField
1549 OTableFieldDescRef aInfo = new OTableFieldDesc(pSourceWin->GetTableName(),aFieldName);
1550 aInfo->SetTabWindow(pSourceWin);
1551 aInfo->SetFieldIndex(nFieldIndex);
1552 aInfo->SetFieldType(pInf->GetKeyType());
1553 aInfo->SetAlias(pSourceWin->GetAliasName());
1555 aInfo->SetDataType(pInf->GetDataType());
1556 aInfo->SetVisible();
1558 return InsertField(aInfo);
1561 OTableFieldDescRef OSelectionBrowseBox::InsertField(const OTableFieldDescRef& _rInfo, sal_uInt16 _nColumnPosition, bool bVis, bool bActivate)
1564 if(m_nMaxColumns && m_nMaxColumns <= FieldsCount())
1565 return nullptr;
1566 if (bActivate)
1567 SaveModified();
1569 // new column description
1570 OTableFieldDescRef pEntry = _rInfo;
1571 pEntry->SetVisible(bVis);
1573 // insert column
1574 InsertColumn( pEntry, _nColumnPosition );
1576 if ( !m_bInUndoMode )
1578 // trigger UndoAction
1579 OTabFieldCreateUndoAct* pUndoAction = new OTabFieldCreateUndoAct( this );
1580 pUndoAction->SetTabFieldDescr( pEntry );
1581 pUndoAction->SetColumnPosition(_nColumnPosition);
1582 getDesignView()->getController().addUndoActionAndInvalidate( pUndoAction );
1585 return pEntry;
1588 sal_uInt16 OSelectionBrowseBox::FieldsCount()
1590 OTableFields::const_iterator aIter = getFields().begin();
1591 OTableFields::const_iterator aEnd = getFields().end();
1592 sal_uInt16 nCount = 0;
1594 while (aIter != aEnd)
1596 if ((*aIter).is() && !(*aIter)->IsEmpty())
1597 ++nCount;
1598 ++aIter;
1601 return nCount;
1604 OTableFieldDescRef OSelectionBrowseBox::FindFirstFreeCol(sal_uInt16& _rColumnPosition )
1606 OTableFields::const_iterator aIter = getFields().begin();
1607 OTableFields::const_iterator aEnd = getFields().end();
1609 _rColumnPosition = BROWSER_INVALIDID;
1611 while ( aIter != aEnd )
1613 ++_rColumnPosition;
1614 OTableFieldDescRef pEntry = (*aIter);
1615 if ( pEntry.is() && pEntry->IsEmpty() )
1616 return pEntry;
1617 ++aIter;
1620 return nullptr;
1623 void OSelectionBrowseBox::CheckFreeColumns(sal_uInt16& _rColumnPosition)
1625 if (FindFirstFreeCol(_rColumnPosition) == nullptr)
1627 // it is full, append a Packen column
1628 AppendNewCol(DEFAULT_QUERY_COLS);
1629 OSL_VERIFY(FindFirstFreeCol(_rColumnPosition).is());
1633 void OSelectionBrowseBox::AddGroupBy( const OTableFieldDescRef& rInfo , sal_uInt32 /*_nCurrentPos*/)
1635 Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
1636 if(!xConnection.is())
1637 return;
1638 OSL_ENSURE(!rInfo->IsEmpty(),"AddGroupBy:: OTableFieldDescRef sollte nicht Empty sein!");
1639 OTableFieldDescRef pEntry;
1640 const Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
1641 const ::comphelper::UStringMixEqual bCase(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers());
1642 //sal_Bool bAppend = sal_False;
1644 OTableFields& rFields = getFields();
1645 OTableFields::const_iterator aIter = rFields.begin();
1646 OTableFields::const_iterator aEnd = rFields.end();
1647 for(;aIter != aEnd;++aIter)
1649 pEntry = *aIter;
1650 OSL_ENSURE(pEntry.is(),"OTableFieldDescRef was null!");
1652 const OUString aField = pEntry->GetField();
1653 const OUString aAlias = pEntry->GetAlias();
1655 if (bCase(aField,rInfo->GetField()) &&
1656 bCase(aAlias,rInfo->GetAlias()) &&
1657 pEntry->GetFunctionType() == rInfo->GetFunctionType() &&
1658 pEntry->GetFunction() == rInfo->GetFunction())
1660 if ( pEntry->isNumericOrAggreateFunction() && rInfo->IsGroupBy() )
1662 pEntry->SetGroupBy(false);
1663 aIter = rFields.end();
1664 break;
1666 else
1668 if ( !pEntry->IsGroupBy() && !pEntry->HasCriteria() ) // here we have a where condition which is no having clause
1670 pEntry->SetGroupBy(rInfo->IsGroupBy());
1671 if(!m_bGroupByUnRelated && pEntry->IsGroupBy())
1672 pEntry->SetVisible();
1673 break;
1680 if (aIter == rFields.end())
1682 OTableFieldDescRef pTmp = InsertField(rInfo, BROWSER_INVALIDID, false, false );
1683 if ( (pTmp->isNumericOrAggreateFunction() && rInfo->IsGroupBy()) ) // the GroupBy is inherited from rInfo
1684 pTmp->SetGroupBy(false);
1688 void OSelectionBrowseBox::DuplicateConditionLevel( const sal_uInt16 nLevel)
1690 const sal_uInt16 nNewLevel = nLevel +1;
1691 OTableFields& rFields = getFields();
1692 OTableFields::const_iterator aIter = rFields.begin();
1693 OTableFields::const_iterator aEnd = rFields.end();
1694 for(;aIter != aEnd;++aIter)
1696 OTableFieldDescRef pEntry = *aIter;
1698 OUString sValue = pEntry->GetCriteria(nLevel);
1699 if ( !sValue.isEmpty() )
1701 pEntry->SetCriteria( nNewLevel, sValue);
1702 if ( nNewLevel == (m_nVisibleCount-BROW_CRIT1_ROW-1) )
1704 RowInserted( GetRowCount()-1 );
1705 m_bVisibleRow.push_back(true);
1706 ++m_nVisibleCount;
1708 m_bVisibleRow[BROW_CRIT1_ROW + nNewLevel] = true;
1713 void OSelectionBrowseBox::AddCondition( const OTableFieldDescRef& rInfo, const OUString& rValue, const sal_uInt16 nLevel,bool _bAddOrOnOneLine )
1715 Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
1716 if(!xConnection.is())
1717 return;
1718 OSL_ENSURE(rInfo.is() && !rInfo->IsEmpty(),"AddCondition:: OTableFieldDescRef sollte nicht Empty sein!");
1720 OTableFieldDescRef pLastEntry;
1721 Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
1722 ::comphelper::UStringMixEqual bCase(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers());
1724 OTableFields& rFields = getFields();
1725 OTableFields::const_iterator aIter = rFields.begin();
1726 OTableFields::const_iterator aEnd = rFields.end();
1727 for(;aIter != aEnd;++aIter)
1729 OTableFieldDescRef pEntry = *aIter;
1730 const OUString aField = pEntry->GetField();
1731 const OUString aAlias = pEntry->GetAlias();
1733 if (bCase(aField,rInfo->GetField()) &&
1734 bCase(aAlias,rInfo->GetAlias()) &&
1735 pEntry->GetFunctionType() == rInfo->GetFunctionType() &&
1736 pEntry->GetFunction() == rInfo->GetFunction() &&
1737 pEntry->IsGroupBy() == rInfo->IsGroupBy() )
1739 if ( pEntry->isNumericOrAggreateFunction() && rInfo->IsGroupBy() )
1740 pEntry->SetGroupBy(false);
1741 else
1743 if(!m_bGroupByUnRelated && pEntry->IsGroupBy())
1744 pEntry->SetVisible();
1746 if (pEntry->GetCriteria(nLevel).isEmpty() )
1748 pEntry->SetCriteria( nLevel, rValue);
1749 if(nLevel == (m_nVisibleCount-BROW_CRIT1_ROW-1))
1751 RowInserted( GetRowCount()-1 );
1752 m_bVisibleRow.push_back(true);
1753 ++m_nVisibleCount;
1755 m_bVisibleRow[BROW_CRIT1_ROW + nLevel] = true;
1756 break;
1758 if ( _bAddOrOnOneLine )
1760 pLastEntry = pEntry;
1764 if ( pLastEntry.is() )
1766 OUString sCriteria = rValue;
1767 OUString sOldCriteria = pLastEntry->GetCriteria( nLevel );
1768 if ( !sOldCriteria.isEmpty() )
1770 sCriteria = "( ";
1771 sCriteria += sOldCriteria;
1772 sCriteria += " OR ";
1773 sCriteria += rValue;
1774 sCriteria += " )";
1776 pLastEntry->SetCriteria( nLevel, sCriteria);
1777 if(nLevel == (m_nVisibleCount-BROW_CRIT1_ROW-1))
1779 RowInserted( GetRowCount()-1 );
1780 m_bVisibleRow.push_back(true);
1781 ++m_nVisibleCount;
1783 m_bVisibleRow[BROW_CRIT1_ROW + nLevel] = true;
1785 else if (aIter == rFields.end())
1787 OTableFieldDescRef pTmp = InsertField(rInfo, BROWSER_INVALIDID, false, false );
1788 if ( pTmp->isNumericOrAggreateFunction() && rInfo->IsGroupBy() ) // the GroupBy was inherited from rInfo
1789 pTmp->SetGroupBy(false);
1790 if ( pTmp.is() )
1792 pTmp->SetCriteria( nLevel, rValue);
1793 if(nLevel == (m_nVisibleCount-BROW_CRIT1_ROW-1))
1795 RowInserted( GetRowCount()-1 );
1796 m_bVisibleRow.push_back(true);
1797 ++m_nVisibleCount;
1803 void OSelectionBrowseBox::AddOrder( const OTableFieldDescRef& rInfo, const EOrderDir eDir, sal_uInt32 _nCurrentPos)
1805 if (_nCurrentPos == 0)
1806 m_nLastSortColumn = SORT_COLUMN_NONE;
1808 Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
1809 if(!xConnection.is())
1810 return;
1811 OSL_ENSURE(!rInfo->IsEmpty(),"AddOrder:: OTableFieldDescRef should not be Empty!");
1812 OTableFieldDescRef pEntry;
1813 Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
1814 ::comphelper::UStringMixEqual bCase(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers());
1816 bool bAppend = false;
1817 OTableFields& rFields = getFields();
1818 OTableFields::const_iterator aIter = rFields.begin();
1819 OTableFields::const_iterator aEnd = rFields.end();
1820 for(;aIter != aEnd;++aIter)
1822 pEntry = *aIter;
1823 OUString aField = pEntry->GetField();
1824 OUString aAlias = pEntry->GetAlias();
1826 if (bCase(aField,rInfo->GetField()) &&
1827 bCase(aAlias,rInfo->GetAlias()))
1829 sal_uInt32 nPos = aIter - rFields.begin();
1830 bAppend = (m_nLastSortColumn != SORT_COLUMN_NONE) && (nPos <= m_nLastSortColumn);
1831 if ( bAppend )
1832 aIter = rFields.end();
1833 else
1835 if ( !m_bOrderByUnRelated )
1836 pEntry->SetVisible();
1837 pEntry->SetOrderDir( eDir );
1838 m_nLastSortColumn = nPos;
1840 break;
1844 if (aIter == rFields.end())
1846 OTableFieldDescRef pTmp = InsertField(rInfo, BROWSER_INVALIDID, false, false );
1847 if(pTmp.is())
1849 m_nLastSortColumn = pTmp->GetColumnId() - 1;
1850 if ( !m_bOrderByUnRelated && !bAppend )
1851 pTmp->SetVisible();
1852 pTmp->SetOrderDir( eDir );
1857 void OSelectionBrowseBox::ArrangeControls(sal_uInt16& nX, sal_uInt16 nY)
1859 EditBrowseBox::ArrangeControls(nX, nY);
1862 bool OSelectionBrowseBox::Save()
1864 bool bRet = true;
1865 if (IsModified())
1866 bRet = SaveModified();
1867 return bRet;
1870 void OSelectionBrowseBox::CellModified()
1872 long nRow = GetRealRow(GetCurRow());
1873 switch (nRow)
1875 case BROW_VIS_ROW:
1877 OTableFieldDescRef pEntry = getEntry(GetColumnPos(GetCurColumnId()) - 1);
1879 sal_Int32 nIdx = m_pOrderCell->GetSelectEntryPos();
1880 if(!m_bOrderByUnRelated && nIdx > 0 &&
1881 nIdx != LISTBOX_ENTRY_NOTFOUND &&
1882 !pEntry->IsEmpty() &&
1883 pEntry->GetOrderDir() != ORDER_NONE)
1885 m_pVisibleCell->GetBox().Check();
1886 pEntry->SetVisible();
1888 else
1889 pEntry->SetVisible(m_pVisibleCell->GetBox().IsChecked());
1891 break;
1893 static_cast<OQueryController&>(getDesignView()->getController()).setModified( true );
1896 void OSelectionBrowseBox::Fill()
1898 OSL_ENSURE(ColCount() >= 1, "OSelectionBrowseBox::Fill : please call only after inserting the handle column !");
1900 sal_uInt16 nColCount = ColCount() - 1;
1901 if (nColCount < DEFAULT_QUERY_COLS)
1902 AppendNewCol(DEFAULT_QUERY_COLS - nColCount);
1905 Size OSelectionBrowseBox::CalcOptimalSize( const Size& _rAvailable )
1907 Size aReturn( _rAvailable.Width(), GetTitleHeight() );
1909 aReturn.Height() += ( m_nVisibleCount ? m_nVisibleCount : 15 ) * GetDataRowHeight();
1910 aReturn.Height() += 40; // just some space
1912 return aReturn;
1915 void OSelectionBrowseBox::Command(const CommandEvent& rEvt)
1917 switch (rEvt.GetCommand())
1919 case CommandEventId::ContextMenu:
1921 Point aMenuPos( rEvt.GetMousePosPixel() );
1923 if (!rEvt.IsMouseEvent())
1925 if ( 1 == GetSelectColumnCount() )
1927 sal_uInt16 nSelId = GetColumnId(
1928 sal::static_int_cast< sal_uInt16 >(
1929 FirstSelectedColumn() ) );
1930 ::Rectangle aColRect( GetFieldRectPixel( 0, nSelId, false ) );
1932 aMenuPos = aColRect.TopCenter();
1934 else
1936 EditBrowseBox::Command(rEvt);
1937 return;
1941 sal_uInt16 nColId = GetColumnId(GetColumnAtXPosPixel( aMenuPos.X() ));
1942 long nRow = GetRowAtYPosPixel( aMenuPos.Y() );
1944 if (nRow < 0 && nColId > HANDLE_ID )
1946 if ( !IsColumnSelected( nColId ) )
1948 adjustSelectionMode( true /* clicked onto a header */ , false /* not onto the handle col */ );
1949 SelectColumnId( nColId );
1952 if (!static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly())
1954 PopupMenu aContextMenu( ModuleRes( RID_QUERYCOLPOPUPMENU ) );
1955 switch (aContextMenu.Execute(this, aMenuPos))
1957 case SID_DELETE:
1958 RemoveField(nColId);
1959 break;
1961 case ID_BROWSER_COLWIDTH:
1962 adjustBrowseBoxColumnWidth( this, nColId );
1963 break;
1967 else if(nRow >= 0 && nColId <= HANDLE_ID)
1969 if (!static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly())
1971 PopupMenu aContextMenu(ModuleRes(RID_QUERYFUNCTION_POPUPMENU));
1972 aContextMenu.CheckItem( ID_QUERY_FUNCTION, m_bVisibleRow[BROW_FUNCTION_ROW]);
1973 aContextMenu.CheckItem( ID_QUERY_TABLENAME, m_bVisibleRow[BROW_TABLE_ROW]);
1974 aContextMenu.CheckItem( ID_QUERY_ALIASNAME, m_bVisibleRow[BROW_COLUMNALIAS_ROW]);
1975 aContextMenu.CheckItem( ID_QUERY_DISTINCT, static_cast<OQueryController&>(getDesignView()->getController()).isDistinct());
1977 switch (aContextMenu.Execute(this, aMenuPos))
1979 case ID_QUERY_FUNCTION:
1980 SetRowVisible(BROW_FUNCTION_ROW, !IsRowVisible(BROW_FUNCTION_ROW));
1981 static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_FUNCTIONS );
1982 break;
1983 case ID_QUERY_TABLENAME:
1984 SetRowVisible(BROW_TABLE_ROW, !IsRowVisible(BROW_TABLE_ROW));
1985 static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_TABLES );
1986 break;
1987 case ID_QUERY_ALIASNAME:
1988 SetRowVisible(BROW_COLUMNALIAS_ROW, !IsRowVisible(BROW_COLUMNALIAS_ROW));
1989 static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_ALIASES );
1990 break;
1991 case ID_QUERY_DISTINCT:
1992 static_cast<OQueryController&>(getDesignView()->getController()).setDistinct(!static_cast<OQueryController&>(getDesignView()->getController()).isDistinct());
1993 static_cast<OQueryController&>(getDesignView()->getController()).setModified( true );
1994 static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_DISTINCT_VALUES );
1995 break;
1998 static_cast<OQueryController&>(getDesignView()->getController()).setModified( true );
2001 else
2003 EditBrowseBox::Command(rEvt);
2004 return;
2007 SAL_FALLTHROUGH;
2009 default:
2010 EditBrowseBox::Command(rEvt);
2014 bool OSelectionBrowseBox::IsRowVisible(sal_uInt16 _nWhich) const
2016 OSL_ENSURE(_nWhich<(m_bVisibleRow.size()), "OSelectionBrowseBox::IsRowVisible : invalid parameter !");
2017 return m_bVisibleRow[_nWhich];
2020 void OSelectionBrowseBox::SetRowVisible(sal_uInt16 _nWhich, bool _bVis)
2022 OSL_ENSURE(_nWhich<m_bVisibleRow.size(), "OSelectionBrowseBox::SetRowVisible : invalid parameter !");
2024 bool bWasEditing = IsEditing();
2025 if (bWasEditing)
2026 DeactivateCell();
2028 // do this before removing or inserting rows, as this triggers ActivateCell-calls, which rely on m_bVisibleRow
2029 m_bVisibleRow[_nWhich] = !m_bVisibleRow[_nWhich];
2031 long nId = GetBrowseRow(_nWhich);
2032 if (_bVis)
2034 RowInserted(nId);
2035 ++m_nVisibleCount;
2037 else
2039 RowRemoved(nId);
2040 --m_nVisibleCount;
2043 if (bWasEditing)
2044 ActivateCell();
2047 long OSelectionBrowseBox::GetBrowseRow(long nRowId) const
2049 sal_uInt16 nCount(0);
2050 for(long i = 0 ; i < nRowId ; ++i)
2052 if ( m_bVisibleRow[i] )
2053 ++nCount;
2055 return nCount;
2058 long OSelectionBrowseBox::GetRealRow(long nRowId) const
2060 long nErg=0,i;
2061 const long nCount = m_bVisibleRow.size();
2062 for(i=0;i < nCount; ++i)
2064 if(m_bVisibleRow[i])
2066 if(nErg++ == nRowId)
2067 break;
2070 OSL_ENSURE(nErg <= long(m_bVisibleRow.size()),"nErg kann nicht groesser als BROW_ROW_CNT sein!");
2071 return i;
2074 static const long nVisibleRowMask[] =
2076 0x0001,
2077 0x0002,
2078 0x0004,
2079 0x0008,
2080 0x0010,
2081 0x0020,
2082 0x0040,
2083 0x0080,
2084 0x0100,
2085 0x0200,
2086 0x0400,
2087 0x0800
2089 sal_Int32 OSelectionBrowseBox::GetNoneVisibleRows() const
2091 sal_Int32 nErg(0);
2092 // only the first 11 row are interesting
2093 sal_Int32 nSize = SAL_N_ELEMENTS(nVisibleRowMask);
2094 for(sal_Int32 i=0;i<nSize;i++)
2096 if(!m_bVisibleRow[i])
2097 nErg |= nVisibleRowMask[i];
2099 return nErg;
2102 void OSelectionBrowseBox::SetNoneVisbleRow(long nRows)
2104 // only the first 11 row are interesting
2105 sal_Int32 nSize = SAL_N_ELEMENTS(nVisibleRowMask);
2106 for(sal_Int32 i=0;i< nSize;i++)
2107 m_bVisibleRow[i] = !(nRows & nVisibleRowMask[i]);
2110 OUString OSelectionBrowseBox::GetCellText(long nRow, sal_uInt16 nColId) const
2113 sal_uInt16 nPos = GetColumnPos(nColId);
2115 OTableFieldDescRef pEntry = getFields()[nPos-1];
2116 OSL_ENSURE(pEntry != nullptr, "OSelectionBrowseBox::GetCellText : invalid column id, prepare for GPF ... ");
2117 if ( pEntry->IsEmpty() )
2118 return OUString();
2120 OUString aText;
2121 switch (nRow)
2123 case BROW_TABLE_ROW:
2124 aText = pEntry->GetAlias();
2125 break;
2126 case BROW_FIELD_ROW:
2128 OUString aField = pEntry->GetField();
2129 if (!aField.isEmpty() && aField[0] == '*') // * durch alias.* ersetzen
2131 aField = pEntry->GetAlias();
2132 if(!aField.isEmpty())
2133 aField += ".";
2134 aField += "*";
2136 aText = aField;
2137 } break;
2138 case BROW_ORDER_ROW:
2139 if (pEntry->GetOrderDir() != ORDER_NONE)
2140 aText = OUString(ModuleRes(STR_QUERY_SORTTEXT)).getToken(sal::static_int_cast< sal_uInt16 >(pEntry->GetOrderDir()), ';');
2141 break;
2142 case BROW_VIS_ROW:
2143 break;
2144 case BROW_COLUMNALIAS_ROW:
2145 aText = pEntry->GetFieldAlias();
2146 break;
2147 case BROW_FUNCTION_ROW:
2148 // we always show the group function at first
2149 if ( pEntry->IsGroupBy() )
2150 aText = m_aFunctionStrings.getToken(comphelper::string::getTokenCount(m_aFunctionStrings, ';')-1, ';');
2151 else if ( pEntry->isNumericOrAggreateFunction() )
2152 aText = pEntry->GetFunction();
2153 break;
2154 default:
2155 aText = pEntry->GetCriteria(sal_uInt16(nRow - BROW_CRIT1_ROW));
2157 return aText;
2160 bool OSelectionBrowseBox::GetFunctionName(sal_uInt32 _nFunctionTokenId, OUString& rFkt)
2162 bool bErg=true;
2163 switch(_nFunctionTokenId)
2165 case SQL_TOKEN_COUNT:
2166 rFkt = (m_pFunctionCell->GetEntryCount() < 3) ? m_pFunctionCell->GetEntry(1) : m_pFunctionCell->GetEntry(2);
2167 break;
2168 case SQL_TOKEN_AVG:
2169 rFkt = m_pFunctionCell->GetEntry(1);
2170 break;
2171 case SQL_TOKEN_MAX:
2172 rFkt = m_pFunctionCell->GetEntry(3);
2173 break;
2174 case SQL_TOKEN_MIN:
2175 rFkt = m_pFunctionCell->GetEntry(4);
2176 break;
2177 case SQL_TOKEN_SUM:
2178 rFkt = m_pFunctionCell->GetEntry(5);
2179 break;
2180 case SQL_TOKEN_EVERY:
2181 rFkt = m_pFunctionCell->GetEntry(6);
2182 break;
2183 case SQL_TOKEN_ANY:
2184 rFkt = m_pFunctionCell->GetEntry(7);
2185 break;
2186 case SQL_TOKEN_SOME:
2187 rFkt = m_pFunctionCell->GetEntry(8);
2188 break;
2189 case SQL_TOKEN_STDDEV_POP:
2190 rFkt = m_pFunctionCell->GetEntry(9);
2191 break;
2192 case SQL_TOKEN_STDDEV_SAMP:
2193 rFkt = m_pFunctionCell->GetEntry(10);
2194 break;
2195 case SQL_TOKEN_VAR_SAMP:
2196 rFkt = m_pFunctionCell->GetEntry(11);
2197 break;
2198 case SQL_TOKEN_VAR_POP:
2199 rFkt = m_pFunctionCell->GetEntry(12);
2200 break;
2201 case SQL_TOKEN_COLLECT:
2202 rFkt = m_pFunctionCell->GetEntry(13);
2203 break;
2204 case SQL_TOKEN_FUSION:
2205 rFkt = m_pFunctionCell->GetEntry(14);
2206 break;
2207 case SQL_TOKEN_INTERSECTION:
2208 rFkt = m_pFunctionCell->GetEntry(15);
2209 break;
2210 default:
2212 sal_Int32 nCount = comphelper::string::getTokenCount(m_aFunctionStrings, ';');
2213 sal_Int32 i;
2214 for( i = 0; i < nCount-1; i++ ) // grouping is not counted
2216 if(rFkt.equalsIgnoreAsciiCase(m_aFunctionStrings.getToken(i, ';')))
2218 rFkt = m_aFunctionStrings.getToken(i, ';');
2219 break;
2222 if(i == nCount-1)
2223 bErg = false;
2227 return bErg;
2230 OUString OSelectionBrowseBox::GetCellContents(sal_Int32 nCellIndex, sal_uInt16 nColId)
2232 if ( GetCurColumnId() == nColId && !m_bInUndoMode )
2233 SaveModified();
2235 sal_uInt16 nPos = GetColumnPos(nColId);
2236 OTableFieldDescRef pEntry = getFields()[nPos - 1];
2237 OSL_ENSURE(pEntry != nullptr, "OSelectionBrowseBox::GetCellContents : invalid column id, prepare for GPF ... ");
2239 switch (nCellIndex)
2241 case BROW_VIS_ROW :
2242 return pEntry->IsVisible() ? OUStringLiteral("1") : OUStringLiteral("0");
2243 case BROW_ORDER_ROW:
2245 sal_Int32 nIdx = m_pOrderCell->GetSelectEntryPos();
2246 if (nIdx == LISTBOX_ENTRY_NOTFOUND)
2247 nIdx = 0;
2248 return OUString::number(nIdx);
2250 default:
2251 return GetCellText(nCellIndex, nColId);
2255 void OSelectionBrowseBox::SetCellContents(sal_Int32 nRow, sal_uInt16 nColId, const OUString& strNewText)
2257 bool bWasEditing = IsEditing() && (GetCurColumnId() == nColId) && IsRowVisible(static_cast<sal_uInt16>(nRow)) && (GetCurRow() == static_cast<sal_uInt16>(GetBrowseRow(nRow)));
2258 if (bWasEditing)
2259 DeactivateCell();
2261 sal_uInt16 nPos = GetColumnPos(nColId);
2262 OTableFieldDescRef pEntry = getEntry(nPos - 1);
2263 OSL_ENSURE(pEntry != nullptr, "OSelectionBrowseBox::SetCellContents : invalid column id, prepare for GPF ... ");
2265 switch (nRow)
2267 case BROW_VIS_ROW:
2268 pEntry->SetVisible(strNewText == "1");
2269 break;
2270 case BROW_FIELD_ROW:
2271 pEntry->SetField(strNewText);
2272 break;
2273 case BROW_TABLE_ROW:
2274 pEntry->SetAlias(strNewText);
2275 break;
2276 case BROW_ORDER_ROW:
2278 sal_uInt16 nIdx = (sal_uInt16)strNewText.toInt32();
2279 pEntry->SetOrderDir(EOrderDir(nIdx));
2280 } break;
2281 case BROW_COLUMNALIAS_ROW:
2282 pEntry->SetFieldAlias(strNewText);
2283 break;
2284 case BROW_FUNCTION_ROW:
2286 OUString sGroupFunctionName = m_aFunctionStrings.getToken(comphelper::string::getTokenCount(m_aFunctionStrings, ';')-1, ';');
2287 pEntry->SetFunction(strNewText);
2288 // first reset this two member
2289 sal_Int32 nFunctionType = pEntry->GetFunctionType();
2290 nFunctionType &= ~FKT_AGGREGATE;
2291 pEntry->SetFunctionType(nFunctionType);
2292 if ( pEntry->IsGroupBy() && !sGroupFunctionName.equalsIgnoreAsciiCase(strNewText) )
2293 pEntry->SetGroupBy(false);
2295 if ( sGroupFunctionName.equalsIgnoreAsciiCase(strNewText) )
2296 pEntry->SetGroupBy(true);
2297 else if ( !strNewText.isEmpty() )
2299 nFunctionType |= FKT_AGGREGATE;
2300 pEntry->SetFunctionType(nFunctionType);
2302 } break;
2303 default:
2304 pEntry->SetCriteria(sal_uInt16(nRow - BROW_CRIT1_ROW), strNewText);
2307 long nCellIndex = GetRealRow(nRow);
2308 if(IsRowVisible(static_cast<sal_uInt16>(nRow)))
2309 RowModified(nCellIndex, nColId);
2311 // the appropriate field-description is now empty -> set Visible to sal_False (now it is consistent to normal empty rows)
2312 if (pEntry->IsEmpty())
2313 pEntry->SetVisible(false);
2315 if (bWasEditing)
2316 ActivateCell(nCellIndex, nColId);
2318 static_cast<OQueryController&>(getDesignView()->getController()).setModified( true );
2321 void OSelectionBrowseBox::ColumnResized(sal_uInt16 nColId)
2323 if (static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly())
2324 return;
2325 // The resizing of columns can't be suppressed (BrowseBox doesn't support that) so we have to do this
2326 // fake. It's not _that_ bad : the user may change column widths while in read-only mode to see all details
2327 // but the changes aren't permanent ...
2329 sal_uInt16 nPos = GetColumnPos(nColId);
2330 OSL_ENSURE(nPos <= getFields().size(),"ColumnResized:: nColId sollte nicht groesser als List::count sein!");
2331 OTableFieldDescRef pEntry = getEntry(nPos-1);
2332 OSL_ENSURE(pEntry.is(), "OSelectionBrowseBox::ColumnResized : keine FieldDescription !");
2333 static_cast<OQueryController&>(getDesignView()->getController()).setModified( true );
2334 EditBrowseBox::ColumnResized(nColId);
2336 if ( pEntry.is())
2338 if ( !m_bInUndoMode )
2340 // create the undo action
2341 OTabFieldSizedUndoAct* pUndo = new OTabFieldSizedUndoAct(this);
2342 pUndo->SetColumnPosition( nPos );
2343 pUndo->SetOriginalWidth(pEntry->GetColWidth());
2344 getDesignView()->getController().addUndoActionAndInvalidate(pUndo);
2346 pEntry->SetColWidth(sal_uInt16(GetColumnWidth(nColId)));
2350 sal_uInt32 OSelectionBrowseBox::GetTotalCellWidth(long nRowId, sal_uInt16 nColId)
2352 sal_uInt16 nPos = GetColumnPos(nColId);
2353 OSL_ENSURE((nPos == 0) || (nPos <= getFields().size()), "OSelectionBrowseBox::GetTotalCellWidth : invalid parameter nColId");
2355 OTableFieldDescRef pEntry = getFields()[nPos-1];
2356 OSL_ENSURE(pEntry.is(), "OSelectionBrowseBox::GetTotalCellWidth : invalid FieldDescription !");
2358 long nRow = GetRealRow(nRowId);
2359 OUString strText(GetCellText(nRow, nColId));
2360 return GetDataWindow().LogicToPixel(Size(GetDataWindow().GetTextWidth(strText),0)).Width();
2363 bool OSelectionBrowseBox::isCutAllowed()
2365 bool bCutAllowed = false;
2366 long nRow = GetRealRow(GetCurRow());
2367 switch (nRow)
2369 case BROW_VIS_ROW:
2370 case BROW_ORDER_ROW:
2371 case BROW_TABLE_ROW:
2372 case BROW_FUNCTION_ROW:
2373 break;
2374 case BROW_FIELD_ROW:
2375 bCutAllowed = !m_pFieldCell->GetSelected().isEmpty();
2376 break;
2377 default:
2378 bCutAllowed = !m_pTextCell->GetSelected().isEmpty();
2379 break;
2381 return bCutAllowed;
2384 void OSelectionBrowseBox::cut()
2386 long nRow = GetRealRow(GetCurRow());
2387 switch (nRow)
2389 case BROW_FIELD_ROW:
2390 m_pFieldCell->Cut();
2391 m_pFieldCell->SetModifyFlag();
2392 break;
2393 default:
2394 m_pTextCell->Cut();
2395 m_pTextCell->SetModifyFlag();
2397 SaveModified();
2398 RowModified(GetBrowseRow(nRow), GetCurColumnId());
2400 invalidateUndoRedo();
2403 void OSelectionBrowseBox::paste()
2405 long nRow = GetRealRow(GetCurRow());
2406 switch (nRow)
2408 case BROW_FIELD_ROW:
2409 m_pFieldCell->Paste();
2410 m_pFieldCell->SetModifyFlag();
2411 break;
2412 default:
2413 m_pTextCell->Paste();
2414 m_pTextCell->SetModifyFlag();
2416 RowModified(GetBrowseRow(nRow), GetCurColumnId());
2417 invalidateUndoRedo();
2420 bool OSelectionBrowseBox::isPasteAllowed()
2422 bool bPasteAllowed = true;
2423 long nRow = GetRealRow(GetCurRow());
2424 switch (nRow)
2426 case BROW_VIS_ROW:
2427 case BROW_ORDER_ROW:
2428 case BROW_TABLE_ROW:
2429 case BROW_FUNCTION_ROW:
2430 bPasteAllowed = false;
2431 break;
2433 return bPasteAllowed;
2436 bool OSelectionBrowseBox::isCopyAllowed()
2438 return isCutAllowed();
2441 void OSelectionBrowseBox::copy()
2443 long nRow = GetRealRow(GetCurRow());
2444 switch (nRow)
2446 case BROW_FIELD_ROW:
2447 m_pFieldCell->Copy();
2448 break;
2449 default:
2450 m_pTextCell->Copy();
2454 void OSelectionBrowseBox::appendUndoAction(const OUString& _rOldValue, const OUString& _rNewValue, sal_Int32 _nRow, bool& _bListAction)
2456 if ( !m_bInUndoMode && _rNewValue != _rOldValue )
2458 if ( !_bListAction )
2460 _bListAction = true;
2461 static_cast<OQueryController&>(getDesignView()->getController()).GetUndoManager().EnterListAction(OUString(),OUString());
2463 appendUndoAction(_rOldValue,_rNewValue,_nRow);
2467 void OSelectionBrowseBox::appendUndoAction(const OUString& _rOldValue,const OUString& _rNewValue,sal_Int32 _nRow)
2469 if ( !m_bInUndoMode && _rNewValue != _rOldValue )
2471 OTabFieldCellModifiedUndoAct* pUndoAct = new OTabFieldCellModifiedUndoAct(this);
2472 pUndoAct->SetCellIndex(_nRow);
2473 OSL_ENSURE(GetColumnPos(GetCurColumnId()) != BROWSER_INVALIDID,"Current position isn't valid!");
2474 pUndoAct->SetColumnPosition( GetColumnPos(GetCurColumnId()) );
2475 pUndoAct->SetCellContents(_rOldValue);
2476 getDesignView()->getController().addUndoActionAndInvalidate(pUndoAct);
2480 IMPL_LINK_NOARG_TYPED(OSelectionBrowseBox, OnInvalidateTimer, Timer *, void)
2482 static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature(SID_CUT);
2483 static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature(SID_COPY);
2484 static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature(SID_PASTE);
2485 if(!m_bStopTimer)
2486 m_timerInvalidate.Start();
2489 void OSelectionBrowseBox::stopTimer()
2491 m_bStopTimer = true;
2492 if (m_timerInvalidate.IsActive())
2493 m_timerInvalidate.Stop();
2496 void OSelectionBrowseBox::startTimer()
2498 m_bStopTimer = false;
2499 if (!m_timerInvalidate.IsActive())
2500 m_timerInvalidate.Start();
2503 OTableFields& OSelectionBrowseBox::getFields() const
2505 OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
2506 return rController.getTableFieldDesc();
2509 void OSelectionBrowseBox::enableControl(const OTableFieldDescRef& _rEntry,Window* _pControl)
2511 bool bEnable = !_rEntry->isCondition();
2512 _pControl->Enable(bEnable);
2513 _pControl->EnableInput(bEnable);
2516 void OSelectionBrowseBox::setTextCellContext(const OTableFieldDescRef& _rEntry,const OUString& _sText,const OString& _sHelpId)
2518 m_pTextCell->SetText(_sText);
2519 m_pTextCell->ClearModifyFlag();
2520 if (!m_pTextCell->HasFocus())
2521 m_pTextCell->GrabFocus();
2523 enableControl(_rEntry,m_pTextCell);
2525 if (m_pTextCell->GetHelpId() != _sHelpId)
2526 // as TextCell is used in various contexts I will delete the cached HelpText
2527 m_pTextCell->SetHelpText(OUString());
2528 m_pTextCell->SetHelpId(_sHelpId);
2531 void OSelectionBrowseBox::invalidateUndoRedo()
2533 OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
2534 rController.InvalidateFeature( ID_BROWSER_UNDO );
2535 rController.InvalidateFeature( ID_BROWSER_REDO );
2536 rController.InvalidateFeature( ID_BROWSER_QUERY_EXECUTE );
2539 OTableFieldDescRef OSelectionBrowseBox::getEntry(OTableFields::size_type _nPos)
2541 // we have to check if we need a new entry at this position
2542 OTableFields& aFields = getFields();
2543 OSL_ENSURE(aFields.size() > _nPos,"ColID is to great!");
2545 OTableFieldDescRef pEntry = aFields[_nPos];
2546 OSL_ENSURE(pEntry.is(),"Invalid entry!");
2547 if ( !pEntry.is() )
2549 pEntry = new OTableFieldDesc();
2550 pEntry->SetColumnId(
2551 GetColumnId(sal::static_int_cast< sal_uInt16 >(_nPos+1)));
2552 aFields[_nPos] = pEntry;
2554 return pEntry;
2557 void OSelectionBrowseBox::GetFocus()
2559 if(!IsEditing() && !m_bWasEditing)
2560 ActivateCell();
2561 EditBrowseBox::GetFocus();
2564 void OSelectionBrowseBox::DeactivateCell(bool _bUpdate)
2566 m_bWasEditing = true;
2567 EditBrowseBox::DeactivateCell(_bUpdate);
2568 m_bWasEditing = false;
2571 OUString OSelectionBrowseBox::GetRowDescription( sal_Int32 _nRow ) const
2573 OUString aLabel(ModuleRes(STR_QUERY_HANDLETEXT));
2575 // from BROW_CRIT2_ROW onwards all rows are shown as "or"
2576 sal_Int32 nToken = (_nRow >= GetBrowseRow(BROW_CRIT2_ROW))
2577 ? BROW_CRIT2_ROW : GetRealRow(_nRow);
2578 return aLabel.getToken(nToken, ';');
2581 OUString OSelectionBrowseBox::GetAccessibleObjectName( ::svt::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition) const
2583 OUString sRetText;
2584 switch( _eObjType )
2586 case ::svt::BBTYPE_ROWHEADERCELL:
2587 sRetText = GetRowDescription(_nPosition);
2588 break;
2589 default:
2590 sRetText = EditBrowseBox::GetAccessibleObjectDescription(_eObjType,_nPosition);
2592 return sRetText;
2595 bool OSelectionBrowseBox::fillEntryTable(OTableFieldDescRef& _pEntry,const OUString& _sTableName)
2597 bool bRet = false;
2598 OJoinTableView::OTableWindowMap& rTabWinList = getDesignView()->getTableView()->GetTabWinMap();
2599 OJoinTableView::OTableWindowMap::const_iterator aIter = rTabWinList.find(_sTableName);
2600 if(aIter != rTabWinList.end())
2602 OQueryTableWindow* pEntryTab = static_cast<OQueryTableWindow*>(aIter->second.get());
2603 if (pEntryTab)
2605 _pEntry->SetTable(pEntryTab->GetTableName());
2606 _pEntry->SetTabWindow(pEntryTab);
2607 bRet = true;
2610 return bRet;
2613 void OSelectionBrowseBox::setFunctionCell(OTableFieldDescRef& _pEntry)
2615 Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
2616 if ( xConnection.is() )
2618 // Aggregate functions in general only available with Core SQL
2619 if ( lcl_SupportsCoreSQLGrammar(xConnection) )
2621 // if we have an asterisk, no other function than count is allowed
2622 m_pFunctionCell->Clear();
2623 m_pFunctionCell->InsertEntry(m_aFunctionStrings.getToken(0, ';'));
2624 if ( isFieldNameAsterisk(_pEntry->GetField()) )
2625 m_pFunctionCell->InsertEntry(m_aFunctionStrings.getToken(2, ';')); // 2 -> COUNT
2626 else
2628 sal_Int32 nCount = comphelper::string::getTokenCount(m_aFunctionStrings, ';');
2629 if ( _pEntry->isNumeric() )
2630 --nCount;
2631 for( sal_Int32 nIdx = 1; nIdx < nCount; nIdx++ )
2632 m_pFunctionCell->InsertEntry(m_aFunctionStrings.getToken(nIdx, ';'));
2635 if ( _pEntry->IsGroupBy() )
2637 OSL_ENSURE(!_pEntry->isNumeric(),"Not allowed to combine group by and numeric values!");
2638 m_pFunctionCell->SelectEntry(m_pFunctionCell->GetEntry(m_pFunctionCell->GetEntryCount() - 1));
2640 else if ( m_pFunctionCell->GetEntryPos(OUString(_pEntry->GetFunction())) != COMBOBOX_ENTRY_NOTFOUND )
2641 m_pFunctionCell->SelectEntry(OUString(_pEntry->GetFunction()));
2642 else
2643 m_pFunctionCell->SelectEntryPos(0);
2645 enableControl(_pEntry,m_pFunctionCell);
2647 else
2649 // only COUNT(*) and COUNT("table".*) allowed
2650 bool bCountRemoved = !isFieldNameAsterisk(_pEntry->GetField());
2651 if ( bCountRemoved )
2652 m_pFunctionCell->RemoveEntry(1);
2654 if ( !bCountRemoved && m_pFunctionCell->GetEntryCount() < 2)
2655 m_pFunctionCell->InsertEntry(m_aFunctionStrings.getToken(2, ';')); // 2 -> COUNT
2657 if(m_pFunctionCell->GetEntryPos(OUString(_pEntry->GetFunction())) != COMBOBOX_ENTRY_NOTFOUND)
2658 m_pFunctionCell->SelectEntry(_pEntry->GetFunction());
2659 else
2660 m_pFunctionCell->SelectEntryPos(0);
2665 Reference< XAccessible > OSelectionBrowseBox::CreateAccessibleCell( sal_Int32 _nRow, sal_uInt16 _nColumnPos )
2667 OTableFieldDescRef pEntry = nullptr;
2668 if(getFields().size() > sal_uInt16(_nColumnPos - 1))
2669 pEntry = getFields()[_nColumnPos - 1];
2671 if ( _nRow == BROW_VIS_ROW && pEntry.is() )
2672 return EditBrowseBox::CreateAccessibleCheckBoxCell( _nRow, _nColumnPos,pEntry->IsVisible() ? TRISTATE_TRUE : TRISTATE_FALSE );
2674 return EditBrowseBox::CreateAccessibleCell( _nRow, _nColumnPos );
2677 bool OSelectionBrowseBox::HasFieldByAliasName(const OUString& rFieldName, OTableFieldDescRef& rInfo) const
2679 OTableFields& aFields = getFields();
2680 OTableFields::const_iterator aIter = aFields.begin();
2681 OTableFields::const_iterator aEnd = aFields.end();
2683 for(;aIter != aEnd;++aIter)
2685 if ( (*aIter)->GetFieldAlias() == rFieldName )
2687 *rInfo = *(*aIter);
2688 break;
2691 return aIter != aEnd;
2694 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */