File: | home/maarten/src/libreoffice/core/include/rtl/ref.hxx |
Warning: | line 192, column 9 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | |||
2 | /* | |||
3 | * This file is part of the LibreOffice project. | |||
4 | * | |||
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/. | |||
8 | * | |||
9 | * This file incorporates work covered by the following license notice: | |||
10 | * | |||
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 . | |||
18 | */ | |||
19 | ||||
20 | #include "SelectionBrowseBox.hxx" | |||
21 | #include <com/sun/star/sdbc/XDatabaseMetaData.hpp> | |||
22 | #include <com/sun/star/sdbc/DataType.hpp> | |||
23 | #include <JoinExchange.hxx> | |||
24 | #include <QueryDesignView.hxx> | |||
25 | #include <querycontroller.hxx> | |||
26 | #include <sqlbison.hxx> | |||
27 | #include <QueryTableView.hxx> | |||
28 | #include <browserids.hxx> | |||
29 | #include <comphelper/stl_types.hxx> | |||
30 | #include <comphelper/string.hxx> | |||
31 | #include "TableFieldInfo.hxx" | |||
32 | #include <core_resource.hxx> | |||
33 | #include <strings.hrc> | |||
34 | #include <strings.hxx> | |||
35 | #include <helpids.h> | |||
36 | #include "QTableWindow.hxx" | |||
37 | #include <vcl/weld.hxx> | |||
38 | #include <vcl/settings.hxx> | |||
39 | #include "QueryDesignFieldUndoAct.hxx" | |||
40 | #include <sqlmessage.hxx> | |||
41 | #include <UITools.hxx> | |||
42 | #include <o3tl/safeint.hxx> | |||
43 | #include <osl/diagnose.h> | |||
44 | #include <i18nlangtag/languagetag.hxx> | |||
45 | #include <vcl/commandevent.hxx> | |||
46 | #include <vcl/svapp.hxx> | |||
47 | ||||
48 | using namespace ::svt; | |||
49 | using namespace ::dbaui; | |||
50 | using namespace ::connectivity; | |||
51 | using namespace ::com::sun::star::uno; | |||
52 | using namespace ::com::sun::star::sdbc; | |||
53 | using namespace ::com::sun::star::beans; | |||
54 | using namespace ::com::sun::star::container; | |||
55 | using namespace ::com::sun::star::util; | |||
56 | using namespace ::com::sun::star::accessibility; | |||
57 | ||||
58 | #define DEFAULT_QUERY_COLS20 20 | |||
59 | #define DEFAULT_SIZEGetTextWidth("0") * 30 GetTextWidth("0") * 30 | |||
60 | #define HANDLE_ID0 0 | |||
61 | #define HANDLE_COLUMN_WIDTH70 70 | |||
62 | #define SORT_COLUMN_NONE0xFFFFFFFF 0xFFFFFFFF | |||
63 | ||||
64 | namespace | |||
65 | { | |||
66 | bool isFieldNameAsterisk(const OUString& _sFieldName ) | |||
67 | { | |||
68 | bool bAsterisk = _sFieldName.isEmpty() || _sFieldName.toChar() == '*'; | |||
69 | if ( !bAsterisk ) | |||
70 | { | |||
71 | sal_Int32 nTokenCount = comphelper::string::getTokenCount(_sFieldName, '.'); | |||
72 | if ( (nTokenCount == 2 && _sFieldName.getToken(1,'.')[0] == '*' ) | |||
73 | || (nTokenCount == 3 && _sFieldName.getToken(2,'.')[0] == '*' ) ) | |||
74 | { | |||
75 | bAsterisk = true; | |||
76 | } | |||
77 | } | |||
78 | return bAsterisk; | |||
79 | } | |||
80 | bool lcl_SupportsCoreSQLGrammar(const Reference< XConnection>& _xConnection) | |||
81 | { | |||
82 | bool bSupportsCoreGrammar = false; | |||
83 | if ( _xConnection.is() ) | |||
84 | { | |||
85 | try | |||
86 | { | |||
87 | Reference< XDatabaseMetaData > xMetaData = _xConnection->getMetaData(); | |||
88 | bSupportsCoreGrammar = xMetaData.is() && xMetaData->supportsCoreSQLGrammar(); | |||
89 | } | |||
90 | catch(Exception&) | |||
91 | { | |||
92 | } | |||
93 | } | |||
94 | return bSupportsCoreGrammar; | |||
95 | } | |||
96 | } | |||
97 | ||||
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(DBA_RES(STR_QUERY_FUNCTIONS)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_QUERY_FUNCTIONS" "\004" u8"(no function);Group" ) )) | |||
104 | ,m_nVisibleCount(0) | |||
105 | ,m_nLastSortColumn(SORT_COLUMN_NONE0xFFFFFFFF) | |||
106 | ,m_bOrderByUnRelated(true) | |||
107 | ,m_bGroupByUnRelated(true) | |||
108 | ,m_bStopTimer(false) | |||
109 | ,m_bWasEditing(false) | |||
110 | ,m_bDisableErrorBox(false) | |||
111 | ,m_bInUndoMode(false) | |||
112 | { | |||
113 | SetHelpId(HID_CTL_QRYDGNCRIT"DBACCESS_HID_CTL_QRYDGNCRIT"); | |||
114 | ||||
115 | m_nMode = BrowserMode::COLUMNSELECTION | BrowserMode::HIDESELECT | |||
116 | | BrowserMode::KEEPHIGHLIGHT | BrowserMode::HIDECURSOR | |||
117 | | BrowserMode::HLINES | BrowserMode::VLINES | |||
118 | | BrowserMode::HEADERBAR_NEW ; | |||
119 | ||||
120 | m_pTextCell = VclPtr<EditControl>::Create(&GetDataWindow()); | |||
121 | m_pVisibleCell = VclPtr<CheckBoxControl>::Create(&GetDataWindow()); | |||
122 | m_pTableCell = VclPtr<ListBoxControl>::Create(&GetDataWindow()); | |||
123 | m_pFieldCell = VclPtr<ComboBoxControl>::Create(&GetDataWindow()); | |||
124 | m_pOrderCell = VclPtr<ListBoxControl>::Create(&GetDataWindow()); | |||
125 | m_pFunctionCell = VclPtr<ListBoxControl>::Create(&GetDataWindow()); | |||
126 | ||||
127 | m_pVisibleCell->SetHelpId(HID_QRYDGN_ROW_VISIBLE"DBACCESS_HID_QRYDGN_ROW_VISIBLE"); | |||
128 | m_pTableCell->SetHelpId(HID_QRYDGN_ROW_TABLE"DBACCESS_HID_QRYDGN_ROW_TABLE"); | |||
129 | m_pFieldCell->SetHelpId(HID_QRYDGN_ROW_FIELD"DBACCESS_HID_QRYDGN_ROW_FIELD"); | |||
130 | weld::ComboBox& rOrderBox = m_pOrderCell->get_widget(); | |||
131 | m_pOrderCell->SetHelpId(HID_QRYDGN_ROW_ORDER"DBACCESS_HID_QRYDGN_ROW_ORDER"); | |||
132 | m_pFunctionCell->SetHelpId(HID_QRYDGN_ROW_FUNCTION"DBACCESS_HID_QRYDGN_ROW_FUNCTION"); | |||
133 | ||||
134 | // switch off triState of css::form::CheckBox | |||
135 | m_pVisibleCell->EnableTriState( false ); | |||
136 | ||||
137 | vcl::Font aTitleFont = OutputDevice::GetDefaultFont( DefaultFontType::SANS_UNICODE,Window::GetSettings().GetLanguageTag().getLanguageType(),GetDefaultFontFlags::OnlyOne); | |||
138 | aTitleFont.SetFontSize(Size(0, 6)); | |||
139 | SetTitleFont(aTitleFont); | |||
140 | ||||
141 | const OUString aTxt(DBA_RES(STR_QUERY_SORTTEXT)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_QUERY_SORTTEXT" "\004" u8"(not sorted);ascending;descending" ) )); | |||
142 | for (sal_Int32 nIdx {0}; nIdx>=0;) | |||
143 | rOrderBox.append_text(aTxt.getToken(0, ';', nIdx)); | |||
144 | ||||
145 | m_bVisibleRow.insert(m_bVisibleRow.end(), BROW_ROW_CNT12, true); | |||
146 | ||||
147 | m_bVisibleRow[BROW_FUNCTION_ROW5] = false; // first hide | |||
148 | ||||
149 | m_timerInvalidate.SetTimeout(200); | |||
150 | m_timerInvalidate.SetInvokeHandler(LINK(this, OSelectionBrowseBox, OnInvalidateTimer)::tools::detail::makeLink( ::tools::detail::castTo<OSelectionBrowseBox *>(this), &OSelectionBrowseBox::LinkStubOnInvalidateTimer )); | |||
151 | m_timerInvalidate.Start(); | |||
152 | } | |||
153 | ||||
154 | OSelectionBrowseBox::~OSelectionBrowseBox() | |||
155 | { | |||
156 | disposeOnce(); | |||
157 | } | |||
158 | ||||
159 | void OSelectionBrowseBox::dispose() | |||
160 | { | |||
161 | m_pTextCell.disposeAndClear(); | |||
162 | m_pVisibleCell.disposeAndClear(); | |||
163 | m_pFieldCell.disposeAndClear(); | |||
164 | m_pTableCell.disposeAndClear(); | |||
| ||||
165 | m_pOrderCell.disposeAndClear(); | |||
166 | m_pFunctionCell.disposeAndClear(); | |||
167 | ::svt::EditBrowseBox::dispose(); | |||
168 | } | |||
169 | ||||
170 | void OSelectionBrowseBox::initialize() | |||
171 | { | |||
172 | Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection(); | |||
173 | if(xConnection.is()) | |||
174 | { | |||
175 | const IParseContext& rContext = static_cast<OQueryController&>(getDesignView()->getController()).getParser().getContext(); | |||
176 | const IParseContext::InternationalKeyCode eFunctions[] = { | |||
177 | IParseContext::InternationalKeyCode::Avg,IParseContext::InternationalKeyCode::Count,IParseContext::InternationalKeyCode::Max | |||
178 | ,IParseContext::InternationalKeyCode::Min,IParseContext::InternationalKeyCode::Sum | |||
179 | ,IParseContext::InternationalKeyCode::Every | |||
180 | ,IParseContext::InternationalKeyCode::Any | |||
181 | ,IParseContext::InternationalKeyCode::Some | |||
182 | ,IParseContext::InternationalKeyCode::StdDevPop | |||
183 | ,IParseContext::InternationalKeyCode::StdDevSamp | |||
184 | ,IParseContext::InternationalKeyCode::VarSamp | |||
185 | ,IParseContext::InternationalKeyCode::VarPop | |||
186 | ,IParseContext::InternationalKeyCode::Collect | |||
187 | ,IParseContext::InternationalKeyCode::Fusion | |||
188 | ,IParseContext::InternationalKeyCode::Intersection | |||
189 | }; | |||
190 | ||||
191 | OUString sGroup = m_aFunctionStrings.copy(m_aFunctionStrings.lastIndexOf(';')+1); | |||
192 | m_aFunctionStrings = m_aFunctionStrings.getToken(0, ';'); | |||
193 | ||||
194 | for (IParseContext::InternationalKeyCode eFunction : eFunctions) | |||
195 | { | |||
196 | m_aFunctionStrings += ";" + OStringToOUString(rContext.getIntlKeywordAscii(eFunction), RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76))); | |||
197 | } | |||
198 | m_aFunctionStrings += ";" + sGroup; | |||
199 | ||||
200 | // Aggregate functions in general available only with Core SQL | |||
201 | // We slip in a few optionals one, too. | |||
202 | if ( lcl_SupportsCoreSQLGrammar(xConnection) ) | |||
203 | { | |||
204 | weld::ComboBox& rComboBox = m_pFunctionCell->get_widget(); | |||
205 | for (sal_Int32 nIdx {0}; nIdx>=0;) | |||
206 | rComboBox.append_text(m_aFunctionStrings.getToken(0, ';', nIdx)); | |||
207 | } | |||
208 | else // else only COUNT(*) and COUNT("table".*) | |||
209 | { | |||
210 | weld::ComboBox& rComboBox = m_pFunctionCell->get_widget(); | |||
211 | rComboBox.append_text(m_aFunctionStrings.getToken(0, ';')); | |||
212 | rComboBox.append_text(m_aFunctionStrings.getToken(2, ';')); // 2 -> COUNT | |||
213 | } | |||
214 | try | |||
215 | { | |||
216 | Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); | |||
217 | if ( xMetaData.is() ) | |||
218 | { | |||
219 | m_bOrderByUnRelated = xMetaData->supportsOrderByUnrelated(); | |||
220 | m_bGroupByUnRelated = xMetaData->supportsGroupByUnrelated(); | |||
221 | } | |||
222 | } | |||
223 | catch(Exception&) | |||
224 | { | |||
225 | } | |||
226 | } | |||
227 | ||||
228 | Init(); | |||
229 | } | |||
230 | ||||
231 | OQueryDesignView* OSelectionBrowseBox::getDesignView() | |||
232 | { | |||
233 | OSL_ENSURE(static_cast<const OQueryDesignView*>(GetParent()),"Parent isn't an OQueryDesignView!")do { if (true && (!(static_cast<const OQueryDesignView *>(GetParent())))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "233" ": "), "%s", "Parent isn't an OQueryDesignView!"); } } while (false); | |||
234 | return static_cast<OQueryDesignView*>(GetParent()); | |||
235 | } | |||
236 | ||||
237 | OQueryDesignView* OSelectionBrowseBox::getDesignView() const | |||
238 | { | |||
239 | OSL_ENSURE(static_cast<const OQueryDesignView*>(GetParent()),"Parent isn't an OQueryDesignView!")do { if (true && (!(static_cast<const OQueryDesignView *>(GetParent())))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "239" ": "), "%s", "Parent isn't an OQueryDesignView!"); } } while (false); | |||
240 | return static_cast<OQueryDesignView*>(GetParent()); | |||
241 | } | |||
242 | ||||
243 | namespace | |||
244 | { | |||
245 | class OSelectionBrwBoxHeader : public ::svt::EditBrowserHeader | |||
246 | { | |||
247 | VclPtr<OSelectionBrowseBox> m_pBrowseBox; | |||
248 | protected: | |||
249 | virtual void Select() override; | |||
250 | public: | |||
251 | explicit OSelectionBrwBoxHeader(OSelectionBrowseBox* pParent); | |||
252 | virtual ~OSelectionBrwBoxHeader() override { disposeOnce(); } | |||
253 | virtual void dispose() override { m_pBrowseBox.clear(); ::svt::EditBrowserHeader::dispose(); } | |||
254 | }; | |||
255 | OSelectionBrwBoxHeader::OSelectionBrwBoxHeader(OSelectionBrowseBox* pParent) | |||
256 | : ::svt::EditBrowserHeader(pParent,WB_BUTTONSTYLE(WinBits(0x0800))|WB_DRAG) | |||
257 | ,m_pBrowseBox(pParent) | |||
258 | { | |||
259 | } | |||
260 | ||||
261 | void OSelectionBrwBoxHeader::Select() | |||
262 | { | |||
263 | EditBrowserHeader::Select(); | |||
264 | m_pBrowseBox->GrabFocus(); | |||
265 | ||||
266 | BrowserMode nMode = m_pBrowseBox->GetMode(); | |||
267 | if ( 0 == m_pBrowseBox->GetSelectColumnCount() ) | |||
268 | { | |||
269 | m_pBrowseBox->DeactivateCell(); | |||
270 | // we are in the right mode if a row has been selected row | |||
271 | if ( nMode & BrowserMode::HIDESELECT ) | |||
272 | { | |||
273 | nMode &= ~BrowserMode::HIDESELECT; | |||
274 | nMode |= BrowserMode::MULTISELECTION; | |||
275 | m_pBrowseBox->SetMode( nMode ); | |||
276 | } | |||
277 | } | |||
278 | m_pBrowseBox->SelectColumnId( GetCurItemId() ); | |||
279 | m_pBrowseBox->DeactivateCell(); | |||
280 | } | |||
281 | } | |||
282 | ||||
283 | VclPtr<BrowserHeader> OSelectionBrowseBox::imp_CreateHeaderBar(BrowseBox* /*pParent*/) | |||
284 | { | |||
285 | return VclPtr<OSelectionBrwBoxHeader>::Create(this); | |||
286 | } | |||
287 | ||||
288 | void OSelectionBrowseBox::ColumnMoved( sal_uInt16 nColId, bool _bCreateUndo ) | |||
289 | { | |||
290 | EditBrowseBox::ColumnMoved( nColId ); | |||
291 | // swap the two columns | |||
292 | sal_uInt16 nNewPos = GetColumnPos( nColId ); | |||
293 | OTableFields& rFields = getFields(); | |||
294 | if ( rFields.size() > o3tl::make_unsigned(nNewPos-1) ) | |||
295 | { | |||
296 | sal_uInt16 nOldPos = 0; | |||
297 | bool bFoundElem = false; | |||
298 | for (auto const& field : rFields) | |||
299 | { | |||
300 | if (field->GetColumnId() == nColId) | |||
301 | { | |||
302 | bFoundElem = true; | |||
303 | break; | |||
304 | } | |||
305 | ++nOldPos; | |||
306 | } | |||
307 | ||||
308 | OSL_ENSURE( (nNewPos-1) != nOldPos && nOldPos < rFields.size(),"Old and new position are equal!")do { if (true && (!((nNewPos-1) != nOldPos && nOldPos < rFields.size()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "308" ": "), "%s", "Old and new position are equal!"); } } while (false); | |||
309 | if (bFoundElem) | |||
310 | { | |||
311 | OTableFieldDescRef pOldEntry = rFields[nOldPos]; | |||
312 | rFields.erase(rFields.begin() + nOldPos); | |||
313 | rFields.insert(rFields.begin() + nNewPos - 1,pOldEntry); | |||
314 | ||||
315 | // create the undo action | |||
316 | if ( !m_bInUndoMode && _bCreateUndo ) | |||
317 | { | |||
318 | std::unique_ptr<OTabFieldMovedUndoAct> pUndoAct(new OTabFieldMovedUndoAct(this)); | |||
319 | pUndoAct->SetColumnPosition( nOldPos + 1); | |||
320 | pUndoAct->SetTabFieldDescr(pOldEntry); | |||
321 | ||||
322 | getDesignView()->getController().addUndoActionAndInvalidate(std::move(pUndoAct)); | |||
323 | } | |||
324 | } | |||
325 | } | |||
326 | else | |||
327 | OSL_FAIL("Invalid column id!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "327" ": "), "%s", "Invalid column id!"); } } while (false ); | |||
328 | } | |||
329 | ||||
330 | void OSelectionBrowseBox::Init() | |||
331 | { | |||
332 | ||||
333 | EditBrowseBox::Init(); | |||
334 | ||||
335 | // set the header bar | |||
336 | VclPtr<BrowserHeader> pNewHeaderBar = CreateHeaderBar(this); | |||
337 | pNewHeaderBar->SetMouseTransparent(false); | |||
338 | ||||
339 | SetHeaderBar(pNewHeaderBar); | |||
340 | SetMode(m_nMode); | |||
341 | ||||
342 | vcl::Font aFont( GetDataWindow().GetFont() ); | |||
343 | aFont.SetWeight( WEIGHT_NORMAL ); | |||
344 | GetDataWindow().SetFont( aFont ); | |||
345 | ||||
346 | Size aHeight; | |||
347 | const Control* pControls[] = { m_pTextCell,m_pVisibleCell,m_pTableCell,m_pFieldCell }; | |||
348 | ||||
349 | for (const Control* pControl : pControls) | |||
350 | { | |||
351 | const Size aTemp(pControl->GetOptimalSize()); | |||
352 | if ( aTemp.Height() > aHeight.Height() ) | |||
353 | aHeight.setHeight( aTemp.Height() ); | |||
354 | } | |||
355 | SetDataRowHeight(aHeight.Height()); | |||
356 | SetTitleLines(1); | |||
357 | // get number of visible rows | |||
358 | for(long i=0;i<BROW_ROW_CNT12;i++) | |||
359 | { | |||
360 | if(m_bVisibleRow[i]) | |||
361 | m_nVisibleCount++; | |||
362 | } | |||
363 | RowInserted(0, m_nVisibleCount, false); | |||
364 | try | |||
365 | { | |||
366 | Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection(); | |||
367 | if(xConnection.is()) | |||
368 | { | |||
369 | Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); | |||
370 | m_nMaxColumns = xMetaData.is() ? xMetaData->getMaxColumnsInSelect() : 0; | |||
371 | ||||
372 | } | |||
373 | else | |||
374 | m_nMaxColumns = 0; | |||
375 | } | |||
376 | catch(const SQLException&) | |||
377 | { | |||
378 | OSL_FAIL("Caught Exception when asking for database metadata options!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "378" ": "), "%s", "Caught Exception when asking for database metadata options!" ); } } while (false); | |||
379 | m_nMaxColumns = 0; | |||
380 | } | |||
381 | } | |||
382 | ||||
383 | void OSelectionBrowseBox::PreFill() | |||
384 | { | |||
385 | SetUpdateMode(false); | |||
386 | ||||
387 | if (GetCurRow() != 0) | |||
388 | GoToRow(0); | |||
389 | ||||
390 | static_cast< OQueryController& >( getDesignView()->getController() ).clearFields(); | |||
391 | ||||
392 | DeactivateCell(); | |||
393 | ||||
394 | RemoveColumns(); | |||
395 | InsertHandleColumn( HANDLE_COLUMN_WIDTH70 ); | |||
396 | SetUpdateMode(true); | |||
397 | } | |||
398 | ||||
399 | void OSelectionBrowseBox::ClearAll() | |||
400 | { | |||
401 | SetUpdateMode(false); | |||
402 | ||||
403 | OTableFields::const_reverse_iterator aIter = getFields().rbegin(); | |||
404 | for ( ;aIter != getFields().rend(); ++aIter ) | |||
405 | { | |||
406 | if ( !(*aIter)->IsEmpty() ) | |||
407 | { | |||
408 | RemoveField( (*aIter)->GetColumnId() ); | |||
409 | aIter = getFields().rbegin(); | |||
410 | } | |||
411 | } | |||
412 | m_nLastSortColumn = SORT_COLUMN_NONE0xFFFFFFFF; | |||
413 | SetUpdateMode(true); | |||
414 | } | |||
415 | ||||
416 | void OSelectionBrowseBox::SetReadOnly(bool bRO) | |||
417 | { | |||
418 | if (bRO) | |||
419 | { | |||
420 | DeactivateCell(); | |||
421 | m_nMode &= ~BrowserMode::HIDECURSOR; | |||
422 | SetMode(m_nMode); | |||
423 | } | |||
424 | else | |||
425 | { | |||
426 | m_nMode |= BrowserMode::HIDECURSOR; | |||
427 | SetMode(m_nMode); | |||
428 | ActivateCell(); | |||
429 | } | |||
430 | } | |||
431 | ||||
432 | CellController* OSelectionBrowseBox::GetController(long nRow, sal_uInt16 nColId) | |||
433 | { | |||
434 | if ( nColId > getFields().size() ) | |||
435 | return nullptr; | |||
436 | OTableFieldDescRef pEntry = getFields()[nColId-1]; | |||
437 | OSL_ENSURE(pEntry.is(), "OSelectionBrowseBox::GetController : invalid FieldDescription !")do { if (true && (!(pEntry.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "437" ": "), "%s", "OSelectionBrowseBox::GetController : invalid FieldDescription !" ); } } while (false); | |||
438 | ||||
439 | if (!pEntry.is()) | |||
440 | return nullptr; | |||
441 | ||||
442 | if (static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly()) | |||
443 | return nullptr; | |||
444 | ||||
445 | long nCellIndex = GetRealRow(nRow); | |||
446 | switch (nCellIndex) | |||
447 | { | |||
448 | case BROW_FIELD_ROW0: | |||
449 | return new ComboBoxCellController(m_pFieldCell); | |||
450 | case BROW_TABLE_ROW2: | |||
451 | return new ListBoxCellController(m_pTableCell); | |||
452 | case BROW_VIS_ROW4: | |||
453 | return new CheckBoxCellController(m_pVisibleCell); | |||
454 | case BROW_ORDER_ROW3: | |||
455 | return new ListBoxCellController(m_pOrderCell); | |||
456 | case BROW_FUNCTION_ROW5: | |||
457 | return new ListBoxCellController(m_pFunctionCell); | |||
458 | default: | |||
459 | return new EditCellController(m_pTextCell); | |||
460 | } | |||
461 | } | |||
462 | ||||
463 | void OSelectionBrowseBox::InitController(CellControllerRef& /*rController*/, long nRow, sal_uInt16 nColId) | |||
464 | { | |||
465 | OSL_ENSURE(nColId != BROWSER_INVALIDID,"An Invalid Id was set!")do { if (true && (!(nColId != ((sal_uInt16) 0xFFFF))) ) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "465" ": "), "%s", "An Invalid Id was set!"); } } while ( false); | |||
466 | if ( nColId == BROWSER_INVALIDID((sal_uInt16) 0xFFFF) ) | |||
467 | return; | |||
468 | sal_uInt16 nPos = GetColumnPos(nColId); | |||
469 | if ( nPos == 0 || nPos == BROWSER_INVALIDID((sal_uInt16) 0xFFFF) || nPos > getFields().size() ) | |||
470 | return; | |||
471 | OTableFieldDescRef pEntry = getFields()[nPos-1]; | |||
472 | OSL_ENSURE(pEntry.is(), "OSelectionBrowseBox::InitController : invalid FieldDescription !")do { if (true && (!(pEntry.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "472" ": "), "%s", "OSelectionBrowseBox::InitController : invalid FieldDescription !" ); } } while (false); | |||
473 | long nCellIndex = GetRealRow(nRow); | |||
474 | ||||
475 | switch (nCellIndex) | |||
476 | { | |||
477 | case BROW_FIELD_ROW0: | |||
478 | { | |||
479 | weld::ComboBox& rComboBox = m_pFieldCell->get_widget(); | |||
480 | rComboBox.clear(); | |||
481 | rComboBox.set_entry_text(OUString()); | |||
482 | ||||
483 | OUString aField(pEntry->GetField()); | |||
484 | OUString aTable(pEntry->GetAlias()); | |||
485 | ||||
486 | getDesignView()->fillValidFields(aTable, rComboBox); | |||
487 | ||||
488 | // replace with alias.* | |||
489 | if (aField.trim() == "*") | |||
490 | { | |||
491 | aField = aTable + ".*"; | |||
492 | } | |||
493 | rComboBox.set_entry_text(aField); | |||
494 | } break; | |||
495 | case BROW_TABLE_ROW2: | |||
496 | { | |||
497 | weld::ComboBox& rComboBox = m_pTableCell->get_widget(); | |||
498 | rComboBox.clear(); | |||
499 | enableControl(pEntry, m_pTableCell); | |||
500 | if ( !pEntry->isCondition() ) | |||
501 | { | |||
502 | for (auto const& tabWin : getDesignView()->getTableView()->GetTabWinMap()) | |||
503 | rComboBox.append_text(static_cast<OQueryTableWindow*>(tabWin.second.get())->GetAliasName()); | |||
504 | ||||
505 | rComboBox.insert_text(0, DBA_RES(STR_QUERY_NOTABLE)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_QUERY_NOTABLE" "\004" u8"(no table)") )); | |||
506 | if (!pEntry->GetAlias().isEmpty()) | |||
507 | rComboBox.set_active_text(pEntry->GetAlias()); | |||
508 | else | |||
509 | rComboBox.set_active_text(DBA_RES(STR_QUERY_NOTABLE)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_QUERY_NOTABLE" "\004" u8"(no table)") )); | |||
510 | } | |||
511 | } break; | |||
512 | case BROW_VIS_ROW4: | |||
513 | { | |||
514 | m_pVisibleCell->GetBox().set_active(pEntry->IsVisible()); | |||
515 | m_pVisibleCell->GetBox().save_state(); | |||
516 | ||||
517 | enableControl(pEntry,m_pTextCell); | |||
518 | ||||
519 | if(!pEntry->IsVisible() && pEntry->GetOrderDir() != ORDER_NONE && !m_bOrderByUnRelated) | |||
520 | { | |||
521 | // a column has to visible in order to show up in ORDER BY | |||
522 | pEntry->SetVisible(); | |||
523 | m_pVisibleCell->GetBox().set_active(pEntry->IsVisible()); | |||
524 | m_pVisibleCell->GetBox().save_state(); | |||
525 | m_pVisibleCell->GetBox().set_sensitive(false); | |||
526 | OUString aMessage(DBA_RES(STR_QRY_ORDERBY_UNRELATED)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_QRY_ORDERBY_UNRELATED" "\004" u8"The database only supports sorting for visible fields." ) )); | |||
527 | OQueryDesignView* paDView = getDesignView(); | |||
528 | std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(paDView ? paDView->GetFrameWeld() : nullptr, | |||
529 | VclMessageType::Info, VclButtonsType::Ok, | |||
530 | aMessage)); | |||
531 | xInfoBox->run(); | |||
532 | } | |||
533 | } break; | |||
534 | case BROW_ORDER_ROW3: | |||
535 | { | |||
536 | weld::ComboBox& rComboBox = m_pOrderCell->get_widget(); | |||
537 | rComboBox.set_active( | |||
538 | sal::static_int_cast< sal_uInt16 >(pEntry->GetOrderDir())); | |||
539 | enableControl(pEntry,m_pOrderCell); | |||
540 | break; | |||
541 | } | |||
542 | case BROW_COLUMNALIAS_ROW1: | |||
543 | setTextCellContext(pEntry,pEntry->GetFieldAlias(),HID_QRYDGN_ROW_ALIAS"DBACCESS_HID_QRYDGN_ROW_ALIAS"); | |||
544 | break; | |||
545 | case BROW_FUNCTION_ROW5: | |||
546 | setFunctionCell(pEntry); | |||
547 | break; | |||
548 | default: | |||
549 | { | |||
550 | sal_uInt16 nIdx = sal_uInt16(nCellIndex - BROW_CRIT1_ROW6); | |||
551 | setTextCellContext(pEntry,pEntry->GetCriteria( nIdx ),HID_QRYDGN_ROW_CRIT"DBACCESS_HID_QRYDGN_ROW_CRIT"); | |||
552 | } | |||
553 | } | |||
554 | Controller()->SaveValue(); | |||
555 | } | |||
556 | ||||
557 | void OSelectionBrowseBox::notifyTableFieldChanged(const OUString& _sOldAlias, const OUString& _sAlias, bool& _bListAction, sal_uInt16 _nColumnId) | |||
558 | { | |||
559 | appendUndoAction(_sOldAlias,_sAlias,BROW_TABLE_ROW2,_bListAction); | |||
560 | if ( m_bVisibleRow[BROW_TABLE_ROW2] ) | |||
561 | RowModified(GetBrowseRow(BROW_TABLE_ROW2), _nColumnId); | |||
562 | } | |||
563 | ||||
564 | void OSelectionBrowseBox::notifyFunctionFieldChanged(const OUString& _sOldFunctionName, const OUString& _sFunctionName, bool& _bListAction, sal_uInt16 _nColumnId) | |||
565 | { | |||
566 | appendUndoAction(_sOldFunctionName,_sFunctionName,BROW_FUNCTION_ROW5,_bListAction); | |||
567 | if ( !m_bVisibleRow[BROW_FUNCTION_ROW5] ) | |||
568 | SetRowVisible(BROW_FUNCTION_ROW5, true); | |||
569 | RowModified(GetBrowseRow(BROW_FUNCTION_ROW5), _nColumnId); | |||
570 | } | |||
571 | ||||
572 | void OSelectionBrowseBox::clearEntryFunctionField(const OUString& _sFieldName,OTableFieldDescRef const & _pEntry, bool& _bListAction,sal_uInt16 _nColumnId) | |||
573 | { | |||
574 | if ( !(isFieldNameAsterisk( _sFieldName ) && (!_pEntry->isNoneFunction() || _pEntry->IsGroupBy())) ) | |||
575 | return; | |||
576 | ||||
577 | OUString sFunctionName; | |||
578 | GetFunctionName(SQL_TOKEN_COUNT,sFunctionName); | |||
579 | OUString sOldLocalizedFunctionName = _pEntry->GetFunction(); | |||
580 | if ( sOldLocalizedFunctionName != sFunctionName || _pEntry->IsGroupBy() ) | |||
581 | { | |||
582 | // append undo action for the function field | |||
583 | _pEntry->SetFunctionType(FKT_NONE); | |||
584 | _pEntry->SetFunction(OUString()); | |||
585 | _pEntry->SetGroupBy(false); | |||
586 | notifyFunctionFieldChanged(sOldLocalizedFunctionName,_pEntry->GetFunction(),_bListAction,_nColumnId); | |||
587 | } | |||
588 | } | |||
589 | ||||
590 | bool OSelectionBrowseBox::fillColumnRef(const OSQLParseNode* _pColumnRef, const Reference< XConnection >& _rxConnection, OTableFieldDescRef const & _pEntry, bool& _bListAction ) | |||
591 | { | |||
592 | OSL_ENSURE(_pColumnRef,"No valid parsenode!")do { if (true && (!(_pColumnRef))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "592" ": "), "%s", "No valid parsenode!"); } } while (false ); | |||
593 | OUString sColumnName,sTableRange; | |||
594 | OSQLParseTreeIterator::getColumnRange(_pColumnRef,_rxConnection,sColumnName,sTableRange); | |||
595 | return fillColumnRef(sColumnName,sTableRange,_rxConnection->getMetaData(),_pEntry,_bListAction); | |||
596 | } | |||
597 | ||||
598 | bool OSelectionBrowseBox::fillColumnRef(const OUString& _sColumnName, const OUString& _sTableRange, const Reference<XDatabaseMetaData>& _xMetaData, OTableFieldDescRef const & _pEntry, bool& _bListAction) | |||
599 | { | |||
600 | bool bError = false; | |||
601 | ::comphelper::UStringMixEqual bCase(_xMetaData->supportsMixedCaseQuotedIdentifiers()); | |||
602 | // check if the table name is the same | |||
603 | if ( !_sTableRange.isEmpty() && (bCase(_pEntry->GetTable(),_sTableRange) || bCase(_pEntry->GetAlias(),_sTableRange)) ) | |||
604 | { // a table was already inserted and the tables contains that column name | |||
605 | ||||
606 | if ( !_pEntry->GetTabWindow() ) | |||
607 | { // fill tab window | |||
608 | OUString sOldAlias = _pEntry->GetAlias(); | |||
609 | if ( !fillEntryTable(_pEntry,_pEntry->GetTable()) ) | |||
610 | fillEntryTable(_pEntry,_pEntry->GetAlias()); // only when the first failed | |||
611 | if ( !bCase(sOldAlias,_pEntry->GetAlias()) ) | |||
612 | notifyTableFieldChanged(sOldAlias,_pEntry->GetAlias(),_bListAction,GetCurColumnId()); | |||
613 | } | |||
614 | } | |||
615 | // check if the table window | |||
616 | OQueryTableWindow* pEntryTab = static_cast<OQueryTableWindow*>(_pEntry->GetTabWindow()); | |||
617 | if ( !pEntryTab ) // no table found with this name so we have to travel through all tables | |||
618 | { | |||
619 | sal_uInt16 nTabCount = 0; | |||
620 | if ( !static_cast<OQueryTableView*>(getDesignView()->getTableView())->FindTableFromField(_sColumnName,_pEntry,nTabCount) ) // error occurred: column not in table window | |||
621 | { | |||
622 | OUString sErrorMsg(DBA_RES(RID_STR_FIELD_DOESNT_EXIST)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("RID_STR_FIELD_DOESNT_EXIST" "\004" u8"Invalid expression, field name '$name$' does not exist." ) )); | |||
623 | sErrorMsg = sErrorMsg.replaceFirst("$name$",_sColumnName); | |||
624 | OSQLErrorBox aWarning(GetFrameWeld(), sErrorMsg); | |||
625 | aWarning.run(); | |||
626 | bError = true; | |||
627 | } | |||
628 | else | |||
629 | { | |||
630 | pEntryTab = static_cast<OQueryTableWindow*>(_pEntry->GetTabWindow()); | |||
631 | notifyTableFieldChanged(OUString(),_pEntry->GetAlias(),_bListAction,GetCurColumnId()); | |||
632 | } | |||
633 | } | |||
634 | if ( pEntryTab ) // here we got a valid table | |||
635 | _pEntry->SetField(_sColumnName); | |||
636 | ||||
637 | return bError; | |||
638 | } | |||
639 | ||||
640 | bool OSelectionBrowseBox::saveField(OUString& _sFieldName ,OTableFieldDescRef const & _pEntry, bool& _bListAction) | |||
641 | { | |||
642 | bool bError = false; | |||
643 | ||||
644 | OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController()); | |||
645 | ||||
646 | // first look if the name can be found in our tables | |||
647 | sal_uInt16 nTabCount = 0; | |||
648 | OUString sOldAlias = _pEntry->GetAlias(); | |||
649 | if ( static_cast<OQueryTableView*>(getDesignView()->getTableView())->FindTableFromField(_sFieldName,_pEntry,nTabCount) ) | |||
650 | { | |||
651 | // append undo action for the alias name | |||
652 | _pEntry->SetField(_sFieldName); | |||
653 | notifyTableFieldChanged(sOldAlias,_pEntry->GetAlias(),_bListAction,GetCurColumnId()); | |||
654 | clearEntryFunctionField(_sFieldName,_pEntry,_bListAction,_pEntry->GetColumnId()); | |||
655 | return bError; | |||
656 | } | |||
657 | ||||
658 | Reference<XConnection> xConnection( rController.getConnection() ); | |||
659 | Reference< XDatabaseMetaData > xMetaData; | |||
660 | if ( xConnection.is() ) | |||
661 | xMetaData = xConnection->getMetaData(); | |||
662 | OSL_ENSURE( xMetaData.is(), "OSelectionBrowseBox::saveField: invalid connection/meta data!" )do { if (true && (!(xMetaData.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "662" ": "), "%s", "OSelectionBrowseBox::saveField: invalid connection/meta data!" ); } } while (false); | |||
663 | if ( !xMetaData.is() ) | |||
664 | return true; | |||
665 | ||||
666 | OUString sErrorMsg; | |||
667 | // second test if the name can be set as select columns in a pseudo statement | |||
668 | // we have to look which entries we should quote | |||
669 | ||||
670 | const OUString sFieldAlias = _pEntry->GetFieldAlias(); | |||
671 | ::connectivity::OSQLParser& rParser( rController.getParser() ); | |||
672 | { | |||
673 | // automatically add parentheses around subqueries | |||
674 | OUString devnull; | |||
675 | std::unique_ptr<OSQLParseNode> pParseNode = rParser.parseTree( devnull, _sFieldName, true ); | |||
676 | if (pParseNode == nullptr) | |||
677 | pParseNode = rParser.parseTree( devnull, _sFieldName ); | |||
678 | if (pParseNode != nullptr && SQL_ISRULE(pParseNode, select_statement)((pParseNode)->isRule() && (pParseNode)->getRuleID () == OSQLParser::RuleID(OSQLParseNode::select_statement))) | |||
679 | _sFieldName = "(" + _sFieldName + ")"; | |||
680 | } | |||
681 | ||||
682 | std::unique_ptr<OSQLParseNode> pParseNode; | |||
683 | { | |||
684 | // 4 passes in trying to interpret the field name | |||
685 | // - don't quote the field name, parse internationally | |||
686 | // - don't quote the field name, parse en-US | |||
687 | // - quote the field name, parse internationally | |||
688 | // - quote the field name, parse en-US | |||
689 | size_t nPass = 4; | |||
690 | OUString sQuotedFullFieldName(::dbtools::quoteName( xMetaData->getIdentifierQuoteString(), _sFieldName )); | |||
691 | OUString sFullFieldName(_sFieldName); | |||
692 | ||||
693 | if ( _pEntry->isAggregateFunction() ) | |||
694 | { | |||
695 | OSL_ENSURE(!_pEntry->GetFunction().isEmpty(),"No empty Function name allowed here! ;-(")do { if (true && (!(!_pEntry->GetFunction().isEmpty ()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "695" ": "), "%s", "No empty Function name allowed here! ;-(" ); } } while (false); | |||
696 | sQuotedFullFieldName = _pEntry->GetFunction() + "(" + sQuotedFullFieldName + ")"; | |||
697 | sFullFieldName = _pEntry->GetFunction() + "(" + sFullFieldName + ")"; | |||
698 | } | |||
699 | ||||
700 | do | |||
701 | { | |||
702 | bool bQuote = ( nPass <= 2 ); | |||
703 | bool bInternational = ( nPass % 2 ) == 0; | |||
704 | ||||
705 | OUString sSql {"SELECT "}; | |||
706 | if ( bQuote ) | |||
707 | sSql += sQuotedFullFieldName; | |||
708 | else | |||
709 | sSql += sFullFieldName; | |||
710 | ||||
711 | if ( !sFieldAlias.isEmpty() ) | |||
712 | { // always quote the alias name: there cannot be a function in it | |||
713 | sSql += " " + ::dbtools::quoteName( xMetaData->getIdentifierQuoteString(), sFieldAlias ); | |||
714 | } | |||
715 | sSql += " FROM x"; | |||
716 | ||||
717 | pParseNode = rParser.parseTree( sErrorMsg, sSql, bInternational ); | |||
718 | } | |||
719 | while ( ( pParseNode == nullptr ) && ( --nPass > 0 ) ); | |||
720 | } | |||
721 | ||||
722 | if ( pParseNode == nullptr ) | |||
723 | { | |||
724 | // something different which we have to check | |||
725 | OUString sErrorMessage( DBA_RES( STR_QRY_COLUMN_NOT_FOUND )::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_QRY_COLUMN_NOT_FOUND" "\004" u8"The column '$name$' is unknown." ) ) ); | |||
726 | sErrorMessage = sErrorMessage.replaceFirst("$name$",_sFieldName); | |||
727 | OSQLErrorBox aWarning(GetFrameWeld(), sErrorMessage); | |||
728 | aWarning.run(); | |||
729 | ||||
730 | return true; | |||
731 | } | |||
732 | ||||
733 | // we got a valid select column | |||
734 | // find what type of column has be inserted | |||
735 | ::connectivity::OSQLParseNode* pSelection = pParseNode->getChild(2); | |||
736 | if ( SQL_ISRULE(pSelection,selection)((pSelection)->isRule() && (pSelection)->getRuleID () == OSQLParser::RuleID(OSQLParseNode::selection)) ) // we found the asterisk | |||
737 | { | |||
738 | _pEntry->SetField(_sFieldName); | |||
739 | clearEntryFunctionField(_sFieldName,_pEntry,_bListAction,_pEntry->GetColumnId()); | |||
740 | } | |||
741 | else // travel through the select column parse node | |||
742 | { | |||
743 | OTableFieldDescRef aSelEntry = _pEntry; | |||
744 | sal_uInt16 nColumnId = aSelEntry->GetColumnId(); | |||
745 | ||||
746 | sal_uInt32 nCount = pSelection->count(); | |||
747 | for (sal_uInt32 i = 0; i < nCount; ++i) | |||
748 | { | |||
749 | if ( i > 0 ) // may we have to append more than one field | |||
750 | { | |||
751 | sal_uInt16 nColumnPosition; | |||
752 | aSelEntry = FindFirstFreeCol(nColumnPosition); | |||
753 | if ( !aSelEntry.is() ) | |||
754 | { | |||
755 | AppendNewCol(); | |||
756 | aSelEntry = FindFirstFreeCol(nColumnPosition); | |||
757 | } | |||
758 | ++nColumnPosition; | |||
759 | nColumnId = GetColumnId(nColumnPosition); | |||
760 | } | |||
761 | ||||
762 | ::connectivity::OSQLParseNode* pChild = pSelection->getChild( i ); | |||
763 | OSL_ENSURE(SQL_ISRULE(pChild,derived_column), "No derived column found!")do { if (true && (!(((pChild)->isRule() && (pChild)->getRuleID() == OSQLParser::RuleID(OSQLParseNode ::derived_column))))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "763" ": "), "%s", "No derived column found!"); } } while (false); | |||
764 | // get the column alias | |||
765 | OUString sColumnAlias = OSQLParseTreeIterator::getColumnAlias(pChild); | |||
766 | if ( !sColumnAlias.isEmpty() ) // we found an as clause | |||
767 | { | |||
768 | OUString aSelectionAlias = aSelEntry->GetFieldAlias(); | |||
769 | aSelEntry->SetFieldAlias( sColumnAlias ); | |||
770 | // append undo | |||
771 | appendUndoAction(aSelectionAlias,aSelEntry->GetFieldAlias(),BROW_COLUMNALIAS_ROW1,_bListAction); | |||
772 | if ( m_bVisibleRow[BROW_COLUMNALIAS_ROW1] ) | |||
773 | RowModified(GetBrowseRow(BROW_COLUMNALIAS_ROW1), nColumnId); | |||
774 | } | |||
775 | ||||
776 | ::connectivity::OSQLParseNode* pColumnRef = pChild->getChild(0); | |||
777 | if ( | |||
778 | pColumnRef->getKnownRuleID() != OSQLParseNode::subquery && | |||
779 | pColumnRef->count() == 3 && | |||
780 | SQL_ISPUNCTUATION(pColumnRef->getChild(0),"(")((pColumnRef->getChild(0))->getNodeType() == SQLNodeType ::Punctuation && (pColumnRef->getChild(0))->getTokenValue () == ("(")) && | |||
781 | SQL_ISPUNCTUATION(pColumnRef->getChild(2),")")((pColumnRef->getChild(2))->getNodeType() == SQLNodeType ::Punctuation && (pColumnRef->getChild(2))->getTokenValue () == (")")) | |||
782 | ) | |||
783 | pColumnRef = pColumnRef->getChild(1); | |||
784 | ||||
785 | if ( SQL_ISRULE(pColumnRef,column_ref)((pColumnRef)->isRule() && (pColumnRef)->getRuleID () == OSQLParser::RuleID(OSQLParseNode::column_ref)) ) // we found a valid column name or more column names | |||
786 | { | |||
787 | // look if we can find the corresponding table | |||
788 | bError = fillColumnRef( pColumnRef, xConnection, aSelEntry, _bListAction ); | |||
789 | ||||
790 | // we found a simple column so we must clear the function fields but only when the column name is '*' | |||
791 | // and the function is different to count | |||
792 | clearEntryFunctionField(_sFieldName,aSelEntry,_bListAction,nColumnId); | |||
793 | } | |||
794 | // do we have an aggregate function and only a function? | |||
795 | else if ( SQL_ISRULE(pColumnRef,general_set_fct)((pColumnRef)->isRule() && (pColumnRef)->getRuleID () == OSQLParser::RuleID(OSQLParseNode::general_set_fct)) ) | |||
796 | { | |||
797 | OUString sLocalizedFunctionName; | |||
798 | if ( GetFunctionName(pColumnRef->getChild(0)->getTokenID(),sLocalizedFunctionName) ) | |||
799 | { | |||
800 | OUString sOldLocalizedFunctionName = aSelEntry->GetFunction(); | |||
801 | aSelEntry->SetFunction(sLocalizedFunctionName); | |||
802 | sal_uInt32 nFunCount = pColumnRef->count() - 1; | |||
803 | sal_Int32 nFunctionType = FKT_AGGREGATE; | |||
804 | bool bQuote = false; | |||
805 | // may be there exists only one parameter which is a column, fill all information into our fields | |||
806 | if ( nFunCount == 4 && SQL_ISRULE(pColumnRef->getChild(3),column_ref)((pColumnRef->getChild(3))->isRule() && (pColumnRef ->getChild(3))->getRuleID() == OSQLParser::RuleID(OSQLParseNode ::column_ref)) ) | |||
807 | bError = fillColumnRef( pColumnRef->getChild(3), xConnection, aSelEntry, _bListAction ); | |||
808 | else if ( nFunCount == 3 ) // we have a COUNT(*) here, so take the first table | |||
809 | bError = fillColumnRef( "*", OUString(), xMetaData, aSelEntry, _bListAction ); | |||
810 | else | |||
811 | { | |||
812 | nFunctionType |= FKT_NUMERIC; | |||
813 | bQuote = true; | |||
814 | aSelEntry->SetDataType(DataType::DOUBLE); | |||
815 | aSelEntry->SetFieldType(TAB_NORMAL_FIELD); | |||
816 | } | |||
817 | ||||
818 | // now parse the parameters | |||
819 | OUString sParameters; | |||
820 | for(sal_uInt32 function = 2; function < nFunCount; ++function) // we only want to parse the parameters of the function | |||
821 | pColumnRef->getChild(function)->parseNodeToStr( sParameters, xConnection, &rParser.getContext(), true, bQuote ); | |||
822 | ||||
823 | aSelEntry->SetFunctionType(nFunctionType); | |||
824 | aSelEntry->SetField(sParameters); | |||
825 | if ( aSelEntry->IsGroupBy() ) | |||
826 | { | |||
827 | sOldLocalizedFunctionName = m_aFunctionStrings.copy(m_aFunctionStrings.lastIndexOf(';')+1); | |||
828 | aSelEntry->SetGroupBy(false); | |||
829 | } | |||
830 | ||||
831 | // append undo action | |||
832 | notifyFunctionFieldChanged(sOldLocalizedFunctionName,sLocalizedFunctionName,_bListAction, nColumnId); | |||
833 | } | |||
834 | else | |||
835 | OSL_FAIL("Unsupported function inserted!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "835" ": "), "%s", "Unsupported function inserted!"); } } while (false); | |||
836 | ||||
837 | } | |||
838 | else | |||
839 | { | |||
840 | // so we first clear the function field | |||
841 | clearEntryFunctionField(_sFieldName,aSelEntry,_bListAction,nColumnId); | |||
842 | OUString sFunction; | |||
843 | pColumnRef->parseNodeToStr( sFunction, | |||
844 | xConnection, | |||
845 | &rController.getParser().getContext(), | |||
846 | true); // quote is to true because we need quoted elements inside the function | |||
847 | ||||
848 | getDesignView()->fillFunctionInfo(pColumnRef,sFunction,aSelEntry); | |||
849 | ||||
850 | if( SQL_ISRULEOR3(pColumnRef, position_exp, extract_exp, fold)((pColumnRef)->isRule() && ( (pColumnRef)->getRuleID () == OSQLParser::RuleID(OSQLParseNode::position_exp) || (pColumnRef )->getRuleID() == OSQLParser::RuleID(OSQLParseNode::extract_exp ) || (pColumnRef)->getRuleID() == OSQLParser::RuleID(OSQLParseNode ::fold))) || | |||
851 | SQL_ISRULEOR3(pColumnRef, char_substring_fct, length_exp, char_value_fct)((pColumnRef)->isRule() && ( (pColumnRef)->getRuleID () == OSQLParser::RuleID(OSQLParseNode::char_substring_fct) || (pColumnRef)->getRuleID() == OSQLParser::RuleID(OSQLParseNode ::length_exp) || (pColumnRef)->getRuleID() == OSQLParser:: RuleID(OSQLParseNode::char_value_fct))) ) | |||
852 | // a calculation has been found ( can be calc and function ) | |||
853 | { | |||
854 | // now parse the whole statement | |||
855 | sal_uInt32 nFunCount = pColumnRef->count(); | |||
856 | OUString sParameters; | |||
857 | for(sal_uInt32 function = 0; function < nFunCount; ++function) | |||
858 | pColumnRef->getChild(function)->parseNodeToStr( sParameters, xConnection, &rParser.getContext(), true ); | |||
859 | ||||
860 | sOldAlias = aSelEntry->GetAlias(); | |||
861 | sal_Int32 nNewFunctionType = aSelEntry->GetFunctionType() | FKT_NUMERIC | FKT_OTHER; | |||
862 | aSelEntry->SetFunctionType(nNewFunctionType); | |||
863 | aSelEntry->SetField(sParameters); | |||
864 | } | |||
865 | else | |||
866 | { | |||
867 | aSelEntry->SetFieldAlias(sColumnAlias); | |||
868 | if ( SQL_ISRULE(pColumnRef,set_fct_spec)((pColumnRef)->isRule() && (pColumnRef)->getRuleID () == OSQLParser::RuleID(OSQLParseNode::set_fct_spec)) ) | |||
869 | aSelEntry->SetFunctionType(/*FKT_NUMERIC | */FKT_OTHER); | |||
870 | else | |||
871 | aSelEntry->SetFunctionType(FKT_NUMERIC | FKT_OTHER); | |||
872 | } | |||
873 | ||||
874 | aSelEntry->SetAlias(OUString()); | |||
875 | notifyTableFieldChanged(sOldAlias,aSelEntry->GetAlias(),_bListAction, nColumnId); | |||
876 | } | |||
877 | ||||
878 | if ( i > 0 && !InsertField(aSelEntry,BROWSER_INVALIDID((sal_uInt16) 0xFFFF),true,false).is() ) // may we have to append more than one field | |||
879 | { // the field could not be inserted | |||
880 | OUString sErrorMessage( DBA_RES( RID_STR_FIELD_DOESNT_EXIST )::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("RID_STR_FIELD_DOESNT_EXIST" "\004" u8"Invalid expression, field name '$name$' does not exist." ) ) ); | |||
881 | sErrorMessage = sErrorMessage.replaceFirst("$name$",aSelEntry->GetField()); | |||
882 | OSQLErrorBox aWarning(GetFrameWeld(), sErrorMessage); | |||
883 | aWarning.run(); | |||
884 | bError = true; | |||
885 | } | |||
886 | } | |||
887 | } | |||
888 | ||||
889 | return bError; | |||
890 | } | |||
891 | ||||
892 | bool OSelectionBrowseBox::SaveModified() | |||
893 | { | |||
894 | OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController()); | |||
895 | OTableFieldDescRef pEntry; | |||
896 | sal_uInt16 nCurrentColumnPos = GetColumnPos(GetCurColumnId()); | |||
897 | if(getFields().size() > o3tl::make_unsigned(nCurrentColumnPos - 1)) | |||
898 | pEntry = getEntry(nCurrentColumnPos - 1); | |||
899 | ||||
900 | bool bWasEmpty = pEntry.is() && pEntry->IsEmpty(); | |||
901 | bool bError = false; | |||
902 | bool bListAction = false; | |||
903 | ||||
904 | if (pEntry.is() && Controller().is() && Controller()->IsValueChangedFromSaved()) | |||
905 | { | |||
906 | // for the Undo-action | |||
907 | OUString strOldCellContents,sNewValue; | |||
908 | long nRow = GetRealRow(GetCurRow()); | |||
909 | bool bAppendRow = false; | |||
910 | switch (nRow) | |||
911 | { | |||
912 | case BROW_VIS_ROW4: | |||
913 | { | |||
914 | bool bOldValue = m_pVisibleCell->GetBox().get_saved_state() != TRISTATE_FALSE; | |||
915 | strOldCellContents = bOldValue ? OUStringLiteral(u"1") : OUStringLiteral(u"0"); | |||
916 | sNewValue = !bOldValue ? OUStringLiteral(u"1") : OUStringLiteral(u"0"); | |||
917 | } | |||
918 | if((m_bOrderByUnRelated || pEntry->GetOrderDir() == ORDER_NONE) && | |||
919 | (m_bGroupByUnRelated || !pEntry->IsGroupBy())) | |||
920 | { | |||
921 | pEntry->SetVisible(m_pVisibleCell->GetBox().get_active()); | |||
922 | } | |||
923 | else | |||
924 | { | |||
925 | pEntry->SetVisible(); | |||
926 | m_pVisibleCell->GetBox().set_active(true); | |||
927 | } | |||
928 | break; | |||
929 | ||||
930 | case BROW_FIELD_ROW0: | |||
931 | { | |||
932 | weld::ComboBox& rComboBox = m_pFieldCell->get_widget(); | |||
933 | OUString aFieldName(rComboBox.get_active_text()); | |||
934 | try | |||
935 | { | |||
936 | if (aFieldName.isEmpty()) | |||
937 | { | |||
938 | OTableFieldDescRef pNewEntry = new OTableFieldDesc(); | |||
939 | pNewEntry->SetColumnId( pEntry->GetColumnId() ); | |||
940 | std::replace(getFields().begin(),getFields().end(),pEntry,pNewEntry); | |||
941 | sal_uInt16 nCol = GetCurColumnId(); | |||
942 | for (int i = 0; i < m_nVisibleCount; i++) // redraw column | |||
943 | RowModified(i,nCol); | |||
944 | } | |||
945 | else | |||
946 | { | |||
947 | strOldCellContents = pEntry->GetField(); | |||
948 | bListAction = true; | |||
949 | if ( !m_bInUndoMode ) | |||
950 | rController.GetUndoManager().EnterListAction(OUString(),OUString(),0,ViewShellId(-1)); | |||
951 | ||||
952 | sal_Int32 nPos = rComboBox.find_text(aFieldName); | |||
953 | OUString aAliasName = pEntry->GetAlias(); | |||
954 | if ( nPos != -1 && aAliasName.isEmpty() && aFieldName.indexOf('.') >= 0 ) | |||
955 | { // special case, we have a table field so we must cut the table name | |||
956 | OUString sTableAlias = aFieldName.getToken(0,'.'); | |||
957 | pEntry->SetAlias(sTableAlias); | |||
958 | OUString sColumnName = aFieldName.copy(sTableAlias.getLength()+1); | |||
959 | const Reference<XConnection>& xConnection = rController.getConnection(); | |||
960 | if ( !xConnection.is() ) | |||
961 | return false; | |||
962 | bError = fillColumnRef( sColumnName, sTableAlias, xConnection->getMetaData(), pEntry, bListAction ); | |||
963 | } | |||
964 | else | |||
965 | bError = true; | |||
966 | ||||
967 | if ( bError ) | |||
968 | bError = saveField(aFieldName,pEntry,bListAction); | |||
969 | } | |||
970 | } | |||
971 | catch(Exception&) | |||
972 | { | |||
973 | bError = true; | |||
974 | } | |||
975 | if ( bError ) | |||
976 | { | |||
977 | sNewValue = aFieldName; | |||
978 | if ( !m_bInUndoMode ) | |||
979 | static_cast<OQueryController&>(getDesignView()->getController()).GetUndoManager().LeaveListAction(); | |||
980 | bListAction = false; | |||
981 | } | |||
982 | else | |||
983 | sNewValue = pEntry->GetField(); | |||
984 | rController.InvalidateFeature( ID_BROWSER_QUERY_EXECUTE( 10000 + 721 ) ); | |||
985 | } | |||
986 | break; | |||
987 | ||||
988 | case BROW_TABLE_ROW2: | |||
989 | { | |||
990 | weld::ComboBox& rComboBox = m_pTableCell->get_widget(); | |||
991 | OUString aAliasName = rComboBox.get_active_text(); | |||
992 | strOldCellContents = pEntry->GetAlias(); | |||
993 | if (rComboBox.get_active() != 0) | |||
994 | { | |||
995 | pEntry->SetAlias(aAliasName); | |||
996 | // we have to set the table name as well as the table window | |||
997 | OJoinTableView::OTableWindowMap& rTabWinList = getDesignView()->getTableView()->GetTabWinMap(); | |||
998 | OJoinTableView::OTableWindowMap::const_iterator aIter = rTabWinList.find(aAliasName); | |||
999 | if(aIter != rTabWinList.end()) | |||
1000 | { | |||
1001 | OQueryTableWindow* pEntryTab = static_cast<OQueryTableWindow*>(aIter->second.get()); | |||
1002 | if (pEntryTab) | |||
1003 | { | |||
1004 | pEntry->SetTable(pEntryTab->GetTableName()); | |||
1005 | pEntry->SetTabWindow(pEntryTab); | |||
1006 | } | |||
1007 | } | |||
1008 | } | |||
1009 | else | |||
1010 | { | |||
1011 | pEntry->SetAlias(OUString()); | |||
1012 | pEntry->SetTable(OUString()); | |||
1013 | pEntry->SetTabWindow(nullptr); | |||
1014 | } | |||
1015 | sNewValue = pEntry->GetAlias(); | |||
1016 | ||||
1017 | } break; | |||
1018 | ||||
1019 | case BROW_ORDER_ROW3: | |||
1020 | { | |||
1021 | strOldCellContents = OUString::number(static_cast<sal_uInt16>(pEntry->GetOrderDir())); | |||
1022 | weld::ComboBox& rComboBox = m_pOrderCell->get_widget(); | |||
1023 | sal_Int32 nIdx = rComboBox.get_active(); | |||
1024 | if (nIdx == -1) | |||
1025 | nIdx = 0; | |||
1026 | pEntry->SetOrderDir(EOrderDir(nIdx)); | |||
1027 | if(!m_bOrderByUnRelated) | |||
1028 | { | |||
1029 | pEntry->SetVisible(); | |||
1030 | m_pVisibleCell->GetBox().set_active(true); | |||
1031 | RowModified(GetBrowseRow(BROW_VIS_ROW4), GetCurColumnId()); | |||
1032 | } | |||
1033 | sNewValue = OUString::number(static_cast<sal_uInt16>(pEntry->GetOrderDir())); | |||
1034 | } break; | |||
1035 | ||||
1036 | case BROW_COLUMNALIAS_ROW1: | |||
1037 | strOldCellContents = pEntry->GetFieldAlias(); | |||
1038 | pEntry->SetFieldAlias(m_pTextCell->get_widget().get_text()); | |||
1039 | sNewValue = pEntry->GetFieldAlias(); | |||
1040 | break; | |||
1041 | case BROW_FUNCTION_ROW5: | |||
1042 | { | |||
1043 | strOldCellContents = pEntry->GetFunction(); | |||
1044 | weld::ComboBox& rComboBox = m_pFunctionCell->get_widget(); | |||
1045 | sal_Int32 nPos = rComboBox.get_active(); | |||
1046 | // these functions are only available in CORE | |||
1047 | OUString sFunctionName = rComboBox.get_text(nPos); | |||
1048 | OUString sGroupFunctionName = m_aFunctionStrings.copy(m_aFunctionStrings.lastIndexOf(';')+1); | |||
1049 | bool bGroupBy = false; | |||
1050 | if ( sGroupFunctionName == sFunctionName ) // check if the function name is GROUP | |||
1051 | { | |||
1052 | bGroupBy = true; | |||
1053 | ||||
1054 | if ( !m_bGroupByUnRelated && !pEntry->IsVisible() ) | |||
1055 | { | |||
1056 | // we have to change the visible flag, so we must append also an undo action | |||
1057 | pEntry->SetVisible(); | |||
1058 | m_pVisibleCell->GetBox().set_active(true); | |||
1059 | appendUndoAction("0","1",BROW_VIS_ROW4,bListAction); | |||
1060 | RowModified(GetBrowseRow(BROW_VIS_ROW4), GetCurColumnId()); | |||
1061 | } | |||
1062 | ||||
1063 | pEntry->SetFunction(OUString()); | |||
1064 | pEntry->SetFunctionType(pEntry->GetFunctionType() & ~FKT_AGGREGATE ); | |||
1065 | } | |||
1066 | else if ( nPos ) // we found an aggregate function | |||
1067 | { | |||
1068 | pEntry->SetFunctionType(pEntry->GetFunctionType() | FKT_AGGREGATE ); | |||
1069 | pEntry->SetFunction(sFunctionName); | |||
1070 | } | |||
1071 | else | |||
1072 | { | |||
1073 | sFunctionName.clear(); | |||
1074 | pEntry->SetFunction(OUString()); | |||
1075 | pEntry->SetFunctionType(pEntry->GetFunctionType() & ~FKT_AGGREGATE ); | |||
1076 | } | |||
1077 | ||||
1078 | pEntry->SetGroupBy(bGroupBy); | |||
1079 | ||||
1080 | sNewValue = sFunctionName; | |||
1081 | } | |||
1082 | break; | |||
1083 | default: | |||
1084 | { | |||
1085 | Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection(); | |||
1086 | if(!xConnection.is()) | |||
1087 | break; | |||
1088 | ||||
1089 | sal_uInt16 nIdx = sal_uInt16(nRow - BROW_CRIT1_ROW6); | |||
1090 | OUString aText = comphelper::string::stripStart(m_pTextCell->get_widget().get_text(), ' '); | |||
1091 | ||||
1092 | OUString aCrit; | |||
1093 | if(!aText.isEmpty()) | |||
1094 | { | |||
1095 | OUString aErrorMsg; | |||
1096 | Reference<XPropertySet> xColumn; | |||
1097 | std::unique_ptr<OSQLParseNode> pParseNode = getDesignView()->getPredicateTreeFromEntry(pEntry,aText,aErrorMsg,xColumn); | |||
1098 | ||||
1099 | if (pParseNode) | |||
1100 | { | |||
1101 | pParseNode->parseNodeToPredicateStr(aCrit, | |||
1102 | xConnection, | |||
1103 | static_cast<OQueryController&>(getDesignView()->getController()).getNumberFormatter(), | |||
1104 | xColumn, | |||
1105 | pEntry->GetAlias(), | |||
1106 | getDesignView()->getLocale(), | |||
1107 | getDesignView()->getDecimalSeparator(), | |||
1108 | &(static_cast<OQueryController&>(getDesignView()->getController()).getParser().getContext())); | |||
1109 | } | |||
1110 | else | |||
1111 | { | |||
1112 | if(xColumn.is()) | |||
1113 | { | |||
1114 | sal_Int32 nType = 0; | |||
1115 | xColumn->getPropertyValue(PROPERTY_TYPE"Type") >>= nType; | |||
1116 | switch(nType) | |||
1117 | { | |||
1118 | case DataType::CHAR: | |||
1119 | case DataType::VARCHAR: | |||
1120 | case DataType::LONGVARCHAR: | |||
1121 | case DataType::CLOB: | |||
1122 | if(!aText.startsWith("'") || !aText.endsWith("'")) | |||
1123 | { | |||
1124 | aText = aText.replaceAll("'", "''"); | |||
1125 | aText = "'" + aText + "'"; | |||
1126 | } | |||
1127 | break; | |||
1128 | default: | |||
1129 | ; | |||
1130 | } | |||
1131 | ::connectivity::OSQLParser& rParser = static_cast<OQueryController&>(getDesignView()->getController()).getParser(); | |||
1132 | pParseNode = rParser.predicateTree(aErrorMsg, | |||
1133 | aText, | |||
1134 | static_cast<OQueryController&>(getDesignView()->getController()).getNumberFormatter(), | |||
1135 | xColumn); | |||
1136 | if (pParseNode) | |||
1137 | { | |||
1138 | pParseNode->parseNodeToPredicateStr(aCrit, | |||
1139 | xConnection, | |||
1140 | static_cast<OQueryController&>(getDesignView()->getController()).getNumberFormatter(), | |||
1141 | xColumn, | |||
1142 | pEntry->GetAlias(), | |||
1143 | getDesignView()->getLocale(), | |||
1144 | getDesignView()->getDecimalSeparator(), | |||
1145 | &(static_cast<OQueryController&>(getDesignView()->getController()).getParser().getContext())); | |||
1146 | } | |||
1147 | else | |||
1148 | { | |||
1149 | if ( !m_bDisableErrorBox ) | |||
1150 | { | |||
1151 | OSQLWarningBox aWarning(GetFrameWeld(), aErrorMsg); | |||
1152 | aWarning.run(); | |||
1153 | } | |||
1154 | bError = true; | |||
1155 | } | |||
1156 | } | |||
1157 | else | |||
1158 | { | |||
1159 | if ( !m_bDisableErrorBox ) | |||
1160 | { | |||
1161 | OSQLWarningBox aWarning(GetFrameWeld(), aErrorMsg); | |||
1162 | aWarning.run(); | |||
1163 | } | |||
1164 | bError = true; | |||
1165 | } | |||
1166 | } | |||
1167 | } | |||
1168 | strOldCellContents = pEntry->GetCriteria(nIdx); | |||
1169 | pEntry->SetCriteria(nIdx, aCrit); | |||
1170 | sNewValue = pEntry->GetCriteria(nIdx); | |||
1171 | if(!aCrit.isEmpty() && nRow >= (GetRowCount()-1)) | |||
1172 | bAppendRow = true; | |||
1173 | } | |||
1174 | } | |||
1175 | if( !bError && Controller().is() ) | |||
1176 | Controller()->SaveValue(); | |||
1177 | ||||
1178 | RowModified(GetCurRow(), GetCurColumnId()); | |||
1179 | ||||
1180 | if ( bAppendRow ) | |||
1181 | { | |||
1182 | RowInserted( GetRowCount()-1 ); | |||
1183 | m_bVisibleRow.push_back(true); | |||
1184 | ++m_nVisibleCount; | |||
1185 | } | |||
1186 | ||||
1187 | if(!bError) | |||
1188 | { | |||
1189 | // and now the undo-action for the total | |||
1190 | appendUndoAction(strOldCellContents,sNewValue,nRow); | |||
1191 | ||||
1192 | } | |||
1193 | } | |||
1194 | ||||
1195 | // did I store data in a FieldDescription which was empty before and which is not empty anymore after the changes? | |||
1196 | if ( pEntry.is() && bWasEmpty && !pEntry->IsEmpty() && !bError ) | |||
1197 | { | |||
1198 | // Default to visible | |||
1199 | pEntry->SetVisible(); | |||
1200 | appendUndoAction("0","1",BROW_VIS_ROW4,bListAction); | |||
1201 | RowModified(BROW_VIS_ROW4, GetCurColumnId()); | |||
1202 | ||||
1203 | // if required add empty columns | |||
1204 | sal_uInt16 nDummy; | |||
1205 | CheckFreeColumns(nDummy); | |||
1206 | } | |||
1207 | ||||
1208 | if ( bListAction && !m_bInUndoMode ) | |||
1209 | static_cast<OQueryController&>(getDesignView()->getController()).GetUndoManager().LeaveListAction(); | |||
1210 | ||||
1211 | return pEntry != nullptr && !bError; | |||
1212 | } | |||
1213 | ||||
1214 | bool OSelectionBrowseBox::SeekRow(long nRow) | |||
1215 | { | |||
1216 | m_nSeekRow = nRow; | |||
1217 | return nRow < m_nVisibleCount; | |||
1218 | } | |||
1219 | ||||
1220 | void OSelectionBrowseBox::PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColumnId) const | |||
1221 | { | |||
1222 | rDev.SetClipRegion(vcl::Region(rRect)); | |||
1223 | ||||
1224 | OTableFieldDescRef pEntry; | |||
1225 | sal_uInt16 nPos = GetColumnPos(nColumnId); | |||
1226 | if(getFields().size() > o3tl::make_unsigned(nPos - 1)) | |||
1227 | pEntry = getFields()[nPos - 1]; | |||
1228 | ||||
1229 | if (!pEntry.is()) | |||
1230 | return; | |||
1231 | ||||
1232 | long nRow = GetRealRow(m_nSeekRow); | |||
1233 | if (nRow == BROW_VIS_ROW4) | |||
1234 | PaintTristate(rRect, pEntry->IsVisible() ? TRISTATE_TRUE : TRISTATE_FALSE); | |||
1235 | else | |||
1236 | rDev.DrawText(rRect, GetCellText(nRow, nColumnId),DrawTextFlags::VCenter); | |||
1237 | ||||
1238 | rDev.SetClipRegion( ); | |||
1239 | } | |||
1240 | ||||
1241 | void OSelectionBrowseBox::PaintStatusCell(OutputDevice& rDev, const tools::Rectangle& rRect) const | |||
1242 | { | |||
1243 | tools::Rectangle aRect(rRect); | |||
1244 | aRect.TopLeft().AdjustY( -2 ); | |||
1245 | OUString aLabel(DBA_RES(STR_QUERY_HANDLETEXT)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_QUERY_HANDLETEXT" "\004" u8"Field;Alias;Table;Sort;Visible;Function;Criterion;Or;Or" ) )); | |||
1246 | ||||
1247 | // from BROW_CRIT2_ROW onwards all rows are shown "or" | |||
1248 | sal_Int32 nToken = (m_nSeekRow >= GetBrowseRow(BROW_CRIT2_ROW7)) | |||
1249 | ? BROW_CRIT2_ROW7 : GetRealRow(m_nSeekRow); | |||
1250 | rDev.DrawText(aRect, aLabel.getToken(nToken, ';'),DrawTextFlags::VCenter); | |||
1251 | } | |||
1252 | ||||
1253 | void OSelectionBrowseBox::RemoveColumn(sal_uInt16 _nColumnId) | |||
1254 | { | |||
1255 | OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController()); | |||
1256 | ||||
1257 | sal_uInt16 nPos = GetColumnPos(_nColumnId); | |||
1258 | // the control should always have exactly one more column: the HandleColumn | |||
1259 | OSL_ENSURE((nPos == 0) || (nPos <= getFields().size()), "OSelectionBrowseBox::RemoveColumn : invalid parameter nColId")do { if (true && (!((nPos == 0) || (nPos <= getFields ().size())))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "1259" ": "), "%s", "OSelectionBrowseBox::RemoveColumn : invalid parameter nColId" ); } } while (false); | |||
1260 | // ColId is synonymous to Position, and the condition should be valid | |||
1261 | ||||
1262 | sal_uInt16 nCurCol = GetCurColumnId(); | |||
1263 | long nCurrentRow = GetCurRow(); | |||
1264 | ||||
1265 | DeactivateCell(); | |||
1266 | ||||
1267 | getFields().erase( getFields().begin() + (nPos - 1) ); | |||
1268 | OTableFieldDescRef pEntry = new OTableFieldDesc(); | |||
1269 | pEntry->SetColumnId(_nColumnId); | |||
1270 | getFields().push_back(pEntry); | |||
1271 | ||||
1272 | EditBrowseBox::RemoveColumn( _nColumnId ); | |||
1273 | InsertDataColumn( _nColumnId , OUString(), DEFAULT_SIZEGetTextWidth("0") * 30 ); | |||
1274 | ||||
1275 | // redraw | |||
1276 | tools::Rectangle aInvalidRect = GetInvalidRect( _nColumnId ); | |||
1277 | Invalidate( aInvalidRect ); | |||
1278 | ||||
1279 | ActivateCell( nCurrentRow, nCurCol ); | |||
1280 | ||||
1281 | rController.setModified( true ); | |||
1282 | ||||
1283 | invalidateUndoRedo(); | |||
1284 | } | |||
1285 | ||||
1286 | void OSelectionBrowseBox::RemoveField(sal_uInt16 nColumnId ) | |||
1287 | { | |||
1288 | OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController()); | |||
1289 | ||||
1290 | sal_uInt16 nPos = GetColumnPos(nColumnId); | |||
1291 | OSL_ENSURE(getFields().size() > o3tl::make_unsigned(nPos-1),"ID is to great!")do { if (true && (!(getFields().size() > o3tl::make_unsigned (nPos-1)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "1291" ": "), "%s", "ID is to great!"); } } while (false ); | |||
1292 | ||||
1293 | OTableFieldDescRef pDesc = getEntry(static_cast<sal_uInt32>(nPos - 1)) ; | |||
1294 | pDesc->SetColWidth( static_cast<sal_uInt16>(GetColumnWidth(nColumnId)) ); // was not stored this before | |||
1295 | ||||
1296 | // trigger UndoAction | |||
1297 | if ( !m_bInUndoMode ) | |||
1298 | { | |||
1299 | std::unique_ptr<OTabFieldDelUndoAct> pUndoAction(new OTabFieldDelUndoAct( this )); | |||
1300 | pUndoAction->SetTabFieldDescr(pDesc); | |||
1301 | pUndoAction->SetColumnPosition(nPos); | |||
1302 | rController.addUndoActionAndInvalidate( std::move(pUndoAction) ); | |||
1303 | } | |||
1304 | ||||
1305 | RemoveColumn(nColumnId); | |||
1306 | ||||
1307 | invalidateUndoRedo(); | |||
1308 | } | |||
1309 | ||||
1310 | void OSelectionBrowseBox::adjustSelectionMode( bool _bClickedOntoHeader, bool _bClickedOntoHandleCol ) | |||
1311 | { | |||
1312 | // if a Header has been selected it should be shown otherwise not | |||
1313 | if ( _bClickedOntoHeader ) | |||
1314 | { | |||
1315 | if (0 == GetSelectColumnCount() ) | |||
1316 | // I am in the correct mode if a selected column exists | |||
1317 | if ( BrowserMode::HIDESELECT == ( m_nMode & BrowserMode::HIDESELECT ) ) | |||
1318 | { | |||
1319 | m_nMode &= ~BrowserMode::HIDESELECT; | |||
1320 | m_nMode |= BrowserMode::MULTISELECTION; | |||
1321 | SetMode( m_nMode ); | |||
1322 | } | |||
1323 | } | |||
1324 | else if ( BrowserMode::HIDESELECT != ( m_nMode & BrowserMode::HIDESELECT ) ) | |||
1325 | { | |||
1326 | if ( GetSelectColumnCount() != 0 ) | |||
1327 | SetNoSelection(); | |||
1328 | ||||
1329 | if ( _bClickedOntoHandleCol ) | |||
1330 | { | |||
1331 | m_nMode |= BrowserMode::HIDESELECT; | |||
1332 | m_nMode &= ~BrowserMode::MULTISELECTION; | |||
1333 | SetMode( m_nMode ); | |||
1334 | } | |||
1335 | } | |||
1336 | } | |||
1337 | ||||
1338 | void OSelectionBrowseBox::MouseButtonDown(const BrowserMouseEvent& rEvt) | |||
1339 | { | |||
1340 | if( rEvt.IsLeft() ) | |||
1341 | { | |||
1342 | bool bOnHandle = HANDLE_ID0 == rEvt.GetColumnId(); | |||
1343 | bool bOnHeader = ( rEvt.GetRow() < 0 ) && !bOnHandle; | |||
1344 | adjustSelectionMode( bOnHeader, bOnHandle ); | |||
1345 | } | |||
1346 | EditBrowseBox::MouseButtonDown(rEvt); | |||
1347 | } | |||
1348 | ||||
1349 | void OSelectionBrowseBox::MouseButtonUp(const BrowserMouseEvent& rEvt) | |||
1350 | { | |||
1351 | EditBrowseBox::MouseButtonUp( rEvt ); | |||
1352 | static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( ID_BROWSER_QUERY_EXECUTE( 10000 + 721 ) ); | |||
1353 | } | |||
1354 | ||||
1355 | void OSelectionBrowseBox::KeyInput( const KeyEvent& rEvt ) | |||
1356 | { | |||
1357 | if (IsColumnSelected(GetCurColumnId())) | |||
1358 | { | |||
1359 | if (rEvt.GetKeyCode().GetCode() == KEY_DELETE && // Delete rows | |||
1360 | !rEvt.GetKeyCode().IsShift() && | |||
1361 | !rEvt.GetKeyCode().IsMod1()) | |||
1362 | { | |||
1363 | RemoveField(GetCurColumnId()); | |||
1364 | return; | |||
1365 | } | |||
1366 | } | |||
1367 | EditBrowseBox::KeyInput(rEvt); | |||
1368 | } | |||
1369 | ||||
1370 | sal_Int8 OSelectionBrowseBox::AcceptDrop( const BrowserAcceptDropEvent& rEvt ) | |||
1371 | { | |||
1372 | sal_Int8 nDropAction = DND_ACTION_NONEcss::datatransfer::dnd::DNDConstants::ACTION_NONE; | |||
1373 | if ( rEvt.GetRow() >= -1 ) | |||
1374 | { | |||
1375 | if ( IsEditing() ) | |||
1376 | { | |||
1377 | // allow the asterisk again | |||
1378 | m_bDisableErrorBox = true; | |||
1379 | SaveModified(); | |||
1380 | m_bDisableErrorBox = false; | |||
1381 | DeactivateCell(); | |||
1382 | } | |||
1383 | // check if the format is already supported, if not deactivate the current cell and try again | |||
1384 | if ( OJoinExchObj::isFormatAvailable(GetDataFlavors()) ) | |||
1385 | nDropAction = DND_ACTION_LINKcss::datatransfer::dnd::DNDConstants::ACTION_LINK; | |||
1386 | } | |||
1387 | ||||
1388 | return nDropAction; | |||
1389 | } | |||
1390 | ||||
1391 | sal_Int8 OSelectionBrowseBox::ExecuteDrop( const BrowserExecuteDropEvent& _rEvt ) | |||
1392 | { | |||
1393 | ||||
1394 | TransferableDataHelper aDropped(_rEvt.maDropEvent.Transferable); | |||
1395 | if (!OJoinExchObj::isFormatAvailable(aDropped.GetDataFlavorExVector())) | |||
1396 | { | |||
1397 | OSL_FAIL("OSelectionBrowseBox::ExecuteDrop: this should never have passed AcceptDrop!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "1397" ": "), "%s", "OSelectionBrowseBox::ExecuteDrop: this should never have passed AcceptDrop!" ); } } while (false); | |||
1398 | return DND_ACTION_NONEcss::datatransfer::dnd::DNDConstants::ACTION_NONE; | |||
1399 | } | |||
1400 | ||||
1401 | // insert the field at the selected position | |||
1402 | OJoinExchangeData jxdSource = OJoinExchObj::GetSourceDescription(_rEvt.maDropEvent.Transferable); | |||
1403 | InsertField(jxdSource); | |||
1404 | ||||
1405 | return DND_ACTION_LINKcss::datatransfer::dnd::DNDConstants::ACTION_LINK; | |||
1406 | } | |||
1407 | ||||
1408 | OTableFieldDescRef const & OSelectionBrowseBox::AppendNewCol( sal_uInt16 nCnt) | |||
1409 | { | |||
1410 | // one or more can be created, but the first one will is not returned | |||
1411 | sal_uInt32 nCount = getFields().size(); | |||
1412 | for (sal_uInt16 i=0 ; i<nCnt ; i++) | |||
1413 | { | |||
1414 | OTableFieldDescRef pEmptyEntry = new OTableFieldDesc(); | |||
1415 | getFields().push_back(pEmptyEntry); | |||
1416 | sal_uInt16 nColumnId = sal::static_int_cast< sal_uInt16 >(getFields().size()); | |||
1417 | pEmptyEntry->SetColumnId( nColumnId ); | |||
1418 | ||||
1419 | InsertDataColumn( nColumnId , OUString(), DEFAULT_SIZEGetTextWidth("0") * 30 ); | |||
1420 | } | |||
1421 | ||||
1422 | return getFields()[nCount]; | |||
1423 | } | |||
1424 | ||||
1425 | void OSelectionBrowseBox::DeleteFields(const OUString& rAliasName) | |||
1426 | { | |||
1427 | if (getFields().empty()) | |||
1428 | return; | |||
1429 | ||||
1430 | sal_uInt16 nColId = GetCurColumnId(); | |||
1431 | sal_uInt32 nRow = GetCurRow(); | |||
1432 | ||||
1433 | bool bWasEditing = IsEditing(); | |||
1434 | if (bWasEditing) | |||
1435 | DeactivateCell(); | |||
1436 | ||||
1437 | auto aIter = std::find_if(getFields().rbegin(), getFields().rend(), | |||
1438 | [&rAliasName](const OTableFieldDescRef pEntry) { return pEntry->GetAlias() == rAliasName; }); | |||
1439 | if (aIter != getFields().rend()) | |||
1440 | { | |||
1441 | sal_uInt16 nPos = sal::static_int_cast<sal_uInt16>(std::distance(aIter, getFields().rend())); | |||
1442 | RemoveField( GetColumnId( nPos ) ); | |||
1443 | } | |||
1444 | ||||
1445 | if (bWasEditing) | |||
1446 | ActivateCell(nRow , nColId); | |||
1447 | } | |||
1448 | ||||
1449 | void OSelectionBrowseBox::SetColWidth(sal_uInt16 nColId, long nNewWidth) | |||
1450 | { | |||
1451 | bool bWasEditing = IsEditing(); | |||
1452 | if (bWasEditing) | |||
1453 | DeactivateCell(); | |||
1454 | ||||
1455 | // create the BaseClass | |||
1456 | SetColumnWidth(nColId, nNewWidth); | |||
1457 | ||||
1458 | // tell it the FieldDescription | |||
1459 | OTableFieldDescRef pEntry = getEntry(GetColumnPos(nColId) - 1); | |||
1460 | if (pEntry.is()) | |||
1461 | pEntry->SetColWidth(sal_uInt16(GetColumnWidth(nColId))); | |||
1462 | ||||
1463 | if (bWasEditing) | |||
1464 | ActivateCell(GetCurRow(), GetCurColumnId()); | |||
1465 | } | |||
1466 | ||||
1467 | tools::Rectangle OSelectionBrowseBox::GetInvalidRect( sal_uInt16 nColId ) | |||
1468 | { | |||
1469 | // The rectangle is the full output area of the window | |||
1470 | tools::Rectangle aInvalidRect( Point(0,0), GetOutputSizePixel() ); | |||
1471 | ||||
1472 | // now update the left side | |||
1473 | tools::Rectangle aFieldRect(GetCellRect( 0, nColId )); // used instead of GetFieldRectPixel | |||
1474 | aInvalidRect.SetLeft( aFieldRect.Left() ); | |||
1475 | ||||
1476 | return aInvalidRect; | |||
1477 | } | |||
1478 | ||||
1479 | void OSelectionBrowseBox::InsertColumn(const OTableFieldDescRef& pEntry, sal_uInt16& _nColumnPosition) | |||
1480 | { | |||
1481 | // the control should have exactly one more column: the HandleColumn | |||
1482 | OSL_ENSURE(_nColumnPosition == BROWSER_INVALIDID || (_nColumnPosition <= static_cast<long>(getFields().size())), "OSelectionBrowseBox::InsertColumn : invalid parameter nColId.")do { if (true && (!(_nColumnPosition == ((sal_uInt16) 0xFFFF) || (_nColumnPosition <= static_cast<long>(getFields ().size()))))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "1482" ": "), "%s", "OSelectionBrowseBox::InsertColumn : invalid parameter nColId." ); } } while (false); | |||
1483 | // -1 means at the end. Count means at the end, others denotes a correct position | |||
1484 | ||||
1485 | sal_uInt16 nCurCol = GetCurColumnId(); | |||
1486 | long nCurrentRow = GetCurRow(); | |||
1487 | ||||
1488 | DeactivateCell(); | |||
1489 | ||||
1490 | // remember the column id of the current position | |||
1491 | sal_uInt16 nColumnId = GetColumnId(_nColumnPosition); | |||
1492 | // put at the end of the list if too small or too big, | |||
1493 | if ((_nColumnPosition == BROWSER_INVALIDID((sal_uInt16) 0xFFFF)) || (_nColumnPosition >= getFields().size())) // append the field | |||
1494 | { | |||
1495 | if (FindFirstFreeCol(_nColumnPosition) == nullptr) // no more free columns | |||
1496 | { | |||
1497 | AppendNewCol(); | |||
1498 | _nColumnPosition = sal::static_int_cast< sal_uInt16 >( | |||
1499 | getFields().size()); | |||
1500 | } | |||
1501 | else | |||
1502 | ++_nColumnPosition; // within the list | |||
1503 | nColumnId = GetColumnId(_nColumnPosition); | |||
1504 | pEntry->SetColumnId( nColumnId ); | |||
1505 | getFields()[ _nColumnPosition - 1] = pEntry; | |||
1506 | } | |||
1507 | ||||
1508 | // check if the column ids are identical, if not we have to move | |||
1509 | if ( pEntry->GetColumnId() != nColumnId ) | |||
1510 | { | |||
1511 | sal_uInt16 nOldPosition = GetColumnPos(pEntry->GetColumnId()); | |||
1512 | OSL_ENSURE( nOldPosition != 0,"Old position was 0. Not possible!")do { if (true && (!(nOldPosition != 0))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "1512" ": "), "%s", "Old position was 0. Not possible!") ; } } while (false); | |||
1513 | SetColumnPos(pEntry->GetColumnId(),_nColumnPosition); | |||
1514 | // we have to delete an empty field for the fields list, because the columns must have equal length | |||
1515 | if ( nOldPosition > 0 && nOldPosition <= getFields().size() ) | |||
1516 | getFields()[nOldPosition - 1] = pEntry; | |||
1517 | ||||
1518 | ColumnMoved(pEntry->GetColumnId(),false); | |||
1519 | } | |||
1520 | ||||
1521 | if ( pEntry->GetFunctionType() & FKT_AGGREGATE ) | |||
1522 | { | |||
1523 | OUString sFunctionName = pEntry->GetFunction(); | |||
1524 | if ( GetFunctionName(sal_uInt32(-1),sFunctionName) ) | |||
1525 | pEntry->SetFunction(sFunctionName); | |||
1526 | } | |||
1527 | ||||
1528 | nColumnId = pEntry->GetColumnId(); | |||
1529 | ||||
1530 | SetColWidth(nColumnId,getDesignView()->getColWidth(GetColumnPos(nColumnId)-1)); | |||
1531 | // redraw | |||
1532 | tools::Rectangle aInvalidRect = GetInvalidRect( nColumnId ); | |||
1533 | Invalidate( aInvalidRect ); | |||
1534 | ||||
1535 | ActivateCell( nCurrentRow, nCurCol ); | |||
1536 | static_cast<OQueryController&>(getDesignView()->getController()).setModified( true ); | |||
1537 | ||||
1538 | invalidateUndoRedo(); | |||
1539 | } | |||
1540 | ||||
1541 | OTableFieldDescRef OSelectionBrowseBox::InsertField(const OJoinExchangeData& jxdSource) | |||
1542 | { | |||
1543 | OQueryTableWindow* pSourceWin = static_cast<OQueryTableWindow*>(jxdSource.pListBox->GetTabWin()); | |||
1544 | if (!pSourceWin) | |||
1545 | return nullptr; | |||
1546 | ||||
1547 | // name and position of the selected field | |||
1548 | weld::TreeView& rTreeView = jxdSource.pListBox->get_widget(); | |||
1549 | OUString aFieldName = rTreeView.get_text(jxdSource.nEntry); | |||
1550 | sal_uInt32 nFieldIndex = jxdSource.nEntry; | |||
1551 | OTableFieldInfo* pInf = reinterpret_cast<OTableFieldInfo*>(rTreeView.get_id(jxdSource.nEntry).toUInt64()); | |||
1552 | ||||
1553 | // construct DragInfo, such that I use the other InsertField | |||
1554 | OTableFieldDescRef aInfo = new OTableFieldDesc(pSourceWin->GetTableName(),aFieldName); | |||
1555 | aInfo->SetTabWindow(pSourceWin); | |||
1556 | aInfo->SetFieldIndex(nFieldIndex); | |||
1557 | aInfo->SetFieldType(pInf->GetKeyType()); | |||
1558 | aInfo->SetAlias(pSourceWin->GetAliasName()); | |||
1559 | ||||
1560 | aInfo->SetDataType(pInf->GetDataType()); | |||
1561 | aInfo->SetVisible(); | |||
1562 | ||||
1563 | return InsertField(aInfo); | |||
1564 | } | |||
1565 | ||||
1566 | OTableFieldDescRef OSelectionBrowseBox::InsertField(const OTableFieldDescRef& _rInfo, sal_uInt16 _nColumnPosition, bool bVis, bool bActivate) | |||
1567 | { | |||
1568 | ||||
1569 | if(m_nMaxColumns && m_nMaxColumns <= FieldsCount()) | |||
1570 | return nullptr; | |||
1571 | if (bActivate) | |||
1572 | SaveModified(); | |||
1573 | ||||
1574 | // new column description | |||
1575 | OTableFieldDescRef pEntry = _rInfo; | |||
1576 | pEntry->SetVisible(bVis); | |||
1577 | ||||
1578 | // insert column | |||
1579 | InsertColumn( pEntry, _nColumnPosition ); | |||
1580 | ||||
1581 | if ( !m_bInUndoMode ) | |||
1582 | { | |||
1583 | // trigger UndoAction | |||
1584 | std::unique_ptr<OTabFieldCreateUndoAct> pUndoAction(new OTabFieldCreateUndoAct( this )); | |||
1585 | pUndoAction->SetTabFieldDescr( pEntry ); | |||
1586 | pUndoAction->SetColumnPosition(_nColumnPosition); | |||
1587 | getDesignView()->getController().addUndoActionAndInvalidate( std::move(pUndoAction) ); | |||
1588 | } | |||
1589 | ||||
1590 | return pEntry; | |||
1591 | } | |||
1592 | ||||
1593 | sal_uInt16 OSelectionBrowseBox::FieldsCount() | |||
1594 | { | |||
1595 | sal_uInt16 nCount = 0; | |||
1596 | for (auto const& field : getFields()) | |||
1597 | { | |||
1598 | if (field.is() && !field->IsEmpty()) | |||
1599 | ++nCount; | |||
1600 | } | |||
1601 | ||||
1602 | return nCount; | |||
1603 | } | |||
1604 | ||||
1605 | OTableFieldDescRef OSelectionBrowseBox::FindFirstFreeCol(sal_uInt16& _rColumnPosition ) | |||
1606 | { | |||
1607 | ||||
1608 | _rColumnPosition = BROWSER_INVALIDID((sal_uInt16) 0xFFFF); | |||
1609 | ||||
1610 | for (auto const& field : getFields()) | |||
1611 | { | |||
1612 | ++_rColumnPosition; | |||
1613 | OTableFieldDescRef pEntry = field; | |||
1614 | if ( pEntry.is() && pEntry->IsEmpty() ) | |||
1615 | return pEntry; | |||
1616 | } | |||
1617 | ||||
1618 | return nullptr; | |||
1619 | } | |||
1620 | ||||
1621 | void OSelectionBrowseBox::CheckFreeColumns(sal_uInt16& _rColumnPosition) | |||
1622 | { | |||
1623 | if (FindFirstFreeCol(_rColumnPosition) == nullptr) | |||
1624 | { | |||
1625 | // it is full, so append a pack of columns | |||
1626 | AppendNewCol(DEFAULT_QUERY_COLS20); | |||
1627 | OSL_VERIFY(FindFirstFreeCol(_rColumnPosition).is())do { if (!(FindFirstFreeCol(_rColumnPosition).is())) do { if ( true && (!(0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "1627" ": "), "OSL_ASSERT: %s", "0"); } } while (false); } while (0); | |||
1628 | } | |||
1629 | } | |||
1630 | ||||
1631 | void OSelectionBrowseBox::AddGroupBy( const OTableFieldDescRef& rInfo ) | |||
1632 | { | |||
1633 | Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection(); | |||
1634 | if(!xConnection.is()) | |||
1635 | return; | |||
1636 | OSL_ENSURE(!rInfo->IsEmpty(),"AddGroupBy:: OTableFieldDescRef should not be empty!")do { if (true && (!(!rInfo->IsEmpty()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "1636" ": "), "%s", "AddGroupBy:: OTableFieldDescRef should not be empty!" ); } } while (false); | |||
1637 | OTableFieldDescRef pEntry; | |||
1638 | const Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); | |||
1639 | const ::comphelper::UStringMixEqual bCase(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers()); | |||
1640 | //sal_Bool bAppend = sal_False; | |||
1641 | ||||
1642 | bool bAllFieldsSearched = true; | |||
1643 | for (auto const& field : getFields()) | |||
1644 | { | |||
1645 | pEntry = field; | |||
1646 | OSL_ENSURE(pEntry.is(),"OTableFieldDescRef was null!")do { if (true && (!(pEntry.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "1646" ": "), "%s", "OTableFieldDescRef was null!"); } } while (false); | |||
1647 | ||||
1648 | const OUString aField = pEntry->GetField(); | |||
1649 | const OUString aAlias = pEntry->GetAlias(); | |||
1650 | ||||
1651 | if (bCase(aField,rInfo->GetField()) && | |||
1652 | bCase(aAlias,rInfo->GetAlias()) && | |||
1653 | pEntry->GetFunctionType() == rInfo->GetFunctionType() && | |||
1654 | pEntry->GetFunction() == rInfo->GetFunction()) | |||
1655 | { | |||
1656 | if ( pEntry->isNumericOrAggregateFunction() && rInfo->IsGroupBy() ) | |||
1657 | { | |||
1658 | pEntry->SetGroupBy(false); | |||
1659 | // we do want to consider that bAllFieldsSearched still true here | |||
1660 | // bAllFieldsSearched = false; | |||
1661 | break; | |||
1662 | } | |||
1663 | else | |||
1664 | { | |||
1665 | if ( !pEntry->IsGroupBy() && !pEntry->HasCriteria() ) // here we have a where condition which is no having clause | |||
1666 | { | |||
1667 | pEntry->SetGroupBy(rInfo->IsGroupBy()); | |||
1668 | if(!m_bGroupByUnRelated && pEntry->IsGroupBy()) | |||
1669 | pEntry->SetVisible(); | |||
1670 | bAllFieldsSearched = false; | |||
1671 | break; | |||
1672 | } | |||
1673 | } | |||
1674 | ||||
1675 | } | |||
1676 | } | |||
1677 | ||||
1678 | if (bAllFieldsSearched) | |||
1679 | { | |||
1680 | OTableFieldDescRef pTmp = InsertField(rInfo, BROWSER_INVALIDID((sal_uInt16) 0xFFFF), false, false ); | |||
1681 | if ( pTmp->isNumericOrAggregateFunction() && rInfo->IsGroupBy() ) // the GroupBy is inherited from rInfo | |||
1682 | pTmp->SetGroupBy(false); | |||
1683 | } | |||
1684 | } | |||
1685 | ||||
1686 | void OSelectionBrowseBox::DuplicateConditionLevel( const sal_uInt16 nLevel) | |||
1687 | { | |||
1688 | const sal_uInt16 nNewLevel = nLevel +1; | |||
1689 | for (auto const& field : getFields()) | |||
1690 | { | |||
1691 | const OTableFieldDescRef& pEntry = field; | |||
1692 | OUString sValue = pEntry->GetCriteria(nLevel); | |||
1693 | if ( !sValue.isEmpty() ) | |||
1694 | { | |||
1695 | pEntry->SetCriteria( nNewLevel, sValue); | |||
1696 | if ( nNewLevel == (m_nVisibleCount-BROW_CRIT1_ROW6-1) ) | |||
1697 | { | |||
1698 | RowInserted( GetRowCount()-1 ); | |||
1699 | m_bVisibleRow.push_back(true); | |||
1700 | ++m_nVisibleCount; | |||
1701 | } | |||
1702 | m_bVisibleRow[BROW_CRIT1_ROW6 + nNewLevel] = true; | |||
1703 | } | |||
1704 | } | |||
1705 | } | |||
1706 | ||||
1707 | void OSelectionBrowseBox::AddCondition( const OTableFieldDescRef& rInfo, const OUString& rValue, const sal_uInt16 nLevel,bool _bAddOrOnOneLine ) | |||
1708 | { | |||
1709 | Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection(); | |||
1710 | if(!xConnection.is()) | |||
1711 | return; | |||
1712 | OSL_ENSURE(rInfo.is() && !rInfo->IsEmpty(),"AddCondition:: OTableFieldDescRef should not be Empty!")do { if (true && (!(rInfo.is() && !rInfo-> IsEmpty()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "1712" ": "), "%s", "AddCondition:: OTableFieldDescRef should not be Empty!" ); } } while (false); | |||
1713 | ||||
1714 | OTableFieldDescRef pLastEntry; | |||
1715 | Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); | |||
1716 | ::comphelper::UStringMixEqual bCase(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers()); | |||
1717 | ||||
1718 | bool bAllFieldsSearched = true; | |||
1719 | for (auto const& field : getFields()) | |||
1720 | { | |||
1721 | const OTableFieldDescRef& pEntry = field; | |||
1722 | const OUString aField = pEntry->GetField(); | |||
1723 | const OUString aAlias = pEntry->GetAlias(); | |||
1724 | ||||
1725 | if (bCase(aField,rInfo->GetField()) && | |||
1726 | bCase(aAlias,rInfo->GetAlias()) && | |||
1727 | pEntry->GetFunctionType() == rInfo->GetFunctionType() && | |||
1728 | pEntry->GetFunction() == rInfo->GetFunction() && | |||
1729 | pEntry->IsGroupBy() == rInfo->IsGroupBy() ) | |||
1730 | { | |||
1731 | if ( pEntry->isNumericOrAggregateFunction() && rInfo->IsGroupBy() ) | |||
1732 | pEntry->SetGroupBy(false); | |||
1733 | else | |||
1734 | { | |||
1735 | if(!m_bGroupByUnRelated && pEntry->IsGroupBy()) | |||
1736 | pEntry->SetVisible(); | |||
1737 | } | |||
1738 | if (pEntry->GetCriteria(nLevel).isEmpty() ) | |||
1739 | { | |||
1740 | pEntry->SetCriteria( nLevel, rValue); | |||
1741 | if(nLevel == (m_nVisibleCount-BROW_CRIT1_ROW6-1)) | |||
1742 | { | |||
1743 | RowInserted( GetRowCount()-1 ); | |||
1744 | m_bVisibleRow.push_back(true); | |||
1745 | ++m_nVisibleCount; | |||
1746 | } | |||
1747 | m_bVisibleRow[BROW_CRIT1_ROW6 + nLevel] = true; | |||
1748 | bAllFieldsSearched = false; | |||
1749 | break; | |||
1750 | } | |||
1751 | if ( _bAddOrOnOneLine ) | |||
1752 | { | |||
1753 | pLastEntry = pEntry; | |||
1754 | } | |||
1755 | } | |||
1756 | } | |||
1757 | if ( pLastEntry.is() ) | |||
1758 | { | |||
1759 | OUString sCriteria = rValue; | |||
1760 | OUString sOldCriteria = pLastEntry->GetCriteria( nLevel ); | |||
1761 | if ( !sOldCriteria.isEmpty() ) | |||
1762 | { | |||
1763 | sCriteria = "( " + sOldCriteria + " OR " + rValue + " )"; | |||
1764 | } | |||
1765 | pLastEntry->SetCriteria( nLevel, sCriteria); | |||
1766 | if(nLevel == (m_nVisibleCount-BROW_CRIT1_ROW6-1)) | |||
1767 | { | |||
1768 | RowInserted( GetRowCount()-1 ); | |||
1769 | m_bVisibleRow.push_back(true); | |||
1770 | ++m_nVisibleCount; | |||
1771 | } | |||
1772 | m_bVisibleRow[BROW_CRIT1_ROW6 + nLevel] = true; | |||
1773 | } | |||
1774 | else if (bAllFieldsSearched) | |||
1775 | { | |||
1776 | OTableFieldDescRef pTmp = InsertField(rInfo, BROWSER_INVALIDID((sal_uInt16) 0xFFFF), false, false ); | |||
1777 | if ( pTmp->isNumericOrAggregateFunction() && rInfo->IsGroupBy() ) // the GroupBy was inherited from rInfo | |||
1778 | pTmp->SetGroupBy(false); | |||
1779 | if ( pTmp.is() ) | |||
1780 | { | |||
1781 | pTmp->SetCriteria( nLevel, rValue); | |||
1782 | if(nLevel == (m_nVisibleCount-BROW_CRIT1_ROW6-1)) | |||
1783 | { | |||
1784 | RowInserted( GetRowCount()-1 ); | |||
1785 | m_bVisibleRow.push_back(true); | |||
1786 | ++m_nVisibleCount; | |||
1787 | } | |||
1788 | } | |||
1789 | } | |||
1790 | } | |||
1791 | ||||
1792 | void OSelectionBrowseBox::AddOrder( const OTableFieldDescRef& rInfo, const EOrderDir eDir, sal_uInt32 _nCurrentPos) | |||
1793 | { | |||
1794 | if (_nCurrentPos == 0) | |||
1795 | m_nLastSortColumn = SORT_COLUMN_NONE0xFFFFFFFF; | |||
1796 | ||||
1797 | Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection(); | |||
1798 | if(!xConnection.is()) | |||
1799 | return; | |||
1800 | OSL_ENSURE(!rInfo->IsEmpty(),"AddOrder:: OTableFieldDescRef should not be Empty!")do { if (true && (!(!rInfo->IsEmpty()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "1800" ": "), "%s", "AddOrder:: OTableFieldDescRef should not be Empty!" ); } } while (false); | |||
1801 | OTableFieldDescRef pEntry; | |||
1802 | Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); | |||
1803 | ::comphelper::UStringMixEqual bCase(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers()); | |||
1804 | ||||
1805 | bool bAppend = false; | |||
1806 | sal_uInt32 nPos = 0; | |||
1807 | bool bAllFieldsSearched = true; | |||
1808 | for (auto const& field : getFields()) | |||
1809 | { | |||
1810 | pEntry = field; | |||
1811 | OUString aField = pEntry->GetField(); | |||
1812 | OUString aAlias = pEntry->GetAlias(); | |||
1813 | ||||
1814 | if (bCase(aField,rInfo->GetField()) && | |||
1815 | bCase(aAlias,rInfo->GetAlias())) | |||
1816 | { | |||
1817 | bAppend = (m_nLastSortColumn != SORT_COLUMN_NONE0xFFFFFFFF) && (nPos <= m_nLastSortColumn); | |||
1818 | if ( bAppend ) | |||
1819 | { | |||
1820 | // we do want to consider that bAllFieldsSearched still true here | |||
1821 | // bAllFieldsSearched = false; | |||
1822 | break; | |||
1823 | } | |||
1824 | else | |||
1825 | { | |||
1826 | if ( !m_bOrderByUnRelated ) | |||
1827 | pEntry->SetVisible(); | |||
1828 | pEntry->SetOrderDir( eDir ); | |||
1829 | m_nLastSortColumn = nPos; | |||
1830 | } | |||
1831 | bAllFieldsSearched = false; | |||
1832 | break; | |||
1833 | } | |||
1834 | ++nPos; | |||
1835 | } | |||
1836 | ||||
1837 | if (bAllFieldsSearched) | |||
1838 | { | |||
1839 | OTableFieldDescRef pTmp = InsertField(rInfo, BROWSER_INVALIDID((sal_uInt16) 0xFFFF), false, false ); | |||
1840 | if(pTmp.is()) | |||
1841 | { | |||
1842 | m_nLastSortColumn = pTmp->GetColumnId() - 1; | |||
1843 | if ( !m_bOrderByUnRelated && !bAppend ) | |||
1844 | pTmp->SetVisible(); | |||
1845 | pTmp->SetOrderDir( eDir ); | |||
1846 | } | |||
1847 | } | |||
1848 | } | |||
1849 | ||||
1850 | bool OSelectionBrowseBox::Save() | |||
1851 | { | |||
1852 | bool bRet = true; | |||
1853 | if (IsModified()) | |||
1854 | bRet = SaveModified(); | |||
1855 | return bRet; | |||
1856 | } | |||
1857 | ||||
1858 | void OSelectionBrowseBox::CellModified() | |||
1859 | { | |||
1860 | long nRow = GetRealRow(GetCurRow()); | |||
1861 | switch (nRow) | |||
1862 | { | |||
1863 | case BROW_VIS_ROW4: | |||
1864 | { | |||
1865 | OTableFieldDescRef pEntry = getEntry(GetColumnPos(GetCurColumnId()) - 1); | |||
1866 | ||||
1867 | weld::ComboBox& rComboBox = m_pOrderCell->get_widget(); | |||
1868 | sal_Int32 nIdx = rComboBox.get_active(); | |||
1869 | if(!m_bOrderByUnRelated && nIdx > 0 && | |||
1870 | nIdx != -1 && | |||
1871 | !pEntry->IsEmpty() && | |||
1872 | pEntry->GetOrderDir() != ORDER_NONE) | |||
1873 | { | |||
1874 | m_pVisibleCell->GetBox().set_active(true); | |||
1875 | pEntry->SetVisible(); | |||
1876 | } | |||
1877 | else | |||
1878 | pEntry->SetVisible(m_pVisibleCell->GetBox().get_active()); | |||
1879 | } | |||
1880 | break; | |||
1881 | } | |||
1882 | static_cast<OQueryController&>(getDesignView()->getController()).setModified( true ); | |||
1883 | } | |||
1884 | ||||
1885 | void OSelectionBrowseBox::Fill() | |||
1886 | { | |||
1887 | OSL_ENSURE(ColCount() >= 1, "OSelectionBrowseBox::Fill : please call only after inserting the handle column !")do { if (true && (!(ColCount() >= 1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "1887" ": "), "%s", "OSelectionBrowseBox::Fill : please call only after inserting the handle column !" ); } } while (false); | |||
1888 | ||||
1889 | sal_uInt16 nColCount = ColCount() - 1; | |||
1890 | if (nColCount < DEFAULT_QUERY_COLS20) | |||
1891 | AppendNewCol(DEFAULT_QUERY_COLS20 - nColCount); | |||
1892 | } | |||
1893 | ||||
1894 | Size OSelectionBrowseBox::CalcOptimalSize( const Size& _rAvailable ) | |||
1895 | { | |||
1896 | Size aReturn( _rAvailable.Width(), GetTitleHeight() ); | |||
1897 | ||||
1898 | aReturn.AdjustHeight(( m_nVisibleCount ? m_nVisibleCount : 15 ) * GetDataRowHeight() ); | |||
1899 | aReturn.AdjustHeight(40 ); // just some space | |||
1900 | ||||
1901 | return aReturn; | |||
1902 | } | |||
1903 | ||||
1904 | void OSelectionBrowseBox::Command(const CommandEvent& rEvt) | |||
1905 | { | |||
1906 | switch (rEvt.GetCommand()) | |||
1907 | { | |||
1908 | case CommandEventId::ContextMenu: | |||
1909 | { | |||
1910 | Point aMenuPos( rEvt.GetMousePosPixel() ); | |||
1911 | ||||
1912 | if (!rEvt.IsMouseEvent()) | |||
1913 | { | |||
1914 | if ( 1 == GetSelectColumnCount() ) | |||
1915 | { | |||
1916 | sal_uInt16 nSelId = GetColumnId( | |||
1917 | sal::static_int_cast< sal_uInt16 >( | |||
1918 | FirstSelectedColumn() ) ); | |||
1919 | ::tools::Rectangle aColRect( GetFieldRectPixel( 0, nSelId, false ) ); | |||
1920 | ||||
1921 | aMenuPos = aColRect.TopCenter(); | |||
1922 | } | |||
1923 | else | |||
1924 | { | |||
1925 | EditBrowseBox::Command(rEvt); | |||
1926 | return; | |||
1927 | } | |||
1928 | } | |||
1929 | ||||
1930 | sal_uInt16 nColId = GetColumnId(GetColumnAtXPosPixel( aMenuPos.X() )); | |||
1931 | long nRow = GetRowAtYPosPixel( aMenuPos.Y() ); | |||
1932 | ||||
1933 | if (nRow < 0 && nColId > HANDLE_ID0 ) | |||
1934 | { | |||
1935 | if ( !IsColumnSelected( nColId ) ) | |||
1936 | { | |||
1937 | adjustSelectionMode( true /* clicked onto a header */ , false /* not onto the handle col */ ); | |||
1938 | SelectColumnId( nColId ); | |||
1939 | } | |||
1940 | ||||
1941 | if (!static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly()) | |||
1942 | { | |||
1943 | VclBuilder aBuilder(nullptr, AllSettings::GetUIRootDir(), "dbaccess/ui/querycolmenu.ui", ""); | |||
1944 | VclPtr<PopupMenu> aContextMenu(aBuilder.get_menu("menu")); | |||
1945 | sal_uInt16 nItemId = aContextMenu->Execute(this, aMenuPos); | |||
1946 | if (nItemId == aContextMenu->GetItemId("delete")) | |||
1947 | RemoveField(nColId); | |||
1948 | else if (nItemId == aContextMenu->GetItemId("width")) | |||
1949 | adjustBrowseBoxColumnWidth( this, nColId ); | |||
1950 | } | |||
1951 | } | |||
1952 | else if(nRow >= 0 && nColId <= HANDLE_ID0) | |||
1953 | { | |||
1954 | if (!static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly()) | |||
1955 | { | |||
1956 | VclBuilder aBuilder(nullptr, AllSettings::GetUIRootDir(), "dbaccess/ui/queryfuncmenu.ui", ""); | |||
1957 | VclPtr<PopupMenu> aContextMenu(aBuilder.get_menu("menu")); | |||
1958 | aContextMenu->CheckItem("functions", m_bVisibleRow[BROW_FUNCTION_ROW5]); | |||
1959 | aContextMenu->CheckItem("tablename", m_bVisibleRow[BROW_TABLE_ROW2]); | |||
1960 | aContextMenu->CheckItem("alias", m_bVisibleRow[BROW_COLUMNALIAS_ROW1]); | |||
1961 | aContextMenu->CheckItem("distinct", static_cast<OQueryController&>(getDesignView()->getController()).isDistinct()); | |||
1962 | ||||
1963 | aContextMenu->Execute(this, aMenuPos); | |||
1964 | ||||
1965 | OString sIdent = aContextMenu->GetCurItemIdent(); | |||
1966 | if (sIdent == "functions") | |||
1967 | { | |||
1968 | SetRowVisible(BROW_FUNCTION_ROW5, !IsRowVisible(BROW_FUNCTION_ROW5)); | |||
1969 | static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_FUNCTIONS( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) + 1) + 46 ) ); | |||
1970 | } | |||
1971 | else if (sIdent == "tablename") | |||
1972 | { | |||
1973 | SetRowVisible(BROW_TABLE_ROW2, !IsRowVisible(BROW_TABLE_ROW2)); | |||
1974 | static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_TABLES( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) + 1) + 47 ) ); | |||
1975 | } | |||
1976 | else if (sIdent == "alias") | |||
1977 | { | |||
1978 | SetRowVisible(BROW_COLUMNALIAS_ROW1, !IsRowVisible(BROW_COLUMNALIAS_ROW1)); | |||
1979 | static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_VIEW_ALIASES( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) + 1) + 48 ) ); | |||
1980 | } | |||
1981 | else if (sIdent == "distinct") | |||
1982 | { | |||
1983 | static_cast<OQueryController&>(getDesignView()->getController()).setDistinct(!static_cast<OQueryController&>(getDesignView()->getController()).isDistinct()); | |||
1984 | static_cast<OQueryController&>(getDesignView()->getController()).setModified( true ); | |||
1985 | static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature( SID_QUERY_DISTINCT_VALUES( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) + 1) + 49 ) ); | |||
1986 | } | |||
1987 | ||||
1988 | static_cast<OQueryController&>(getDesignView()->getController()).setModified( true ); | |||
1989 | } | |||
1990 | } | |||
1991 | else | |||
1992 | { | |||
1993 | EditBrowseBox::Command(rEvt); | |||
1994 | return; | |||
1995 | } | |||
1996 | ||||
1997 | [[fallthrough]]; | |||
1998 | } | |||
1999 | default: | |||
2000 | EditBrowseBox::Command(rEvt); | |||
2001 | } | |||
2002 | } | |||
2003 | ||||
2004 | bool OSelectionBrowseBox::IsRowVisible(sal_uInt16 _nWhich) const | |||
2005 | { | |||
2006 | OSL_ENSURE(_nWhich<(m_bVisibleRow.size()), "OSelectionBrowseBox::IsRowVisible : invalid parameter !")do { if (true && (!(_nWhich<(m_bVisibleRow.size()) ))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "2006" ": "), "%s", "OSelectionBrowseBox::IsRowVisible : invalid parameter !" ); } } while (false); | |||
2007 | return m_bVisibleRow[_nWhich]; | |||
2008 | } | |||
2009 | ||||
2010 | void OSelectionBrowseBox::SetRowVisible(sal_uInt16 _nWhich, bool _bVis) | |||
2011 | { | |||
2012 | OSL_ENSURE(_nWhich<m_bVisibleRow.size(), "OSelectionBrowseBox::SetRowVisible : invalid parameter !")do { if (true && (!(_nWhich<m_bVisibleRow.size())) ) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "2012" ": "), "%s", "OSelectionBrowseBox::SetRowVisible : invalid parameter !" ); } } while (false); | |||
2013 | ||||
2014 | bool bWasEditing = IsEditing(); | |||
2015 | if (bWasEditing) | |||
2016 | DeactivateCell(); | |||
2017 | ||||
2018 | // do this before removing or inserting rows, as this triggers ActivateCell-calls, which rely on m_bVisibleRow | |||
2019 | m_bVisibleRow[_nWhich] = !m_bVisibleRow[_nWhich]; | |||
2020 | ||||
2021 | long nId = GetBrowseRow(_nWhich); | |||
2022 | if (_bVis) | |||
2023 | { | |||
2024 | RowInserted(nId); | |||
2025 | ++m_nVisibleCount; | |||
2026 | } | |||
2027 | else | |||
2028 | { | |||
2029 | RowRemoved(nId); | |||
2030 | --m_nVisibleCount; | |||
2031 | } | |||
2032 | ||||
2033 | if (bWasEditing) | |||
2034 | ActivateCell(); | |||
2035 | } | |||
2036 | ||||
2037 | long OSelectionBrowseBox::GetBrowseRow(long nRowId) const | |||
2038 | { | |||
2039 | sal_uInt16 nCount(0); | |||
2040 | for(long i = 0 ; i < nRowId ; ++i) | |||
2041 | { | |||
2042 | if ( m_bVisibleRow[i] ) | |||
2043 | ++nCount; | |||
2044 | } | |||
2045 | return nCount; | |||
2046 | } | |||
2047 | ||||
2048 | long OSelectionBrowseBox::GetRealRow(long nRowId) const | |||
2049 | { | |||
2050 | long nErg=0,i; | |||
2051 | const long nCount = m_bVisibleRow.size(); | |||
2052 | for(i=0;i < nCount; ++i) | |||
2053 | { | |||
2054 | if(m_bVisibleRow[i] && nErg++ == nRowId) | |||
2055 | break; | |||
2056 | } | |||
2057 | OSL_ENSURE(nErg <= long(m_bVisibleRow.size()),"nErg cannot be greater than BROW_ROW_CNT!")do { if (true && (!(nErg <= long(m_bVisibleRow.size ())))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "2057" ": "), "%s", "nErg cannot be greater than BROW_ROW_CNT!" ); } } while (false); | |||
2058 | return i; | |||
2059 | } | |||
2060 | ||||
2061 | const long nVisibleRowMask[] = | |||
2062 | { | |||
2063 | 0x0001, | |||
2064 | 0x0002, | |||
2065 | 0x0004, | |||
2066 | 0x0008, | |||
2067 | 0x0010, | |||
2068 | 0x0020, | |||
2069 | 0x0040, | |||
2070 | 0x0080, | |||
2071 | 0x0100, | |||
2072 | 0x0200, | |||
2073 | 0x0400, | |||
2074 | 0x0800 | |||
2075 | }; | |||
2076 | sal_Int32 OSelectionBrowseBox::GetNoneVisibleRows() const | |||
2077 | { | |||
2078 | sal_Int32 nErg(0); | |||
2079 | // only the first 11 rows are interesting | |||
2080 | sal_Int32 const nSize = SAL_N_ELEMENTS(nVisibleRowMask)(sizeof(sal_n_array_size(nVisibleRowMask))); | |||
2081 | for(sal_Int32 i=0;i<nSize;i++) | |||
2082 | { | |||
2083 | if(!m_bVisibleRow[i]) | |||
2084 | nErg |= nVisibleRowMask[i]; | |||
2085 | } | |||
2086 | return nErg; | |||
2087 | } | |||
2088 | ||||
2089 | void OSelectionBrowseBox::SetNoneVisibleRow(long nRows) | |||
2090 | { | |||
2091 | // only the first 11 rows are interesting | |||
2092 | sal_Int32 const nSize = SAL_N_ELEMENTS(nVisibleRowMask)(sizeof(sal_n_array_size(nVisibleRowMask))); | |||
2093 | for(sal_Int32 i=0;i< nSize;i++) | |||
2094 | m_bVisibleRow[i] = !(nRows & nVisibleRowMask[i]); | |||
2095 | } | |||
2096 | ||||
2097 | OUString OSelectionBrowseBox::GetCellText(long nRow, sal_uInt16 nColId) const | |||
2098 | { | |||
2099 | ||||
2100 | sal_uInt16 nPos = GetColumnPos(nColId); | |||
2101 | ||||
2102 | OTableFieldDescRef pEntry = getFields()[nPos-1]; | |||
2103 | OSL_ENSURE(pEntry != nullptr, "OSelectionBrowseBox::GetCellText : invalid column id, prepare for GPF ... ")do { if (true && (!(pEntry != nullptr))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "2103" ": "), "%s", "OSelectionBrowseBox::GetCellText : invalid column id, prepare for GPF ... " ); } } while (false); | |||
2104 | if ( pEntry->IsEmpty() ) | |||
2105 | return OUString(); | |||
2106 | ||||
2107 | OUString aText; | |||
2108 | switch (nRow) | |||
2109 | { | |||
2110 | case BROW_TABLE_ROW2: | |||
2111 | aText = pEntry->GetAlias(); | |||
2112 | break; | |||
2113 | case BROW_FIELD_ROW0: | |||
2114 | { | |||
2115 | OUString aField = pEntry->GetField(); | |||
2116 | if (!aField.isEmpty() && aField[0] == '*') // * replace with alias.* | |||
2117 | { | |||
2118 | aField = pEntry->GetAlias(); | |||
2119 | if(!aField.isEmpty()) | |||
2120 | aField += "."; | |||
2121 | aField += "*"; | |||
2122 | } | |||
2123 | aText = aField; | |||
2124 | } break; | |||
2125 | case BROW_ORDER_ROW3: | |||
2126 | if (pEntry->GetOrderDir() != ORDER_NONE) | |||
2127 | aText = DBA_RES(STR_QUERY_SORTTEXT)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_QUERY_SORTTEXT" "\004" u8"(not sorted);ascending;descending" ) ).getToken(sal::static_int_cast< sal_uInt16 >(pEntry->GetOrderDir()), ';'); | |||
2128 | break; | |||
2129 | case BROW_VIS_ROW4: | |||
2130 | break; | |||
2131 | case BROW_COLUMNALIAS_ROW1: | |||
2132 | aText = pEntry->GetFieldAlias(); | |||
2133 | break; | |||
2134 | case BROW_FUNCTION_ROW5: | |||
2135 | // we always show the group function at first | |||
2136 | if ( pEntry->IsGroupBy() ) | |||
2137 | aText = m_aFunctionStrings.copy(m_aFunctionStrings.lastIndexOf(';')+1); | |||
2138 | else if ( pEntry->isNumericOrAggregateFunction() ) | |||
2139 | aText = pEntry->GetFunction(); | |||
2140 | break; | |||
2141 | default: | |||
2142 | aText = pEntry->GetCriteria(sal_uInt16(nRow - BROW_CRIT1_ROW6)); | |||
2143 | } | |||
2144 | return aText; | |||
2145 | } | |||
2146 | ||||
2147 | bool OSelectionBrowseBox::GetFunctionName(sal_uInt32 _nFunctionTokenId, OUString& rFkt) | |||
2148 | { | |||
2149 | weld::ComboBox& rComboBox = m_pFunctionCell->get_widget(); | |||
2150 | switch(_nFunctionTokenId) | |||
2151 | { | |||
2152 | case SQL_TOKEN_COUNT: | |||
2153 | rFkt = (rComboBox.get_count() < 3) ? rComboBox.get_text(1) : rComboBox.get_text(2); | |||
2154 | break; | |||
2155 | case SQL_TOKEN_AVG: | |||
2156 | rFkt = rComboBox.get_text(1); | |||
2157 | break; | |||
2158 | case SQL_TOKEN_MAX: | |||
2159 | rFkt = rComboBox.get_text(3); | |||
2160 | break; | |||
2161 | case SQL_TOKEN_MIN: | |||
2162 | rFkt = rComboBox.get_text(4); | |||
2163 | break; | |||
2164 | case SQL_TOKEN_SUM: | |||
2165 | rFkt = rComboBox.get_text(5); | |||
2166 | break; | |||
2167 | case SQL_TOKEN_EVERY: | |||
2168 | rFkt = rComboBox.get_text(6); | |||
2169 | break; | |||
2170 | case SQL_TOKEN_ANY: | |||
2171 | rFkt = rComboBox.get_text(7); | |||
2172 | break; | |||
2173 | case SQL_TOKEN_SOME: | |||
2174 | rFkt = rComboBox.get_text(8); | |||
2175 | break; | |||
2176 | case SQL_TOKEN_STDDEV_POP: | |||
2177 | rFkt = rComboBox.get_text(9); | |||
2178 | break; | |||
2179 | case SQL_TOKEN_STDDEV_SAMP: | |||
2180 | rFkt = rComboBox.get_text(10); | |||
2181 | break; | |||
2182 | case SQL_TOKEN_VAR_SAMP: | |||
2183 | rFkt = rComboBox.get_text(11); | |||
2184 | break; | |||
2185 | case SQL_TOKEN_VAR_POP: | |||
2186 | rFkt = rComboBox.get_text(12); | |||
2187 | break; | |||
2188 | case SQL_TOKEN_COLLECT: | |||
2189 | rFkt = rComboBox.get_text(13); | |||
2190 | break; | |||
2191 | case SQL_TOKEN_FUSION: | |||
2192 | rFkt = rComboBox.get_text(14); | |||
2193 | break; | |||
2194 | case SQL_TOKEN_INTERSECTION: | |||
2195 | rFkt = rComboBox.get_text(15); | |||
2196 | break; | |||
2197 | default: | |||
2198 | { | |||
2199 | const sal_Int32 nStopIdx = m_aFunctionStrings.lastIndexOf(';'); // grouping is not counted | |||
2200 | for (sal_Int32 nIdx {0}; nIdx<nStopIdx;) | |||
2201 | { | |||
2202 | const OUString sFunc {m_aFunctionStrings.getToken(0, ';', nIdx)}; | |||
2203 | if (rFkt.equalsIgnoreAsciiCase(sFunc)) | |||
2204 | { | |||
2205 | rFkt = sFunc; | |||
2206 | return true; | |||
2207 | } | |||
2208 | } | |||
2209 | return false; | |||
2210 | } | |||
2211 | } | |||
2212 | ||||
2213 | return true; | |||
2214 | } | |||
2215 | ||||
2216 | OUString OSelectionBrowseBox::GetCellContents(sal_Int32 nCellIndex, sal_uInt16 nColId) | |||
2217 | { | |||
2218 | if ( GetCurColumnId() == nColId && !m_bInUndoMode ) | |||
2219 | SaveModified(); | |||
2220 | ||||
2221 | sal_uInt16 nPos = GetColumnPos(nColId); | |||
2222 | OTableFieldDescRef pEntry = getFields()[nPos - 1]; | |||
2223 | OSL_ENSURE(pEntry != nullptr, "OSelectionBrowseBox::GetCellContents : invalid column id, prepare for GPF ... ")do { if (true && (!(pEntry != nullptr))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "2223" ": "), "%s", "OSelectionBrowseBox::GetCellContents : invalid column id, prepare for GPF ... " ); } } while (false); | |||
2224 | ||||
2225 | switch (nCellIndex) | |||
2226 | { | |||
2227 | case BROW_VIS_ROW4 : | |||
2228 | return pEntry->IsVisible() ? std::u16string_view(u"1") : std::u16string_view(u"0"); | |||
2229 | case BROW_ORDER_ROW3: | |||
2230 | { | |||
2231 | sal_Int32 nIdx = m_pOrderCell->get_widget().get_active(); | |||
2232 | if (nIdx == -1) | |||
2233 | nIdx = 0; | |||
2234 | return OUString::number(nIdx); | |||
2235 | } | |||
2236 | default: | |||
2237 | return GetCellText(nCellIndex, nColId); | |||
2238 | } | |||
2239 | } | |||
2240 | ||||
2241 | void OSelectionBrowseBox::SetCellContents(sal_Int32 nRow, sal_uInt16 nColId, const OUString& strNewText) | |||
2242 | { | |||
2243 | bool bWasEditing = IsEditing() && (GetCurColumnId() == nColId) && IsRowVisible(static_cast<sal_uInt16>(nRow)) && (GetCurRow() == static_cast<sal_uInt16>(GetBrowseRow(nRow))); | |||
2244 | if (bWasEditing) | |||
2245 | DeactivateCell(); | |||
2246 | ||||
2247 | sal_uInt16 nPos = GetColumnPos(nColId); | |||
2248 | OTableFieldDescRef pEntry = getEntry(nPos - 1); | |||
2249 | OSL_ENSURE(pEntry != nullptr, "OSelectionBrowseBox::SetCellContents : invalid column id, prepare for GPF ... ")do { if (true && (!(pEntry != nullptr))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "2249" ": "), "%s", "OSelectionBrowseBox::SetCellContents : invalid column id, prepare for GPF ... " ); } } while (false); | |||
2250 | ||||
2251 | switch (nRow) | |||
2252 | { | |||
2253 | case BROW_VIS_ROW4: | |||
2254 | pEntry->SetVisible(strNewText == "1"); | |||
2255 | break; | |||
2256 | case BROW_FIELD_ROW0: | |||
2257 | pEntry->SetField(strNewText); | |||
2258 | break; | |||
2259 | case BROW_TABLE_ROW2: | |||
2260 | pEntry->SetAlias(strNewText); | |||
2261 | break; | |||
2262 | case BROW_ORDER_ROW3: | |||
2263 | { | |||
2264 | sal_uInt16 nIdx = static_cast<sal_uInt16>(strNewText.toInt32()); | |||
2265 | pEntry->SetOrderDir(EOrderDir(nIdx)); | |||
2266 | } break; | |||
2267 | case BROW_COLUMNALIAS_ROW1: | |||
2268 | pEntry->SetFieldAlias(strNewText); | |||
2269 | break; | |||
2270 | case BROW_FUNCTION_ROW5: | |||
2271 | { | |||
2272 | OUString sGroupFunctionName = m_aFunctionStrings.copy(m_aFunctionStrings.lastIndexOf(';')+1); | |||
2273 | pEntry->SetFunction(strNewText); | |||
2274 | // first reset this two member | |||
2275 | sal_Int32 nFunctionType = pEntry->GetFunctionType(); | |||
2276 | nFunctionType &= ~FKT_AGGREGATE; | |||
2277 | pEntry->SetFunctionType(nFunctionType); | |||
2278 | if ( pEntry->IsGroupBy() && !sGroupFunctionName.equalsIgnoreAsciiCase(strNewText) ) | |||
2279 | pEntry->SetGroupBy(false); | |||
2280 | ||||
2281 | if ( sGroupFunctionName.equalsIgnoreAsciiCase(strNewText) ) | |||
2282 | pEntry->SetGroupBy(true); | |||
2283 | else if ( !strNewText.isEmpty() ) | |||
2284 | { | |||
2285 | nFunctionType |= FKT_AGGREGATE; | |||
2286 | pEntry->SetFunctionType(nFunctionType); | |||
2287 | } | |||
2288 | } break; | |||
2289 | default: | |||
2290 | pEntry->SetCriteria(sal_uInt16(nRow - BROW_CRIT1_ROW6), strNewText); | |||
2291 | } | |||
2292 | ||||
2293 | long nCellIndex = GetRealRow(nRow); | |||
2294 | if(IsRowVisible(static_cast<sal_uInt16>(nRow))) | |||
2295 | RowModified(nCellIndex, nColId); | |||
2296 | ||||
2297 | // the appropriate field-description is now empty -> set Visible to sal_False (now it is consistent to normal empty rows) | |||
2298 | if (pEntry->IsEmpty()) | |||
2299 | pEntry->SetVisible(false); | |||
2300 | ||||
2301 | if (bWasEditing) | |||
2302 | ActivateCell(nCellIndex, nColId); | |||
2303 | ||||
2304 | static_cast<OQueryController&>(getDesignView()->getController()).setModified( true ); | |||
2305 | } | |||
2306 | ||||
2307 | void OSelectionBrowseBox::ColumnResized(sal_uInt16 nColId) | |||
2308 | { | |||
2309 | if (static_cast<OQueryController&>(getDesignView()->getController()).isReadOnly()) | |||
2310 | return; | |||
2311 | // The resizing of columns can't be suppressed (BrowseBox doesn't support that) so we have to do this | |||
2312 | // fake. It's not _that_ bad : the user may change column widths while in read-only mode to see all details | |||
2313 | // but the changes aren't permanent ... | |||
2314 | ||||
2315 | sal_uInt16 nPos = GetColumnPos(nColId); | |||
2316 | OSL_ENSURE(nPos <= getFields().size(),"ColumnResized:: nColId should not be greater than List::count!")do { if (true && (!(nPos <= getFields().size()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "2316" ": "), "%s", "ColumnResized:: nColId should not be greater than List::count!" ); } } while (false); | |||
2317 | OTableFieldDescRef pEntry = getEntry(nPos-1); | |||
2318 | OSL_ENSURE(pEntry.is(), "OSelectionBrowseBox::ColumnResized : invalid FieldDescription !")do { if (true && (!(pEntry.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "2318" ": "), "%s", "OSelectionBrowseBox::ColumnResized : invalid FieldDescription !" ); } } while (false); | |||
2319 | static_cast<OQueryController&>(getDesignView()->getController()).setModified( true ); | |||
2320 | EditBrowseBox::ColumnResized(nColId); | |||
2321 | ||||
2322 | if ( pEntry.is()) | |||
2323 | { | |||
2324 | if ( !m_bInUndoMode ) | |||
2325 | { | |||
2326 | // create the undo action | |||
2327 | std::unique_ptr<OTabFieldSizedUndoAct> pUndo(new OTabFieldSizedUndoAct(this)); | |||
2328 | pUndo->SetColumnPosition( nPos ); | |||
2329 | pUndo->SetOriginalWidth(pEntry->GetColWidth()); | |||
2330 | getDesignView()->getController().addUndoActionAndInvalidate(std::move(pUndo)); | |||
2331 | } | |||
2332 | pEntry->SetColWidth(sal_uInt16(GetColumnWidth(nColId))); | |||
2333 | } | |||
2334 | } | |||
2335 | ||||
2336 | sal_uInt32 OSelectionBrowseBox::GetTotalCellWidth(long nRowId, sal_uInt16 nColId) | |||
2337 | { | |||
2338 | sal_uInt16 nPos = GetColumnPos(nColId); | |||
2339 | OSL_ENSURE((nPos == 0) || (nPos <= getFields().size()), "OSelectionBrowseBox::GetTotalCellWidth : invalid parameter nColId")do { if (true && (!((nPos == 0) || (nPos <= getFields ().size())))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "2339" ": "), "%s", "OSelectionBrowseBox::GetTotalCellWidth : invalid parameter nColId" ); } } while (false); | |||
2340 | ||||
2341 | OTableFieldDescRef pEntry = getFields()[nPos-1]; | |||
2342 | OSL_ENSURE(pEntry.is(), "OSelectionBrowseBox::GetTotalCellWidth : invalid FieldDescription !")do { if (true && (!(pEntry.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "2342" ": "), "%s", "OSelectionBrowseBox::GetTotalCellWidth : invalid FieldDescription !" ); } } while (false); | |||
2343 | ||||
2344 | long nRow = GetRealRow(nRowId); | |||
2345 | OUString strText(GetCellText(nRow, nColId)); | |||
2346 | return GetDataWindow().LogicToPixel(Size(GetDataWindow().GetTextWidth(strText),0)).Width(); | |||
2347 | } | |||
2348 | ||||
2349 | bool OSelectionBrowseBox::isCutAllowed() const | |||
2350 | { | |||
2351 | bool bCutAllowed = false; | |||
2352 | long nRow = GetRealRow(GetCurRow()); | |||
2353 | switch (nRow) | |||
2354 | { | |||
2355 | case BROW_VIS_ROW4: | |||
2356 | case BROW_ORDER_ROW3: | |||
2357 | case BROW_TABLE_ROW2: | |||
2358 | case BROW_FUNCTION_ROW5: | |||
2359 | break; | |||
2360 | case BROW_FIELD_ROW0: | |||
2361 | { | |||
2362 | weld::ComboBox& rComboBox = m_pFieldCell->get_widget(); | |||
2363 | int nStartPos, nEndPos; | |||
2364 | bCutAllowed = rComboBox.get_entry_selection_bounds(nStartPos, nEndPos); | |||
2365 | break; | |||
2366 | } | |||
2367 | default: | |||
2368 | { | |||
2369 | weld::Entry& rEntry = m_pTextCell->get_widget(); | |||
2370 | int nStartPos, nEndPos; | |||
2371 | bCutAllowed = rEntry.get_selection_bounds(nStartPos, nEndPos); | |||
2372 | break; | |||
2373 | } | |||
2374 | } | |||
2375 | return bCutAllowed; | |||
2376 | } | |||
2377 | ||||
2378 | void OSelectionBrowseBox::cut() | |||
2379 | { | |||
2380 | long nRow = GetRealRow(GetCurRow()); | |||
2381 | switch (nRow) | |||
2382 | { | |||
2383 | case BROW_FIELD_ROW0: | |||
2384 | { | |||
2385 | weld::ComboBox& rComboBox = m_pFieldCell->get_widget(); | |||
2386 | rComboBox.cut_entry_clipboard(); | |||
2387 | break; | |||
2388 | } | |||
2389 | default: | |||
2390 | { | |||
2391 | weld::Entry& rEntry = m_pTextCell->get_widget(); | |||
2392 | rEntry.cut_clipboard(); | |||
2393 | } | |||
2394 | } | |||
2395 | SaveModified(); | |||
2396 | RowModified(GetBrowseRow(nRow), GetCurColumnId()); | |||
2397 | ||||
2398 | invalidateUndoRedo(); | |||
2399 | } | |||
2400 | ||||
2401 | void OSelectionBrowseBox::paste() | |||
2402 | { | |||
2403 | long nRow = GetRealRow(GetCurRow()); | |||
2404 | switch (nRow) | |||
2405 | { | |||
2406 | case BROW_FIELD_ROW0: | |||
2407 | { | |||
2408 | weld::ComboBox& rComboBox = m_pFieldCell->get_widget(); | |||
2409 | rComboBox.paste_entry_clipboard(); | |||
2410 | break; | |||
2411 | } | |||
2412 | default: | |||
2413 | { | |||
2414 | weld::Entry& rEntry = m_pTextCell->get_widget(); | |||
2415 | rEntry.paste_clipboard(); | |||
2416 | break; | |||
2417 | } | |||
2418 | } | |||
2419 | RowModified(GetBrowseRow(nRow), GetCurColumnId()); | |||
2420 | invalidateUndoRedo(); | |||
2421 | } | |||
2422 | ||||
2423 | bool OSelectionBrowseBox::isPasteAllowed() const | |||
2424 | { | |||
2425 | bool bPasteAllowed = true; | |||
2426 | long nRow = GetRealRow(GetCurRow()); | |||
2427 | switch (nRow) | |||
2428 | { | |||
2429 | case BROW_VIS_ROW4: | |||
2430 | case BROW_ORDER_ROW3: | |||
2431 | case BROW_TABLE_ROW2: | |||
2432 | case BROW_FUNCTION_ROW5: | |||
2433 | bPasteAllowed = false; | |||
2434 | break; | |||
2435 | } | |||
2436 | return bPasteAllowed; | |||
2437 | } | |||
2438 | ||||
2439 | bool OSelectionBrowseBox::isCopyAllowed() const | |||
2440 | { | |||
2441 | return isCutAllowed(); | |||
2442 | } | |||
2443 | ||||
2444 | void OSelectionBrowseBox::copy() | |||
2445 | { | |||
2446 | long nRow = GetRealRow(GetCurRow()); | |||
2447 | switch (nRow) | |||
2448 | { | |||
2449 | case BROW_FIELD_ROW0: | |||
2450 | { | |||
2451 | weld::ComboBox& rComboBox = m_pFieldCell->get_widget(); | |||
2452 | rComboBox.copy_entry_clipboard(); | |||
2453 | break; | |||
2454 | } | |||
2455 | default: | |||
2456 | { | |||
2457 | weld::Entry& rEntry = m_pTextCell->get_widget(); | |||
2458 | rEntry.copy_clipboard(); | |||
2459 | break; | |||
2460 | } | |||
2461 | } | |||
2462 | } | |||
2463 | ||||
2464 | void OSelectionBrowseBox::appendUndoAction(const OUString& _rOldValue, const OUString& _rNewValue, sal_Int32 _nRow, bool& _bListAction) | |||
2465 | { | |||
2466 | if ( !m_bInUndoMode && _rNewValue != _rOldValue ) | |||
2467 | { | |||
2468 | if ( !_bListAction ) | |||
2469 | { | |||
2470 | _bListAction = true; | |||
2471 | static_cast<OQueryController&>(getDesignView()->getController()).GetUndoManager().EnterListAction(OUString(),OUString(),0,ViewShellId(-1)); | |||
2472 | } | |||
2473 | appendUndoAction(_rOldValue,_rNewValue,_nRow); | |||
2474 | } | |||
2475 | } | |||
2476 | ||||
2477 | void OSelectionBrowseBox::appendUndoAction(const OUString& _rOldValue,const OUString& _rNewValue,sal_Int32 _nRow) | |||
2478 | { | |||
2479 | if ( !m_bInUndoMode && _rNewValue != _rOldValue ) | |||
2480 | { | |||
2481 | std::unique_ptr<OTabFieldCellModifiedUndoAct> pUndoAct(new OTabFieldCellModifiedUndoAct(this)); | |||
2482 | pUndoAct->SetCellIndex(_nRow); | |||
2483 | OSL_ENSURE(GetColumnPos(GetCurColumnId()) != BROWSER_INVALIDID,"Current position isn't valid!")do { if (true && (!(GetColumnPos(GetCurColumnId()) != ((sal_uInt16) 0xFFFF)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "2483" ": "), "%s", "Current position isn't valid!"); } } while (false); | |||
2484 | pUndoAct->SetColumnPosition( GetColumnPos(GetCurColumnId()) ); | |||
2485 | pUndoAct->SetCellContents(_rOldValue); | |||
2486 | getDesignView()->getController().addUndoActionAndInvalidate(std::move(pUndoAct)); | |||
2487 | } | |||
2488 | } | |||
2489 | ||||
2490 | IMPL_LINK_NOARG(OSelectionBrowseBox, OnInvalidateTimer, Timer *, void)void OSelectionBrowseBox::LinkStubOnInvalidateTimer(void * instance , Timer * data) { return static_cast<OSelectionBrowseBox * >(instance)->OnInvalidateTimer(data); } void OSelectionBrowseBox ::OnInvalidateTimer(__attribute__ ((unused)) Timer *) | |||
2491 | { | |||
2492 | static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature(SID_CUT(5000 + 710)); | |||
2493 | static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature(SID_COPY(5000 + 711)); | |||
2494 | static_cast<OQueryController&>(getDesignView()->getController()).InvalidateFeature(SID_PASTE(5000 + 712)); | |||
2495 | if(!m_bStopTimer) | |||
2496 | m_timerInvalidate.Start(); | |||
2497 | } | |||
2498 | ||||
2499 | void OSelectionBrowseBox::stopTimer() | |||
2500 | { | |||
2501 | m_bStopTimer = true; | |||
2502 | if (m_timerInvalidate.IsActive()) | |||
2503 | m_timerInvalidate.Stop(); | |||
2504 | } | |||
2505 | ||||
2506 | void OSelectionBrowseBox::startTimer() | |||
2507 | { | |||
2508 | m_bStopTimer = false; | |||
2509 | if (!m_timerInvalidate.IsActive()) | |||
2510 | m_timerInvalidate.Start(); | |||
2511 | } | |||
2512 | ||||
2513 | OTableFields& OSelectionBrowseBox::getFields() const | |||
2514 | { | |||
2515 | OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController()); | |||
2516 | return rController.getTableFieldDesc(); | |||
2517 | } | |||
2518 | ||||
2519 | void OSelectionBrowseBox::enableControl(const OTableFieldDescRef& _rEntry,Window* _pControl) | |||
2520 | { | |||
2521 | bool bEnable = !_rEntry->isCondition(); | |||
2522 | _pControl->Enable(bEnable); | |||
2523 | _pControl->EnableInput(bEnable); | |||
2524 | } | |||
2525 | ||||
2526 | void OSelectionBrowseBox::setTextCellContext(const OTableFieldDescRef& _rEntry,const OUString& _sText,const OString& _sHelpId) | |||
2527 | { | |||
2528 | weld::Entry& rEntry = m_pTextCell->get_widget(); | |||
2529 | rEntry.set_text(_sText); | |||
2530 | rEntry.save_value(); | |||
2531 | if (!m_pTextCell->HasFocus()) | |||
2532 | m_pTextCell->GrabFocus(); | |||
2533 | ||||
2534 | enableControl(_rEntry,m_pTextCell); | |||
2535 | ||||
2536 | if (m_pTextCell->GetHelpId() != _sHelpId) | |||
2537 | // as TextCell is used in various contexts I will delete the cached HelpText | |||
2538 | m_pTextCell->SetHelpText(OUString()); | |||
2539 | m_pTextCell->SetHelpId(_sHelpId); | |||
2540 | } | |||
2541 | ||||
2542 | void OSelectionBrowseBox::invalidateUndoRedo() | |||
2543 | { | |||
2544 | OQueryController& rController = static_cast<OQueryController&>(getDesignView()->getController()); | |||
2545 | rController.InvalidateFeature( ID_BROWSER_UNDO(5000 + 701) ); | |||
2546 | rController.InvalidateFeature( ID_BROWSER_REDO(5000 + 700) ); | |||
2547 | rController.InvalidateFeature( ID_BROWSER_QUERY_EXECUTE( 10000 + 721 ) ); | |||
2548 | } | |||
2549 | ||||
2550 | OTableFieldDescRef OSelectionBrowseBox::getEntry(OTableFields::size_type _nPos) | |||
2551 | { | |||
2552 | // we have to check if we need a new entry at this position | |||
2553 | OTableFields& aFields = getFields(); | |||
2554 | OSL_ENSURE(aFields.size() > _nPos,"ColID is to great!")do { if (true && (!(aFields.size() > _nPos))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "2554" ": "), "%s", "ColID is to great!"); } } while (false ); | |||
2555 | ||||
2556 | OTableFieldDescRef pEntry = aFields[_nPos]; | |||
2557 | OSL_ENSURE(pEntry.is(),"Invalid entry!")do { if (true && (!(pEntry.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "2557" ": "), "%s", "Invalid entry!"); } } while (false); | |||
2558 | if ( !pEntry.is() ) | |||
2559 | { | |||
2560 | pEntry = new OTableFieldDesc(); | |||
2561 | pEntry->SetColumnId( | |||
2562 | GetColumnId(sal::static_int_cast< sal_uInt16 >(_nPos+1))); | |||
2563 | aFields[_nPos] = pEntry; | |||
2564 | } | |||
2565 | return pEntry; | |||
2566 | } | |||
2567 | ||||
2568 | void OSelectionBrowseBox::GetFocus() | |||
2569 | { | |||
2570 | if(!IsEditing() && !m_bWasEditing) | |||
2571 | ActivateCell(); | |||
2572 | EditBrowseBox::GetFocus(); | |||
2573 | } | |||
2574 | ||||
2575 | void OSelectionBrowseBox::DeactivateCell(bool _bUpdate) | |||
2576 | { | |||
2577 | m_bWasEditing = true; | |||
2578 | EditBrowseBox::DeactivateCell(_bUpdate); | |||
2579 | m_bWasEditing = false; | |||
2580 | } | |||
2581 | ||||
2582 | OUString OSelectionBrowseBox::GetRowDescription( sal_Int32 _nRow ) const | |||
2583 | { | |||
2584 | OUString aLabel(DBA_RES(STR_QUERY_HANDLETEXT)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_QUERY_HANDLETEXT" "\004" u8"Field;Alias;Table;Sort;Visible;Function;Criterion;Or;Or" ) )); | |||
2585 | ||||
2586 | // from BROW_CRIT2_ROW onwards all rows are shown as "or" | |||
2587 | sal_Int32 nToken = (_nRow >= GetBrowseRow(BROW_CRIT2_ROW7)) | |||
2588 | ? BROW_CRIT2_ROW7 : GetRealRow(_nRow); | |||
2589 | return aLabel.getToken(nToken, ';'); | |||
2590 | } | |||
2591 | ||||
2592 | OUString OSelectionBrowseBox::GetAccessibleObjectName( ::vcl::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition) const | |||
2593 | { | |||
2594 | OUString sRetText; | |||
2595 | switch( _eObjType ) | |||
2596 | { | |||
2597 | case ::vcl::BBTYPE_ROWHEADERCELL: | |||
2598 | sRetText = GetRowDescription(_nPosition); | |||
2599 | break; | |||
2600 | default: | |||
2601 | sRetText = EditBrowseBox::GetAccessibleObjectDescription(_eObjType,_nPosition); | |||
2602 | } | |||
2603 | return sRetText; | |||
2604 | } | |||
2605 | ||||
2606 | bool OSelectionBrowseBox::fillEntryTable(OTableFieldDescRef const & _pEntry,const OUString& _sTableName) | |||
2607 | { | |||
2608 | bool bRet = false; | |||
2609 | OJoinTableView::OTableWindowMap& rTabWinList = getDesignView()->getTableView()->GetTabWinMap(); | |||
2610 | OJoinTableView::OTableWindowMap::const_iterator aIter = rTabWinList.find(_sTableName); | |||
2611 | if(aIter != rTabWinList.end()) | |||
2612 | { | |||
2613 | OQueryTableWindow* pEntryTab = static_cast<OQueryTableWindow*>(aIter->second.get()); | |||
2614 | if (pEntryTab) | |||
2615 | { | |||
2616 | _pEntry->SetTable(pEntryTab->GetTableName()); | |||
2617 | _pEntry->SetTabWindow(pEntryTab); | |||
2618 | bRet = true; | |||
2619 | } | |||
2620 | } | |||
2621 | return bRet; | |||
2622 | } | |||
2623 | ||||
2624 | void OSelectionBrowseBox::setFunctionCell(OTableFieldDescRef const & _pEntry) | |||
2625 | { | |||
2626 | Reference< XConnection> xConnection = static_cast<OQueryController&>(getDesignView()->getController()).getConnection(); | |||
2627 | if ( !xConnection.is() ) | |||
2628 | return; | |||
2629 | ||||
2630 | // Aggregate functions in general only available with Core SQL | |||
2631 | if ( lcl_SupportsCoreSQLGrammar(xConnection) ) | |||
2632 | { | |||
2633 | sal_Int32 nIdx {0}; | |||
2634 | // if we have an asterisk, no other function than count is allowed | |||
2635 | weld::ComboBox& rComboBox = m_pFunctionCell->get_widget(); | |||
2636 | rComboBox.clear(); | |||
2637 | rComboBox.append_text(m_aFunctionStrings.getToken(0, ';', nIdx)); | |||
2638 | if ( isFieldNameAsterisk(_pEntry->GetField()) ) | |||
2639 | rComboBox.append_text(m_aFunctionStrings.getToken(1, ';', nIdx)); // 2nd token: COUNT | |||
2640 | else | |||
2641 | { | |||
2642 | const bool bSkipLastToken {_pEntry->isNumeric()}; | |||
2643 | while (nIdx>0) | |||
2644 | { | |||
2645 | const OUString sTok {m_aFunctionStrings.getToken(0, ';', nIdx)}; | |||
2646 | if (bSkipLastToken && nIdx<0) | |||
2647 | break; | |||
2648 | rComboBox.append_text(sTok); | |||
2649 | } | |||
2650 | } | |||
2651 | ||||
2652 | if ( _pEntry->IsGroupBy() ) | |||
2653 | { | |||
2654 | OSL_ENSURE(!_pEntry->isNumeric(),"Not allowed to combine group by and numeric values!")do { if (true && (!(!_pEntry->isNumeric()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx" ":" "2654" ": "), "%s", "Not allowed to combine group by and numeric values!" ); } } while (false); | |||
2655 | rComboBox.set_active_text(rComboBox.get_text(rComboBox.get_count() - 1)); | |||
2656 | } | |||
2657 | else if (rComboBox.find_text(_pEntry->GetFunction()) != -1) | |||
2658 | rComboBox.set_active_text(_pEntry->GetFunction()); | |||
2659 | else | |||
2660 | rComboBox.set_active(0); | |||
2661 | ||||
2662 | enableControl(_pEntry, m_pFunctionCell); | |||
2663 | } | |||
2664 | else | |||
2665 | { | |||
2666 | // only COUNT(*) and COUNT("table".*) allowed | |||
2667 | bool bCountRemoved = !isFieldNameAsterisk(_pEntry->GetField()); | |||
2668 | weld::ComboBox& rComboBox = m_pFunctionCell->get_widget(); | |||
2669 | if ( bCountRemoved ) | |||
2670 | rComboBox.remove(1); | |||
2671 | ||||
2672 | if ( !bCountRemoved && rComboBox.get_count() < 2) | |||
2673 | rComboBox.append_text(m_aFunctionStrings.getToken(2, ';')); // 2 -> COUNT | |||
2674 | ||||
2675 | if (rComboBox.find_text(_pEntry->GetFunction()) != -1) | |||
2676 | rComboBox.set_active_text(_pEntry->GetFunction()); | |||
2677 | else | |||
2678 | rComboBox.set_active(0); | |||
2679 | } | |||
2680 | } | |||
2681 | ||||
2682 | Reference< XAccessible > OSelectionBrowseBox::CreateAccessibleCell( sal_Int32 _nRow, sal_uInt16 _nColumnPos ) | |||
2683 | { | |||
2684 | OTableFieldDescRef pEntry; | |||
2685 | if(getFields().size() > o3tl::make_unsigned(_nColumnPos - 1)) | |||
2686 | pEntry = getFields()[_nColumnPos - 1]; | |||
2687 | ||||
2688 | if ( _nRow == BROW_VIS_ROW4 && pEntry.is() ) | |||
2689 | return EditBrowseBox::CreateAccessibleCheckBoxCell( _nRow, _nColumnPos,pEntry->IsVisible() ? TRISTATE_TRUE : TRISTATE_FALSE ); | |||
2690 | ||||
2691 | return EditBrowseBox::CreateAccessibleCell( _nRow, _nColumnPos ); | |||
2692 | } | |||
2693 | ||||
2694 | bool OSelectionBrowseBox::HasFieldByAliasName(const OUString& rFieldName, OTableFieldDescRef const & rInfo) const | |||
2695 | { | |||
2696 | for (auto const& field : getFields()) | |||
2697 | { | |||
2698 | if ( field->GetFieldAlias() == rFieldName ) | |||
2699 | { | |||
2700 | *rInfo = *field; | |||
2701 | return true; | |||
2702 | } | |||
2703 | } | |||
2704 | return false; | |||
2705 | } | |||
2706 | ||||
2707 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | /* |
3 | * This file is part of the LibreOffice project. |
4 | * |
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/. |
8 | * |
9 | * This file incorporates work covered by the following license notice: |
10 | * |
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 . |
18 | */ |
19 | |
20 | #ifndef INCLUDED_VCL_PTR_HXX |
21 | #define INCLUDED_VCL_PTR_HXX |
22 | |
23 | #include <sal/config.h> |
24 | |
25 | #include <rtl/ref.hxx> |
26 | |
27 | #include <utility> |
28 | #include <type_traits> |
29 | |
30 | #ifdef DBG_UTIL |
31 | #ifndef _WIN32 |
32 | #include <vcl/vclmain.hxx> |
33 | #endif |
34 | #endif |
35 | |
36 | class VclReferenceBase; |
37 | |
38 | namespace vcl::detail { |
39 | |
40 | template<typename> |
41 | constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; } |
42 | |
43 | template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase( |
44 | int (*)[sizeof(T)]) |
45 | { return std::is_base_of<VclReferenceBase, T>::value; } |
46 | |
47 | } // namespace vcl::detail |
48 | |
49 | /** |
50 | * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses. |
51 | * |
52 | * For more details on the design please see vcl/README.lifecycle |
53 | * |
54 | * @param reference_type must be a subclass of vcl::Window |
55 | */ |
56 | template <class reference_type> |
57 | class VclPtr |
58 | { |
59 | static_assert( |
60 | vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>( |
61 | nullptr), |
62 | "template argument type must be derived from VclReferenceBase"); |
63 | |
64 | ::rtl::Reference<reference_type> m_rInnerRef; |
65 | |
66 | public: |
67 | /** Constructor... |
68 | */ |
69 | VclPtr() |
70 | : m_rInnerRef() |
71 | {} |
72 | |
73 | /** Constructor... |
74 | */ |
75 | VclPtr (reference_type * pBody) |
76 | : m_rInnerRef(pBody) |
77 | {} |
78 | |
79 | /** Constructor... that doesn't take a ref. |
80 | */ |
81 | VclPtr (reference_type * pBody, __sal_NoAcquire) |
82 | : m_rInnerRef(pBody, SAL_NO_ACQUIRE) |
83 | {} |
84 | |
85 | /** Up-casting conversion constructor: Copies interface reference. |
86 | |
87 | Does not work for up-casts to ambiguous bases. For the special case of |
88 | up-casting to Reference< XInterface >, see the corresponding conversion |
89 | operator. |
90 | |
91 | @param rRef another reference |
92 | */ |
93 | template< class derived_type > |
94 | VclPtr( |
95 | const VclPtr< derived_type > & rRef, |
96 | typename std::enable_if< |
97 | std::is_base_of<reference_type, derived_type>::value, int>::type |
98 | = 0 ) |
99 | : m_rInnerRef( static_cast<reference_type*>(rRef) ) |
100 | { |
101 | } |
102 | |
103 | #if defined(DBG_UTIL) && !defined(_WIN32) |
104 | virtual ~VclPtr() |
105 | { |
106 | assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain ::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()" , "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx" , 106, __extension__ __PRETTY_FUNCTION__)); |
107 | // We can be one of the intermediate counts, but if we are the last |
108 | // VclPtr keeping this object alive, then something forgot to call dispose(). |
109 | assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef ->isDisposed() || m_rInnerRef->getRefCount() > 1) && "someone forgot to call dispose()") ? void (0) : __assert_fail ("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\"" , "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx" , 110, __extension__ __PRETTY_FUNCTION__)) |
110 | && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef ->isDisposed() || m_rInnerRef->getRefCount() > 1) && "someone forgot to call dispose()") ? void (0) : __assert_fail ("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\"" , "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx" , 110, __extension__ __PRETTY_FUNCTION__)); |
111 | } |
112 | VclPtr(VclPtr const &) = default; |
113 | VclPtr(VclPtr &&) = default; |
114 | VclPtr & operator =(VclPtr const &) = default; |
115 | VclPtr & operator =(VclPtr &&) = default; |
116 | #endif |
117 | |
118 | /** |
119 | * A construction helper for VclPtr. Since VclPtr types are created |
120 | * with a reference-count of one - to help fit into the existing |
121 | * code-flow; this helps us to construct them easily. |
122 | * |
123 | * For more details on the design please see vcl/README.lifecycle |
124 | * |
125 | * @tparam reference_type must be a subclass of vcl::Window |
126 | */ |
127 | template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg) |
128 | { |
129 | return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE ); |
130 | } |
131 | |
132 | /** Probably most common used: handle->someBodyOp(). |
133 | */ |
134 | reference_type * operator->() const |
135 | { |
136 | return m_rInnerRef.get(); |
137 | } |
138 | |
139 | /** Get the body. Can be used instead of operator->(). |
140 | I.e. handle->someBodyOp() and handle.get()->someBodyOp() |
141 | are the same. |
142 | */ |
143 | reference_type * get() const |
144 | { |
145 | return m_rInnerRef.get(); |
146 | } |
147 | |
148 | void set(reference_type *pBody) |
149 | { |
150 | m_rInnerRef.set(pBody); |
151 | } |
152 | |
153 | void reset(reference_type *pBody) |
154 | { |
155 | m_rInnerRef.set(pBody); |
156 | } |
157 | |
158 | /** Up-casting copy assignment operator. |
159 | |
160 | Does not work for up-casts to ambiguous bases. |
161 | |
162 | @param rRef another reference |
163 | */ |
164 | template<typename derived_type> |
165 | typename std::enable_if< |
166 | std::is_base_of<reference_type, derived_type>::value, |
167 | VclPtr &>::type |
168 | operator =(VclPtr<derived_type> const & rRef) |
169 | { |
170 | m_rInnerRef.set(rRef.get()); |
171 | return *this; |
172 | } |
173 | |
174 | VclPtr & operator =(reference_type * pBody) |
175 | { |
176 | m_rInnerRef.set(pBody); |
177 | return *this; |
178 | } |
179 | |
180 | operator reference_type * () const |
181 | { |
182 | return m_rInnerRef.get(); |
183 | } |
184 | |
185 | explicit operator bool () const |
186 | { |
187 | return m_rInnerRef.get() != nullptr; |
188 | } |
189 | |
190 | void clear() |
191 | { |
192 | m_rInnerRef.clear(); |
193 | } |
194 | |
195 | void reset() |
196 | { |
197 | m_rInnerRef.clear(); |
198 | } |
199 | |
200 | void disposeAndClear() |
201 | { |
202 | // hold it alive for the lifetime of this method |
203 | ::rtl::Reference<reference_type> aTmp(m_rInnerRef); |
204 | m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-) |
205 | if (aTmp.get()) { |
206 | aTmp->disposeOnce(); |
207 | } |
208 | } |
209 | |
210 | /** Needed to place VclPtr's into STL collection. |
211 | */ |
212 | bool operator< (const VclPtr<reference_type> & handle) const |
213 | { |
214 | return (m_rInnerRef < handle.m_rInnerRef); |
215 | } |
216 | }; // class VclPtr |
217 | |
218 | template<typename T1, typename T2> |
219 | inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) { |
220 | return p1.get() == p2.get(); |
221 | } |
222 | |
223 | template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2) |
224 | { |
225 | return p1.get() == p2; |
226 | } |
227 | |
228 | template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) { |
229 | return p1.get() == p2; |
230 | } |
231 | |
232 | template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2) |
233 | { |
234 | return p1 == p2.get(); |
235 | } |
236 | |
237 | template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) { |
238 | return p1 == p2.get(); |
239 | } |
240 | |
241 | template<typename T1, typename T2> |
242 | inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) { |
243 | return !(p1 == p2); |
244 | } |
245 | |
246 | template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2) |
247 | { |
248 | return !(p1 == p2); |
249 | } |
250 | |
251 | template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) { |
252 | return !(p1 == p2); |
253 | } |
254 | |
255 | template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2) |
256 | { |
257 | return !(p1 == p2); |
258 | } |
259 | |
260 | template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) { |
261 | return !(p1 == p2); |
262 | } |
263 | |
264 | /** |
265 | * A construction helper for a temporary VclPtr. Since VclPtr types |
266 | * are created with a reference-count of one - to help fit into |
267 | * the existing code-flow; this helps us to construct them easily. |
268 | * see also VclPtr::Create and ScopedVclPtr |
269 | * |
270 | * For more details on the design please see vcl/README.lifecycle |
271 | * |
272 | * @param reference_type must be a subclass of vcl::Window |
273 | */ |
274 | template <class reference_type> |
275 | class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type> |
276 | { |
277 | public: |
278 | template<typename... Arg> VclPtrInstance(Arg &&... arg) |
279 | : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE ) |
280 | { |
281 | } |
282 | |
283 | /** |
284 | * Override and disallow this, to prevent people accidentally calling it and actually |
285 | * getting VclPtr::Create and getting a naked VclPtr<> instance |
286 | */ |
287 | template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete; |
288 | }; |
289 | |
290 | template <class reference_type> |
291 | class ScopedVclPtr : public VclPtr<reference_type> |
292 | { |
293 | public: |
294 | /** Constructor... |
295 | */ |
296 | ScopedVclPtr() |
297 | : VclPtr<reference_type>() |
298 | {} |
299 | |
300 | /** Constructor |
301 | */ |
302 | ScopedVclPtr (reference_type * pBody) |
303 | : VclPtr<reference_type>(pBody) |
304 | {} |
305 | |
306 | /** Copy constructor... |
307 | */ |
308 | ScopedVclPtr (const VclPtr<reference_type> & handle) |
309 | : VclPtr<reference_type>(handle) |
310 | {} |
311 | |
312 | /** |
313 | Assignment that releases the last reference. |
314 | */ |
315 | void disposeAndReset(reference_type *pBody) |
316 | { |
317 | if (pBody != this->get()) { |
318 | VclPtr<reference_type>::disposeAndClear(); |
319 | VclPtr<reference_type>::set(pBody); |
320 | } |
321 | } |
322 | |
323 | /** |
324 | Assignment that releases the last reference. |
325 | */ |
326 | ScopedVclPtr<reference_type>& operator = (reference_type * pBody) |
327 | { |
328 | disposeAndReset(pBody); |
329 | return *this; |
330 | } |
331 | |
332 | /** Up-casting conversion constructor: Copies interface reference. |
333 | |
334 | Does not work for up-casts to ambiguous bases. For the special case of |
335 | up-casting to Reference< XInterface >, see the corresponding conversion |
336 | operator. |
337 | |
338 | @param rRef another reference |
339 | */ |
340 | template< class derived_type > |
341 | ScopedVclPtr( |
342 | const VclPtr< derived_type > & rRef, |
343 | typename std::enable_if< |
344 | std::is_base_of<reference_type, derived_type>::value, int>::type |
345 | = 0 ) |
346 | : VclPtr<reference_type>( rRef ) |
347 | { |
348 | } |
349 | |
350 | /** Up-casting assignment operator. |
351 | |
352 | Does not work for up-casts to ambiguous bases. |
353 | |
354 | @param rRef another VclPtr |
355 | */ |
356 | template<typename derived_type> |
357 | typename std::enable_if< |
358 | std::is_base_of<reference_type, derived_type>::value, |
359 | ScopedVclPtr &>::type |
360 | operator =(VclPtr<derived_type> const & rRef) |
361 | { |
362 | disposeAndReset(rRef.get()); |
363 | return *this; |
364 | } |
365 | |
366 | /** |
367 | * Override and disallow this, to prevent people accidentally calling it and actually |
368 | * getting VclPtr::Create and getting a naked VclPtr<> instance |
369 | */ |
370 | template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete; |
371 | |
372 | ~ScopedVclPtr() |
373 | { |
374 | VclPtr<reference_type>::disposeAndClear(); |
375 | assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get( ) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr" , "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx" , 375, __extension__ __PRETTY_FUNCTION__)); // make sure there are no lingering references |
376 | } |
377 | |
378 | private: |
379 | // Most likely we don't want this default copy-constructor. |
380 | ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete; |
381 | // And certainly we don't want a default assignment operator. |
382 | ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete; |
383 | // And disallow reset as that doesn't call disposeAndClear on the original reference |
384 | void reset() = delete; |
385 | void reset(reference_type *pBody) = delete; |
386 | |
387 | protected: |
388 | ScopedVclPtr (reference_type * pBody, __sal_NoAcquire) |
389 | : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE) |
390 | {} |
391 | }; |
392 | |
393 | /** |
394 | * A construction helper for ScopedVclPtr. Since VclPtr types are created |
395 | * with a reference-count of one - to help fit into the existing |
396 | * code-flow; this helps us to construct them easily. |
397 | * |
398 | * For more details on the design please see vcl/README.lifecycle |
399 | * |
400 | * @param reference_type must be a subclass of vcl::Window |
401 | */ |
402 | #if defined _MSC_VER |
403 | #pragma warning(push) |
404 | #pragma warning(disable: 4521) // " multiple copy constructors specified" |
405 | #endif |
406 | template <class reference_type> |
407 | class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type> |
408 | { |
409 | public: |
410 | template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg) |
411 | : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE ) |
412 | { |
413 | } |
414 | |
415 | /** |
416 | * Override and disallow this, to prevent people accidentally calling it and actually |
417 | * getting VclPtr::Create and getting a naked VclPtr<> instance |
418 | */ |
419 | template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete; |
420 | |
421 | private: |
422 | // Prevent the above perfect forwarding ctor from hijacking (accidental) |
423 | // attempts at ScopedVclPtrInstance copy construction (where the hijacking |
424 | // would typically lead to somewhat obscure error messages); both non-const |
425 | // and const variants are needed here, as the ScopedVclPtr base class has a |
426 | // const--variant copy ctor, so the implicitly declared copy ctor for |
427 | // ScopedVclPtrInstance would also be the const variant, so non-const copy |
428 | // construction attempts would be hijacked by the perfect forwarding ctor; |
429 | // but if we only declared a non-const variant here, the const variant would |
430 | // no longer be implicitly declared (as there would already be an explicitly |
431 | // declared copy ctor), so const copy construction attempts would then be |
432 | // hijacked by the perfect forwarding ctor: |
433 | ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete; |
434 | ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete; |
435 | }; |
436 | #if defined _MSC_VER |
437 | #pragma warning(pop) |
438 | #endif |
439 | |
440 | #endif // INCLUDED_VCL_PTR_HXX |
441 | |
442 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | ||||||||
2 | /* | ||||||||
3 | * This file is part of the LibreOffice project. | ||||||||
4 | * | ||||||||
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/. | ||||||||
8 | * | ||||||||
9 | * This file incorporates work covered by the following license notice: | ||||||||
10 | * | ||||||||
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 . | ||||||||
18 | */ | ||||||||
19 | |||||||||
20 | #ifndef INCLUDED_RTL_REF_HXX | ||||||||
21 | #define INCLUDED_RTL_REF_HXX | ||||||||
22 | |||||||||
23 | #include "sal/config.h" | ||||||||
24 | |||||||||
25 | #include <cassert> | ||||||||
26 | #include <cstddef> | ||||||||
27 | #include <functional> | ||||||||
28 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||||
29 | #include <type_traits> | ||||||||
30 | #endif | ||||||||
31 | |||||||||
32 | #include "sal/types.h" | ||||||||
33 | |||||||||
34 | namespace rtl | ||||||||
35 | { | ||||||||
36 | |||||||||
37 | /** Template reference class for reference type. | ||||||||
38 | */ | ||||||||
39 | template <class reference_type> | ||||||||
40 | class Reference | ||||||||
41 | { | ||||||||
42 | /** The <b>reference_type</b> body pointer. | ||||||||
43 | */ | ||||||||
44 | reference_type * m_pBody; | ||||||||
45 | |||||||||
46 | |||||||||
47 | public: | ||||||||
48 | /** Constructor... | ||||||||
49 | */ | ||||||||
50 | Reference() | ||||||||
51 | : m_pBody (NULL__null) | ||||||||
52 | {} | ||||||||
53 | |||||||||
54 | |||||||||
55 | /** Constructor... | ||||||||
56 | */ | ||||||||
57 | Reference (reference_type * pBody, __sal_NoAcquire) | ||||||||
58 | : m_pBody (pBody) | ||||||||
59 | { | ||||||||
60 | } | ||||||||
61 | |||||||||
62 | /** Constructor... | ||||||||
63 | */ | ||||||||
64 | Reference (reference_type * pBody) | ||||||||
65 | : m_pBody (pBody) | ||||||||
66 | { | ||||||||
67 | if (m_pBody) | ||||||||
68 | m_pBody->acquire(); | ||||||||
69 | } | ||||||||
70 | |||||||||
71 | /** Copy constructor... | ||||||||
72 | */ | ||||||||
73 | Reference (const Reference<reference_type> & handle) | ||||||||
74 | : m_pBody (handle.m_pBody) | ||||||||
75 | { | ||||||||
76 | if (m_pBody) | ||||||||
77 | m_pBody->acquire(); | ||||||||
78 | } | ||||||||
79 | |||||||||
80 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||||
81 | /** Move constructor... | ||||||||
82 | */ | ||||||||
83 | Reference (Reference<reference_type> && handle) noexcept | ||||||||
84 | : m_pBody (handle.m_pBody) | ||||||||
85 | { | ||||||||
86 | handle.m_pBody = nullptr; | ||||||||
87 | } | ||||||||
88 | #endif | ||||||||
89 | |||||||||
90 | #if defined LIBO_INTERNAL_ONLY1 | ||||||||
91 | /** Up-casting conversion constructor: Copies interface reference. | ||||||||
92 | |||||||||
93 | Does not work for up-casts to ambiguous bases. | ||||||||
94 | |||||||||
95 | @param rRef another reference | ||||||||
96 | */ | ||||||||
97 | template< class derived_type > | ||||||||
98 | inline Reference( | ||||||||
99 | const Reference< derived_type > & rRef, | ||||||||
100 | std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 ) | ||||||||
101 | : m_pBody (rRef.get()) | ||||||||
102 | { | ||||||||
103 | if (m_pBody) | ||||||||
104 | m_pBody->acquire(); | ||||||||
105 | } | ||||||||
106 | #endif | ||||||||
107 | |||||||||
108 | /** Destructor... | ||||||||
109 | */ | ||||||||
110 | ~Reference() COVERITY_NOEXCEPT_FALSE | ||||||||
111 | { | ||||||||
112 | if (m_pBody) | ||||||||
113 | m_pBody->release(); | ||||||||
114 | } | ||||||||
115 | |||||||||
116 | /** Set... | ||||||||
117 | Similar to assignment. | ||||||||
118 | */ | ||||||||
119 | Reference<reference_type> & | ||||||||
120 | SAL_CALL set (reference_type * pBody) | ||||||||
121 | { | ||||||||
122 | if (pBody) | ||||||||
123 | pBody->acquire(); | ||||||||
124 | reference_type * const pOld = m_pBody; | ||||||||
125 | m_pBody = pBody; | ||||||||
126 | if (pOld) | ||||||||
127 | pOld->release(); | ||||||||
128 | return *this; | ||||||||
129 | } | ||||||||
130 | |||||||||
131 | /** Assignment. | ||||||||
132 | Unbinds this instance from its body (if bound) and | ||||||||
133 | bind it to the body represented by the handle. | ||||||||
134 | */ | ||||||||
135 | Reference<reference_type> & | ||||||||
136 | SAL_CALL operator= (const Reference<reference_type> & handle) | ||||||||
137 | { | ||||||||
138 | return set( handle.m_pBody ); | ||||||||
139 | } | ||||||||
140 | |||||||||
141 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||||
142 | /** Assignment. | ||||||||
143 | * Unbinds this instance from its body (if bound), | ||||||||
144 | * bind it to the body represented by the handle, and | ||||||||
145 | * set the body represented by the handle to nullptr. | ||||||||
146 | */ | ||||||||
147 | Reference<reference_type> & | ||||||||
148 | operator= (Reference<reference_type> && handle) | ||||||||
149 | { | ||||||||
150 | // self-movement guts ourself | ||||||||
151 | if (m_pBody) | ||||||||
152 | m_pBody->release(); | ||||||||
153 | m_pBody = handle.m_pBody; | ||||||||
154 | handle.m_pBody = nullptr; | ||||||||
155 | return *this; | ||||||||
156 | } | ||||||||
157 | #endif | ||||||||
158 | |||||||||
159 | /** Assignment... | ||||||||
160 | */ | ||||||||
161 | Reference<reference_type> & | ||||||||
162 | SAL_CALL operator= (reference_type * pBody) | ||||||||
163 | { | ||||||||
164 | return set( pBody ); | ||||||||
165 | } | ||||||||
166 | |||||||||
167 | /** Unbind the body from this handle. | ||||||||
168 | Note that for a handle representing a large body, | ||||||||
169 | "handle.clear().set(new body());" _might_ | ||||||||
170 | perform a little bit better than "handle.set(new body());", | ||||||||
171 | since in the second case two large objects exist in memory | ||||||||
172 | (the old body and the new body). | ||||||||
173 | */ | ||||||||
174 | Reference<reference_type> & SAL_CALL clear() | ||||||||
175 | { | ||||||||
176 | if (m_pBody
| ||||||||
177 | { | ||||||||
178 | reference_type * const pOld = m_pBody; | ||||||||
179 | m_pBody = NULL__null; | ||||||||
180 | pOld->release(); | ||||||||
181 | } | ||||||||
182 | return *this; | ||||||||
183 | } | ||||||||
184 | |||||||||
185 | |||||||||
186 | /** Get the body. Can be used instead of operator->(). | ||||||||
187 | I.e. handle->someBodyOp() and handle.get()->someBodyOp() | ||||||||
188 | are the same. | ||||||||
189 | */ | ||||||||
190 | reference_type * SAL_CALL get() const | ||||||||
191 | { | ||||||||
192 | return m_pBody; | ||||||||
| |||||||||
193 | } | ||||||||
194 | |||||||||
195 | |||||||||
196 | /** Probably most common used: handle->someBodyOp(). | ||||||||
197 | */ | ||||||||
198 | reference_type * SAL_CALL operator->() const | ||||||||
199 | { | ||||||||
200 | assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail ("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx" , 200, __extension__ __PRETTY_FUNCTION__)); | ||||||||
201 | return m_pBody; | ||||||||
202 | } | ||||||||
203 | |||||||||
204 | |||||||||
205 | /** Allows (*handle).someBodyOp(). | ||||||||
206 | */ | ||||||||
207 | reference_type & SAL_CALL operator*() const | ||||||||
208 | { | ||||||||
209 | assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail ("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx" , 209, __extension__ __PRETTY_FUNCTION__)); | ||||||||
210 | return *m_pBody; | ||||||||
211 | } | ||||||||
212 | |||||||||
213 | |||||||||
214 | /** Returns True if the handle does point to a valid body. | ||||||||
215 | */ | ||||||||
216 | bool SAL_CALL is() const | ||||||||
217 | { | ||||||||
218 | return (m_pBody != NULL__null); | ||||||||
219 | } | ||||||||
220 | |||||||||
221 | #if defined LIBO_INTERNAL_ONLY1 | ||||||||
222 | /** Returns True if the handle does point to a valid body. | ||||||||
223 | */ | ||||||||
224 | explicit operator bool() const | ||||||||
225 | { | ||||||||
226 | return is(); | ||||||||
227 | } | ||||||||
228 | #endif | ||||||||
229 | |||||||||
230 | /** Returns True if this points to pBody. | ||||||||
231 | */ | ||||||||
232 | bool SAL_CALL operator== (const reference_type * pBody) const | ||||||||
233 | { | ||||||||
234 | return (m_pBody == pBody); | ||||||||
235 | } | ||||||||
236 | |||||||||
237 | |||||||||
238 | /** Returns True if handle points to the same body. | ||||||||
239 | */ | ||||||||
240 | bool | ||||||||
241 | SAL_CALL operator== (const Reference<reference_type> & handle) const | ||||||||
242 | { | ||||||||
243 | return (m_pBody == handle.m_pBody); | ||||||||
244 | } | ||||||||
245 | |||||||||
246 | |||||||||
247 | /** Needed to place References into STL collection. | ||||||||
248 | */ | ||||||||
249 | bool | ||||||||
250 | SAL_CALL operator!= (const Reference<reference_type> & handle) const | ||||||||
251 | { | ||||||||
252 | return (m_pBody != handle.m_pBody); | ||||||||
253 | } | ||||||||
254 | |||||||||
255 | |||||||||
256 | /** Needed to place References into STL collection. | ||||||||
257 | */ | ||||||||
258 | bool | ||||||||
259 | SAL_CALL operator< (const Reference<reference_type> & handle) const | ||||||||
260 | { | ||||||||
261 | return (m_pBody < handle.m_pBody); | ||||||||
262 | } | ||||||||
263 | |||||||||
264 | |||||||||
265 | /** Needed to place References into STL collection. | ||||||||
266 | */ | ||||||||
267 | bool | ||||||||
268 | SAL_CALL operator> (const Reference<reference_type> & handle) const | ||||||||
269 | { | ||||||||
270 | return (m_pBody > handle.m_pBody); | ||||||||
271 | } | ||||||||
272 | }; | ||||||||
273 | |||||||||
274 | } // namespace rtl | ||||||||
275 | |||||||||
276 | #if defined LIBO_INTERNAL_ONLY1 | ||||||||
277 | namespace std | ||||||||
278 | { | ||||||||
279 | |||||||||
280 | /// @cond INTERNAL | ||||||||
281 | /** | ||||||||
282 | Make rtl::Reference hashable by default for use in STL containers. | ||||||||
283 | |||||||||
284 | @since LibreOffice 6.3 | ||||||||
285 | */ | ||||||||
286 | template<typename T> | ||||||||
287 | struct hash<::rtl::Reference<T>> | ||||||||
288 | { | ||||||||
289 | std::size_t operator()(::rtl::Reference<T> const & s) const | ||||||||
290 | { return std::size_t(s.get()); } | ||||||||
291 | }; | ||||||||
292 | /// @endcond | ||||||||
293 | |||||||||
294 | } | ||||||||
295 | |||||||||
296 | #endif | ||||||||
297 | |||||||||
298 | #endif /* ! INCLUDED_RTL_REF_HXX */ | ||||||||
299 | |||||||||
300 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | /* |
3 | * This file is part of the LibreOffice project. |
4 | * |
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/. |
8 | * |
9 | * This file incorporates work covered by the following license notice: |
10 | * |
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 . |
18 | */ |
19 | #ifndef INCLUDED_VCL_Reference_HXX |
20 | #define INCLUDED_VCL_Reference_HXX |
21 | |
22 | #include <vcl/dllapi.h> |
23 | #include <osl/interlck.h> |
24 | |
25 | class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase |
26 | { |
27 | mutable oslInterlockedCount mnRefCnt; |
28 | |
29 | template<typename T> friend class VclPtr; |
30 | |
31 | public: |
32 | void acquire() const |
33 | { |
34 | osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1); |
35 | } |
36 | |
37 | void release() const |
38 | { |
39 | if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0) |
40 | delete this; |
41 | } |
42 | #ifdef DBG_UTIL |
43 | #ifndef _WIN32 |
44 | sal_Int32 getRefCount() const { return mnRefCnt; } |
45 | #endif |
46 | #endif |
47 | |
48 | |
49 | private: |
50 | VclReferenceBase(const VclReferenceBase&) = delete; |
51 | VclReferenceBase& operator=(const VclReferenceBase&) = delete; |
52 | |
53 | bool mbDisposed : 1; |
54 | |
55 | protected: |
56 | VclReferenceBase(); |
57 | protected: |
58 | virtual ~VclReferenceBase(); |
59 | |
60 | protected: |
61 | virtual void dispose(); |
62 | |
63 | public: |
64 | void disposeOnce(); |
65 | bool isDisposed() const { return mbDisposed; } |
66 | |
67 | }; |
68 | #endif |