Bump version to 5.0-14
[LibreOffice.git] / dbaccess / source / ui / querydesign / SelectionBrowseBox.cxx
blob4db452c88486dd7a27900cafd5260a774c463025
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 CHECKBOX_SIZE 10
59 #define HANDLE_ID 0
60 #define HANDLE_COLUMN_WITDH 70
61 #define SORT_COLUMN_NONE 0xFFFFFFFF
63 namespace
65 bool isFieldNameAsterisk(const OUString& _sFieldName )
67 bool bAsterisk = !(!_sFieldName.isEmpty() && _sFieldName.toChar() != '*');
68 if ( !bAsterisk )
70 OUString sName = _sFieldName;
71 sal_Int32 nTokenCount = comphelper::string::getTokenCount(sName, '.');
72 if ( (nTokenCount == 2 && sName.getToken(1,'.')[0] == '*' )
73 || (nTokenCount == 3 && sName.getToken(2,'.')[0] == '*' ) )
75 bAsterisk = true;
78 return bAsterisk;
80 bool lcl_SupportsCoreSQLGrammar(const Reference< XConnection>& _xConnection)
82 bool bSupportsCoreGrammar = false;
83 if ( _xConnection.is() )
85 try
87 Reference< XDatabaseMetaData > xMetaData = _xConnection->getMetaData();
88 bSupportsCoreGrammar = xMetaData.is() && xMetaData->supportsCoreSQLGrammar();
90 catch(Exception&)
94 return bSupportsCoreGrammar;
98 OSelectionBrowseBox::OSelectionBrowseBox( vcl::Window* pParent )
99 :EditBrowseBox( pParent,EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT, WB_3DLOOK, BrowserMode::COLUMNSELECTION | BrowserMode::KEEPHIGHLIGHT | BrowserMode::HIDESELECT |
100 BrowserMode::HIDECURSOR | BrowserMode::HLINES | BrowserMode::VLINES )
101 ,m_nSeekRow(0)
102 ,m_nMaxColumns(0)
103 ,m_aFunctionStrings(ModuleRes(STR_QUERY_FUNCTIONS))
104 ,m_nVisibleCount(0)
105 ,m_nLastSortColumn(SORT_COLUMN_NONE)
106 ,m_bOrderByUnRelated(true)
107 ,m_bGroupByUnRelated(true)
108 ,m_bStopTimer(false)
109 ,m_bWasEditing(false)
110 ,m_bDisableErrorBox(false)
111 ,m_bInUndoMode(false)
113 SetHelpId(HID_CTL_QRYDGNCRIT);
115 m_nMode = BrowserMode::COLUMNSELECTION | BrowserMode::HIDESELECT
116 | BrowserMode::KEEPHIGHLIGHT | BrowserMode::HIDECURSOR
117 | BrowserMode::HLINES | BrowserMode::VLINES
118 | BrowserMode::HEADERBAR_NEW ;
120 m_pTextCell = VclPtr<Edit>::Create(&GetDataWindow(), 0);
121 m_pVisibleCell = VclPtr<CheckBoxControl>::Create(&GetDataWindow());
122 m_pTableCell = VclPtr<ListBoxControl>::Create(&GetDataWindow()); m_pTableCell->SetDropDownLineCount( 20 );
123 m_pFieldCell = VclPtr<ComboBoxControl>::Create(&GetDataWindow()); m_pFieldCell->SetDropDownLineCount( 20 );
124 m_pOrderCell = VclPtr<ListBoxControl>::Create(&GetDataWindow());
125 m_pFunctionCell = VclPtr<ListBoxControl>::Create(&GetDataWindow()); m_pFunctionCell->SetDropDownLineCount( 20 );
127 m_pVisibleCell->SetHelpId(HID_QRYDGN_ROW_VISIBLE);
128 m_pTableCell->SetHelpId(HID_QRYDGN_ROW_TABLE);
129 m_pFieldCell->SetHelpId(HID_QRYDGN_ROW_FIELD);
130 m_pOrderCell->SetHelpId(HID_QRYDGN_ROW_ORDER);
131 m_pFunctionCell->SetHelpId(HID_QRYDGN_ROW_FUNCTION);
133 // switch off triState of ::com::sun::star::form::CheckBox
134 m_pVisibleCell->GetBox().EnableTriState( false );
136 vcl::Font aTitleFont = OutputDevice::GetDefaultFont( DefaultFontType::SANS_UNICODE,Window::GetSettings().GetLanguageTag().getLanguageType(),GetDefaultFontFlags::OnlyOne);
137 aTitleFont.SetSize(Size(0, 6));
138 SetTitleFont(aTitleFont);
140 OUString aTxt(ModuleRes(STR_QUERY_SORTTEXT));
141 sal_Int32 nCount = comphelper::string::getTokenCount(aTxt, ';');
142 for (sal_Int32 nIdx = 0; nIdx < nCount; nIdx++)
143 m_pOrderCell->InsertEntry(aTxt.getToken(nIdx, ';'));
145 for(long i=0;i < BROW_ROW_CNT;i++)
146 m_bVisibleRow.push_back(true);
148 m_bVisibleRow[BROW_FUNCTION_ROW] = false; // first hide
150 m_timerInvalidate.SetTimeout(200);
151 m_timerInvalidate.SetTimeoutHdl(LINK(this, OSelectionBrowseBox, OnInvalidateTimer));
152 m_timerInvalidate.Start();
155 OSelectionBrowseBox::~OSelectionBrowseBox()
157 disposeOnce();
160 void OSelectionBrowseBox::dispose()
162 m_pTextCell.disposeAndClear();
163 m_pVisibleCell.disposeAndClear();
164 m_pFieldCell.disposeAndClear();
165 m_pTableCell.disposeAndClear();
166 m_pOrderCell.disposeAndClear();
167 m_pFunctionCell.disposeAndClear();
168 ::svt::EditBrowseBox::dispose();
171 void OSelectionBrowseBox::initialize()
173 Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
174 if(xConnection.is())
176 const IParseContext& rContext = static_cast<OQueryController&>(getDesignView()->getController()).getParser().getContext();
177 IParseContext::InternationalKeyCode eFunctions[] = { IParseContext::KEY_AVG,IParseContext::KEY_COUNT,IParseContext::KEY_MAX
178 ,IParseContext::KEY_MIN,IParseContext::KEY_SUM
179 ,IParseContext::KEY_EVERY
180 ,IParseContext::KEY_ANY
181 ,IParseContext::KEY_SOME
182 ,IParseContext::KEY_STDDEV_POP
183 ,IParseContext::KEY_STDDEV_SAMP
184 ,IParseContext::KEY_VAR_SAMP
185 ,IParseContext::KEY_VAR_POP
186 ,IParseContext::KEY_COLLECT
187 ,IParseContext::KEY_FUSION
188 ,IParseContext::KEY_INTERSECTION
191 OUString sGroup = m_aFunctionStrings.getToken(comphelper::string::getTokenCount(m_aFunctionStrings, ';') - 1, ';');
192 m_aFunctionStrings = m_aFunctionStrings.getToken(0, ';');
194 for (size_t i = 0; i < sizeof (eFunctions) / sizeof (eFunctions[0]); ++i)
196 m_aFunctionStrings += ";";
197 m_aFunctionStrings += OStringToOUString(rContext.getIntlKeywordAscii(eFunctions[i]),
198 RTL_TEXTENCODING_UTF8);
200 m_aFunctionStrings += ";";
201 m_aFunctionStrings += sGroup;
203 // Aggregate functions in general available only with Core SQL
204 // We slip in a few optionals one, too.
205 if ( lcl_SupportsCoreSQLGrammar(xConnection) )
207 sal_Int32 nCount = comphelper::string::getTokenCount(m_aFunctionStrings, ';');
208 for( sal_Int32 nIdx = 0; nIdx < nCount; nIdx++ )
209 m_pFunctionCell->InsertEntry(m_aFunctionStrings.getToken(nIdx, ';'));
211 else // else only COUNT(*) and COUNT("table".*)
213 m_pFunctionCell->InsertEntry(m_aFunctionStrings.getToken(0, ';'));
214 m_pFunctionCell->InsertEntry(m_aFunctionStrings.getToken(2, ';')); // 2 -> COUNT
218 Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
219 if ( xMetaData.is() )
221 m_bOrderByUnRelated = xMetaData->supportsOrderByUnrelated();
222 m_bGroupByUnRelated = xMetaData->supportsGroupByUnrelated();
225 catch(Exception&)
230 Init();
233 OQueryDesignView* OSelectionBrowseBox::getDesignView()
235 OSL_ENSURE(static_cast<const OQueryDesignView*>(GetParent()),"Parent isn't an OQueryDesignView!");
236 return static_cast<OQueryDesignView*>(GetParent());
239 OQueryDesignView* OSelectionBrowseBox::getDesignView() const
241 OSL_ENSURE(static_cast<const OQueryDesignView*>(GetParent()),"Parent isn't an OQueryDesignView!");
242 return static_cast<OQueryDesignView*>(GetParent());
245 namespace
247 class OSelectionBrwBoxHeader : public ::svt::EditBrowserHeader
249 VclPtr<OSelectionBrowseBox> m_pBrowseBox;
250 protected:
251 virtual void Select() SAL_OVERRIDE;
252 public:
253 OSelectionBrwBoxHeader(OSelectionBrowseBox* pParent);
254 virtual ~OSelectionBrwBoxHeader() { disposeOnce(); }
255 virtual void dispose() SAL_OVERRIDE { m_pBrowseBox.clear(); ::svt::EditBrowserHeader::dispose(); }
257 OSelectionBrwBoxHeader::OSelectionBrwBoxHeader(OSelectionBrowseBox* pParent)
258 : ::svt::EditBrowserHeader(pParent,WB_BUTTONSTYLE|WB_DRAG)
259 ,m_pBrowseBox(pParent)
263 void OSelectionBrwBoxHeader::Select()
265 EditBrowserHeader::Select();
266 m_pBrowseBox->GrabFocus();
268 BrowserMode nMode = m_pBrowseBox->GetMode();
269 if ( 0 == m_pBrowseBox->GetSelectColumnCount() )
271 m_pBrowseBox->DeactivateCell();
272 // we are in the right mode if a row hase been selected row
273 if ( BrowserMode::HIDESELECT == ( nMode & BrowserMode::HIDESELECT ) )
275 nMode &= ~BrowserMode::HIDESELECT;
276 nMode |= BrowserMode::MULTISELECTION;
277 m_pBrowseBox->SetMode( nMode );
280 m_pBrowseBox->SelectColumnId( GetCurItemId() );
281 m_pBrowseBox->DeactivateCell();
285 VclPtr<BrowserHeader> OSelectionBrowseBox::imp_CreateHeaderBar(BrowseBox* /*pParent*/)
287 return VclPtr<OSelectionBrwBoxHeader>::Create(this);
290 void OSelectionBrowseBox::ColumnMoved( sal_uInt16 nColId, bool _bCreateUndo )
292 EditBrowseBox::ColumnMoved( nColId );
293 // swap the two columns
294 sal_uInt16 nNewPos = GetColumnPos( nColId );
295 OTableFields& rFields = getFields();
296 if ( rFields.size() > sal_uInt16(nNewPos-1) )
298 sal_uInt16 nOldPos = 0;
299 OTableFields::iterator aEnd = rFields.end();
300 OTableFields::iterator aIter = rFields.begin();
301 for (; aIter != aEnd && ( (*aIter)->GetColumnId() != nColId ); ++aIter,++nOldPos)
304 OSL_ENSURE( (nNewPos-1) != nOldPos && nOldPos < rFields.size(),"Old and new position are equal!");
305 if ( aIter != aEnd )
307 OTableFieldDescRef pOldEntry = rFields[nOldPos];
308 rFields.erase(rFields.begin() + nOldPos);
309 rFields.insert(rFields.begin() + nNewPos - 1,pOldEntry);
311 // create the undo action
312 if ( !m_bInUndoMode && _bCreateUndo )
314 OTabFieldMovedUndoAct* pUndoAct = new OTabFieldMovedUndoAct(this);
315 pUndoAct->SetColumnPosition( nOldPos + 1);
316 pUndoAct->SetTabFieldDescr(pOldEntry);
318 getDesignView()->getController().addUndoActionAndInvalidate(pUndoAct);
322 else
323 OSL_FAIL("Invalid column id!");
326 void OSelectionBrowseBox::Init()
329 EditBrowseBox::Init();
331 // set the header bar
332 BrowserHeader* pNewHeaderBar = CreateHeaderBar(this);
333 pNewHeaderBar->SetMouseTransparent(false);
335 SetHeaderBar(pNewHeaderBar);
336 SetMode(m_nMode);
338 vcl::Font aFont( GetDataWindow().GetFont() );
339 aFont.SetWeight( WEIGHT_NORMAL );
340 GetDataWindow().SetFont( aFont );
342 Size aHeight;
343 const Control* pControls[] = { m_pTextCell,m_pVisibleCell,m_pTableCell,m_pFieldCell };
345 for (sal_Size i = 0; i < sizeof (pControls) / sizeof (pControls[0]); ++i)
347 const Size aTemp(pControls[i]->GetOptimalSize());
348 if ( aTemp.Height() > aHeight.Height() )
349 aHeight.Height() = aTemp.Height();
351 SetDataRowHeight(aHeight.Height());
352 SetTitleLines(1);
353 // get number of visible rows
354 for(long i=0;i<BROW_ROW_CNT;i++)
356 if(m_bVisibleRow[i])
357 m_nVisibleCount++;
359 RowInserted(0, m_nVisibleCount, false);
362 Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
363 if(xConnection.is())
365 Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
366 m_nMaxColumns = xMetaData.is() ? xMetaData->getMaxColumnsInSelect() : 0;
369 else
370 m_nMaxColumns = 0;
372 catch(const SQLException&)
374 OSL_FAIL("Catched Exception when asking for database metadata options!");
375 m_nMaxColumns = 0;
379 void OSelectionBrowseBox::PreFill()
381 SetUpdateMode(false);
383 if (GetCurRow() != 0)
384 GoToRow(0);
386 static_cast< OQueryController& >( getDesignView()->getController() ).clearFields();
388 DeactivateCell();
390 RemoveColumns();
391 InsertHandleColumn( HANDLE_COLUMN_WITDH );
392 SetUpdateMode(true);
395 void OSelectionBrowseBox::ClearAll()
397 SetUpdateMode(false);
399 OTableFields::reverse_iterator aIter = getFields().rbegin();
400 for ( ;aIter != getFields().rend(); ++aIter )
402 if ( !(*aIter)->IsEmpty() )
404 RemoveField( (*aIter)->GetColumnId() );
405 aIter = getFields().rbegin();
408 m_nLastSortColumn = SORT_COLUMN_NONE;
409 SetUpdateMode(true);
412 void OSelectionBrowseBox::SetReadOnly(bool bRO)
414 if (bRO)
416 DeactivateCell();
417 m_nMode &= ~BrowserMode::HIDECURSOR;
418 SetMode(m_nMode);
420 else
422 m_nMode |= BrowserMode::HIDECURSOR;
423 SetMode(m_nMode);
424 ActivateCell();
428 CellController* OSelectionBrowseBox::GetController(long nRow, sal_uInt16 nColId)
430 if ( nColId > getFields().size() )
431 return NULL;
432 OTableFieldDescRef pEntry = getFields()[nColId-1];
433 OSL_ENSURE(pEntry.is(), "OSelectionBrowseBox::GetController : keine FieldDescription !");
435 if (!pEntry.is())
436 return NULL;
438 if (static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly())
439 return NULL;
441 long nCellIndex = GetRealRow(nRow);
442 switch (nCellIndex)
444 case BROW_FIELD_ROW:
445 return new ComboBoxCellController(m_pFieldCell);
446 case BROW_TABLE_ROW:
447 return new ListBoxCellController(m_pTableCell);
448 case BROW_VIS_ROW:
449 return new CheckBoxCellController(m_pVisibleCell);
450 case BROW_ORDER_ROW:
451 return new ListBoxCellController(m_pOrderCell);
452 case BROW_FUNCTION_ROW:
453 return new ListBoxCellController(m_pFunctionCell);
454 default:
455 return new EditCellController(m_pTextCell);
459 void OSelectionBrowseBox::InitController(CellControllerRef& /*rController*/, long nRow, sal_uInt16 nColId)
461 OSL_ENSURE(nColId != BROWSER_INVALIDID,"An Invalid Id was set!");
462 if ( nColId == BROWSER_INVALIDID )
463 return;
464 sal_uInt16 nPos = GetColumnPos(nColId);
465 if ( nPos == 0 || nPos == BROWSER_INVALIDID || nPos > getFields().size() )
466 return;
467 OTableFieldDescRef pEntry = getFields()[nPos-1];
468 OSL_ENSURE(pEntry.is(), "OSelectionBrowseBox::InitController : keine FieldDescription !");
469 long nCellIndex = GetRealRow(nRow);
471 switch (nCellIndex)
473 case BROW_FIELD_ROW:
475 m_pFieldCell->Clear();
476 m_pFieldCell->SetText(OUString());
478 OUString aField(pEntry->GetField());
479 OUString aTable(pEntry->GetAlias());
481 getDesignView()->fillValidFields(aTable, m_pFieldCell);
483 // replace with alias.*
484 if (aField.trim() == "*")
486 aField = aTable + ".*";
488 m_pFieldCell->SetText(aField);
489 } break;
490 case BROW_TABLE_ROW:
492 m_pTableCell->Clear();
493 enableControl(pEntry,m_pTableCell);
494 if ( !pEntry->isCondition() )
496 OJoinTableView::OTableWindowMap& rTabWinList = getDesignView()->getTableView()->GetTabWinMap();
497 OJoinTableView::OTableWindowMap::iterator aIter = rTabWinList.begin();
498 OJoinTableView::OTableWindowMap::iterator aEnd = rTabWinList.end();
500 for(;aIter != aEnd;++aIter)
501 m_pTableCell->InsertEntry(static_cast<OQueryTableWindow*>(aIter->second.get())->GetAliasName());
503 m_pTableCell->InsertEntry(OUString(ModuleRes(STR_QUERY_NOTABLE)), 0);
504 if (!pEntry->GetAlias().isEmpty())
505 m_pTableCell->SelectEntry(pEntry->GetAlias());
506 else
507 m_pTableCell->SelectEntry(OUString(ModuleRes(STR_QUERY_NOTABLE)));
509 } break;
510 case BROW_VIS_ROW:
512 m_pVisibleCell->GetBox().Check(pEntry->IsVisible());
513 m_pVisibleCell->GetBox().SaveValue();
515 enableControl(pEntry,m_pTextCell);
517 if(!pEntry->IsVisible() && pEntry->GetOrderDir() != ORDER_NONE && !m_bOrderByUnRelated)
519 // a column has to visible in order to show up in ORDER BY
520 pEntry->SetVisible(true);
521 m_pVisibleCell->GetBox().Check(pEntry->IsVisible());
522 m_pVisibleCell->GetBox().SaveValue();
523 m_pVisibleCell->GetBox().Disable();
524 m_pVisibleCell->GetBox().EnableInput(false);
525 OUString aMessage(ModuleRes(STR_QRY_ORDERBY_UNRELATED));
526 OQueryDesignView* paDView = getDesignView();
527 ScopedVclPtr<InfoBox>::Create(paDView, aMessage)->Execute();
529 } break;
530 case BROW_ORDER_ROW:
531 m_pOrderCell->SelectEntryPos(
532 sal::static_int_cast< sal_uInt16 >(pEntry->GetOrderDir()));
533 enableControl(pEntry,m_pOrderCell);
534 break;
535 case BROW_COLUMNALIAS_ROW:
536 setTextCellContext(pEntry,pEntry->GetFieldAlias(),HID_QRYDGN_ROW_ALIAS);
537 break;
538 case BROW_FUNCTION_ROW:
539 setFunctionCell(pEntry);
540 break;
541 default:
543 sal_uInt16 nIdx = sal_uInt16(nCellIndex - BROW_CRIT1_ROW);
544 setTextCellContext(pEntry,pEntry->GetCriteria( nIdx ),HID_QRYDGN_ROW_CRIT);
547 Controller()->ClearModified();
550 void OSelectionBrowseBox::notifyTableFieldChanged(const OUString& _sOldAlias, const OUString& _sAlias, bool& _bListAction, sal_uInt16 _nColumnId)
552 appendUndoAction(_sOldAlias,_sAlias,BROW_TABLE_ROW,_bListAction);
553 if ( m_bVisibleRow[BROW_TABLE_ROW] )
554 RowModified(GetBrowseRow(BROW_TABLE_ROW), _nColumnId);
557 void OSelectionBrowseBox::notifyFunctionFieldChanged(const OUString& _sOldFunctionName, const OUString& _sFunctionName, bool& _bListAction, sal_uInt16 _nColumnId)
559 appendUndoAction(_sOldFunctionName,_sFunctionName,BROW_FUNCTION_ROW,_bListAction);
560 if ( !m_bVisibleRow[BROW_FUNCTION_ROW] )
561 SetRowVisible(BROW_FUNCTION_ROW, true);
562 RowModified(GetBrowseRow(BROW_FUNCTION_ROW), _nColumnId);
565 void OSelectionBrowseBox::clearEntryFunctionField(const OUString& _sFieldName,OTableFieldDescRef& _pEntry, bool& _bListAction,sal_uInt16 _nColumnId)
567 if ( isFieldNameAsterisk( _sFieldName ) && (!_pEntry->isNoneFunction() || _pEntry->IsGroupBy()) )
569 OUString sFunctionName;
570 GetFunctionName(SQL_TOKEN_COUNT,sFunctionName);
571 OUString sOldLocalizedFunctionName = _pEntry->GetFunction();
572 if ( sOldLocalizedFunctionName != sFunctionName || _pEntry->IsGroupBy() )
574 // append undo action for the function field
575 _pEntry->SetFunctionType(FKT_NONE);
576 _pEntry->SetFunction(OUString());
577 _pEntry->SetGroupBy(false);
578 notifyFunctionFieldChanged(sOldLocalizedFunctionName,_pEntry->GetFunction(),_bListAction,_nColumnId);
583 bool OSelectionBrowseBox::fillColumnRef(const OSQLParseNode* _pColumnRef, const Reference< XConnection >& _rxConnection, OTableFieldDescRef& _pEntry, bool& _bListAction )
585 OSL_ENSURE(_pColumnRef,"No valid parsenode!");
586 OUString sColumnName,sTableRange;
587 OSQLParseTreeIterator::getColumnRange(_pColumnRef,_rxConnection,sColumnName,sTableRange);
588 return fillColumnRef(sColumnName,sTableRange,_rxConnection->getMetaData(),_pEntry,_bListAction);
591 bool OSelectionBrowseBox::fillColumnRef(const OUString& _sColumnName, const OUString& _sTableRange, const Reference<XDatabaseMetaData>& _xMetaData, OTableFieldDescRef& _pEntry, bool& _bListAction)
593 bool bError = false;
594 ::comphelper::UStringMixEqual bCase(_xMetaData->supportsMixedCaseQuotedIdentifiers());
595 // check if the table name is the same
596 if ( !_sTableRange.isEmpty() && (bCase(_pEntry->GetTable(),_sTableRange) || bCase(_pEntry->GetAlias(),_sTableRange)) )
597 { // a table was already inserted and the tables contains that column name
599 if ( !_pEntry->GetTabWindow() )
600 { // fill tab window
601 OUString sOldAlias = _pEntry->GetAlias();
602 if ( !fillEntryTable(_pEntry,_pEntry->GetTable()) )
603 fillEntryTable(_pEntry,_pEntry->GetAlias()); // only when the first failed
604 if ( !bCase(sOldAlias,_pEntry->GetAlias()) )
605 notifyTableFieldChanged(sOldAlias,_pEntry->GetAlias(),_bListAction,GetCurColumnId());
608 // check if the table window
609 OQueryTableWindow* pEntryTab = static_cast<OQueryTableWindow*>(_pEntry->GetTabWindow());
610 if ( !pEntryTab ) // no table found with this name so we have to travel through all tables
612 sal_uInt16 nTabCount = 0;
613 if ( !static_cast<OQueryTableView*>(getDesignView()->getTableView())->FindTableFromField(_sColumnName,_pEntry,nTabCount) ) // error occurred: column not in table window
615 OUString sErrorMsg(ModuleRes(RID_STR_FIELD_DOESNT_EXIST));
616 sErrorMsg = sErrorMsg.replaceFirst("$name$",_sColumnName);
617 ScopedVclPtr<OSQLErrorBox>::Create( this, sErrorMsg )->Execute();
618 bError = true;
620 else
622 pEntryTab = static_cast<OQueryTableWindow*>(_pEntry->GetTabWindow());
623 notifyTableFieldChanged(OUString(),_pEntry->GetAlias(),_bListAction,GetCurColumnId());
626 if ( pEntryTab ) // here we got a valid table
627 _pEntry->SetField(_sColumnName);
629 return bError;
632 bool OSelectionBrowseBox::saveField(OUString& _sFieldName ,OTableFieldDescRef& _pEntry, bool& _bListAction)
634 bool bError = false;
636 OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
638 // first look if the name can be found in our tables
639 sal_uInt16 nTabCount = 0;
640 OUString sOldAlias = _pEntry->GetAlias();
641 if ( static_cast<OQueryTableView*>(getDesignView()->getTableView())->FindTableFromField(_sFieldName,_pEntry,nTabCount) )
643 // append undo action for the alias name
644 _pEntry->SetField(_sFieldName);
645 notifyTableFieldChanged(sOldAlias,_pEntry->GetAlias(),_bListAction,GetCurColumnId());
646 clearEntryFunctionField(_sFieldName,_pEntry,_bListAction,_pEntry->GetColumnId());
647 return bError;
650 Reference<XConnection> xConnection( rController.getConnection() );
651 Reference< XDatabaseMetaData > xMetaData;
652 if ( xConnection.is() )
653 xMetaData = xConnection->getMetaData();
654 OSL_ENSURE( xMetaData.is(), "OSelectionBrowseBox::saveField: invalid connection/meta data!" );
655 if ( !xMetaData.is() )
656 return true;
658 OUString sErrorMsg;
659 // second test if the name can be set as select columns in a pseudo statement
660 // we have to look which entries we should quote
662 const OUString sFieldAlias = _pEntry->GetFieldAlias();
663 ::connectivity::OSQLParser& rParser( rController.getParser() );
665 // automatically add parentheses around subqueries
666 OSQLParseNode *pParseNode = NULL;
667 OUString devnull;
668 pParseNode = rParser.parseTree( devnull, _sFieldName, true );
669 if (pParseNode == NULL)
670 pParseNode = rParser.parseTree( devnull, _sFieldName, false );
671 if (pParseNode != NULL && SQL_ISRULE(pParseNode, select_statement))
672 _sFieldName = "(" + _sFieldName + ")";
675 OSQLParseNode* pParseNode = NULL;
677 // 4 passes in trying to interprete the field name
678 // - don't quote the field name, parse internationally
679 // - don't quote the field name, parse en-US
680 // - quote the field name, parse internationally
681 // - quote the field name, parse en-US
682 size_t nPass = 4;
683 OUString sQuotedFullFieldName(::dbtools::quoteName( xMetaData->getIdentifierQuoteString(), _sFieldName ));
684 OUString sFullFieldName(_sFieldName);
686 if ( _pEntry->isAggreateFunction() )
688 OSL_ENSURE(!_pEntry->GetFunction().isEmpty(),"Functionname darf hier nicht leer sein! ;-(");
689 sQuotedFullFieldName = _pEntry->GetFunction() + "(" + sQuotedFullFieldName + ")";
690 sFullFieldName = _pEntry->GetFunction() + "(" + sFullFieldName + ")";
695 bool bQuote = ( nPass <= 2 );
696 bool bInternational = ( nPass % 2 ) == 0;
698 OUString sSql;
699 if ( bQuote )
700 sSql += sQuotedFullFieldName;
701 else
702 sSql += sFullFieldName;
704 sSql = "SELECT " + sSql;
705 if ( !sFieldAlias.isEmpty() )
706 { // always quote the alias name: there cannot be a function in it
707 sSql += " ";
708 sSql += ::dbtools::quoteName( xMetaData->getIdentifierQuoteString(), sFieldAlias );
710 sSql += " FROM x";
712 pParseNode = rParser.parseTree( sErrorMsg, sSql, bInternational );
714 while ( ( pParseNode == NULL ) && ( --nPass > 0 ) );
717 if ( pParseNode == NULL )
719 // something different which we have to check
720 OUString sErrorMessage( ModuleRes( STR_QRY_COLUMN_NOT_FOUND ) );
721 sErrorMessage = sErrorMessage.replaceFirst("$name$",_sFieldName);
722 ScopedVclPtr<OSQLErrorBox>::Create( this, sErrorMessage )->Execute();
724 return true;
727 // we got a valid select column
728 // find what type of column has be inserted
729 ::connectivity::OSQLParseNode* pSelection = pParseNode->getChild(2);
730 if ( SQL_ISRULE(pSelection,selection) ) // we found the asterisk
732 _pEntry->SetField(_sFieldName);
733 clearEntryFunctionField(_sFieldName,_pEntry,_bListAction,_pEntry->GetColumnId());
735 else // travel through the select column parse node
737 ::comphelper::UStringMixEqual bCase(xMetaData->supportsMixedCaseQuotedIdentifiers());
739 OTableFieldDescRef aSelEntry = _pEntry;
740 sal_uInt16 nColumnId = aSelEntry->GetColumnId();
742 sal_uInt32 nCount = pSelection->count();
743 for (sal_uInt32 i = 0; i < nCount; ++i)
745 if ( i > 0 ) // may we have to append more than one field
747 sal_uInt16 nColumnPostion;
748 aSelEntry = FindFirstFreeCol(nColumnPostion);
749 if ( !aSelEntry.is() )
751 AppendNewCol(1);
752 aSelEntry = FindFirstFreeCol(nColumnPostion);
754 ++nColumnPostion;
755 nColumnId = GetColumnId(nColumnPostion);
758 ::connectivity::OSQLParseNode* pChild = pSelection->getChild( i );
759 OSL_ENSURE(SQL_ISRULE(pChild,derived_column), "No derived column found!");
760 // get the column alias
761 OUString sColumnAlias = OSQLParseTreeIterator::getColumnAlias(pChild);
762 if ( !sColumnAlias.isEmpty() ) // we found an as clause
764 OUString aSelectionAlias = aSelEntry->GetFieldAlias();
765 aSelEntry->SetFieldAlias( sColumnAlias );
766 // append undo
767 appendUndoAction(aSelectionAlias,aSelEntry->GetFieldAlias(),BROW_COLUMNALIAS_ROW,_bListAction);
768 if ( m_bVisibleRow[BROW_COLUMNALIAS_ROW] )
769 RowModified(GetBrowseRow(BROW_COLUMNALIAS_ROW), nColumnId);
772 ::connectivity::OSQLParseNode* pColumnRef = pChild->getChild(0);
773 if (
774 pColumnRef->getKnownRuleID() != OSQLParseNode::subquery &&
775 pColumnRef->count() == 3 &&
776 SQL_ISPUNCTUATION(pColumnRef->getChild(0),"(") &&
777 SQL_ISPUNCTUATION(pColumnRef->getChild(2),")")
779 pColumnRef = pColumnRef->getChild(1);
781 if ( SQL_ISRULE(pColumnRef,column_ref) ) // we found a valid column name or more column names
783 // look if we can find the corresponding table
784 bError = fillColumnRef( pColumnRef, xConnection, aSelEntry, _bListAction );
786 // we found a simple column so we must clear the function fields but only when the column name is '*'
787 // and the function is different to count
788 clearEntryFunctionField(_sFieldName,aSelEntry,_bListAction,nColumnId);
790 // do we have a aggregate function and only a function?
791 else if ( SQL_ISRULE(pColumnRef,general_set_fct) )
793 OUString sLocalizedFunctionName;
794 if ( GetFunctionName(pColumnRef->getChild(0)->getTokenID(),sLocalizedFunctionName) )
796 OUString sOldLocalizedFunctionName = aSelEntry->GetFunction();
797 aSelEntry->SetFunction(sLocalizedFunctionName);
798 sal_uInt32 nFunCount = pColumnRef->count() - 1;
799 sal_Int32 nFunctionType = FKT_AGGREGATE;
800 bool bQuote = false;
801 // may be there exists only one parameter which is a column, fill all information into our fields
802 if ( nFunCount == 4 && SQL_ISRULE(pColumnRef->getChild(3),column_ref) )
803 bError = fillColumnRef( pColumnRef->getChild(3), xConnection, aSelEntry, _bListAction );
804 else if ( nFunCount == 3 ) // we have a COUNT(*) here, so take the first table
805 bError = fillColumnRef( OUString("*"), OUString(), xMetaData, aSelEntry, _bListAction );
806 else
808 nFunctionType |= FKT_NUMERIC;
809 bQuote = true;
810 aSelEntry->SetDataType(DataType::DOUBLE);
811 aSelEntry->SetFieldType(TAB_NORMAL_FIELD);
814 // now parse the parameters
815 OUString sParameters;
816 for(sal_uInt32 function = 2; function < nFunCount; ++function) // we only want to parse the parameters of the function
817 pColumnRef->getChild(function)->parseNodeToStr( sParameters, xConnection, &rParser.getContext(), true, bQuote );
819 aSelEntry->SetFunctionType(nFunctionType);
820 aSelEntry->SetField(sParameters);
821 if ( aSelEntry->IsGroupBy() )
823 sOldLocalizedFunctionName = m_aFunctionStrings.getToken(comphelper::string::getTokenCount(m_aFunctionStrings, ';')-1, ';');
824 aSelEntry->SetGroupBy(false);
827 // append undo action
828 notifyFunctionFieldChanged(sOldLocalizedFunctionName,sLocalizedFunctionName,_bListAction, nColumnId);
830 else
831 OSL_FAIL("Unsupported function inserted!");
834 else
836 // so we first clear the function field
837 clearEntryFunctionField(_sFieldName,aSelEntry,_bListAction,nColumnId);
838 OUString sFunction;
839 pColumnRef->parseNodeToStr( sFunction,
840 xConnection,
841 &rController.getParser().getContext(),
842 true,
843 true); // quote is to true because we need quoted elements inside the function
845 getDesignView()->fillFunctionInfo(pColumnRef,sFunction,aSelEntry);
847 if( SQL_ISRULEOR3(pColumnRef, position_exp, extract_exp, fold) ||
848 SQL_ISRULEOR3(pColumnRef, char_substring_fct, length_exp, char_value_fct) )
849 // a calculation has been found ( can be calc and function )
851 // now parse the whole statement
852 sal_uInt32 nFunCount = pColumnRef->count();
853 OUString sParameters;
854 for(sal_uInt32 function = 0; function < nFunCount; ++function)
855 pColumnRef->getChild(function)->parseNodeToStr( sParameters, xConnection, &rParser.getContext(), true, true );
857 sOldAlias = aSelEntry->GetAlias();
858 sal_Int32 nNewFunctionType = aSelEntry->GetFunctionType() | FKT_NUMERIC | FKT_OTHER;
859 aSelEntry->SetFunctionType(nNewFunctionType);
860 aSelEntry->SetField(sParameters);
862 else
864 aSelEntry->SetFieldAlias(sColumnAlias);
865 if ( SQL_ISRULE(pColumnRef,set_fct_spec) )
866 aSelEntry->SetFunctionType(/*FKT_NUMERIC | */FKT_OTHER);
867 else
868 aSelEntry->SetFunctionType(FKT_NUMERIC | FKT_OTHER);
871 aSelEntry->SetAlias(OUString());
872 notifyTableFieldChanged(sOldAlias,aSelEntry->GetAlias(),_bListAction, nColumnId);
875 if ( i > 0 && !InsertField(aSelEntry,BROWSER_INVALIDID,true,false).is() ) // may we have to append more than one field
876 { // the field could not be inserted
877 OUString sErrorMessage( ModuleRes( RID_STR_FIELD_DOESNT_EXIST ) );
878 sErrorMessage = sErrorMessage.replaceFirst("$name$",aSelEntry->GetField());
879 ScopedVclPtr<OSQLErrorBox>::Create( this, sErrorMessage )->Execute();
880 bError = true;
884 delete pParseNode;
886 return bError;
889 bool OSelectionBrowseBox::SaveModified()
891 OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
892 OTableFieldDescRef pEntry = NULL;
893 sal_uInt16 nCurrentColumnPos = GetColumnPos(GetCurColumnId());
894 if(getFields().size() > static_cast<sal_uInt16>(nCurrentColumnPos - 1))
895 pEntry = getEntry(nCurrentColumnPos - 1);
897 bool bWasEmpty = pEntry.is() && pEntry->IsEmpty();
898 bool bError = false;
899 bool bListAction = false;
901 if (pEntry.is() && Controller().Is() && Controller()->IsModified())
903 // for the Undo-action
904 OUString strOldCellContents,sNewValue;
905 long nRow = GetRealRow(GetCurRow());
906 bool bAppendRow = false;
907 switch (nRow)
909 case BROW_VIS_ROW:
911 bool bOldValue = m_pVisibleCell->GetBox().GetSavedValue() != TRISTATE_FALSE;
912 strOldCellContents = bOldValue ? OUStringLiteral("1") : OUStringLiteral("0");
913 sNewValue = !bOldValue ? OUStringLiteral("1") : OUStringLiteral("0");
915 if((m_bOrderByUnRelated || pEntry->GetOrderDir() == ORDER_NONE) &&
916 (m_bGroupByUnRelated || !pEntry->IsGroupBy()))
918 pEntry->SetVisible(m_pVisibleCell->GetBox().IsChecked());
920 else
922 pEntry->SetVisible(true);
923 m_pVisibleCell->GetBox().Check();
925 break;
927 case BROW_FIELD_ROW:
929 OUString aFieldName(m_pFieldCell->GetText());
932 if (aFieldName.isEmpty())
934 OTableFieldDescRef pNewEntry = new OTableFieldDesc();
935 pNewEntry->SetColumnId( pEntry->GetColumnId() );
936 ::std::replace(getFields().begin(),getFields().end(),pEntry,pNewEntry);
937 sal_uInt16 nCol = GetCurColumnId();
938 for (int i = 0; i < m_nVisibleCount; i++) // redraw column
939 RowModified(i,nCol);
941 else
943 strOldCellContents = pEntry->GetField();
944 bListAction = true;
945 if ( !m_bInUndoMode )
946 rController.GetUndoManager().EnterListAction(OUString(),OUString());
948 sal_Int32 nPos = m_pFieldCell->GetEntryPos(aFieldName);
949 OUString aAliasName = pEntry->GetAlias();
950 if ( nPos != COMBOBOX_ENTRY_NOTFOUND && aAliasName.isEmpty() && comphelper::string::getTokenCount(aFieldName, '.') > 1 )
951 { // special case, we have a table field so we must cut the table name
952 OUString sTableAlias = aFieldName.getToken(0,'.');
953 pEntry->SetAlias(sTableAlias);
954 OUString sColumnName = aFieldName.copy(sTableAlias.getLength()+1,aFieldName.getLength() - sTableAlias.getLength() -1);
955 Reference<XConnection> xConnection = rController.getConnection();
956 if ( !xConnection.is() )
957 return false;
958 bError = fillColumnRef( sColumnName, sTableAlias, xConnection->getMetaData(), pEntry, bListAction );
960 else
961 bError = true;
963 if ( bError )
964 bError = saveField(aFieldName,pEntry,bListAction);
967 catch(Exception&)
969 bError = true;
971 if ( bError )
973 sNewValue = aFieldName;
974 if ( !m_bInUndoMode )
975 static_cast<OQueryController&>(getDesignView()->getController()).GetUndoManager().LeaveListAction();
976 bListAction = false;
978 else
979 sNewValue = pEntry->GetField();
980 rController.InvalidateFeature( ID_BROWSER_QUERY_EXECUTE );
982 break;
984 case BROW_TABLE_ROW:
986 OUString aAliasName = m_pTableCell->GetSelectEntry();
987 strOldCellContents = pEntry->GetAlias();
988 if ( m_pTableCell->GetSelectEntryPos() != 0 )
990 pEntry->SetAlias(aAliasName);
991 // we have to set the table name as well as the table window
992 OJoinTableView::OTableWindowMap& rTabWinList = getDesignView()->getTableView()->GetTabWinMap();
993 OJoinTableView::OTableWindowMap::iterator aIter = rTabWinList.find(aAliasName);
994 if(aIter != rTabWinList.end())
996 OQueryTableWindow* pEntryTab = static_cast<OQueryTableWindow*>(aIter->second.get());
997 if (pEntryTab)
999 pEntry->SetTable(pEntryTab->GetTableName());
1000 pEntry->SetTabWindow(pEntryTab);
1004 else
1006 pEntry->SetAlias(OUString());
1007 pEntry->SetTable(OUString());
1008 pEntry->SetTabWindow(NULL);
1010 sNewValue = pEntry->GetAlias();
1012 } break;
1014 case BROW_ORDER_ROW:
1016 strOldCellContents = OUString::number((sal_uInt16)pEntry->GetOrderDir());
1017 sal_Int32 nIdx = m_pOrderCell->GetSelectEntryPos();
1018 if (nIdx == LISTBOX_ENTRY_NOTFOUND)
1019 nIdx = 0;
1020 pEntry->SetOrderDir(EOrderDir(nIdx));
1021 if(!m_bOrderByUnRelated)
1023 pEntry->SetVisible(true);
1024 m_pVisibleCell->GetBox().Check();
1025 RowModified(GetBrowseRow(BROW_VIS_ROW), GetCurColumnId());
1027 sNewValue = OUString::number((sal_uInt16)pEntry->GetOrderDir());
1028 } break;
1030 case BROW_COLUMNALIAS_ROW:
1031 strOldCellContents = pEntry->GetFieldAlias();
1032 pEntry->SetFieldAlias(m_pTextCell->GetText());
1033 sNewValue = pEntry->GetFieldAlias();
1034 break;
1035 case BROW_FUNCTION_ROW:
1037 strOldCellContents = pEntry->GetFunction();
1038 sal_Int32 nPos = m_pFunctionCell->GetSelectEntryPos();
1039 // these functions are only available in CORE
1040 OUString sFunctionName = m_pFunctionCell->GetEntry(nPos);
1041 OUString sGroupFunctionName = m_aFunctionStrings.getToken(comphelper::string::getTokenCount(m_aFunctionStrings, ';')-1, ';');
1042 bool bGroupBy = false;
1043 if ( sGroupFunctionName.equals(sFunctionName) ) // check if the function name is GROUP
1045 bGroupBy = true;
1047 if ( !m_bGroupByUnRelated && !pEntry->IsVisible() )
1049 // we have to change the visblie flag, so we must append also an undo action
1050 pEntry->SetVisible(true);
1051 m_pVisibleCell->GetBox().Check();
1052 appendUndoAction("0","1",BROW_VIS_ROW,bListAction);
1053 RowModified(GetBrowseRow(BROW_VIS_ROW), GetCurColumnId());
1056 pEntry->SetFunction(OUString());
1057 pEntry->SetFunctionType(pEntry->GetFunctionType() & ~FKT_AGGREGATE );
1059 else if ( nPos ) // we found an aggregate function
1061 pEntry->SetFunctionType(pEntry->GetFunctionType() | FKT_AGGREGATE );
1062 pEntry->SetFunction(sFunctionName);
1064 else
1066 sFunctionName.clear();
1067 pEntry->SetFunction(OUString());
1068 pEntry->SetFunctionType(pEntry->GetFunctionType() & ~FKT_AGGREGATE );
1071 pEntry->SetGroupBy(bGroupBy);
1073 sNewValue = sFunctionName;
1075 break;
1076 default:
1078 Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
1079 if(!xConnection.is())
1080 break;
1082 sal_uInt16 nIdx = sal_uInt16(nRow - BROW_CRIT1_ROW);
1083 OUString aText = comphelper::string::stripStart(m_pTextCell->GetText(), ' ');
1085 OUString aCrit;
1086 if(!aText.isEmpty())
1088 OUString aErrorMsg;
1089 Reference<XPropertySet> xColumn;
1090 OSQLParseNode* pParseNode = getDesignView()->getPredicateTreeFromEntry(pEntry,aText,aErrorMsg,xColumn);
1092 if (pParseNode)
1094 pParseNode->parseNodeToPredicateStr(aCrit,
1095 xConnection,
1096 static_cast<OQueryController&>(getDesignView()->getController()).getNumberFormatter(),
1097 xColumn,
1098 pEntry->GetAlias(),
1099 getDesignView()->getLocale(),
1100 static_cast<sal_Char>(getDesignView()->getDecimalSeparator().toChar()),
1101 &(static_cast<OQueryController&>(getDesignView()->getController()).getParser().getContext()));
1102 delete pParseNode;
1104 else
1106 if(xColumn.is())
1108 sal_Int32 nType = 0;
1109 xColumn->getPropertyValue(PROPERTY_TYPE) >>= nType;
1110 switch(nType)
1112 case DataType::CHAR:
1113 case DataType::VARCHAR:
1114 case DataType::LONGVARCHAR:
1115 case DataType::CLOB:
1116 if(!aText.startsWith("'") || !aText.endsWith("'"))
1118 aText = aText.replaceAll("'", "''");
1119 aText = "'" + aText + "'";
1121 break;
1122 default:
1125 ::connectivity::OSQLParser& rParser = static_cast<OQueryController&>(getDesignView()->getController()).getParser();
1126 pParseNode = rParser.predicateTree(aErrorMsg,
1127 aText,
1128 static_cast<OQueryController&>(getDesignView()->getController()).getNumberFormatter(),
1129 xColumn);
1130 if (pParseNode)
1132 pParseNode->parseNodeToPredicateStr(aCrit,
1133 xConnection,
1134 static_cast<OQueryController&>(getDesignView()->getController()).getNumberFormatter(),
1135 xColumn,
1136 pEntry->GetAlias(),
1137 getDesignView()->getLocale(),
1138 static_cast<sal_Char>(getDesignView()->getDecimalSeparator().toChar()),
1139 &(static_cast<OQueryController&>(getDesignView()->getController()).getParser().getContext()));
1140 delete pParseNode;
1142 else
1144 if ( !m_bDisableErrorBox )
1146 ScopedVclPtr<OSQLWarningBox>::Create( this, aErrorMsg )->Execute();
1148 bError = true;
1151 else
1153 if ( !m_bDisableErrorBox )
1155 ScopedVclPtr<OSQLWarningBox>::Create( this, aErrorMsg )->Execute();
1157 bError = true;
1161 strOldCellContents = pEntry->GetCriteria(nIdx);
1162 pEntry->SetCriteria(nIdx, aCrit);
1163 sNewValue = pEntry->GetCriteria(nIdx);
1164 if(!aCrit.isEmpty() && nRow >= (GetRowCount()-1))
1165 bAppendRow = true;
1168 if(!bError && Controller())
1169 Controller()->ClearModified();
1171 RowModified(GetCurRow(), GetCurColumnId());
1173 if ( bAppendRow )
1175 RowInserted( GetRowCount()-1, 1, true );
1176 m_bVisibleRow.push_back(true);
1177 ++m_nVisibleCount;
1180 if(!bError)
1182 // and now the undo-action for the total
1183 appendUndoAction(strOldCellContents,sNewValue,nRow);
1188 // did I store data in a FieldDescription which was empty before and which is not empty anymore after the changes?
1189 if ( pEntry.is() && bWasEmpty && !pEntry->IsEmpty() && !bError )
1191 // Default to visible
1192 pEntry->SetVisible(true);
1193 appendUndoAction("0","1",BROW_VIS_ROW,bListAction);
1194 RowModified(BROW_VIS_ROW, GetCurColumnId());
1196 // if required add empty columns
1197 sal_uInt16 nDummy;
1198 CheckFreeColumns(nDummy);
1201 if ( bListAction && !m_bInUndoMode )
1202 static_cast<OQueryController&>(getDesignView()->getController()).GetUndoManager().LeaveListAction();
1204 return pEntry != NULL && !bError;
1207 bool OSelectionBrowseBox::SeekRow(long nRow)
1209 m_nSeekRow = nRow;
1210 return nRow < m_nVisibleCount;
1213 void OSelectionBrowseBox::PaintCell(OutputDevice& rDev, const Rectangle& rRect, sal_uInt16 nColumnId) const
1215 rDev.SetClipRegion(vcl::Region(rRect));
1217 OTableFieldDescRef pEntry = NULL;
1218 sal_uInt16 nPos = GetColumnPos(nColumnId);
1219 if(getFields().size() > sal_uInt16(nPos - 1))
1220 pEntry = getFields()[nPos - 1];
1222 if (!pEntry.is())
1223 return;
1225 long nRow = GetRealRow(m_nSeekRow);
1226 if (nRow == BROW_VIS_ROW)
1227 PaintTristate(rDev, rRect, pEntry->IsVisible() ? TRISTATE_TRUE : TRISTATE_FALSE);
1228 else
1229 rDev.DrawText(rRect, GetCellText(nRow, nColumnId),DrawTextFlags::VCenter);
1231 rDev.SetClipRegion( );
1234 void OSelectionBrowseBox::PaintStatusCell(OutputDevice& rDev, const Rectangle& rRect) const
1236 Rectangle aRect(rRect);
1237 aRect.TopLeft().Y() -= 2;
1238 OUString aLabel(ModuleRes(STR_QUERY_HANDLETEXT));
1240 // from BROW_CRIT2_ROW onwards all rows are shown "or"
1241 sal_Int32 nToken = (m_nSeekRow >= GetBrowseRow(BROW_CRIT2_ROW))
1242 ? BROW_CRIT2_ROW : GetRealRow(m_nSeekRow);
1243 rDev.DrawText(aRect, aLabel.getToken(nToken, ';'),DrawTextFlags::VCenter);
1246 void OSelectionBrowseBox::RemoveColumn(sal_uInt16 _nColumnId)
1248 OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
1250 sal_uInt16 nPos = GetColumnPos(_nColumnId);
1251 // the control should always have exactly one more column: the HandleColumn
1252 OSL_ENSURE((nPos == 0) || (nPos <= getFields().size()), "OSelectionBrowseBox::RemoveColumn : invalid parameter nColId");
1253 // ColId is synonymous to Position, and the condition should be valid
1255 sal_uInt16 nCurCol = GetCurColumnId();
1256 long nCurrentRow = GetCurRow();
1258 DeactivateCell();
1260 getFields().erase( getFields().begin() + (nPos - 1) );
1261 OTableFieldDescRef pEntry = new OTableFieldDesc();
1262 pEntry->SetColumnId(_nColumnId);
1263 getFields().push_back(pEntry);
1265 EditBrowseBox::RemoveColumn( _nColumnId );
1266 InsertDataColumn( _nColumnId , OUString(), DEFAULT_SIZE, HeaderBarItemBits::STDSTYLE, HEADERBAR_APPEND);
1268 // Neuzeichnen
1269 Rectangle aInvalidRect = GetInvalidRect( _nColumnId );
1270 Invalidate( aInvalidRect );
1272 ActivateCell( nCurrentRow, nCurCol );
1274 rController.setModified( sal_True );
1276 invalidateUndoRedo();
1279 void OSelectionBrowseBox::RemoveField(sal_uInt16 nColumnId )
1281 OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
1283 sal_uInt16 nPos = GetColumnPos(nColumnId);
1284 OSL_ENSURE(getFields().size() > sal_uInt16(nPos-1),"ID is to great!");
1286 OTableFieldDescRef pDesc = getEntry((sal_uInt32)(nPos - 1)) ;
1287 pDesc->SetColWidth( (sal_uInt16)GetColumnWidth(nColumnId) ); // was not stored this before
1289 // trigger UndoAction
1290 if ( !m_bInUndoMode )
1292 OTabFieldDelUndoAct* pUndoAction = new OTabFieldDelUndoAct( this );
1293 pUndoAction->SetTabFieldDescr(pDesc);
1294 pUndoAction->SetColumnPosition(nPos);
1295 rController.addUndoActionAndInvalidate( pUndoAction );
1298 RemoveColumn(nColumnId);
1300 invalidateUndoRedo();
1303 void OSelectionBrowseBox::adjustSelectionMode( bool _bClickedOntoHeader, bool _bClickedOntoHandleCol )
1305 // if a Header has been selected it should be shown otherwise not
1306 if ( _bClickedOntoHeader )
1308 if (0 == GetSelectColumnCount() )
1309 // I am in the correct mode if a selected column exists
1310 if ( BrowserMode::HIDESELECT == ( m_nMode & BrowserMode::HIDESELECT ) )
1312 m_nMode &= ~BrowserMode::HIDESELECT;
1313 m_nMode |= BrowserMode::MULTISELECTION;
1314 SetMode( m_nMode );
1317 else if ( BrowserMode::HIDESELECT != ( m_nMode & BrowserMode::HIDESELECT ) )
1319 if ( GetSelectColumnCount() != 0 )
1320 SetNoSelection();
1322 if ( _bClickedOntoHandleCol )
1324 m_nMode |= BrowserMode::HIDESELECT;
1325 m_nMode &= ~BrowserMode::MULTISELECTION;
1326 SetMode( m_nMode );
1331 void OSelectionBrowseBox::MouseButtonDown(const BrowserMouseEvent& rEvt)
1333 if( rEvt.IsLeft() )
1335 bool bOnHandle = HANDLE_ID == rEvt.GetColumnId();
1336 bool bOnHeader = ( rEvt.GetRow() < 0 ) && !bOnHandle;
1337 adjustSelectionMode( bOnHeader, bOnHandle );
1339 EditBrowseBox::MouseButtonDown(rEvt);
1342 void OSelectionBrowseBox::MouseButtonUp(const BrowserMouseEvent& rEvt)
1344 EditBrowseBox::MouseButtonUp( rEvt );
1345 static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( ID_BROWSER_QUERY_EXECUTE );
1348 void OSelectionBrowseBox::KeyInput( const KeyEvent& rEvt )
1350 if (IsColumnSelected(GetCurColumnId()))
1352 if (rEvt.GetKeyCode().GetCode() == KEY_DELETE && // Delete rows
1353 !rEvt.GetKeyCode().IsShift() &&
1354 !rEvt.GetKeyCode().IsMod1())
1356 RemoveField(GetCurColumnId());
1357 return;
1360 EditBrowseBox::KeyInput(rEvt);
1363 sal_Int8 OSelectionBrowseBox::AcceptDrop( const BrowserAcceptDropEvent& rEvt )
1365 sal_Int8 nDropAction = DND_ACTION_NONE;
1366 if ( rEvt.GetRow() >= -1 )
1368 if ( IsEditing() )
1370 // allow the asterisk again
1371 m_bDisableErrorBox = true;
1372 SaveModified();
1373 m_bDisableErrorBox = false;
1374 DeactivateCell();
1376 // check if the format is already supported, if not deactivate the current cell and try again
1377 if ( OJoinExchObj::isFormatAvailable(GetDataFlavors()) )
1378 nDropAction = DND_ACTION_LINK;
1381 return nDropAction;
1384 sal_Int8 OSelectionBrowseBox::ExecuteDrop( const BrowserExecuteDropEvent& _rEvt )
1387 TransferableDataHelper aDropped(_rEvt.maDropEvent.Transferable);
1388 if (!OJoinExchObj::isFormatAvailable(aDropped.GetDataFlavorExVector()))
1390 OSL_FAIL("OSelectionBrowseBox::ExecuteDrop: this should never have passed AcceptDrop!");
1391 return DND_ACTION_NONE;
1394 OTableFieldDesc aInfo;
1395 // insert the field at the selected position
1396 OJoinExchangeData jxdSource = OJoinExchObj::GetSourceDescription(_rEvt.maDropEvent.Transferable);
1397 InsertField(jxdSource);
1399 return DND_ACTION_LINK;
1402 OTableFieldDescRef OSelectionBrowseBox::AppendNewCol( sal_uInt16 nCnt)
1404 // one or more can be created, but the first one will is not returned
1405 sal_uInt32 nCount = getFields().size();
1406 for (sal_uInt16 i=0 ; i<nCnt ; i++)
1408 OTableFieldDescRef pEmptyEntry = new OTableFieldDesc();
1409 getFields().push_back(pEmptyEntry);
1410 sal_uInt16 nColumnId = sal::static_int_cast< sal_uInt16 >(getFields().size());
1411 pEmptyEntry->SetColumnId( nColumnId );
1413 InsertDataColumn( nColumnId , OUString(), DEFAULT_SIZE, HeaderBarItemBits::STDSTYLE, HEADERBAR_APPEND);
1416 return getFields()[nCount];
1419 void OSelectionBrowseBox::DeleteFields(const OUString& rAliasName)
1421 if (!getFields().empty())
1423 sal_uInt16 nColId = GetCurColumnId();
1424 sal_uInt32 nRow = GetCurRow();
1426 bool bWasEditing = IsEditing();
1427 if (bWasEditing)
1428 DeactivateCell();
1430 OTableFields::reverse_iterator aIter = getFields().rbegin();
1431 OTableFieldDescRef pEntry = NULL;
1432 for(sal_uInt16 nPos=sal::static_int_cast< sal_uInt16 >(getFields().size());aIter != getFields().rend();++aIter,--nPos)
1434 pEntry = *aIter;
1435 if ( pEntry->GetAlias().equals( rAliasName ) )
1437 RemoveField( GetColumnId( nPos ) );
1438 break;
1442 if (bWasEditing)
1443 ActivateCell(nRow , nColId);
1447 void OSelectionBrowseBox::SetColWidth(sal_uInt16 nColId, long nNewWidth)
1449 bool bWasEditing = IsEditing();
1450 if (bWasEditing)
1451 DeactivateCell();
1453 // create the BaseClass
1454 SetColumnWidth(nColId, nNewWidth);
1456 // tell it the FieldDescription
1457 OTableFieldDescRef pEntry = getEntry(GetColumnPos(nColId) - 1);
1458 if (pEntry.is())
1459 pEntry->SetColWidth(sal_uInt16(GetColumnWidth(nColId)));
1461 if (bWasEditing)
1462 ActivateCell(GetCurRow(), GetCurColumnId());
1465 Rectangle OSelectionBrowseBox::GetInvalidRect( sal_uInt16 nColId )
1467 // The rectangle is the full output area of the window
1468 Rectangle aInvalidRect( Point(0,0), GetOutputSizePixel() );
1470 // now update the left side
1471 Rectangle aFieldRect(GetCellRect( 0, nColId )); // used instead of GetFieldRectPixel
1472 aInvalidRect.Left() = aFieldRect.Left();
1474 return aInvalidRect;
1477 void OSelectionBrowseBox::InsertColumn(OTableFieldDescRef pEntry, sal_uInt16& _nColumnPosition)
1479 // the control should have exactly one more column: the HandleColumn
1480 OSL_ENSURE(_nColumnPosition == BROWSER_INVALIDID || (_nColumnPosition <= (long)getFields().size()), "OSelectionBrowseBox::InsertColumn : invalid parameter nColId.");
1481 // -1 means at the end. Count means at the end, others denotes a correct position
1483 sal_uInt16 nCurCol = GetCurColumnId();
1484 long nCurrentRow = GetCurRow();
1486 DeactivateCell();
1488 // remember the column id of the current position
1489 sal_uInt16 nColumnId = GetColumnId(_nColumnPosition);
1490 // put at the end of the list if to small or to big,
1491 if ((_nColumnPosition == BROWSER_INVALIDID) || (_nColumnPosition >= getFields().size())) // append the field
1493 if (FindFirstFreeCol(_nColumnPosition) == NULL) // no more free columns
1495 AppendNewCol(1);
1496 _nColumnPosition = sal::static_int_cast< sal_uInt16 >(
1497 getFields().size());
1499 else
1500 ++_nColumnPosition; // within the list
1501 nColumnId = GetColumnId(_nColumnPosition);
1502 pEntry->SetColumnId( nColumnId );
1503 getFields()[ _nColumnPosition - 1] = pEntry;
1506 // check if the column ids are identical, if not we have to move
1507 if ( pEntry->GetColumnId() != nColumnId )
1509 sal_uInt16 nOldPosition = GetColumnPos(pEntry->GetColumnId());
1510 OSL_ENSURE( nOldPosition != 0,"Old position was 0. Not possible!");
1511 SetColumnPos(pEntry->GetColumnId(),_nColumnPosition);
1512 // we have to delete an empty field for the fields list, because the columns must have equal length
1513 if ( nOldPosition > 0 && nOldPosition <= getFields().size() )
1514 getFields()[nOldPosition - 1] = pEntry;
1516 ColumnMoved(pEntry->GetColumnId(),false);
1519 if ( pEntry->GetFunctionType() & (FKT_AGGREGATE) )
1521 OUString sFunctionName = pEntry->GetFunction();
1522 if ( GetFunctionName(sal_uInt32(-1),sFunctionName) )
1523 pEntry->SetFunction(sFunctionName);
1526 nColumnId = pEntry->GetColumnId();
1528 SetColWidth(nColumnId,getDesignView()->getColWidth(GetColumnPos(nColumnId)-1));
1529 // redraw
1530 Rectangle aInvalidRect = GetInvalidRect( nColumnId );
1531 Invalidate( aInvalidRect );
1533 ActivateCell( nCurrentRow, nCurCol );
1534 static_cast<OQueryController&>(getDesignView()->getController()).setModified( sal_True );
1536 invalidateUndoRedo();
1539 OTableFieldDescRef OSelectionBrowseBox::InsertField(const OJoinExchangeData& jxdSource, sal_uInt16 _nColumnPosition, bool bVis, bool bActivate)
1541 OQueryTableWindow* pSourceWin = static_cast<OQueryTableWindow*>(jxdSource.pListBox->GetTabWin());
1542 if (!pSourceWin)
1543 return NULL;
1545 // name and position of the selected field
1546 OUString aFieldName = jxdSource.pListBox->GetEntryText(jxdSource.pEntry);
1547 sal_uInt32 nFieldIndex = jxdSource.pListBox->GetModel()->GetAbsPos(jxdSource.pEntry);
1548 OTableFieldInfo* pInf = static_cast<OTableFieldInfo*>(jxdSource.pEntry->GetUserData());
1550 // construct DragInfo, such that I use the other InsertField
1551 OTableFieldDescRef aInfo = new OTableFieldDesc(pSourceWin->GetTableName(),aFieldName);
1552 aInfo->SetTabWindow(pSourceWin);
1553 aInfo->SetFieldIndex(nFieldIndex);
1554 aInfo->SetFieldType(pInf->GetKeyType());
1555 aInfo->SetAlias(pSourceWin->GetAliasName());
1557 aInfo->SetDataType(pInf->GetDataType());
1558 aInfo->SetVisible(bVis);
1560 return InsertField(aInfo, _nColumnPosition, bVis, bActivate);
1563 OTableFieldDescRef OSelectionBrowseBox::InsertField(const OTableFieldDescRef& _rInfo, sal_uInt16 _nColumnPosition, bool bVis, bool bActivate)
1566 if(m_nMaxColumns && m_nMaxColumns <= FieldsCount())
1567 return NULL;
1568 if (bActivate)
1569 SaveModified();
1571 // new column description
1572 OTableFieldDescRef pEntry = _rInfo;
1573 pEntry->SetVisible(bVis);
1575 // insert column
1576 InsertColumn( pEntry, _nColumnPosition );
1578 if ( !m_bInUndoMode )
1580 // trigger UndoAction
1581 OTabFieldCreateUndoAct* pUndoAction = new OTabFieldCreateUndoAct( this );
1582 pUndoAction->SetTabFieldDescr( pEntry );
1583 pUndoAction->SetColumnPosition(_nColumnPosition);
1584 getDesignView()->getController().addUndoActionAndInvalidate( pUndoAction );
1587 return pEntry;
1590 sal_uInt16 OSelectionBrowseBox::FieldsCount()
1592 OTableFields::iterator aIter = getFields().begin();
1593 sal_uInt16 nCount = 0;
1595 while (aIter != getFields().end())
1597 if ((*aIter).is() && !(*aIter)->IsEmpty())
1598 ++nCount;
1599 ++aIter;
1602 return nCount;
1605 OTableFieldDescRef OSelectionBrowseBox::FindFirstFreeCol(sal_uInt16& _rColumnPosition )
1607 OTableFields::iterator aIter = getFields().begin();
1608 OTableFields::iterator aEnd = getFields().end();
1610 _rColumnPosition = BROWSER_INVALIDID;
1612 while ( aIter != aEnd )
1614 ++_rColumnPosition;
1615 OTableFieldDescRef pEntry = (*aIter);
1616 if ( pEntry.is() && pEntry->IsEmpty() )
1617 return pEntry;
1618 ++aIter;
1621 return NULL;
1624 void OSelectionBrowseBox::CheckFreeColumns(sal_uInt16& _rColumnPosition)
1626 if (FindFirstFreeCol(_rColumnPosition) == NULL)
1628 // it is full, append a Packen column
1629 AppendNewCol(DEFAULT_QUERY_COLS);
1630 OSL_VERIFY(FindFirstFreeCol(_rColumnPosition).is());
1634 void OSelectionBrowseBox::AddGroupBy( const OTableFieldDescRef& rInfo , sal_uInt32 /*_nCurrentPos*/)
1636 Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
1637 if(!xConnection.is())
1638 return;
1639 OSL_ENSURE(!rInfo->IsEmpty(),"AddGroupBy:: OTableFieldDescRef sollte nicht Empty sein!");
1640 OTableFieldDescRef pEntry;
1641 const Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
1642 const ::comphelper::UStringMixEqual bCase(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers());
1643 //sal_Bool bAppend = sal_False;
1645 OTableFields& rFields = getFields();
1646 OTableFields::iterator aIter = rFields.begin();
1647 OTableFields::iterator aEnd = rFields.end();
1648 for(;aIter != aEnd;++aIter)
1650 pEntry = *aIter;
1651 OSL_ENSURE(pEntry.is(),"OTableFieldDescRef was null!");
1653 const OUString aField = pEntry->GetField();
1654 const OUString aAlias = pEntry->GetAlias();
1656 if (bCase(aField,rInfo->GetField()) &&
1657 bCase(aAlias,rInfo->GetAlias()) &&
1658 pEntry->GetFunctionType() == rInfo->GetFunctionType() &&
1659 pEntry->GetFunction() == rInfo->GetFunction())
1661 if ( pEntry->isNumericOrAggreateFunction() && rInfo->IsGroupBy() )
1663 pEntry->SetGroupBy(false);
1664 aIter = rFields.end();
1665 break;
1667 else
1669 if ( !pEntry->IsGroupBy() && !pEntry->HasCriteria() ) // here we have a where condition which is no having clause
1671 pEntry->SetGroupBy(rInfo->IsGroupBy());
1672 if(!m_bGroupByUnRelated && pEntry->IsGroupBy())
1673 pEntry->SetVisible(true);
1674 break;
1681 if (aIter == rFields.end())
1683 OTableFieldDescRef pTmp = InsertField(rInfo, BROWSER_INVALIDID, false, false );
1684 if ( (pTmp->isNumericOrAggreateFunction() && rInfo->IsGroupBy()) ) // the GroupBy is inherited from rInfo
1685 pTmp->SetGroupBy(false);
1689 void OSelectionBrowseBox::DuplicateConditionLevel( const sal_uInt16 nLevel)
1691 const sal_uInt16 nNewLevel = nLevel +1;
1692 OTableFields& rFields = getFields();
1693 OTableFields::iterator aIter = rFields.begin();
1694 OTableFields::iterator aEnd = rFields.end();
1695 for(;aIter != aEnd;++aIter)
1697 OTableFieldDescRef pEntry = *aIter;
1699 OUString sValue = pEntry->GetCriteria(nLevel);
1700 if ( !sValue.isEmpty() )
1702 pEntry->SetCriteria( nNewLevel, sValue);
1703 if ( nNewLevel == (m_nVisibleCount-BROW_CRIT1_ROW-1) )
1705 RowInserted( GetRowCount()-1, 1, true );
1706 m_bVisibleRow.push_back(true);
1707 ++m_nVisibleCount;
1709 m_bVisibleRow[BROW_CRIT1_ROW + nNewLevel] = true;
1714 void OSelectionBrowseBox::AddCondition( const OTableFieldDescRef& rInfo, const OUString& rValue, const sal_uInt16 nLevel,bool _bAddOrOnOneLine )
1716 Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
1717 if(!xConnection.is())
1718 return;
1719 OSL_ENSURE(rInfo.is() && !rInfo->IsEmpty(),"AddCondition:: OTableFieldDescRef sollte nicht Empty sein!");
1721 OTableFieldDescRef pLastEntry;
1722 Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
1723 ::comphelper::UStringMixEqual bCase(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers());
1725 OTableFields& rFields = getFields();
1726 OTableFields::iterator aIter = rFields.begin();
1727 OTableFields::iterator aEnd = rFields.end();
1728 for(;aIter != aEnd;++aIter)
1730 OTableFieldDescRef pEntry = *aIter;
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->isNumericOrAggreateFunction() && rInfo->IsGroupBy() )
1741 pEntry->SetGroupBy(false);
1742 else
1744 if(!m_bGroupByUnRelated && pEntry->IsGroupBy())
1745 pEntry->SetVisible(true);
1747 if (pEntry->GetCriteria(nLevel).isEmpty() )
1749 pEntry->SetCriteria( nLevel, rValue);
1750 if(nLevel == (m_nVisibleCount-BROW_CRIT1_ROW-1))
1752 RowInserted( GetRowCount()-1, 1, true );
1753 m_bVisibleRow.push_back(true);
1754 ++m_nVisibleCount;
1756 m_bVisibleRow[BROW_CRIT1_ROW + nLevel] = true;
1757 break;
1759 if ( _bAddOrOnOneLine )
1761 pLastEntry = pEntry;
1765 if ( pLastEntry.is() )
1767 OUString sCriteria = rValue;
1768 OUString sOldCriteria = pLastEntry->GetCriteria( nLevel );
1769 if ( !sOldCriteria.isEmpty() )
1771 sCriteria = "( ";
1772 sCriteria += sOldCriteria;
1773 sCriteria += " OR ";
1774 sCriteria += rValue;
1775 sCriteria += " )";
1777 pLastEntry->SetCriteria( nLevel, sCriteria);
1778 if(nLevel == (m_nVisibleCount-BROW_CRIT1_ROW-1))
1780 RowInserted( GetRowCount()-1, 1, true );
1781 m_bVisibleRow.push_back(true);
1782 ++m_nVisibleCount;
1784 m_bVisibleRow[BROW_CRIT1_ROW + nLevel] = true;
1786 else if (aIter == rFields.end())
1788 OTableFieldDescRef pTmp = InsertField(rInfo, BROWSER_INVALIDID, false, false );
1789 if ( pTmp->isNumericOrAggreateFunction() && rInfo->IsGroupBy() ) // the GroupBy was inherited from rInfo
1790 pTmp->SetGroupBy(false);
1791 if ( pTmp.is() )
1793 pTmp->SetCriteria( nLevel, rValue);
1794 if(nLevel == (m_nVisibleCount-BROW_CRIT1_ROW-1))
1796 RowInserted( GetRowCount()-1, 1, true );
1797 m_bVisibleRow.push_back(true);
1798 ++m_nVisibleCount;
1804 void OSelectionBrowseBox::AddOrder( const OTableFieldDescRef& rInfo, const EOrderDir eDir, sal_uInt32 _nCurrentPos)
1806 if (_nCurrentPos == 0)
1807 m_nLastSortColumn = SORT_COLUMN_NONE;
1809 Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
1810 if(!xConnection.is())
1811 return;
1812 OSL_ENSURE(!rInfo->IsEmpty(),"AddOrder:: OTableFieldDescRef should not be Empty!");
1813 OTableFieldDescRef pEntry;
1814 Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
1815 ::comphelper::UStringMixEqual bCase(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers());
1817 bool bAppend = false;
1818 OTableFields& rFields = getFields();
1819 OTableFields::iterator aIter = rFields.begin();
1820 OTableFields::iterator aEnd = rFields.end();
1821 for(;aIter != aEnd;++aIter)
1823 pEntry = *aIter;
1824 OUString aField = pEntry->GetField();
1825 OUString aAlias = pEntry->GetAlias();
1827 if (bCase(aField,rInfo->GetField()) &&
1828 bCase(aAlias,rInfo->GetAlias()))
1830 sal_uInt32 nPos = aIter - rFields.begin();
1831 bAppend = (m_nLastSortColumn != SORT_COLUMN_NONE) && (nPos <= m_nLastSortColumn);
1832 if ( bAppend )
1833 aIter = rFields.end();
1834 else
1836 if ( !m_bOrderByUnRelated )
1837 pEntry->SetVisible(true);
1838 pEntry->SetOrderDir( eDir );
1839 m_nLastSortColumn = nPos;
1841 break;
1845 if (aIter == rFields.end())
1847 OTableFieldDescRef pTmp = InsertField(rInfo, BROWSER_INVALIDID, false, false );
1848 if(pTmp.is())
1850 m_nLastSortColumn = pTmp->GetColumnId() - 1;
1851 if ( !m_bOrderByUnRelated && !bAppend )
1852 pTmp->SetVisible(true);
1853 pTmp->SetOrderDir( eDir );
1858 void OSelectionBrowseBox::ArrangeControls(sal_uInt16& nX, sal_uInt16 nY)
1860 EditBrowseBox::ArrangeControls(nX, nY);
1863 bool OSelectionBrowseBox::Save()
1865 bool bRet = true;
1866 if (IsModified())
1867 bRet = SaveModified();
1868 return bRet;
1871 void OSelectionBrowseBox::CellModified()
1873 long nRow = GetRealRow(GetCurRow());
1874 switch (nRow)
1876 case BROW_VIS_ROW:
1878 OTableFieldDescRef pEntry = getEntry(GetColumnPos(GetCurColumnId()) - 1);
1880 sal_Int32 nIdx = m_pOrderCell->GetSelectEntryPos();
1881 if(!m_bOrderByUnRelated && nIdx > 0 &&
1882 nIdx != LISTBOX_ENTRY_NOTFOUND &&
1883 !pEntry->IsEmpty() &&
1884 pEntry->GetOrderDir() != ORDER_NONE)
1886 m_pVisibleCell->GetBox().Check();
1887 pEntry->SetVisible(true);
1889 else
1890 pEntry->SetVisible(m_pVisibleCell->GetBox().IsChecked());
1892 break;
1894 static_cast<OQueryController&>(getDesignView()->getController()).setModified( sal_True );
1897 void OSelectionBrowseBox::Fill()
1899 OSL_ENSURE(ColCount() >= 1, "OSelectionBrowseBox::Fill : please call only after inserting the handle column !");
1901 sal_uInt16 nColCount = ColCount() - 1;
1902 if (nColCount < DEFAULT_QUERY_COLS)
1903 AppendNewCol(DEFAULT_QUERY_COLS - nColCount);
1906 Size OSelectionBrowseBox::CalcOptimalSize( const Size& _rAvailable )
1908 Size aReturn( _rAvailable.Width(), GetTitleHeight() );
1910 aReturn.Height() += ( m_nVisibleCount ? m_nVisibleCount : 15 ) * GetDataRowHeight();
1911 aReturn.Height() += 40; // just some space
1913 return aReturn;
1916 void OSelectionBrowseBox::Command(const CommandEvent& rEvt)
1918 switch (rEvt.GetCommand())
1920 case CommandEventId::ContextMenu:
1922 Point aMenuPos( rEvt.GetMousePosPixel() );
1924 if (!rEvt.IsMouseEvent())
1926 if ( 1 == GetSelectColumnCount() )
1928 sal_uInt16 nSelId = GetColumnId(
1929 sal::static_int_cast< sal_uInt16 >(
1930 FirstSelectedColumn() ) );
1931 ::Rectangle aColRect( GetFieldRectPixel( 0, nSelId, false ) );
1933 aMenuPos = aColRect.TopCenter();
1935 else
1937 EditBrowseBox::Command(rEvt);
1938 return;
1942 sal_uInt16 nColId = GetColumnId(GetColumnAtXPosPixel( aMenuPos.X() ));
1943 long nRow = GetRowAtYPosPixel( aMenuPos.Y() );
1945 if (nRow < 0 && nColId > HANDLE_ID )
1947 if ( !IsColumnSelected( nColId ) )
1949 adjustSelectionMode( true /* clicked onto a header */ , false /* not onto the handle col */ );
1950 SelectColumnId( nColId );
1953 if (!static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly())
1955 PopupMenu aContextMenu( ModuleRes( RID_QUERYCOLPOPUPMENU ) );
1956 switch (aContextMenu.Execute(this, aMenuPos))
1958 case SID_DELETE:
1959 RemoveField(nColId);
1960 break;
1962 case ID_BROWSER_COLWIDTH:
1963 adjustBrowseBoxColumnWidth( this, nColId );
1964 break;
1968 else if(nRow >= 0 && nColId <= HANDLE_ID)
1970 if (!static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly())
1972 PopupMenu aContextMenu(ModuleRes(RID_QUERYFUNCTION_POPUPMENU));
1973 aContextMenu.CheckItem( ID_QUERY_FUNCTION, m_bVisibleRow[BROW_FUNCTION_ROW]);
1974 aContextMenu.CheckItem( ID_QUERY_TABLENAME, m_bVisibleRow[BROW_TABLE_ROW]);
1975 aContextMenu.CheckItem( ID_QUERY_ALIASNAME, m_bVisibleRow[BROW_COLUMNALIAS_ROW]);
1976 aContextMenu.CheckItem( ID_QUERY_DISTINCT, static_cast<OQueryController&>(getDesignView()->getController()).isDistinct());
1978 switch (aContextMenu.Execute(this, aMenuPos))
1980 case ID_QUERY_FUNCTION:
1981 SetRowVisible(BROW_FUNCTION_ROW, !IsRowVisible(BROW_FUNCTION_ROW));
1982 static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_FUNCTIONS );
1983 break;
1984 case ID_QUERY_TABLENAME:
1985 SetRowVisible(BROW_TABLE_ROW, !IsRowVisible(BROW_TABLE_ROW));
1986 static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_TABLES );
1987 break;
1988 case ID_QUERY_ALIASNAME:
1989 SetRowVisible(BROW_COLUMNALIAS_ROW, !IsRowVisible(BROW_COLUMNALIAS_ROW));
1990 static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_ALIASES );
1991 break;
1992 case ID_QUERY_DISTINCT:
1993 static_cast<OQueryController&>(getDesignView()->getController()).setDistinct(!static_cast<OQueryController&>(getDesignView()->getController()).isDistinct());
1994 static_cast<OQueryController&>(getDesignView()->getController()).setModified( sal_True );
1995 static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_DISTINCT_VALUES );
1996 break;
1999 static_cast<OQueryController&>(getDesignView()->getController()).setModified( sal_True );
2002 else
2004 EditBrowseBox::Command(rEvt);
2005 return;
2008 //fall-through
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,1);
2035 ++m_nVisibleCount;
2037 else
2039 RowRemoved(nId,1);
2040 --m_nVisibleCount;
2043 if (bWasEditing)
2044 ActivateCell();
2047 long OSelectionBrowseBox::GetBrowseRow(long nRowId) const
2049 sal_uInt16 nCount(0);
2050 for(sal_uInt16 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 = sizeof(nVisibleRowMask) / sizeof(nVisibleRowMask[0]);
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 = sizeof(nVisibleRowMask) / sizeof(nVisibleRowMask[0]);
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 != NULL, "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 != NULL, "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(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 != NULL, "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( sal_True );
2321 sal_uInt32 OSelectionBrowseBox::GetTotalCellWidth(long nRow, sal_uInt16 nColId) const
2324 long nRowId = GetRealRow(nRow);
2325 if (nRowId == BROW_VIS_ROW)
2326 return CHECKBOX_SIZE;
2327 else
2328 return GetDataWindow().GetTextWidth(GetCellText(nRowId, nColId));
2331 void OSelectionBrowseBox::ColumnResized(sal_uInt16 nColId)
2333 if (static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly())
2334 return;
2335 // The resizing of columns can't be suppressed (BrowseBox doesn't support that) so we have to do this
2336 // fake. It's not _that_ bad : the user may change column widths while in read-only mode to see all details
2337 // but the changes aren't permanent ...
2339 sal_uInt16 nPos = GetColumnPos(nColId);
2340 OSL_ENSURE(nPos <= getFields().size(),"ColumnResized:: nColId sollte nicht groesser als List::count sein!");
2341 OTableFieldDescRef pEntry = getEntry(nPos-1);
2342 OSL_ENSURE(pEntry.is(), "OSelectionBrowseBox::ColumnResized : keine FieldDescription !");
2343 static_cast<OQueryController&>(getDesignView()->getController()).setModified( sal_True );
2344 EditBrowseBox::ColumnResized(nColId);
2346 if ( pEntry.is())
2348 if ( !m_bInUndoMode )
2350 // create the undo action
2351 OTabFieldSizedUndoAct* pUndo = new OTabFieldSizedUndoAct(this);
2352 pUndo->SetColumnPosition( nPos );
2353 pUndo->SetOriginalWidth(pEntry->GetColWidth());
2354 getDesignView()->getController().addUndoActionAndInvalidate(pUndo);
2356 pEntry->SetColWidth(sal_uInt16(GetColumnWidth(nColId)));
2360 sal_uInt32 OSelectionBrowseBox::GetTotalCellWidth(long nRowId, sal_uInt16 nColId)
2362 sal_uInt16 nPos = GetColumnPos(nColId);
2363 OSL_ENSURE((nPos == 0) || (nPos <= getFields().size()), "OSelectionBrowseBox::GetTotalCellWidth : invalid parameter nColId");
2365 OTableFieldDescRef pEntry = getFields()[nPos-1];
2366 OSL_ENSURE(pEntry.is(), "OSelectionBrowseBox::GetTotalCellWidth : invalid FieldDescription !");
2368 long nRow = GetRealRow(nRowId);
2369 OUString strText(GetCellText(nRow, nColId));
2370 return GetDataWindow().LogicToPixel(Size(GetDataWindow().GetTextWidth(strText),0)).Width();
2373 bool OSelectionBrowseBox::isCutAllowed()
2375 bool bCutAllowed = false;
2376 long nRow = GetRealRow(GetCurRow());
2377 switch (nRow)
2379 case BROW_VIS_ROW:
2380 case BROW_ORDER_ROW:
2381 case BROW_TABLE_ROW:
2382 case BROW_FUNCTION_ROW:
2383 break;
2384 case BROW_FIELD_ROW:
2385 bCutAllowed = !m_pFieldCell->GetSelected().isEmpty();
2386 break;
2387 default:
2388 bCutAllowed = !m_pTextCell->GetSelected().isEmpty();
2389 break;
2391 return bCutAllowed;
2394 void OSelectionBrowseBox::cut()
2396 long nRow = GetRealRow(GetCurRow());
2397 switch (nRow)
2399 case BROW_FIELD_ROW:
2400 m_pFieldCell->Cut();
2401 m_pFieldCell->SetModifyFlag();
2402 break;
2403 default:
2404 m_pTextCell->Cut();
2405 m_pTextCell->SetModifyFlag();
2407 SaveModified();
2408 RowModified(GetBrowseRow(nRow), GetCurColumnId());
2410 invalidateUndoRedo();
2413 void OSelectionBrowseBox::paste()
2415 long nRow = GetRealRow(GetCurRow());
2416 switch (nRow)
2418 case BROW_FIELD_ROW:
2419 m_pFieldCell->Paste();
2420 m_pFieldCell->SetModifyFlag();
2421 break;
2422 default:
2423 m_pTextCell->Paste();
2424 m_pTextCell->SetModifyFlag();
2426 RowModified(GetBrowseRow(nRow), GetCurColumnId());
2427 invalidateUndoRedo();
2430 bool OSelectionBrowseBox::isPasteAllowed()
2432 bool bPasteAllowed = true;
2433 long nRow = GetRealRow(GetCurRow());
2434 switch (nRow)
2436 case BROW_VIS_ROW:
2437 case BROW_ORDER_ROW:
2438 case BROW_TABLE_ROW:
2439 case BROW_FUNCTION_ROW:
2440 bPasteAllowed = false;
2441 break;
2443 return bPasteAllowed;
2446 bool OSelectionBrowseBox::isCopyAllowed()
2448 return isCutAllowed();
2451 void OSelectionBrowseBox::copy()
2453 long nRow = GetRealRow(GetCurRow());
2454 switch (nRow)
2456 case BROW_FIELD_ROW:
2457 m_pFieldCell->Copy();
2458 break;
2459 default:
2460 m_pTextCell->Copy();
2464 void OSelectionBrowseBox::appendUndoAction(const OUString& _rOldValue, const OUString& _rNewValue, sal_Int32 _nRow, bool& _bListAction)
2466 if ( !m_bInUndoMode && _rNewValue != _rOldValue )
2468 if ( !_bListAction )
2470 _bListAction = true;
2471 static_cast<OQueryController&>(getDesignView()->getController()).GetUndoManager().EnterListAction(OUString(),OUString());
2473 appendUndoAction(_rOldValue,_rNewValue,_nRow);
2477 void OSelectionBrowseBox::appendUndoAction(const OUString& _rOldValue,const OUString& _rNewValue,sal_Int32 _nRow)
2479 if ( !m_bInUndoMode && _rNewValue != _rOldValue )
2481 OTabFieldCellModifiedUndoAct* pUndoAct = new OTabFieldCellModifiedUndoAct(this);
2482 pUndoAct->SetCellIndex(_nRow);
2483 OSL_ENSURE(GetColumnPos(GetCurColumnId()) != BROWSER_INVALIDID,"Current position isn't valid!");
2484 pUndoAct->SetColumnPosition( GetColumnPos(GetCurColumnId()) );
2485 pUndoAct->SetCellContents(_rOldValue);
2486 getDesignView()->getController().addUndoActionAndInvalidate(pUndoAct);
2490 IMPL_LINK_NOARG_TYPED(OSelectionBrowseBox, OnInvalidateTimer, Timer *, void)
2492 static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature(SID_CUT);
2493 static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature(SID_COPY);
2494 static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature(SID_PASTE);
2495 if(!m_bStopTimer)
2496 m_timerInvalidate.Start();
2499 void OSelectionBrowseBox::stopTimer()
2501 m_bStopTimer = true;
2502 if (m_timerInvalidate.IsActive())
2503 m_timerInvalidate.Stop();
2506 void OSelectionBrowseBox::startTimer()
2508 m_bStopTimer = false;
2509 if (!m_timerInvalidate.IsActive())
2510 m_timerInvalidate.Start();
2513 OTableFields& OSelectionBrowseBox::getFields() const
2515 OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
2516 return rController.getTableFieldDesc();
2519 void OSelectionBrowseBox::enableControl(const OTableFieldDescRef& _rEntry,Window* _pControl)
2521 bool bEnable = !_rEntry->isCondition();
2522 _pControl->Enable(bEnable);
2523 _pControl->EnableInput(bEnable);
2526 void OSelectionBrowseBox::setTextCellContext(const OTableFieldDescRef& _rEntry,const OUString& _sText,const OString& _sHelpId)
2528 m_pTextCell->SetText(_sText);
2529 m_pTextCell->ClearModifyFlag();
2530 if (!m_pTextCell->HasFocus())
2531 m_pTextCell->GrabFocus();
2533 enableControl(_rEntry,m_pTextCell);
2535 if (m_pTextCell->GetHelpId() != _sHelpId)
2536 // as TextCell is used in various contexts I will delete the cached HelpText
2537 m_pTextCell->SetHelpText(OUString());
2538 m_pTextCell->SetHelpId(_sHelpId);
2541 void OSelectionBrowseBox::invalidateUndoRedo()
2543 OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController());
2544 rController.InvalidateFeature( ID_BROWSER_UNDO );
2545 rController.InvalidateFeature( ID_BROWSER_REDO );
2546 rController.InvalidateFeature( ID_BROWSER_QUERY_EXECUTE );
2549 OTableFieldDescRef OSelectionBrowseBox::getEntry(OTableFields::size_type _nPos)
2551 // we have to check if we need a new entry at this position
2552 OTableFields& aFields = getFields();
2553 OSL_ENSURE(aFields.size() > _nPos,"ColID is to great!");
2555 OTableFieldDescRef pEntry = aFields[_nPos];
2556 OSL_ENSURE(pEntry.is(),"Invalid entry!");
2557 if ( !pEntry.is() )
2559 pEntry = new OTableFieldDesc();
2560 pEntry->SetColumnId(
2561 GetColumnId(sal::static_int_cast< sal_uInt16 >(_nPos+1)));
2562 aFields[_nPos] = pEntry;
2564 return pEntry;
2567 void OSelectionBrowseBox::GetFocus()
2569 if(!IsEditing() && !m_bWasEditing)
2570 ActivateCell();
2571 EditBrowseBox::GetFocus();
2574 void OSelectionBrowseBox::DeactivateCell(bool _bUpdate)
2576 m_bWasEditing = true;
2577 EditBrowseBox::DeactivateCell(_bUpdate);
2578 m_bWasEditing = false;
2581 OUString OSelectionBrowseBox::GetRowDescription( sal_Int32 _nRow ) const
2583 OUString aLabel(ModuleRes(STR_QUERY_HANDLETEXT));
2585 // from BROW_CRIT2_ROW onwards all rows are shown as "or"
2586 sal_Int32 nToken = (_nRow >= GetBrowseRow(BROW_CRIT2_ROW))
2587 ? BROW_CRIT2_ROW : GetRealRow(_nRow);
2588 return aLabel.getToken(nToken, ';');
2591 OUString OSelectionBrowseBox::GetAccessibleObjectName( ::svt::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition) const
2593 OUString sRetText;
2594 switch( _eObjType )
2596 case ::svt::BBTYPE_ROWHEADERCELL:
2597 sRetText = GetRowDescription(_nPosition);
2598 break;
2599 default:
2600 sRetText = EditBrowseBox::GetAccessibleObjectDescription(_eObjType,_nPosition);
2602 return sRetText;
2605 bool OSelectionBrowseBox::fillEntryTable(OTableFieldDescRef& _pEntry,const OUString& _sTableName)
2607 bool bRet = false;
2608 OJoinTableView::OTableWindowMap& rTabWinList = getDesignView()->getTableView()->GetTabWinMap();
2609 OJoinTableView::OTableWindowMap::iterator aIter = rTabWinList.find(_sTableName);
2610 if(aIter != rTabWinList.end())
2612 OQueryTableWindow* pEntryTab = static_cast<OQueryTableWindow*>(aIter->second.get());
2613 if (pEntryTab)
2615 _pEntry->SetTable(pEntryTab->GetTableName());
2616 _pEntry->SetTabWindow(pEntryTab);
2617 bRet = true;
2620 return bRet;
2623 void OSelectionBrowseBox::setFunctionCell(OTableFieldDescRef& _pEntry)
2625 Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection();
2626 if ( xConnection.is() )
2628 // Aggregate functions in general only available with Core SQL
2629 if ( lcl_SupportsCoreSQLGrammar(xConnection) )
2631 // if we have an asterisk, no other function than count is allowed
2632 m_pFunctionCell->Clear();
2633 m_pFunctionCell->InsertEntry(m_aFunctionStrings.getToken(0, ';'));
2634 if ( isFieldNameAsterisk(_pEntry->GetField()) )
2635 m_pFunctionCell->InsertEntry(m_aFunctionStrings.getToken(2, ';')); // 2 -> COUNT
2636 else
2638 sal_Int32 nCount = comphelper::string::getTokenCount(m_aFunctionStrings, ';');
2639 if ( _pEntry->isNumeric() )
2640 --nCount;
2641 for( sal_Int32 nIdx = 1; nIdx < nCount; nIdx++ )
2642 m_pFunctionCell->InsertEntry(m_aFunctionStrings.getToken(nIdx, ';'));
2645 if ( _pEntry->IsGroupBy() )
2647 OSL_ENSURE(!_pEntry->isNumeric(),"Not allowed to combine group by and numeric values!");
2648 m_pFunctionCell->SelectEntry(m_pFunctionCell->GetEntry(m_pFunctionCell->GetEntryCount() - 1));
2650 else if ( m_pFunctionCell->GetEntryPos(OUString(_pEntry->GetFunction())) != COMBOBOX_ENTRY_NOTFOUND )
2651 m_pFunctionCell->SelectEntry(OUString(_pEntry->GetFunction()));
2652 else
2653 m_pFunctionCell->SelectEntryPos(0);
2655 enableControl(_pEntry,m_pFunctionCell);
2657 else
2659 // only COUNT(*) and COUNT("table".*) allowed
2660 bool bCountRemoved = !isFieldNameAsterisk(_pEntry->GetField());
2661 if ( bCountRemoved )
2662 m_pFunctionCell->RemoveEntry(1);
2664 if ( !bCountRemoved && m_pFunctionCell->GetEntryCount() < 2)
2665 m_pFunctionCell->InsertEntry(m_aFunctionStrings.getToken(2, ';')); // 2 -> COUNT
2667 if(m_pFunctionCell->GetEntryPos(OUString(_pEntry->GetFunction())) != COMBOBOX_ENTRY_NOTFOUND)
2668 m_pFunctionCell->SelectEntry(_pEntry->GetFunction());
2669 else
2670 m_pFunctionCell->SelectEntryPos(0);
2675 Reference< XAccessible > OSelectionBrowseBox::CreateAccessibleCell( sal_Int32 _nRow, sal_uInt16 _nColumnPos )
2677 OTableFieldDescRef pEntry = NULL;
2678 if(getFields().size() > sal_uInt16(_nColumnPos - 1))
2679 pEntry = getFields()[_nColumnPos - 1];
2681 if ( _nRow == BROW_VIS_ROW && pEntry.is() )
2682 return EditBrowseBox::CreateAccessibleCheckBoxCell( _nRow, _nColumnPos,pEntry->IsVisible() ? TRISTATE_TRUE : TRISTATE_FALSE );
2684 return EditBrowseBox::CreateAccessibleCell( _nRow, _nColumnPos );
2687 bool OSelectionBrowseBox::HasFieldByAliasName(const OUString& rFieldName, OTableFieldDescRef& rInfo) const
2689 OTableFields& aFields = getFields();
2690 OTableFields::iterator aIter = aFields.begin();
2691 OTableFields::iterator aEnd = aFields.end();
2693 for(;aIter != aEnd;++aIter)
2695 if ( (*aIter)->GetFieldAlias() == rFieldName )
2697 *rInfo = *(*aIter);
2698 break;
2701 return aIter != aEnd;
2704 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */