Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 192, column 9
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name TEditControl.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D DBACCESS_DLLIMPLEMENTATION -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/unixODBC/inc -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/dbaccess/inc -I /home/maarten/src/libreoffice/core/dbaccess/source/inc -I /home/maarten/src/libreoffice/core/dbaccess/source/ui/inc -I /home/maarten/src/libreoffice/core/workdir/YaccTarget/connectivity/source/parse -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TEditControl.cxx

/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TEditControl.cxx

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 "TEditControl.hxx"
21#include <com/sun/star/sdbc/ColumnValue.hpp>
22#include <com/sun/star/sdbc/SQLException.hpp>
23#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
24#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
25#include <com/sun/star/util/XNumberFormatTypes.hpp>
26#include <core_resource.hxx>
27#include <strings.hrc>
28#include <strings.hxx>
29#include <helpids.h>
30#include <comphelper/types.hxx>
31#include <FieldDescControl.hxx>
32#include <FieldDescriptions.hxx>
33#include "TableUndo.hxx"
34#include <TableController.hxx>
35#include <connectivity/dbmetadata.hxx>
36#include <connectivity/dbtools.hxx>
37#include <SqlNameEdit.hxx>
38#include <TableRowExchange.hxx>
39#include <sot/storage.hxx>
40#include <svx/svxids.hrc>
41#include <UITools.hxx>
42#include "TableFieldControl.hxx"
43#include <dsntypes.hxx>
44#include <vcl/builder.hxx>
45#include <vcl/commandevent.hxx>
46#include <vcl/menu.hxx>
47#include <vcl/svapp.hxx>
48
49using namespace ::dbaui;
50using namespace ::comphelper;
51using namespace ::svt;
52using namespace ::com::sun::star::uno;
53using namespace ::com::sun::star::container;
54using namespace ::com::sun::star::io;
55using namespace ::com::sun::star::beans;
56using namespace ::com::sun::star::util;
57using namespace ::com::sun::star::lang;
58using namespace ::com::sun::star::sdbc;
59using namespace ::com::sun::star::sdbcx;
60using namespace ::com::sun::star::sdb;
61
62
63#define HANDLE_ID0 0
64
65// default field widths
66#define FIELDNAME_WIDTH100 100
67#define FIELDTYPE_WIDTH150 150
68#define FIELDDESCR_WIDTH300 300
69
70// Maximum length in description field
71#define MAX_DESCR_LEN256 256
72
73OTableEditorCtrl::ClipboardInvalidator::ClipboardInvalidator(OTableEditorCtrl* _pOwner)
74: m_pOwner(_pOwner)
75{
76
77 m_aInvalidateTimer.SetTimeout(500);
78 m_aInvalidateTimer.SetInvokeHandler(LINK(this, OTableEditorCtrl::ClipboardInvalidator, OnInvalidate)::tools::detail::makeLink( ::tools::detail::castTo<OTableEditorCtrl
::ClipboardInvalidator *>(this), &OTableEditorCtrl::ClipboardInvalidator
::LinkStubOnInvalidate)
);
79 m_aInvalidateTimer.Start();
80}
81
82OTableEditorCtrl::ClipboardInvalidator::~ClipboardInvalidator()
83{
84 m_aInvalidateTimer.Stop();
85}
86
87void OTableEditorCtrl::ClipboardInvalidator::Stop()
88{
89 m_aInvalidateTimer.Stop();
90}
91
92IMPL_LINK_NOARG(OTableEditorCtrl::ClipboardInvalidator, OnInvalidate, Timer *, void)void OTableEditorCtrl::ClipboardInvalidator::LinkStubOnInvalidate
(void * instance, Timer * data) { return static_cast<OTableEditorCtrl
::ClipboardInvalidator *>(instance)->OnInvalidate(data)
; } void OTableEditorCtrl::ClipboardInvalidator::OnInvalidate
(__attribute__ ((unused)) Timer *)
93{
94 m_pOwner->GetView()->getController().InvalidateFeature(SID_CUT(5000 + 710));
95 m_pOwner->GetView()->getController().InvalidateFeature(SID_COPY(5000 + 711));
96 m_pOwner->GetView()->getController().InvalidateFeature(SID_PASTE(5000 + 712));
97}
98
99void OTableEditorCtrl::Init()
100{
101 OTableRowView::Init();
102
103 // Should it be opened ReadOnly?
104 bool bRead(GetView()->getController().isReadOnly());
105
106 SetReadOnly( bRead );
107
108 // Insert the columns
109 InsertDataColumn( FIELD_NAME1, DBA_RES(STR_TAB_FIELD_COLUMN_NAME)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_TAB_FIELD_COLUMN_NAME" "\004" u8"Field Name"
) )
, FIELDNAME_WIDTH100 );
110
111 InsertDataColumn( FIELD_TYPE2, DBA_RES(STR_TAB_FIELD_COLUMN_DATATYPE)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_TAB_FIELD_COLUMN_DATATYPE" "\004" u8"Field Type"
) )
, FIELDTYPE_WIDTH150 );
112
113 ::dbaccess::ODsnTypeCollection aDsnTypes(GetView()->getController().getORB());
114 bool bShowColumnDescription = aDsnTypes.supportsColumnDescription(::comphelper::getString(GetView()->getController().getDataSource()->getPropertyValue(PROPERTY_URL"URL")));
115 InsertDataColumn( HELP_TEXT3, DBA_RES(STR_TAB_HELP_TEXT)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_TAB_HELP_TEXT" "\004" u8"Description") )
, bShowColumnDescription ? FIELDTYPE_WIDTH150 : FIELDDESCR_WIDTH300 );
116
117 if ( bShowColumnDescription )
118 {
119 InsertDataColumn( COLUMN_DESCRIPTION4, DBA_RES(STR_COLUMN_DESCRIPTION)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_COLUMN_DESCRIPTION" "\004" u8"Column Description"
) )
, FIELDTYPE_WIDTH150 );
120 }
121
122 InitCellController();
123
124 // Insert the rows
125 RowInserted(0, m_pRowList->size());
126}
127
128OTableEditorCtrl::OTableEditorCtrl(vcl::Window* pWindow, OTableDesignView* pView)
129 :OTableRowView(pWindow)
130 ,m_pView(pView)
131 ,pNameCell(nullptr)
132 ,pTypeCell(nullptr)
133 ,pHelpTextCell(nullptr)
134 ,pDescrCell(nullptr)
135 ,pDescrWin(nullptr)
136 ,nCutEvent(nullptr)
137 ,nPasteEvent(nullptr)
138 ,nDeleteEvent(nullptr)
139 ,nInsNewRowsEvent(nullptr)
140 ,nInvalidateTypeEvent(nullptr)
141 ,m_eChildFocus(NONE)
142 ,nOldDataPos(-1)
143 ,bReadOnly(true)
144 ,m_aInvalidate(this)
145{
146 SetHelpId(HID_TABDESIGN_BACKGROUND"DBACCESS_HID_TABDESIGN_BACKGROUND");
147 GetDataWindow().SetHelpId(HID_CTL_TABLEEDIT"DBACCESS_HID_CTL_TABLEEDIT");
148
149 m_pRowList = &GetView()->getController().getRows();
150 m_nDataPos = 0;
151}
152
153SfxUndoManager& OTableEditorCtrl::GetUndoManager() const
154{
155 return GetView()->getController().GetUndoManager();
156}
157
158
159void OTableEditorCtrl::SetReadOnly( bool bRead )
160{
161 // nothing to do?
162 if (bRead == IsReadOnly())
163 // This check is important, as the underlying Def may be unnecessarily locked or unlocked
164 // or worse, this action may not be reversed afterwards
165 return;
166
167 bReadOnly = bRead;
168
169 // Disable active cells
170 long nRow(GetCurRow());
171 sal_uInt16 nCol(GetCurColumnId());
172 DeactivateCell();
173
174 // Select the correct Browsers cursor
175 BrowserMode nMode(BrowserMode::COLUMNSELECTION | BrowserMode::MULTISELECTION | BrowserMode::KEEPHIGHLIGHT |
176 BrowserMode::HLINES | BrowserMode::VLINES|BrowserMode::AUTOSIZE_LASTCOL);
177 if( !bReadOnly )
178 nMode |= BrowserMode::HIDECURSOR;
179 SetMode(nMode);
180
181 if( !bReadOnly )
182 ActivateCell( nRow, nCol );
183}
184
185void OTableEditorCtrl::InitCellController()
186{
187 // Cell Field name
188 sal_Int32 nMaxTextLen = 0;
189 OUString sExtraNameChars;
190 Reference<XConnection> xCon;
191 try
192 {
193 xCon = GetView()->getController().getConnection();
194 Reference< XDatabaseMetaData> xMetaData = xCon.is() ? xCon->getMetaData() : Reference< XDatabaseMetaData>();
195
196 // length 0 is treated by Entry::set_max_length as unlimited
197 nMaxTextLen = xMetaData.is() ? xMetaData->getMaxColumnNameLength() : 0;
198
199 sExtraNameChars = xMetaData.is() ? xMetaData->getExtraNameCharacters() : OUString();
200
201 }
202 catch(SQLException&)
203 {
204 OSL_FAIL("getMaxColumnNameLength")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TEditControl.cxx"
":" "204" ": "), "%s", "getMaxColumnNameLength"); } } while (
false)
;
205 }
206
207 pNameCell = VclPtr<OSQLNameEditControl>::Create(&GetDataWindow(), sExtraNameChars);
208 pNameCell->get_widget().set_max_length(nMaxTextLen);
209 pNameCell->setCheck( isSQL92CheckEnabled(xCon) );
210
211 // Cell type
212 pTypeCell = VclPtr<ListBoxControl>::Create( &GetDataWindow() );
213
214 // Cell description
215 pDescrCell = VclPtr<EditControl>::Create(&GetDataWindow());
216 pDescrCell->get_widget().set_max_length(MAX_DESCR_LEN256);
217
218 pHelpTextCell = VclPtr<EditControl>::Create(&GetDataWindow());
219 pHelpTextCell->get_widget().set_max_length(MAX_DESCR_LEN256);
220
221 pNameCell->SetHelpId(HID_TABDESIGN_NAMECELL"DBACCESS_HID_TABDESIGN_NAMECELL");
222 pTypeCell->SetHelpId(HID_TABDESIGN_TYPECELL"DBACCESS_HID_TABDESIGN_TYPECELL");
223 pDescrCell->SetHelpId(HID_TABDESIGN_COMMENTCELL"DBACCESS_HID_TABDESIGN_COMMENTCELL");
224 pHelpTextCell->SetHelpId(HID_TABDESIGN_HELPTEXT"DBACCESS_HID_TABDESIGN_HELPTEXT");
225
226 Size aHeight;
227 const Control* pControls[] = { pTypeCell,pDescrCell,pNameCell,pHelpTextCell};
228 for(const Control* pControl : pControls)
229 {
230 const Size aTemp(pControl->GetOptimalSize());
231 if ( aTemp.Height() > aHeight.Height() )
232 aHeight.setHeight( aTemp.Height() );
233 }
234 SetDataRowHeight(aHeight.Height());
235
236 ClearModified();
237}
238
239void OTableEditorCtrl::ClearModified()
240{
241 pNameCell->get_widget().save_value();
242 pDescrCell->get_widget().save_value();
243 pHelpTextCell->get_widget().save_value();
244 pTypeCell->get_widget().save_value();
245}
246
247OTableEditorCtrl::~OTableEditorCtrl()
248{
249 disposeOnce();
250}
251
252void OTableEditorCtrl::dispose()
253{
254 // Reset the Undo-Manager
255 GetUndoManager().Clear();
256
257 m_aInvalidate.Stop();
258
259 // Take possible Events from the queue
260 if( nCutEvent )
1
Assuming field 'nCutEvent' is null
2
Taking false branch
261 Application::RemoveUserEvent( nCutEvent );
262 if( nPasteEvent )
3
Assuming field 'nPasteEvent' is null
4
Taking false branch
263 Application::RemoveUserEvent( nPasteEvent );
264 if( nDeleteEvent )
5
Assuming field 'nDeleteEvent' is null
6
Taking false branch
265 Application::RemoveUserEvent( nDeleteEvent );
266 if( nInsNewRowsEvent )
7
Assuming field 'nInsNewRowsEvent' is null
8
Taking false branch
267 Application::RemoveUserEvent( nInsNewRowsEvent );
268 if( nInvalidateTypeEvent )
9
Assuming field 'nInvalidateTypeEvent' is null
10
Taking false branch
269 Application::RemoveUserEvent( nInvalidateTypeEvent );
270
271 // Delete the control types
272 pNameCell.disposeAndClear();
273 pTypeCell.disposeAndClear();
274 pDescrCell.disposeAndClear();
11
Calling 'VclPtr::disposeAndClear'
275 pHelpTextCell.disposeAndClear();
276 pDescrWin = nullptr;
277 m_pView.clear();
278 OTableRowView::dispose();
279}
280
281bool OTableEditorCtrl::SetDataPtr( long nRow )
282{
283 if(nRow == -1)
284 return false;
285
286 OSL_ENSURE(nRow < static_cast<long>(m_pRowList->size()),"Row is greater than size!")do { if (true && (!(nRow < static_cast<long>
(m_pRowList->size())))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TEditControl.cxx"
":" "286" ": "), "%s", "Row is greater than size!"); } } while
(false)
;
287 if(nRow >= static_cast<long>(m_pRowList->size()))
288 return false;
289 pActRow = (*m_pRowList)[nRow];
290 return pActRow != nullptr;
291}
292
293bool OTableEditorCtrl::SeekRow(long _nRow)
294{
295 // Call the Base class to remember which row must be repainted
296 EditBrowseBox::SeekRow(_nRow);
297
298 m_nCurrentPos = _nRow;
299 return SetDataPtr(_nRow);
300}
301
302void OTableEditorCtrl::PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect,
303 sal_uInt16 nColumnId ) const
304{
305 const OUString aText( GetCellText( m_nCurrentPos, nColumnId ));
306
307 rDev.Push( PushFlags::CLIPREGION );
308 rDev.SetClipRegion(vcl::Region(rRect));
309 rDev.DrawText( rRect, aText, DrawTextFlags::Left | DrawTextFlags::VCenter );
310 rDev.Pop();
311}
312
313CellController* OTableEditorCtrl::GetController(long nRow, sal_uInt16 nColumnId)
314{
315 // If EditorCtrl is ReadOnly, editing is forbidden
316 Reference<XPropertySet> xTable = GetView()->getController().getTable();
317 if (IsReadOnly() || ( xTable.is() &&
318 xTable->getPropertySetInfo()->hasPropertyByName(PROPERTY_TYPE"Type") &&
319 ::comphelper::getString(xTable->getPropertyValue(PROPERTY_TYPE"Type")) == "VIEW"))
320 return nullptr;
321
322 // If the row is ReadOnly, editing is forbidden
323 SetDataPtr( nRow );
324 if( pActRow->IsReadOnly() )
325 return nullptr;
326
327 OFieldDescription* pActFieldDescr = pActRow->GetActFieldDescr();
328 switch (nColumnId)
329 {
330 case FIELD_NAME1:
331 return new EditCellController( pNameCell );
332 case FIELD_TYPE2:
333 if (pActFieldDescr && !pActFieldDescr->GetName().isEmpty())
334 return new ListBoxCellController( pTypeCell );
335 else return nullptr;
336 case HELP_TEXT3:
337 if (pActFieldDescr && !pActFieldDescr->GetName().isEmpty())
338 return new EditCellController( pHelpTextCell );
339 else
340 return nullptr;
341 case COLUMN_DESCRIPTION4:
342 if (pActFieldDescr && !pActFieldDescr->GetName().isEmpty())
343 return new EditCellController( pDescrCell );
344 else
345 return nullptr;
346 default:
347 return nullptr;
348 }
349}
350
351void OTableEditorCtrl::InitController(CellControllerRef&, long nRow, sal_uInt16 nColumnId)
352{
353 SeekRow( nRow == -1 ? GetCurRow() : nRow);
354 OFieldDescription* pActFieldDescr = pActRow->GetActFieldDescr();
355 OUString aInitString;
356
357 switch (nColumnId)
358 {
359 case FIELD_NAME1:
360 {
361 if( pActFieldDescr )
362 aInitString = pActFieldDescr->GetName();
363
364 weld::Entry& rEntry = pNameCell->get_widget();
365 rEntry.set_text(aInitString);
366 rEntry.save_value();
367 break;
368 }
369 case FIELD_TYPE2:
370 {
371 if ( pActFieldDescr && pActFieldDescr->getTypeInfo() )
372 aInitString = pActFieldDescr->getTypeInfo()->aUIName;
373
374 // Set the ComboBox contents
375 weld::ComboBox& rTypeList = pTypeCell->get_widget();
376 rTypeList.clear();
377 if( !pActFieldDescr )
378 break;
379
380 const OTypeInfoMap& rTypeInfo = GetView()->getController().getTypeInfo();
381 for (auto const& elem : rTypeInfo)
382 rTypeList.append_text(elem.second->aUIName);
383 rTypeList.set_active_text(aInitString);
384 }
385
386 break;
387 case HELP_TEXT3:
388 {
389 if( pActFieldDescr )
390 aInitString = pActFieldDescr->GetHelpText();
391 weld::Entry& rEntry = pHelpTextCell->get_widget();
392 rEntry.set_text(aInitString);
393 rEntry.save_value();
394 break;
395 }
396 case COLUMN_DESCRIPTION4:
397 {
398 if( pActFieldDescr )
399 aInitString = pActFieldDescr->GetDescription();
400 weld::Entry& rEntry = pDescrCell->get_widget();
401 rEntry.set_text(aInitString);
402 rEntry.save_value();
403 break;
404 }
405 }
406}
407
408EditBrowseBox::RowStatus OTableEditorCtrl::GetRowStatus(long nRow) const
409{
410 const_cast<OTableEditorCtrl*>(this)->SetDataPtr( nRow );
411 if( !pActRow )
412 return EditBrowseBox::CLEAN;
413 if (nRow >= 0 && nRow == m_nDataPos)
414 {
415 if( pActRow->IsPrimaryKey() )
416 return EditBrowseBox::CURRENT_PRIMARYKEY;
417 return EditBrowseBox::CURRENT;
418 }
419 else
420 {
421 if( pActRow->IsPrimaryKey() )
422 return EditBrowseBox::PRIMARYKEY;
423 return EditBrowseBox::CLEAN;
424 }
425}
426
427void OTableEditorCtrl::SaveCurRow()
428{
429 if (GetFieldDescr(GetCurRow()) == nullptr)
430 // there is no data in the current row
431 return;
432 if (!SaveModified())
433 return;
434
435 SetDataPtr(GetCurRow());
436 pDescrWin->SaveData( pActRow->GetActFieldDescr() );
437}
438
439void OTableEditorCtrl::DisplayData(long nRow)
440{
441 // go to the correct cell
442 SetDataPtr(nRow);
443
444 // Disable Edit-Mode temporarily
445 bool bWasEditing = IsEditing();
446 if (bWasEditing)
447 DeactivateCell();
448
449 CellControllerRef aTemp;
450 InitController(aTemp, nRow, FIELD_NAME1);
451 InitController(aTemp, nRow, FIELD_TYPE2);
452 InitController(aTemp, nRow, COLUMN_DESCRIPTION4);
453 InitController(aTemp, nRow, HELP_TEXT3);
454
455 GoToRow(nRow);
456 // Update the Description-Window
457 GetView()->GetDescWin()->DisplayData(GetFieldDescr(nRow));
458 // redraw the row
459 RowModified(nRow);
460
461 // and re-enable edit mode
462 ActivateCell(nRow, GetCurColumnId());
463}
464
465void OTableEditorCtrl::CursorMoved()
466{
467 // New line?
468 m_nDataPos = GetCurRow();
469 if( m_nDataPos != nOldDataPos && m_nDataPos != -1)
470 {
471 CellControllerRef aTemp;
472 InitController(aTemp,m_nDataPos,FIELD_NAME1);
473 InitController(aTemp,m_nDataPos,FIELD_TYPE2);
474 InitController(aTemp,m_nDataPos,COLUMN_DESCRIPTION4);
475 InitController(aTemp,m_nDataPos,HELP_TEXT3);
476 }
477
478 OTableRowView::CursorMoved();
479}
480
481sal_Int32 OTableEditorCtrl::HasFieldName( const OUString& rFieldName )
482{
483
484 Reference<XConnection> xCon = GetView()->getController().getConnection();
485 Reference< XDatabaseMetaData> xMetaData = xCon.is() ? xCon->getMetaData() : Reference< XDatabaseMetaData>();
486
487 ::comphelper::UStringMixEqual bCase(!xMetaData.is() || xMetaData->supportsMixedCaseQuotedIdentifiers());
488
489 sal_Int32 nCount(0);
490 for (auto const& row : *m_pRowList)
491 {
492 OFieldDescription* pFieldDescr = row->GetActFieldDescr();
493 if( pFieldDescr && bCase(rFieldName,pFieldDescr->GetName()))
494 nCount++;
495 }
496 return nCount;
497}
498
499void OTableEditorCtrl::SaveData(long nRow, sal_uInt16 nColId)
500{
501 // Store the cell content
502 SetDataPtr( nRow == -1 ? GetCurRow() : nRow);
503 OFieldDescription* pActFieldDescr = pActRow->GetActFieldDescr();
504
505 switch( nColId)
506 {
507 // Store NameCell
508 case FIELD_NAME1:
509 {
510 // If there is no name, do nothing
511 weld::Entry& rEntry = pNameCell->get_widget();
512 const OUString aName(rEntry.get_text());
513
514 if( aName.isEmpty() )
515 {
516 // If FieldDescr exists, the field is deleted and the old content restored
517 if (pActFieldDescr)
518 {
519 GetUndoManager().AddUndoAction(std::make_unique<OTableEditorTypeSelUndoAct>(this, nRow, FIELD_TYPE2, pActFieldDescr->getTypeInfo()));
520 SwitchType(TOTypeInfoSP());
521 pActFieldDescr = pActRow->GetActFieldDescr();
522 }
523 else
524 return;
525 }
526 if(pActFieldDescr)
527 pActFieldDescr->SetName( aName );
528 rEntry.save_value();
529
530 break;
531 }
532
533 // Store the field type
534 case FIELD_TYPE2:
535 break;
536
537 // Store DescrCell
538 case HELP_TEXT3:
539 {
540 // if the current field description is NULL, set Default
541 weld::Entry& rEntry = pHelpTextCell->get_widget();
542 if( !pActFieldDescr )
543 {
544 rEntry.set_text(OUString());
545 rEntry.save_value();
546 }
547 else
548 pActFieldDescr->SetHelpText(rEntry.get_text());
549 break;
550 }
551 case COLUMN_DESCRIPTION4:
552 {
553 // Set the default if the field description is null
554 weld::Entry& rEntry = pDescrCell->get_widget();
555 if( !pActFieldDescr )
556 {
557 rEntry.set_text(OUString());
558 rEntry.save_value();
559 }
560 else
561 pActFieldDescr->SetDescription(rEntry.get_text());
562 break;
563 }
564 case FIELD_PROPERTY_DEFAULT8:
565 case FIELD_PROPERTY_REQUIRED5:
566 case FIELD_PROPERTY_TEXTLEN9:
567 case FIELD_PROPERTY_NUMTYPE6:
568 case FIELD_PROPERTY_AUTOINC7:
569 case FIELD_PROPERTY_LENGTH10:
570 case FIELD_PROPERTY_SCALE11:
571 case FIELD_PROPERTY_BOOL_DEFAULT12:
572 pDescrWin->SaveData(pActFieldDescr);
573
574 if ( FIELD_PROPERTY_AUTOINC7 == nColId && pActFieldDescr->IsAutoIncrement() )
575 {
576 OTableController& rController = GetView()->getController();
577 if ( rController.isAutoIncrementPrimaryKey() )
578 {
579 pActFieldDescr->SetPrimaryKey( true );
580 InvalidateHandleColumn();
581 Invalidate();
582 }
583 }
584 break;
585 }
586}
587
588bool OTableEditorCtrl::SaveModified()
589{
590 sal_uInt16 nColId = GetCurColumnId();
591
592 switch( nColId )
593 {
594 // Field type
595 case FIELD_TYPE2:
596 {
597 // Reset the type
598 resetType();
599 } break;
600 }
601
602 return true;
603}
604
605bool OTableEditorCtrl::CursorMoving(long nNewRow, sal_uInt16 nNewCol)
606{
607
608 if (!EditBrowseBox::CursorMoving(nNewRow, nNewCol))
609 return false;
610
611 // Called after SaveModified(), current row is still the old one
612 m_nDataPos = nNewRow;
613 nOldDataPos = GetCurRow();
614
615 // Reset the markers
616 InvalidateStatusCell( nOldDataPos );
617 InvalidateStatusCell( m_nDataPos );
618
619 // Store the data from the Property window
620 if( SetDataPtr(nOldDataPos) && pDescrWin)
621 pDescrWin->SaveData( pActRow->GetActFieldDescr() );
622
623 // Show new data in the Property window
624 if( SetDataPtr(m_nDataPos) && pDescrWin)
625 pDescrWin->DisplayData( pActRow->GetActFieldDescr() );
626
627 return true;
628}
629
630IMPL_LINK_NOARG( OTableEditorCtrl, InvalidateFieldType, void*, void )void OTableEditorCtrl::LinkStubInvalidateFieldType(void * instance
, void* data) { return static_cast<OTableEditorCtrl *>(
instance)->InvalidateFieldType(data); } void OTableEditorCtrl
::InvalidateFieldType(__attribute__ ((unused)) void*)
631{
632 nInvalidateTypeEvent = nullptr;
633 Invalidate( GetFieldRectPixel(nOldDataPos, FIELD_TYPE2) );
634}
635
636void OTableEditorCtrl::CellModified( long nRow, sal_uInt16 nColId )
637{
638
639 // If the description is null, use the default
640 if(nRow == -1)
641 nRow = GetCurRow();
642 SetDataPtr( nRow );
643 OFieldDescription* pActFieldDescr = pActRow->GetActFieldDescr();
644
645 OUString sActionDescription;
646 switch ( nColId )
647 {
648 case FIELD_NAME1: sActionDescription = DBA_RES( STR_CHANGE_COLUMN_NAME )::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_CHANGE_COLUMN_NAME" "\004" u8"change field name"
) )
; break;
649 case FIELD_TYPE2: sActionDescription = DBA_RES( STR_CHANGE_COLUMN_TYPE )::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_CHANGE_COLUMN_TYPE" "\004" u8"change field type"
) )
; break;
650 case HELP_TEXT3:
651 case COLUMN_DESCRIPTION4: sActionDescription = DBA_RES( STR_CHANGE_COLUMN_DESCRIPTION )::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_CHANGE_COLUMN_DESCRIPTION" "\004" u8"change field description"
) )
; break;
652 default: sActionDescription = DBA_RES( STR_CHANGE_COLUMN_ATTRIBUTE )::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_CHANGE_COLUMN_ATTRIBUTE" "\004" u8"change field attribute"
) )
; break;
653 }
654
655 GetUndoManager().EnterListAction( sActionDescription, OUString(), 0, ViewShellId(-1) );
656 if (!pActFieldDescr)
657 {
658 const OTypeInfoMap& rTypeInfoMap = GetView()->getController().getTypeInfo();
659 if ( !rTypeInfoMap.empty() )
660 {
661 OTypeInfoMap::const_iterator aTypeIter = rTypeInfoMap.find(DataType::VARCHAR);
662 if ( aTypeIter == rTypeInfoMap.end() )
663 aTypeIter = rTypeInfoMap.begin();
664 pActRow->SetFieldType( aTypeIter->second );
665 }
666 else
667 pActRow->SetFieldType( GetView()->getController().getTypeInfoFallBack() );
668
669 nInvalidateTypeEvent = Application::PostUserEvent( LINK(this, OTableEditorCtrl, InvalidateFieldType)::tools::detail::makeLink( ::tools::detail::castTo<OTableEditorCtrl
*>(this), &OTableEditorCtrl::LinkStubInvalidateFieldType
)
, nullptr, true );
670 pActFieldDescr = pActRow->GetActFieldDescr();
671 pDescrWin->DisplayData( pActFieldDescr );
672 GetUndoManager().AddUndoAction( std::make_unique<OTableEditorTypeSelUndoAct>(this, nRow, nColId+1, TOTypeInfoSP()) );
673 }
674
675 if( nColId != FIELD_TYPE2 )
676 GetUndoManager().AddUndoAction( std::make_unique<OTableDesignCellUndoAct>(this, nRow, nColId) );
677 else
678 {
679 GetUndoManager().AddUndoAction(std::make_unique<OTableEditorTypeSelUndoAct>(this, GetCurRow(), nColId, GetFieldDescr(GetCurRow())->getTypeInfo()));
680 resetType();
681 }
682
683 SaveData(nRow,nColId);
684 // SaveData could create an undo action as well
685 GetUndoManager().LeaveListAction();
686 RowModified(nRow);
687
688 // Set the Modify flag
689 GetView()->getController().setModified( true );
690 InvalidateFeatures();
691}
692
693void OTableEditorCtrl::resetType()
694{
695 sal_Int32 nPos = pTypeCell->get_widget().get_active();
696 if(nPos != -1)
697 SwitchType( GetView()->getController().getTypeInfo(nPos) );
698 else
699 SwitchType(TOTypeInfoSP());
700}
701
702void OTableEditorCtrl::CellModified()
703{
704 CellModified( GetCurRow(), GetCurColumnId() );
705}
706
707void OTableEditorCtrl::InvalidateFeatures()
708{
709 GetView()->getController().InvalidateFeature(SID_UNDO(5000 + 701));
710 GetView()->getController().InvalidateFeature(SID_REDO(5000 + 700));
711 GetView()->getController().InvalidateFeature(SID_SAVEDOC(5000 + 505));
712}
713
714void OTableEditorCtrl::CopyRows()
715{
716 // set to the right row and save it
717 if( SetDataPtr(m_nDataPos) )
718 pDescrWin->SaveData( pActRow->GetActFieldDescr() );
719
720 // Copy selected rows to the ClipboardList
721 std::shared_ptr<OTableRow> pClipboardRow;
722 std::shared_ptr<OTableRow> pRow;
723 std::vector< std::shared_ptr<OTableRow> > vClipboardList;
724 vClipboardList.reserve(GetSelectRowCount());
725
726 for( long nIndex=FirstSelectedRow(); nIndex != SFX_ENDOFSELECTION(-1); nIndex=NextSelectedRow() )
727 {
728 pRow = (*m_pRowList)[nIndex];
729 OSL_ENSURE(pRow,"OTableEditorCtrl::CopyRows: Row is NULL!")do { if (true && (!(pRow))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TEditControl.cxx"
":" "729" ": "), "%s", "OTableEditorCtrl::CopyRows: Row is NULL!"
); } } while (false)
;
730 if ( pRow && pRow->GetActFieldDescr() )
731 {
732 pClipboardRow = std::make_shared<OTableRow>( *pRow );
733 vClipboardList.push_back( pClipboardRow);
734 }
735 }
736 if(!vClipboardList.empty())
737 {
738 rtl::Reference<OTableRowExchange> pData = new OTableRowExchange(vClipboardList);
739 pData->CopyToClipboard(GetParent());
740 }
741}
742
743OUString OTableEditorCtrl::GenerateName( const OUString& rName )
744{
745 // Create a base name for appending numbers to
746 OUString aBaseName;
747 Reference<XConnection> xCon = GetView()->getController().getConnection();
748 Reference< XDatabaseMetaData> xMetaData = xCon.is() ? xCon->getMetaData() : Reference< XDatabaseMetaData>();
749
750 sal_Int32 nMaxTextLen(xMetaData.is() ? xMetaData->getMaxColumnNameLength() : 0);
751
752 if( (rName.getLength()+2) >nMaxTextLen )
753 aBaseName = rName.copy( 0, nMaxTextLen-2 );
754 else
755 aBaseName = rName;
756
757 // append a sequential number to the base name (up to 99)
758 OUString aFieldName( rName);
759 sal_Int32 i=1;
760 while( HasFieldName(aFieldName) )
761 {
762 aFieldName = aBaseName + OUString::number(i);
763 i++;
764 }
765
766 return aFieldName;
767}
768
769void OTableEditorCtrl::InsertRows( long nRow )
770{
771
772 std::vector< std::shared_ptr<OTableRow> > vInsertedUndoRedoRows; // need for undo/redo handling
773 // get rows from clipboard
774 TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromSystemClipboard(GetParent()));
775 if(aTransferData.HasFormat(SotClipboardFormatId::SBA_TABED))
776 {
777 ::tools::SvRef<SotStorageStream> aStreamRef;
778 bool bOk = aTransferData.GetSotStorageStream(SotClipboardFormatId::SBA_TABED,aStreamRef);
779 if (bOk && aStreamRef.is())
780 {
781 aStreamRef->Seek(STREAM_SEEK_TO_BEGIN0L);
782 aStreamRef->ResetError();
783 long nInsertRow = nRow;
784 std::shared_ptr<OTableRow> pRow;
785 sal_Int32 nSize = 0;
786 (*aStreamRef).ReadInt32( nSize );
787 vInsertedUndoRedoRows.reserve(nSize);
788 for(sal_Int32 i=0;i < nSize;++i)
789 {
790 pRow = std::make_shared<OTableRow>();
791 ReadOTableRow( *aStreamRef, *pRow );
792 pRow->SetReadOnly( false );
793 sal_Int32 nType = pRow->GetActFieldDescr()->GetType();
794 if ( pRow->GetActFieldDescr() )
795 pRow->GetActFieldDescr()->SetType(GetView()->getController().getTypeInfoByType(nType));
796 // Adjust the field names
797 pRow->GetActFieldDescr()->SetName( GenerateName( pRow->GetActFieldDescr()->GetName() ) );
798 pRow->SetPos(nInsertRow);
799 m_pRowList->insert( m_pRowList->begin()+nInsertRow,pRow );
800 vInsertedUndoRedoRows.push_back(std::make_shared<OTableRow>(*pRow));
801 nInsertRow++;
802 }
803 }
804 }
805 // RowInserted calls CursorMoved.
806 // The UI data should not be stored here.
807 RowInserted( nRow,vInsertedUndoRedoRows.size() );
808
809 // Create the Undo-Action
810 GetUndoManager().AddUndoAction( std::make_unique<OTableEditorInsUndoAct>(this, nRow,vInsertedUndoRedoRows) );
811 GetView()->getController().setModified( true );
812 InvalidateFeatures();
813}
814
815void OTableEditorCtrl::DeleteRows()
816{
817 OSL_ENSURE(GetView()->getController().isDropAllowed(),"Call of DeleteRows not valid here. Please check isDropAllowed!")do { if (true && (!(GetView()->getController().isDropAllowed
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TEditControl.cxx"
":" "817" ": "), "%s", "Call of DeleteRows not valid here. Please check isDropAllowed!"
); } } while (false)
;
818 // Create the Undo-Action
819 GetUndoManager().AddUndoAction( std::make_unique<OTableEditorDelUndoAct>(this) );
820
821 // Delete all marked rows
822 long nIndex = FirstSelectedRow();
823 nOldDataPos = nIndex;
824
825 while( nIndex != SFX_ENDOFSELECTION(-1) )
826 {
827 // Remove rows
828 m_pRowList->erase( m_pRowList->begin()+nIndex );
829 RowRemoved( nIndex );
830
831 // Insert the empty row at the end
832 m_pRowList->push_back( std::make_shared<OTableRow>());
833 RowInserted( GetRowCount()-1 );
834
835 nIndex = FirstSelectedRow();
836 }
837
838 // Force the current record to be displayed
839 m_nDataPos = GetCurRow();
840 InvalidateStatusCell( nOldDataPos );
841 InvalidateStatusCell( m_nDataPos );
842 SetDataPtr( m_nDataPos );
843 ActivateCell();
844 pDescrWin->DisplayData( pActRow->GetActFieldDescr() );
845 GetView()->getController().setModified( true );
846 InvalidateFeatures();
847}
848
849void OTableEditorCtrl::InsertNewRows( long nRow )
850{
851 OSL_ENSURE(GetView()->getController().isAddAllowed(),"Call of InsertNewRows not valid here. Please check isAppendAllowed!")do { if (true && (!(GetView()->getController().isAddAllowed
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TEditControl.cxx"
":" "851" ": "), "%s", "Call of InsertNewRows not valid here. Please check isAppendAllowed!"
); } } while (false)
;
852 // Create Undo-Action
853 long nInsertRows = GetSelectRowCount();
854 if( !nInsertRows )
855 nInsertRows = 1;
856 GetUndoManager().AddUndoAction( std::make_unique<OTableEditorInsNewUndoAct>(this, nRow, nInsertRows) );
857 // Insert the number of selected rows
858 for( long i=nRow; i<(nRow+nInsertRows); i++ )
859 m_pRowList->insert( m_pRowList->begin()+i ,std::make_shared<OTableRow>());
860 RowInserted( nRow, nInsertRows );
861
862 GetView()->getController().setModified( true );
863 InvalidateFeatures();
864}
865
866void OTableEditorCtrl::SetControlText( long nRow, sal_uInt16 nColId, const OUString& rText )
867{
868 // Set the Browser Controls
869 if( nColId < FIELD_FIRST_VIRTUAL_COLUMN5 )
870 {
871 GoToRow( nRow );
872 GoToColumnId( nColId );
873 CellControllerRef xController = Controller();
874 if(xController.is())
875 xController->GetWindow().SetText( rText );
876 else
877 RowModified(nRow,nColId);
878 }
879
880 // Set the Tabpage controls
881 else
882 {
883 pDescrWin->SetControlText( nColId, rText );
884 }
885}
886
887void OTableEditorCtrl::SetCellData( long nRow, sal_uInt16 nColId, const TOTypeInfoSP& _pTypeInfo )
888{
889 // Relocate the current pointer
890 if( nRow == -1 )
891 nRow = GetCurRow();
892 OFieldDescription* pFieldDescr = GetFieldDescr( nRow );
893 if( !pFieldDescr && nColId != FIELD_TYPE2)
894 return;
895
896 // Set individual fields
897 switch( nColId )
898 {
899 case FIELD_TYPE2:
900 SwitchType( _pTypeInfo );
901 break;
902 default:
903 OSL_FAIL("OTableEditorCtrl::SetCellData: invalid column!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TEditControl.cxx"
":" "903" ": "), "%s", "OTableEditorCtrl::SetCellData: invalid column!"
); } } while (false)
;
904 }
905 SetControlText(nRow,nColId,_pTypeInfo ? _pTypeInfo->aUIName : OUString());
906}
907
908void OTableEditorCtrl::SetCellData( long nRow, sal_uInt16 nColId, const css::uno::Any& _rNewData )
909{
910 // Relocate the current pointer
911 if( nRow == -1 )
912 nRow = GetCurRow();
913 OFieldDescription* pFieldDescr = GetFieldDescr( nRow );
914 if( !pFieldDescr && nColId != FIELD_TYPE2)
915 return;
916
917 OUString sValue;
918 // Set individual fields
919 switch( nColId )
920 {
921 case FIELD_NAME1:
922 sValue = ::comphelper::getString(_rNewData);
923 pFieldDescr->SetName( sValue );
924 break;
925
926 case FIELD_TYPE2:
927 OSL_FAIL("OTableEditorCtrl::SetCellData: invalid column!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TEditControl.cxx"
":" "927" ": "), "%s", "OTableEditorCtrl::SetCellData: invalid column!"
); } } while (false)
;
928 break;
929
930 case COLUMN_DESCRIPTION4:
931 sValue = ::comphelper::getString(_rNewData);
932 pFieldDescr->SetDescription( sValue );
933 break;
934
935 case FIELD_PROPERTY_DEFAULT8:
936 pFieldDescr->SetControlDefault( _rNewData );
937 sValue = GetView()->GetDescWin()->getGenPage()->getControlDefault(pFieldDescr);
938 break;
939
940 case FIELD_PROPERTY_REQUIRED5:
941 {
942 sValue = ::comphelper::getString(_rNewData);
943 pFieldDescr->SetIsNullable( sValue.toInt32() );
944 }
945 break;
946
947 case FIELD_PROPERTY_TEXTLEN9:
948 case FIELD_PROPERTY_LENGTH10:
949 {
950 sValue = ::comphelper::getString(_rNewData);
951 pFieldDescr->SetPrecision( sValue.toInt32() );
952 }
953 break;
954
955 case FIELD_PROPERTY_NUMTYPE6:
956 OSL_FAIL("OTableEditorCtrl::SetCellData: invalid column!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TEditControl.cxx"
":" "956" ": "), "%s", "OTableEditorCtrl::SetCellData: invalid column!"
); } } while (false)
;
957 break;
958
959 case FIELD_PROPERTY_AUTOINC7:
960 {
961 sValue = ::comphelper::getString(_rNewData);
962 pFieldDescr->SetAutoIncrement(sValue == DBA_RES(STR_VALUE_YES)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_VALUE_YES" "\004" u8"Yes") )
);
963 }
964 break;
965 case FIELD_PROPERTY_SCALE11:
966 {
967 sValue = ::comphelper::getString(_rNewData);
968 pFieldDescr->SetScale(sValue.toInt32());
969 }
970 break;
971
972 case FIELD_PROPERTY_BOOL_DEFAULT12:
973 sValue = GetView()->GetDescWin()->BoolStringPersistent(::comphelper::getString(_rNewData));
974 pFieldDescr->SetControlDefault(makeAny(sValue));
975 break;
976
977 case FIELD_PROPERTY_FORMAT13:
978 {
979 sValue = ::comphelper::getString(_rNewData);
980 pFieldDescr->SetFormatKey(sValue.toInt32());
981 }
982 break;
983 }
984
985 SetControlText(nRow,nColId,sValue);
986}
987
988Any OTableEditorCtrl::GetCellData( long nRow, sal_uInt16 nColId )
989{
990 OFieldDescription* pFieldDescr = GetFieldDescr( nRow );
991 if( !pFieldDescr )
992 return Any();
993
994 // Relocate the current pointer
995 if( nRow==-1 )
996 nRow = GetCurRow();
997 SetDataPtr( nRow );
998
999 static const OUString strYes(DBA_RES(STR_VALUE_YES)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_VALUE_YES" "\004" u8"Yes") )
);
1000 static const OUString strNo(DBA_RES(STR_VALUE_NO)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_VALUE_NO" "\004" u8"No") )
);
1001 OUString sValue;
1002 // Read out the fields
1003 switch( nColId )
1004 {
1005 case FIELD_NAME1:
1006 sValue = pFieldDescr->GetName();
1007 break;
1008
1009 case FIELD_TYPE2:
1010 if ( pFieldDescr->getTypeInfo() )
1011 sValue = pFieldDescr->getTypeInfo()->aUIName;
1012 break;
1013
1014 case COLUMN_DESCRIPTION4:
1015 sValue = pFieldDescr->GetDescription();
1016 break;
1017 case HELP_TEXT3:
1018 sValue = pFieldDescr->GetHelpText();
1019 break;
1020
1021 case FIELD_PROPERTY_DEFAULT8:
1022 return pFieldDescr->GetControlDefault();
1023
1024 case FIELD_PROPERTY_REQUIRED5:
1025 sValue = pFieldDescr->GetIsNullable() == ColumnValue::NULLABLE ? strYes : strNo;
1026 break;
1027
1028 case FIELD_PROPERTY_TEXTLEN9:
1029 case FIELD_PROPERTY_LENGTH10:
1030 sValue = OUString::number(pFieldDescr->GetPrecision());
1031 break;
1032
1033 case FIELD_PROPERTY_NUMTYPE6:
1034 OSL_FAIL("OTableEditorCtrl::GetCellData: invalid column!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TEditControl.cxx"
":" "1034" ": "), "%s", "OTableEditorCtrl::GetCellData: invalid column!"
); } } while (false)
;
1035 break;
1036
1037 case FIELD_PROPERTY_AUTOINC7:
1038 sValue = pFieldDescr->IsAutoIncrement() ? strYes : strNo;
1039 break;
1040
1041 case FIELD_PROPERTY_SCALE11:
1042 sValue = OUString::number(pFieldDescr->GetScale());
1043 break;
1044
1045 case FIELD_PROPERTY_BOOL_DEFAULT12:
1046 sValue = GetView()->GetDescWin()->BoolStringUI(::comphelper::getString(pFieldDescr->GetControlDefault()));
1047 break;
1048
1049 case FIELD_PROPERTY_FORMAT13:
1050 sValue = OUString::number(pFieldDescr->GetFormatKey());
1051 break;
1052 }
1053
1054 return makeAny(sValue);
1055}
1056
1057OUString OTableEditorCtrl::GetCellText( long nRow, sal_uInt16 nColId ) const
1058{
1059 OUString sCellText;
1060 const_cast< OTableEditorCtrl* >( this )->GetCellData( nRow, nColId ) >>= sCellText;
1061 return sCellText;
1062}
1063
1064sal_uInt32 OTableEditorCtrl::GetTotalCellWidth(long nRow, sal_uInt16 nColId)
1065{
1066 return GetTextWidth(GetCellText(nRow, nColId)) + 2 * GetTextWidth("0");
1067}
1068
1069OFieldDescription* OTableEditorCtrl::GetFieldDescr( long nRow )
1070{
1071 std::vector< std::shared_ptr<OTableRow> >::size_type nListCount(
1072 m_pRowList->size());
1073 if( (nRow<0) || (sal::static_int_cast< unsigned long >(nRow)>=nListCount) )
1074 {
1075 OSL_FAIL("(nRow<0) || (nRow>=nListCount)")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TEditControl.cxx"
":" "1075" ": "), "%s", "(nRow<0) || (nRow>=nListCount)"
); } } while (false)
;
1076 return nullptr;
1077 }
1078 std::shared_ptr<OTableRow> pRow = (*m_pRowList)[ nRow ];
1079 if( !pRow )
1080 return nullptr;
1081 return pRow->GetActFieldDescr();
1082}
1083
1084bool OTableEditorCtrl::IsCutAllowed()
1085{
1086 bool bIsCutAllowed = (GetView()->getController().isAddAllowed() && GetView()->getController().isDropAllowed()) ||
1087 GetView()->getController().isAlterAllowed();
1088
1089 if (bIsCutAllowed)
1090 {
1091 int nStartPos, nEndPos;
1092 switch(m_eChildFocus)
1093 {
1094 case DESCRIPTION:
1095 {
1096 weld::Entry& rEntry = pDescrCell->get_widget();
1097 bIsCutAllowed = rEntry.get_selection_bounds(nStartPos, nEndPos);
1098 break;
1099 }
1100 case HELPTEXT:
1101 {
1102 weld::Entry& rEntry = pHelpTextCell->get_widget();
1103 bIsCutAllowed = rEntry.get_selection_bounds(nStartPos, nEndPos);
1104 break;
1105 }
1106 case NAME:
1107 {
1108 weld::Entry& rEntry = pNameCell->get_widget();
1109 bIsCutAllowed = rEntry.get_selection_bounds(nStartPos, nEndPos);
1110 break;
1111 }
1112 case ROW:
1113 bIsCutAllowed = IsCopyAllowed();
1114 break;
1115 default:
1116 bIsCutAllowed = false;
1117 break;
1118 }
1119 }
1120
1121 return bIsCutAllowed;
1122}
1123
1124bool OTableEditorCtrl::IsCopyAllowed()
1125{
1126 bool bIsCopyAllowed = false;
1127 int nStartPos, nEndPos;
1128 if (m_eChildFocus == DESCRIPTION )
1129 {
1130 weld::Entry& rEntry = pDescrCell->get_widget();
1131 bIsCopyAllowed = rEntry.get_selection_bounds(nStartPos, nEndPos);
1132 }
1133 else if(HELPTEXT == m_eChildFocus )
1134 {
1135 weld::Entry& rEntry = pHelpTextCell->get_widget();
1136 bIsCopyAllowed = rEntry.get_selection_bounds(nStartPos, nEndPos);
1137 }
1138 else if(m_eChildFocus == NAME)
1139 {
1140 weld::Entry& rEntry = pNameCell->get_widget();
1141 bIsCopyAllowed = rEntry.get_selection_bounds(nStartPos, nEndPos);
1142 }
1143 else if(m_eChildFocus == ROW)
1144 {
1145 Reference<XPropertySet> xTable = GetView()->getController().getTable();
1146 if( !GetSelectRowCount() || (xTable.is() && ::comphelper::getString(xTable->getPropertyValue(PROPERTY_TYPE"Type")) == "VIEW"))
1147 return false;
1148
1149 // If one of the selected rows is empty, Copy is not possible
1150 std::shared_ptr<OTableRow> pRow;
1151 long nIndex = FirstSelectedRow();
1152 while( nIndex != SFX_ENDOFSELECTION(-1) )
1153 {
1154 pRow = (*m_pRowList)[nIndex];
1155 if( !pRow->GetActFieldDescr() )
1156 return false;
1157
1158 nIndex = NextSelectedRow();
1159 }
1160
1161 bIsCopyAllowed = true;
1162 }
1163
1164 return bIsCopyAllowed;
1165}
1166
1167bool OTableEditorCtrl::IsPasteAllowed() const
1168{
1169 bool bAllowed = GetView()->getController().isAddAllowed();
1170 if ( bAllowed )
1171 {
1172 TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromSystemClipboard(GetParent()));
1173 bool bRowFormat = aTransferData.HasFormat(SotClipboardFormatId::SBA_TABED);
1174 if ( m_eChildFocus == ROW )
1175 bAllowed = bRowFormat;
1176 else
1177 bAllowed = !bRowFormat && aTransferData.HasFormat(SotClipboardFormatId::STRING);
1178 }
1179
1180 return bAllowed;
1181}
1182
1183void OTableEditorCtrl::cut()
1184{
1185 if(m_eChildFocus == NAME)
1186 {
1187 if(GetView()->getController().isAlterAllowed())
1188 {
1189 SaveData(-1,FIELD_NAME1);
1190 pNameCell->get_widget().cut_clipboard();
1191 CellModified(-1,FIELD_NAME1);
1192 }
1193 }
1194 else if(m_eChildFocus == DESCRIPTION)
1195 {
1196 if(GetView()->getController().isAlterAllowed())
1197 {
1198 SaveData(-1,COLUMN_DESCRIPTION4);
1199 pDescrCell->get_widget().cut_clipboard();
1200 CellModified(-1,COLUMN_DESCRIPTION4);
1201 }
1202 }
1203 else if(HELPTEXT == m_eChildFocus )
1204 {
1205 if(GetView()->getController().isAlterAllowed())
1206 {
1207 SaveData(-1,HELP_TEXT3);
1208 pHelpTextCell->get_widget().cut_clipboard();
1209 CellModified(-1,HELP_TEXT3);
1210 }
1211 }
1212 else if(m_eChildFocus == ROW)
1213 {
1214 if (nCutEvent)
1215 Application::RemoveUserEvent(nCutEvent);
1216 nCutEvent = Application::PostUserEvent(LINK(this, OTableEditorCtrl, DelayedCut)::tools::detail::makeLink( ::tools::detail::castTo<OTableEditorCtrl
*>(this), &OTableEditorCtrl::LinkStubDelayedCut)
, nullptr, true);
1217 }
1218}
1219
1220void OTableEditorCtrl::copy()
1221{
1222 if (GetSelectRowCount())
1223 OTableRowView::copy();
1224 else if(m_eChildFocus == NAME)
1225 {
1226 weld::Entry& rEntry = pNameCell->get_widget();
1227 rEntry.copy_clipboard();
1228 }
1229 else if(HELPTEXT == m_eChildFocus )
1230 {
1231 weld::Entry& rEntry = pHelpTextCell->get_widget();
1232 rEntry.copy_clipboard();
1233 }
1234 else if(m_eChildFocus == DESCRIPTION )
1235 {
1236 weld::Entry& rEntry = pDescrCell->get_widget();
1237 rEntry.copy_clipboard();
1238 }
1239}
1240
1241void OTableEditorCtrl::paste()
1242{
1243 TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromSystemClipboard(GetParent()));
1244 if(aTransferData.HasFormat(SotClipboardFormatId::SBA_TABED))
1245 {
1246 if( nPasteEvent )
1247 Application::RemoveUserEvent( nPasteEvent );
1248 nPasteEvent = Application::PostUserEvent( LINK(this, OTableEditorCtrl, DelayedPaste)::tools::detail::makeLink( ::tools::detail::castTo<OTableEditorCtrl
*>(this), &OTableEditorCtrl::LinkStubDelayedPaste)
, nullptr, true );
1249 }
1250 else if(m_eChildFocus == NAME)
1251 {
1252 if(GetView()->getController().isAlterAllowed())
1253 {
1254 pNameCell->get_widget().paste_clipboard();
1255 CellModified();
1256 }
1257 }
1258 else if(HELPTEXT == m_eChildFocus )
1259 {
1260 if(GetView()->getController().isAlterAllowed())
1261 {
1262 pHelpTextCell->get_widget().paste_clipboard();
1263 CellModified();
1264 }
1265 }
1266 else if(m_eChildFocus == DESCRIPTION)
1267 {
1268 if(GetView()->getController().isAlterAllowed())
1269 {
1270 pDescrCell->get_widget().paste_clipboard();
1271 CellModified();
1272 }
1273 }
1274}
1275
1276bool OTableEditorCtrl::IsDeleteAllowed()
1277{
1278
1279 return GetSelectRowCount() != 0 && GetView()->getController().isDropAllowed();
1280}
1281
1282bool OTableEditorCtrl::IsInsertNewAllowed( long nRow )
1283{
1284
1285 bool bInsertNewAllowed = GetView()->getController().isAddAllowed();
1286 // If fields can be added, Paste in the new fields
1287 if (bInsertNewAllowed && !GetView()->getController().isDropAllowed())
1288 {
1289 SetDataPtr(nRow);
1290 if( GetActRow()->IsReadOnly() )
1291 return false;
1292 }
1293
1294 return bInsertNewAllowed;
1295}
1296
1297bool OTableEditorCtrl::IsPrimaryKeyAllowed()
1298{
1299 if( !GetSelectRowCount() )
1300 return false;
1301
1302 OTableController& rController = GetView()->getController();
1303 if ( !rController.getSdbMetaData().supportsPrimaryKeys() )
1304 return false;
1305
1306 Reference<XPropertySet> xTable = rController.getTable();
1307 // Key must not be changed
1308 // This applies only if the table is not new and not a css::sdbcx::View. Otherwise no DROP is executed
1309
1310 if(xTable.is() && ::comphelper::getString(xTable->getPropertyValue(PROPERTY_TYPE"Type")) == "VIEW")
1311 return false;
1312 // If there is an empty field, no primary key
1313 // The entry is only permitted if
1314 // - there are no empty entries in the selection
1315 // - No Memo or Image entries
1316 // - DROP is not permitted (see above) and the column is not Required (not null flag is not set).
1317 long nIndex = FirstSelectedRow();
1318 std::shared_ptr<OTableRow> pRow;
1319 while( nIndex != SFX_ENDOFSELECTION(-1) )
1320 {
1321 pRow = (*m_pRowList)[nIndex];
1322 OFieldDescription* pFieldDescr = pRow->GetActFieldDescr();
1323 if(!pFieldDescr)
1324 return false;
1325 else
1326 {
1327 // Memo and Image fields cannot be primary keys
1328 // or if the column cannot be dropped and the Required flag is not set
1329 // or if a css::sdbcx::View is available and the Required flag is not set
1330 const TOTypeInfoSP& pTypeInfo = pFieldDescr->getTypeInfo();
1331 if( pTypeInfo->nSearchType == ColumnSearch::NONE
1332 || (pFieldDescr->IsNullable() && pRow->IsReadOnly())
1333 )
1334 return false;
1335 }
1336
1337 nIndex = NextSelectedRow();
1338 }
1339
1340 return true;
1341}
1342
1343void OTableEditorCtrl::Command(const CommandEvent& rEvt)
1344{
1345 switch (rEvt.GetCommand())
1346 {
1347 case CommandEventId::ContextMenu:
1348 {
1349 Point aMenuPos( rEvt.GetMousePosPixel() );
1350 if (!rEvt.IsMouseEvent())
1351 {
1352 if ( 1 == GetSelectColumnCount() )
1353 {
1354 sal_uInt16 nSelId = GetColumnId(
1355 sal::static_int_cast< sal_uInt16 >(
1356 FirstSelectedColumn() ) );
1357 ::tools::Rectangle aColRect( GetFieldRectPixel( 0, nSelId, false ) );
1358
1359 aMenuPos = aColRect.TopCenter();
1360 }
1361 else if ( GetSelectRowCount() > 0 )
1362 {
1363 ::tools::Rectangle aColRect( GetFieldRectPixel( FirstSelectedRow(), HANDLE_ID0 ) );
1364
1365 aMenuPos = aColRect.TopCenter();
1366 }
1367 else
1368 {
1369 OTableRowView::Command(rEvt);
1370 return;
1371 }
1372 }
1373
1374 // Show the Context menu
1375 if( !IsReadOnly() )
1376 {
1377 sal_uInt16 nColId = GetColumnId(GetColumnAtXPosPixel(aMenuPos.X()));
1378 long nRow = GetRowAtYPosPixel(aMenuPos.Y());
1379
1380 if ( HANDLE_ID0 != nColId )
1381 {
1382 if ( nRow < 0 && nColId != BROWSER_INVALIDID((sal_uInt16) 0xFFFF) )
1383 { // hit the header
1384 if ( 3 != nColId )
1385 { // 3 would mean the last column, and this last column is auto-sized
1386 if ( !IsColumnSelected( nColId ) )
1387 SelectColumnId( nColId );
1388
1389 VclBuilder aBuilder(nullptr, AllSettings::GetUIRootDir(), "dbaccess/ui/querycolmenu.ui", "");
1390 VclPtr<PopupMenu> aContextMenu(aBuilder.get_menu("menu"));
1391 aContextMenu->EnableItem(aContextMenu->GetItemId("delete"), false);
1392 aContextMenu->RemoveDisabledEntries(true, true);
1393 if (aContextMenu->Execute(this, aMenuPos) == aContextMenu->GetItemId("width"))
1394 adjustBrowseBoxColumnWidth( this, nColId );
1395 }
1396 }
1397 }
1398 else
1399 {
1400 VclBuilder aBuilder(nullptr, AllSettings::GetUIRootDir(), "dbaccess/ui/tabledesignrowmenu.ui", "");
1401 VclPtr<PopupMenu> aContextMenu(aBuilder.get_menu("menu"));
1402
1403 aContextMenu->EnableItem(aContextMenu->GetItemId("cut"), IsCutAllowed());
1404 aContextMenu->EnableItem(aContextMenu->GetItemId("copy"), IsCopyAllowed());
1405 aContextMenu->EnableItem(aContextMenu->GetItemId("paste"), IsPasteAllowed());
1406 aContextMenu->EnableItem(aContextMenu->GetItemId("delete"), IsDeleteAllowed());
1407 aContextMenu->EnableItem(aContextMenu->GetItemId("primarykey"), IsPrimaryKeyAllowed());
1408 aContextMenu->EnableItem(aContextMenu->GetItemId("insert"), IsInsertNewAllowed(nRow));
1409 aContextMenu->CheckItem("primarykey", IsRowSelected(GetCurRow()) && IsPrimaryKey());
1410
1411 // remove all the disable entries
1412 aContextMenu->RemoveDisabledEntries(true, true);
1413
1414 if( SetDataPtr(m_nDataPos) )
1415 pDescrWin->SaveData( pActRow->GetActFieldDescr() );
1416
1417 // All actions which change the number of rows must be run asynchronously
1418 // otherwise there may be problems between the Context menu and the Browser
1419 m_nDataPos = GetCurRow();
1420 aContextMenu->Execute(this, aMenuPos);
1421 OString sIdent = aContextMenu->GetCurItemIdent();
1422 if (sIdent == "cut")
1423 cut();
1424 else if (sIdent == "copy")
1425 copy();
1426 else if (sIdent == "paste")
1427 paste();
1428 else if (sIdent == "delete")
1429 {
1430 if( nDeleteEvent )
1431 Application::RemoveUserEvent( nDeleteEvent );
1432 nDeleteEvent = Application::PostUserEvent( LINK(this, OTableEditorCtrl, DelayedDelete)::tools::detail::makeLink( ::tools::detail::castTo<OTableEditorCtrl
*>(this), &OTableEditorCtrl::LinkStubDelayedDelete)
, nullptr, true );
1433 }
1434 else if (sIdent == "insert")
1435 {
1436 if( nInsNewRowsEvent )
1437 Application::RemoveUserEvent( nInsNewRowsEvent );
1438 nInsNewRowsEvent = Application::PostUserEvent( LINK(this, OTableEditorCtrl, DelayedInsNewRows)::tools::detail::makeLink( ::tools::detail::castTo<OTableEditorCtrl
*>(this), &OTableEditorCtrl::LinkStubDelayedInsNewRows
)
, nullptr, true );
1439 }
1440 else if (sIdent == "primarykey")
1441 {
1442 SetPrimaryKey( !IsPrimaryKey() );
1443 }
1444 }
1445 }
1446 }
1447 break;
1448 default:
1449 OTableRowView::Command(rEvt);
1450 }
1451
1452}
1453
1454IMPL_LINK_NOARG( OTableEditorCtrl, DelayedCut, void*, void )void OTableEditorCtrl::LinkStubDelayedCut(void * instance, void
* data) { return static_cast<OTableEditorCtrl *>(instance
)->DelayedCut(data); } void OTableEditorCtrl::DelayedCut(__attribute__
((unused)) void*)
1455{
1456 nCutEvent = nullptr;
1457 OTableRowView::cut();
1458}
1459
1460IMPL_LINK_NOARG( OTableEditorCtrl, DelayedPaste, void*, void )void OTableEditorCtrl::LinkStubDelayedPaste(void * instance, void
* data) { return static_cast<OTableEditorCtrl *>(instance
)->DelayedPaste(data); } void OTableEditorCtrl::DelayedPaste
(__attribute__ ((unused)) void*)
1461{
1462 nPasteEvent = nullptr;
1463
1464 sal_Int32 nPastePosition = GetView()->getController().getFirstEmptyRowPosition();
1465 if ( !GetView()->getController().getTable().is() )
1466 nPastePosition = GetSelectRowCount() ? FirstSelectedRow() : GetCurRow();
1467
1468 if (!IsInsertNewAllowed(nPastePosition))
1469 { // Insertion is not allowed, only appending, so test if there are full cells after the PastePosition
1470
1471 auto aIter = std::find_if(m_pRowList->rbegin(), m_pRowList->rend(), [](const std::shared_ptr<OTableRow>& rxRow) {
1472 return rxRow && rxRow->GetActFieldDescr() && !rxRow->GetActFieldDescr()->GetName().isEmpty(); });
1473 auto nFreeFromPos = static_cast<sal_Int32>(std::distance(aIter, m_pRowList->rend())); // from here on there are only empty rows
1474 if (nPastePosition < nFreeFromPos) // if at least one PastePosition is full, go right to the end
1475 nPastePosition = nFreeFromPos;
1476 }
1477
1478 OTableRowView::Paste( nPastePosition );
1479 SetNoSelection();
1480 GoToRow( nPastePosition );
1481}
1482
1483IMPL_LINK_NOARG( OTableEditorCtrl, DelayedDelete, void*, void )void OTableEditorCtrl::LinkStubDelayedDelete(void * instance,
void* data) { return static_cast<OTableEditorCtrl *>(instance
)->DelayedDelete(data); } void OTableEditorCtrl::DelayedDelete
(__attribute__ ((unused)) void*)
1484{
1485 nDeleteEvent = nullptr;
1486 DeleteRows();
1487}
1488
1489IMPL_LINK_NOARG( OTableEditorCtrl, DelayedInsNewRows, void*, void )void OTableEditorCtrl::LinkStubDelayedInsNewRows(void * instance
, void* data) { return static_cast<OTableEditorCtrl *>(
instance)->DelayedInsNewRows(data); } void OTableEditorCtrl
::DelayedInsNewRows(__attribute__ ((unused)) void*)
1490{
1491 nInsNewRowsEvent = nullptr;
1492 sal_Int32 nPastePosition = GetView()->getController().getFirstEmptyRowPosition();
1493 if ( !GetView()->getController().getTable().is() )
1494 nPastePosition = GetSelectRowCount() ? FirstSelectedRow() : m_nDataPos;
1495
1496 InsertNewRows( nPastePosition );
1497 SetNoSelection();
1498 GoToRow( nPastePosition );
1499}
1500
1501void OTableEditorCtrl::AdjustFieldDescription(OFieldDescription* _pFieldDesc,
1502 MultiSelection& _rMultiSel,
1503 sal_Int32 _nPos,
1504 bool _bSet,
1505 bool _bPrimaryKey)
1506{
1507 _pFieldDesc->SetPrimaryKey( _bPrimaryKey );
1508 if(!_bSet && _pFieldDesc->getTypeInfo()->bNullable)
1509 {
1510 _pFieldDesc->SetIsNullable(ColumnValue::NO_NULLS);
1511 _pFieldDesc->SetControlDefault(Any());
1512 }
1513 if ( _pFieldDesc->IsAutoIncrement() && !_bPrimaryKey )
1514 {
1515 OTableController& rController = GetView()->getController();
1516 if ( rController.isAutoIncrementPrimaryKey() )
1517 {
1518 _pFieldDesc->SetAutoIncrement(false);
1519 }
1520 }
1521 // update field description
1522 pDescrWin->DisplayData(_pFieldDesc);
1523
1524 _rMultiSel.Insert( _nPos );
1525 _rMultiSel.Select( _nPos );
1526}
1527
1528void OTableEditorCtrl::SetPrimaryKey( bool bSet )
1529{
1530 // Delete any existing Primary Keys
1531 MultiSelection aDeletedPrimKeys;
1532 aDeletedPrimKeys.SetTotalRange( Range(0,GetRowCount()) );
1533
1534 sal_Int32 nRow = 0;
1535 for (auto const& row : *m_pRowList)
1536 {
1537 OFieldDescription* pFieldDescr = row->GetActFieldDescr();
1538 if( pFieldDescr && row->IsPrimaryKey() && (!bSet || !IsRowSelected(nRow)) )
1539 {
1540 AdjustFieldDescription(pFieldDescr,aDeletedPrimKeys,nRow,bSet,false);
1541 }
1542 ++nRow;
1543 }
1544
1545 // Set the primary keys of the marked rows
1546 MultiSelection aInsertedPrimKeys;
1547 aInsertedPrimKeys.SetTotalRange( Range(0,GetRowCount()) );
1548 if( bSet )
1549 {
1550 long nIndex = FirstSelectedRow();
1551 while( nIndex != SFX_ENDOFSELECTION(-1) )
1552 {
1553 // Set the key
1554 std::shared_ptr<OTableRow> pRow = (*m_pRowList)[nIndex];
1555 OFieldDescription* pFieldDescr = pRow->GetActFieldDescr();
1556 if(pFieldDescr)
1557 AdjustFieldDescription(pFieldDescr,aInsertedPrimKeys,nIndex,false,true);
1558
1559 nIndex = NextSelectedRow();
1560 }
1561 }
1562
1563 GetUndoManager().AddUndoAction( std::make_unique<OPrimKeyUndoAct>(this, aDeletedPrimKeys, aInsertedPrimKeys) );
1564
1565 // Invalidate the handle-columns
1566 InvalidateHandleColumn();
1567
1568 // Set the TableDocSh's ModifyFlag
1569 GetView()->getController().setModified( true );
1570 InvalidateFeatures();
1571}
1572
1573bool OTableEditorCtrl::IsPrimaryKey()
1574{
1575 // Are all marked fields part of the Primary Key ?
1576 long nPrimaryKeys = 0;
1577 sal_Int32 nRow=0;
1578 for (auto const& row : *m_pRowList)
1579 {
1580 if( IsRowSelected(nRow) && !row->IsPrimaryKey() )
1581 return false;
1582 if( row->IsPrimaryKey() )
1583 ++nPrimaryKeys;
1584 ++nRow;
1585 }
1586
1587 // Are there any unselected fields that are part of the Key ?
1588 return GetSelectRowCount() == nPrimaryKeys;
1589}
1590
1591void OTableEditorCtrl::SwitchType( const TOTypeInfoSP& _pType )
1592{
1593 // if there is no assigned field name
1594 long nRow(GetCurRow());
1595 OFieldDescription* pActFieldDescr = GetFieldDescr( nRow );
1596 if( pActFieldDescr )
1597 // Store the old description
1598 pDescrWin->SaveData( pActFieldDescr );
1599
1600 if ( nRow < 0 || nRow > static_cast<long>(m_pRowList->size()) )
1601 return;
1602 // Show the new description
1603 std::shared_ptr<OTableRow> pRow = (*m_pRowList)[nRow];
1604 pRow->SetFieldType( _pType, true );
1605 if ( _pType )
1606 {
1607 weld::ComboBox& rTypeList = pTypeCell->get_widget();
1608 const sal_Int32 nCurrentlySelected = rTypeList.get_active();
1609
1610 if ( ( nCurrentlySelected == -1 )
1611 || ( GetView()->getController().getTypeInfo( nCurrentlySelected ) != _pType )
1612 )
1613 {
1614 sal_Int32 nEntryPos = 0;
1615 const OTypeInfoMap& rTypeInfo = GetView()->getController().getTypeInfo();
1616 for (auto const& elem : rTypeInfo)
1617 {
1618 if(elem.second == _pType)
1619 break;
1620 ++nEntryPos;
1621 }
1622 if (nEntryPos < rTypeList.get_count())
1623 rTypeList.set_active(nEntryPos);
1624 }
1625 }
1626
1627 pActFieldDescr = pRow->GetActFieldDescr();
1628 if (pActFieldDescr != nullptr && !pActFieldDescr->GetFormatKey())
1629 {
1630 sal_Int32 nFormatKey = ::dbtools::getDefaultNumberFormat( pActFieldDescr->GetType(),
1631 pActFieldDescr->GetScale(),
1632 pActFieldDescr->IsCurrency(),
1633 Reference< XNumberFormatTypes>(GetView()->getController().getNumberFormatter()->getNumberFormatsSupplier()->getNumberFormats(),UNO_QUERY),
1634 GetView()->getLocale());
1635
1636 pActFieldDescr->SetFormatKey(nFormatKey);
1637 }
1638
1639 pDescrWin->DisplayData( pActFieldDescr );
1640}
1641
1642OTableDesignView* OTableEditorCtrl::GetView() const
1643{
1644 return m_pView;
1645}
1646
1647void OTableEditorCtrl::DeactivateCell(bool bUpdate)
1648{
1649 OTableRowView::DeactivateCell(bUpdate);
1650 // now we have to deactivate the field description
1651 long nRow(GetCurRow());
1652 if (pDescrWin)
1653 pDescrWin->SetReadOnly(bReadOnly || !SetDataPtr(nRow) || GetActRow()->IsReadOnly());
1654}
1655
1656bool OTableEditorCtrl::PreNotify( NotifyEvent& rNEvt )
1657{
1658 if (rNEvt.GetType() == MouseNotifyEvent::GETFOCUS)
1659 {
1660 if( pHelpTextCell && pHelpTextCell->HasChildPathFocus() )
1661 m_eChildFocus = HELPTEXT;
1662 else if( pDescrCell && pDescrCell->HasChildPathFocus() )
1663 m_eChildFocus = DESCRIPTION;
1664 else if(pNameCell && pNameCell->HasChildPathFocus() )
1665 m_eChildFocus = NAME;
1666 else
1667 m_eChildFocus = ROW;
1668 }
1669
1670 return OTableRowView::PreNotify(rNEvt);
1671}
1672
1673/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx

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
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<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 */
56template <class reference_type>
57class 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
66public:
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);
12
Calling copy constructor for 'Reference<svt::EditControl>'
15
Returning from copy constructor for 'Reference<svt::EditControl>'
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
16
Calling 'Reference::clear'
23
Returning; memory was released
205 if (aTmp.get()) {
24
Calling 'Reference::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
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<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 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
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
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
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
378private:
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
387protected:
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
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
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
421private:
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: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

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
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
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)
13
Assuming field 'm_pBody' is non-null
14
Taking true branch
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
16.1
Field 'm_pBody' is non-null
16.1
Field 'm_pBody' is non-null
16.1
Field 'm_pBody' is non-null
16.1
Field 'm_pBody' is non-null
)
17
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
18
Calling 'VclReferenceBase::release'
22
Returning; memory was released
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;
25
Use of memory after it is freed
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
277namespace 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*/
286template<typename T>
287struct 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: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

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
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
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)
19
Assuming the condition is true
20
Taking true branch
40 delete this;
21
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif