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 fmgridcl.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 -isystem /usr/include/libxml2 -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 SVXCORE_DLLIMPLEMENTATION -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/epoxy/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium/public -D COMPONENT_BUILD -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/svx/inc -I /home/maarten/src/libreoffice/core/svx/source/inc -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/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/svx/sdi -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/svx/source/fmcomp/fmgridcl.cxx

/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.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 <svx/fmgridif.hxx>
21#include <fmprop.hxx>
22#include <svx/fmtools.hxx>
23#include <fmservs.hxx>
24#include <fmurl.hxx>
25#include <formcontrolfactory.hxx>
26#include <gridcell.hxx>
27#include <gridcols.hxx>
28#include <svx/dbaexchange.hxx>
29#include <svx/dialmgr.hxx>
30#include <svx/strings.hrc>
31#include <svx/fmgridcl.hxx>
32#include <svx/svxdlg.hxx>
33#include <svx/svxids.hrc>
34#include <bitmaps.hlst>
35
36#include <com/sun/star/form/XConfirmDeleteListener.hpp>
37#include <com/sun/star/form/XFormComponent.hpp>
38#include <com/sun/star/form/XGridColumnFactory.hpp>
39#include <com/sun/star/io/XPersistObject.hpp>
40#include <com/sun/star/sdb/CommandType.hpp>
41#include <com/sun/star/sdb/RowChangeAction.hpp>
42#include <com/sun/star/sdb/XQueriesSupplier.hpp>
43#include <com/sun/star/sdbc/DataType.hpp>
44#include <com/sun/star/sdbc/SQLException.hpp>
45#include <com/sun/star/sdbc/XPreparedStatement.hpp>
46#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
47#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
48#include <com/sun/star/sdbcx/XDeleteRows.hpp>
49#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
50#include <com/sun/star/util/XNumberFormats.hpp>
51#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
52#include <com/sun/star/util/URLTransformer.hpp>
53#include <com/sun/star/util/XURLTransformer.hpp>
54#include <com/sun/star/view/XSelectionSupplier.hpp>
55#include <comphelper/processfactory.hxx>
56#include <comphelper/property.hxx>
57#include <comphelper/string.hxx>
58#include <comphelper/types.hxx>
59#include <connectivity/dbtools.hxx>
60#include <sfx2/dispatch.hxx>
61#include <sfx2/viewfrm.hxx>
62#include <svl/eitem.hxx>
63#include <vcl/builder.hxx>
64#include <vcl/commandevent.hxx>
65#include <vcl/svapp.hxx>
66#include <tools/debug.hxx>
67#include <tools/multisel.hxx>
68#include <tools/diagnose_ex.h>
69#include <vcl/help.hxx>
70#include <vcl/image.hxx>
71#include <vcl/menu.hxx>
72#include <vcl/settings.hxx>
73#include <sal/log.hxx>
74#include <i18nlangtag/languagetag.hxx>
75#include <memory>
76
77using namespace ::com::sun::star::uno;
78using namespace ::com::sun::star::view;
79using namespace ::com::sun::star::beans;
80using namespace ::com::sun::star::lang;
81using namespace ::com::sun::star::sdbcx;
82using namespace ::com::sun::star::sdbc;
83using namespace ::com::sun::star::sdb;
84using namespace ::com::sun::star::form;
85using namespace ::com::sun::star::util;
86using namespace ::com::sun::star::container;
87using namespace ::cppu;
88using namespace ::svxform;
89using namespace ::svx;
90using namespace ::dbtools;
91
92struct FmGridHeaderData
93{
94 ODataAccessDescriptor aDropData;
95 Point aDropPosPixel;
96 sal_Int8 nDropAction;
97 Reference< XInterface > xDroppedStatement;
98 Reference< XInterface > xDroppedResultSet;
99};
100
101static void SetMenuItem(const OUString& rImgID, const OString &rID, Menu& rMenu, bool bDesignMode)
102{
103 Image aImage(StockImage::Yes, rImgID);
104 sal_uInt16 nID = rMenu.GetItemId(rID);
105 rMenu.SetItemImage(nID, aImage);
106 rMenu.EnableItem(nID, bDesignMode);
107}
108
109FmGridHeader::FmGridHeader( BrowseBox* pParent, WinBits nWinBits)
110 :EditBrowserHeader(pParent, nWinBits)
111 ,DropTargetHelper(this)
112 ,m_pImpl(new FmGridHeaderData)
113{
114}
115
116FmGridHeader::~FmGridHeader()
117{
118 disposeOnce();
119}
120
121void FmGridHeader::dispose()
122{
123 m_pImpl.reset();
124 DropTargetHelper::dispose();
125 svt::EditBrowserHeader::dispose();
126}
127
128sal_uInt16 FmGridHeader::GetModelColumnPos(sal_uInt16 nId) const
129{
130 return static_cast<FmGridControl*>(GetParent())->GetModelColumnPos(nId);
131}
132
133void FmGridHeader::notifyColumnSelect(sal_uInt16 nColumnId)
134{
135 sal_uInt16 nPos = GetModelColumnPos(nColumnId);
136 Reference< XIndexAccess > xColumns = static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns();
137 if ( nPos < xColumns->getCount() )
138 {
139 Reference< XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY);
140 if ( xSelSupplier.is() )
141 {
142 Reference< XPropertySet > xColumn;
143 xColumns->getByIndex(nPos) >>= xColumn;
144 xSelSupplier->select(makeAny(xColumn));
145 }
146 }
147}
148
149void FmGridHeader::Select()
150{
151 EditBrowserHeader::Select();
152 notifyColumnSelect(GetCurItemId());
153}
154
155void FmGridHeader::RequestHelp( const HelpEvent& rHEvt )
156{
157 sal_uInt16 nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
158 if ( nItemId )
159 {
160 if ( rHEvt.GetMode() & (HelpEventMode::QUICK | HelpEventMode::BALLOON) )
161 {
162 tools::Rectangle aItemRect = GetItemRect( nItemId );
163 Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
164 aItemRect.SetLeft( aPt.X() );
165 aItemRect.SetTop( aPt.Y() );
166 aPt = OutputToScreenPixel( aItemRect.BottomRight() );
167 aItemRect.SetRight( aPt.X() );
168 aItemRect.SetBottom( aPt.Y() );
169
170 sal_uInt16 nPos = GetModelColumnPos(nItemId);
171 Reference< css::container::XIndexContainer > xColumns(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
172 try
173 {
174 Reference< css::beans::XPropertySet > xColumn(xColumns->getByIndex(nPos),UNO_QUERY);
175 OUString aHelpText;
176 xColumn->getPropertyValue(FM_PROP_HELPTEXT"HelpText") >>= aHelpText;
177 if ( aHelpText.isEmpty() )
178 xColumn->getPropertyValue(FM_PROP_DESCRIPTION"Description") >>= aHelpText;
179 if ( !aHelpText.isEmpty() )
180 {
181 if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
182 Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aHelpText );
183 else
184 Help::ShowQuickHelp( this, aItemRect, aHelpText );
185 return;
186 }
187 }
188 catch(Exception&)
189 {
190 return;
191 }
192 }
193 }
194 EditBrowserHeader::RequestHelp( rHEvt );
195}
196
197sal_Int8 FmGridHeader::AcceptDrop( const AcceptDropEvent& rEvt )
198{
199 // drop allowed in design mode only
200 if (!static_cast<FmGridControl*>(GetParent())->IsDesignMode())
201 return DND_ACTION_NONEcss::datatransfer::dnd::DNDConstants::ACTION_NONE;
202
203 // search for recognized formats
204 const DataFlavorExVector& rFlavors = GetDataFlavorExVector();
205 if (OColumnTransferable::canExtractColumnDescriptor(rFlavors, ColumnTransferFormatFlags::COLUMN_DESCRIPTOR | ColumnTransferFormatFlags::FIELD_DESCRIPTOR))
206 return rEvt.mnAction;
207
208 return DND_ACTION_NONEcss::datatransfer::dnd::DNDConstants::ACTION_NONE;
209}
210
211sal_Int8 FmGridHeader::ExecuteDrop( const ExecuteDropEvent& _rEvt )
212{
213 if (!static_cast<FmGridControl*>(GetParent())->IsDesignMode())
214 return DND_ACTION_NONEcss::datatransfer::dnd::DNDConstants::ACTION_NONE;
215
216 TransferableDataHelper aDroppedData(_rEvt.maDropEvent.Transferable);
217
218 // check the formats
219 bool bColumnDescriptor = OColumnTransferable::canExtractColumnDescriptor(aDroppedData.GetDataFlavorExVector(), ColumnTransferFormatFlags::COLUMN_DESCRIPTOR);
220 bool bFieldDescriptor = OColumnTransferable::canExtractColumnDescriptor(aDroppedData.GetDataFlavorExVector(), ColumnTransferFormatFlags::FIELD_DESCRIPTOR);
221 if (!bColumnDescriptor && !bFieldDescriptor)
222 {
223 OSL_FAIL("FmGridHeader::ExecuteDrop: should never have reached this (no extractable format)!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "223" ": "), "%s", "FmGridHeader::ExecuteDrop: should never have reached this (no extractable format)!"
); } } while (false)
;
224 return DND_ACTION_NONEcss::datatransfer::dnd::DNDConstants::ACTION_NONE;
225 }
226
227 // extract the descriptor
228 OUString sDatasource, sCommand, sFieldName,sDatabaseLocation;
229 sal_Int32 nCommandType = CommandType::COMMAND;
230 Reference< XPreparedStatement > xStatement;
231 Reference< XResultSet > xResultSet;
232 Reference< XPropertySet > xField;
233 Reference< XConnection > xConnection;
234
235 ODataAccessDescriptor aColumn = OColumnTransferable::extractColumnDescriptor(aDroppedData);
236 if (aColumn.has(DataAccessDescriptorProperty::DataSource)) aColumn[DataAccessDescriptorProperty::DataSource] >>= sDatasource;
237 if (aColumn.has(DataAccessDescriptorProperty::DatabaseLocation)) aColumn[DataAccessDescriptorProperty::DatabaseLocation] >>= sDatabaseLocation;
238 if (aColumn.has(DataAccessDescriptorProperty::Command)) aColumn[DataAccessDescriptorProperty::Command] >>= sCommand;
239 if (aColumn.has(DataAccessDescriptorProperty::CommandType)) aColumn[DataAccessDescriptorProperty::CommandType] >>= nCommandType;
240 if (aColumn.has(DataAccessDescriptorProperty::ColumnName)) aColumn[DataAccessDescriptorProperty::ColumnName] >>= sFieldName;
241 if (aColumn.has(DataAccessDescriptorProperty::ColumnObject))aColumn[DataAccessDescriptorProperty::ColumnObject] >>= xField;
242 if (aColumn.has(DataAccessDescriptorProperty::Connection)) aColumn[DataAccessDescriptorProperty::Connection] >>= xConnection;
243
244 if ( sFieldName.isEmpty()
245 || sCommand.isEmpty()
246 || ( sDatasource.isEmpty()
247 && sDatabaseLocation.isEmpty()
248 && !xConnection.is()
249 )
250 )
251 {
252 OSL_FAIL( "FmGridHeader::ExecuteDrop: somebody started a nonsense drag operation!!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "252" ": "), "%s", "FmGridHeader::ExecuteDrop: somebody started a nonsense drag operation!!"
); } } while (false)
;
253 return DND_ACTION_NONEcss::datatransfer::dnd::DNDConstants::ACTION_NONE;
254 }
255
256 try
257 {
258 // need a connection
259 if (!xConnection.is())
260 { // the transferable did not contain the connection -> build an own one
261 try
262 {
263 OUString sSignificantSource( sDatasource.isEmpty() ? sDatabaseLocation : sDatasource );
264 xConnection = getConnection_withFeedback(sSignificantSource, OUString(), OUString(),
265 static_cast<FmGridControl*>(GetParent())->getContext(), nullptr );
266 }
267 catch(NoSuchElementException&)
268 { // allowed, means sDatasource isn't a valid data source name...
269 }
270 catch(Exception&)
271 {
272 OSL_FAIL("FmGridHeader::ExecuteDrop: could not retrieve the database access object !")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "272" ": "), "%s", "FmGridHeader::ExecuteDrop: could not retrieve the database access object !"
); } } while (false)
;
273 }
274
275 if (!xConnection.is())
276 {
277 OSL_FAIL("FmGridHeader::ExecuteDrop: could not retrieve the database access object !")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "277" ": "), "%s", "FmGridHeader::ExecuteDrop: could not retrieve the database access object !"
); } } while (false)
;
278 return DND_ACTION_NONEcss::datatransfer::dnd::DNDConstants::ACTION_NONE;
279 }
280 }
281
282 // try to obtain the column object
283 if (!xField.is())
284 {
285#ifdef DBG_UTIL
286 Reference< XServiceInfo > xServiceInfo(xConnection, UNO_QUERY);
287 DBG_ASSERT(xServiceInfo.is() && xServiceInfo->supportsService(SRV_SDB_CONNECTION), "FmGridHeader::ExecuteDrop: invalid connection (no database access connection !)")do { if (true && (!(xServiceInfo.is() && xServiceInfo
->supportsService("com.sun.star.sdb.Connection")))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "287" ": "), "%s", "FmGridHeader::ExecuteDrop: invalid connection (no database access connection !)"
); } } while (false)
;
288#endif
289
290 Reference< XNameAccess > xFields;
291 switch (nCommandType)
292 {
293 case CommandType::TABLE:
294 {
295 Reference< XTablesSupplier > xSupplyTables(xConnection, UNO_QUERY);
296 Reference< XColumnsSupplier > xSupplyColumns;
297 xSupplyTables->getTables()->getByName(sCommand) >>= xSupplyColumns;
298 xFields = xSupplyColumns->getColumns();
299 }
300 break;
301 case CommandType::QUERY:
302 {
303 Reference< XQueriesSupplier > xSupplyQueries(xConnection, UNO_QUERY);
304 Reference< XColumnsSupplier > xSupplyColumns;
305 xSupplyQueries->getQueries()->getByName(sCommand) >>= xSupplyColumns;
306 xFields = xSupplyColumns->getColumns();
307 }
308 break;
309 default:
310 {
311 xStatement = xConnection->prepareStatement(sCommand);
312 // not interested in any results
313
314 Reference< XPropertySet > xStatProps(xStatement,UNO_QUERY);
315 xStatProps->setPropertyValue("MaxRows", makeAny(sal_Int32(0)));
316
317 xResultSet = xStatement->executeQuery();
318 Reference< XColumnsSupplier > xSupplyCols(xResultSet, UNO_QUERY);
319 if (xSupplyCols.is())
320 xFields = xSupplyCols->getColumns();
321 }
322 }
323
324 if (xFields.is() && xFields->hasByName(sFieldName))
325 xFields->getByName(sFieldName) >>= xField;
326
327 if (!xField.is())
328 {
329 ::comphelper::disposeComponent(xStatement);
330 return DND_ACTION_NONEcss::datatransfer::dnd::DNDConstants::ACTION_NONE;
331 }
332 }
333
334 // do the drop asynchronously
335 // (85957 - UI actions within the drop are not allowed, but we want to open a popup menu)
336 m_pImpl->aDropData = aColumn;
337 m_pImpl->aDropData[DataAccessDescriptorProperty::Connection] <<= xConnection;
338 m_pImpl->aDropData[DataAccessDescriptorProperty::ColumnObject] <<= xField;
339
340 m_pImpl->nDropAction = _rEvt.mnAction;
341 m_pImpl->aDropPosPixel = _rEvt.maPosPixel;
342 m_pImpl->xDroppedStatement = xStatement;
343 m_pImpl->xDroppedResultSet = xResultSet;
344
345 PostUserEvent(LINK(this, FmGridHeader, OnAsyncExecuteDrop)::tools::detail::makeLink( ::tools::detail::castTo<FmGridHeader
*>(this), &FmGridHeader::LinkStubOnAsyncExecuteDrop)
, nullptr, true);
346 }
347 catch (Exception&)
348 {
349 TOOLS_WARN_EXCEPTION("svx", "caught an exception while creatin' the column !")do { css::uno::Any tools_warn_exception( DbgGetCaughtException
() ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "svx")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "caught an exception while creatin' the column !"
<< " " << exceptionToString(tools_warn_exception
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), (
"svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "349" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "caught an exception while creatin' the column !"
<< " " << exceptionToString(tools_warn_exception
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "caught an exception while creatin' the column !" <<
" " << exceptionToString(tools_warn_exception); ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "349" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "caught an exception while creatin' the column !"
<< " " << exceptionToString(tools_warn_exception
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), (
"svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "349" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "caught an exception while creatin' the column !"
<< " " << exceptionToString(tools_warn_exception
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "caught an exception while creatin' the column !" <<
" " << exceptionToString(tools_warn_exception); ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "349" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false); } while (false)
;
350 ::comphelper::disposeComponent(xStatement);
351 return DND_ACTION_NONEcss::datatransfer::dnd::DNDConstants::ACTION_NONE;
352 }
353
354 return DND_ACTION_LINKcss::datatransfer::dnd::DNDConstants::ACTION_LINK;
355}
356
357IMPL_LINK_NOARG( FmGridHeader, OnAsyncExecuteDrop, void*, void )void FmGridHeader::LinkStubOnAsyncExecuteDrop(void * instance
, void* data) { return static_cast<FmGridHeader *>(instance
)->OnAsyncExecuteDrop(data); } void FmGridHeader::OnAsyncExecuteDrop
(__attribute__ ((unused)) void*)
358{
359 OUString sCommand, sFieldName,sURL;
360 sal_Int32 nCommandType = CommandType::COMMAND;
361 Reference< XPropertySet > xField;
362 Reference< XConnection > xConnection;
363
364 OUString sDatasource = m_pImpl->aDropData.getDataSource();
365 if ( sDatasource.isEmpty() && m_pImpl->aDropData.has(DataAccessDescriptorProperty::ConnectionResource) )
366 m_pImpl->aDropData[DataAccessDescriptorProperty::ConnectionResource] >>= sURL;
367 m_pImpl->aDropData[DataAccessDescriptorProperty::Command] >>= sCommand;
368 m_pImpl->aDropData[DataAccessDescriptorProperty::CommandType] >>= nCommandType;
369 m_pImpl->aDropData[DataAccessDescriptorProperty::ColumnName] >>= sFieldName;
370 m_pImpl->aDropData[DataAccessDescriptorProperty::Connection] >>= xConnection;
371 m_pImpl->aDropData[DataAccessDescriptorProperty::ColumnObject] >>= xField;
372
373 try
374 {
375 // need number formats
376 Reference< XNumberFormatsSupplier > xSupplier = getNumberFormats(xConnection, true);
377 Reference< XNumberFormats > xNumberFormats;
378 if (xSupplier.is())
379 xNumberFormats = xSupplier->getNumberFormats();
380 if (!xNumberFormats.is())
381 {
382 ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
383 ::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
384 return;
385 }
386
387 // The field now needs two pieces of information:
388 // a.) Name of the field for label and ControlSource
389 // b.) FormatKey, to determine which field is to be created
390 sal_Int32 nDataType = 0;
391 xField->getPropertyValue(FM_PROP_FIELDTYPE"Type") >>= nDataType;
392 // these datatypes can not be processed in Gridcontrol
393 switch (nDataType)
394 {
395 case DataType::BLOB:
396 case DataType::LONGVARBINARY:
397 case DataType::BINARY:
398 case DataType::VARBINARY:
399 case DataType::OTHER:
400 ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
401 ::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
402 return;
403 }
404
405 // Creating the column
406 Reference< XIndexContainer > xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
407 Reference< XGridColumnFactory > xFactory(xCols, UNO_QUERY);
408
409 sal_uInt16 nColId = GetItemId(m_pImpl->aDropPosPixel);
410 // insert position, always before the current column
411 sal_uInt16 nPos = GetModelColumnPos(nColId);
412 Reference< XPropertySet > xCol, xSecondCol;
413
414 // Create Column based on type, default textfield
415 std::vector<OString> aPossibleTypes;
416 std::vector<OUString> aImgResId;
417 switch (nDataType)
418 {
419 case DataType::BIT:
420 case DataType::BOOLEAN:
421 aPossibleTypes.emplace_back(FM_COL_CHECKBOX"CheckBox");
422 aImgResId.emplace_back(RID_SVXBMP_CHECKBOX"res/sx10596.png");
423 break;
424 case DataType::TINYINT:
425 case DataType::SMALLINT:
426 case DataType::INTEGER:
427 aPossibleTypes.emplace_back(FM_COL_NUMERICFIELD"NumericField");
428 aImgResId.emplace_back(RID_SVXBMP_NUMERICFIELD"res/sx10706.png");
429 aPossibleTypes.emplace_back(FM_COL_FORMATTEDFIELD"FormattedField");
430 aImgResId.emplace_back(RID_SVXBMP_FORMATTEDFIELD"res/sx10728.png");
431 break;
432 case DataType::REAL:
433 case DataType::DOUBLE:
434 case DataType::NUMERIC:
435 case DataType::DECIMAL:
436 aPossibleTypes.emplace_back(FM_COL_FORMATTEDFIELD"FormattedField");
437 aImgResId.emplace_back(RID_SVXBMP_FORMATTEDFIELD"res/sx10728.png");
438 aPossibleTypes.emplace_back(FM_COL_NUMERICFIELD"NumericField");
439 aImgResId.emplace_back(RID_SVXBMP_NUMERICFIELD"res/sx10706.png");
440 break;
441 case DataType::TIMESTAMP:
442 aPossibleTypes.emplace_back("dateandtimefield");
443 aImgResId.emplace_back(RID_SVXBMP_DATE_N_TIME_FIELDS"res/sx10757.png");
444 aPossibleTypes.emplace_back(FM_COL_DATEFIELD"DateField");
445 aImgResId.emplace_back(RID_SVXBMP_DATEFIELD"res/sx10704.png");
446 aPossibleTypes.emplace_back(FM_COL_TIMEFIELD"TimeField");
447 aImgResId.emplace_back(RID_SVXBMP_TIMEFIELD"res/sx10705.png");
448 aPossibleTypes.emplace_back(FM_COL_FORMATTEDFIELD"FormattedField");
449 aImgResId.emplace_back(RID_SVXBMP_FORMATTEDFIELD"res/sx10728.png");
450 break;
451 case DataType::DATE:
452 aPossibleTypes.emplace_back(FM_COL_DATEFIELD"DateField");
453 aImgResId.emplace_back(RID_SVXBMP_DATEFIELD"res/sx10704.png");
454 aPossibleTypes.emplace_back(FM_COL_FORMATTEDFIELD"FormattedField");
455 aImgResId.emplace_back(RID_SVXBMP_FORMATTEDFIELD"res/sx10728.png");
456 break;
457 case DataType::TIME:
458 aPossibleTypes.emplace_back(FM_COL_TIMEFIELD"TimeField");
459 aImgResId.emplace_back(RID_SVXBMP_TIMEFIELD"res/sx10705.png");
460 aPossibleTypes.emplace_back(FM_COL_FORMATTEDFIELD"FormattedField");
461 aImgResId.emplace_back(RID_SVXBMP_FORMATTEDFIELD"res/sx10728.png");
462 break;
463 case DataType::CHAR:
464 case DataType::VARCHAR:
465 case DataType::LONGVARCHAR:
466 default:
467 aPossibleTypes.emplace_back(FM_COL_TEXTFIELD"TextField");
468 aImgResId.emplace_back(RID_SVXBMP_EDITBOX"res/sx10599.png");
469 aPossibleTypes.emplace_back(FM_COL_FORMATTEDFIELD"FormattedField");
470 aImgResId.emplace_back(RID_SVXBMP_FORMATTEDFIELD"res/sx10728.png");
471 break;
472 }
473 // if it's a currency field, a "currency field" option
474 try
475 {
476 if ( ::comphelper::hasProperty(FM_PROP_ISCURRENCY"IsCurrency", xField)
477 && ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_ISCURRENCY"IsCurrency")))
478 {
479 aPossibleTypes.insert(aPossibleTypes.begin(), FM_COL_CURRENCYFIELD"CurrencyField");
480 aImgResId.insert(aImgResId.begin(), RID_SVXBMP_CURRENCYFIELD"res/sx10707.png");
481 }
482 }
483 catch (const Exception&)
484 {
485 TOOLS_WARN_EXCEPTION("svx", "")do { css::uno::Any tools_warn_exception( DbgGetCaughtException
() ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "svx")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "" << " " << exceptionToString(tools_warn_exception
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), (
"svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "485" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "" << " " << exceptionToString
(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "" << " " << exceptionToString
(tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "485" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "" << " " << exceptionToString(tools_warn_exception
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), (
"svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "485" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "" << " " << exceptionToString
(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "" << " " << exceptionToString
(tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "485" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false); } while (false)
;
486 }
487
488 assert(aPossibleTypes.size() == aImgResId.size())(static_cast <bool> (aPossibleTypes.size() == aImgResId
.size()) ? void (0) : __assert_fail ("aPossibleTypes.size() == aImgResId.size()"
, "/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
, 488, __extension__ __PRETTY_FUNCTION__))
;
489
490 bool bDateNTimeCol = false;
491 if (!aPossibleTypes.empty())
492 {
493 OString sPreferredType = aPossibleTypes[0];
494 if ((m_pImpl->nDropAction == DND_ACTION_LINKcss::datatransfer::dnd::DNDConstants::ACTION_LINK) && (aPossibleTypes.size() > 1))
495 {
496 VclBuilder aBuilder(nullptr, AllSettings::GetUIRootDir(), "svx/ui/colsmenu.ui", "");
497 VclPtr<PopupMenu> aInsertMenu(aBuilder.get_menu("menu"));
498 PopupMenu* pTypeMenu = aInsertMenu->GetPopupMenu(aInsertMenu->GetItemId("insert"));
499 pTypeMenu->ShowItem(pTypeMenu->GetItemId("dateandtimefield"));
500 std::vector<OString>::const_iterator iter;
501 std::vector<OUString>::const_iterator imgiter;
502 for (iter = aPossibleTypes.begin(), imgiter = aImgResId.begin();
503 iter != aPossibleTypes.end(); ++iter, ++imgiter)
504 {
505 SetMenuItem(*imgiter, *iter, *pTypeMenu, true);
506 }
507 if (pTypeMenu->Execute(this, m_pImpl->aDropPosPixel))
508 sPreferredType = pTypeMenu->GetCurItemIdent();
509 }
510
511 bDateNTimeCol = sPreferredType == "dateandtimefield";
512 sal_uInt16 nColCount = bDateNTimeCol ? 2 : 1;
513 OUString sFieldService;
514 while (nColCount--)
515 {
516 if (bDateNTimeCol)
517 sPreferredType = nColCount ? FM_COL_DATEFIELD"DateField" : FM_COL_TIMEFIELD"TimeField";
518
519 sFieldService = OUString::fromUtf8(sPreferredType);
520 Reference< XPropertySet > xThisRoundCol;
521 if ( !sFieldService.isEmpty() )
522 xThisRoundCol = xFactory->createColumn(sFieldService);
523 if (nColCount)
524 xSecondCol = xThisRoundCol;
525 else
526 xCol = xThisRoundCol;
527 }
528 }
529
530 if (!xCol.is() || (bDateNTimeCol && !xSecondCol.is()))
531 {
532 ::comphelper::disposeComponent(xCol); // in case only the creation of the second column failed
533 ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
534 ::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
535 return;
536 }
537
538 if (bDateNTimeCol)
539 {
540 OUString sTimePostfix(SvxResId(RID_STR_POSTFIX_TIMEreinterpret_cast<char const *>("RID_STR_POSTFIX_TIME" "\004"
u8" (Time)")
));
541 xCol->setPropertyValue(FM_PROP_LABEL"Label", makeAny( OUString( sFieldName + sTimePostfix ) ) );
542
543 OUString sDatePostfix(SvxResId( RID_STR_POSTFIX_DATEreinterpret_cast<char const *>("RID_STR_POSTFIX_DATE" "\004"
u8" (Date)")
));
544 xSecondCol->setPropertyValue(FM_PROP_LABEL"Label", makeAny( OUString( sFieldName + sDatePostfix ) ) );
545 }
546 else
547 xCol->setPropertyValue(FM_PROP_LABEL"Label", makeAny(sFieldName));
548
549 // insert now
550 Any aElement;
551 aElement <<= xCol;
552
553 xCols->insertByIndex(nPos, aElement);
554
555 FormControlFactory aControlFactory;
556 aControlFactory.initializeControlModel( DocumentClassification::classifyHostDocument( xCols ), xCol );
557 FormControlFactory::initializeFieldDependentProperties( xField, xCol, xNumberFormats );
558
559 xCol->setPropertyValue(FM_PROP_CONTROLSOURCE"DataField", makeAny(sFieldName));
560 if ( xSecondCol.is() )
561 xSecondCol->setPropertyValue(FM_PROP_CONTROLSOURCE"DataField", makeAny(sFieldName));
562
563 if (bDateNTimeCol)
564 {
565 OUString aPostfix[] = {
566 SvxResId(RID_STR_POSTFIX_DATEreinterpret_cast<char const *>("RID_STR_POSTFIX_DATE" "\004"
u8" (Date)")
),
567 SvxResId(RID_STR_POSTFIX_TIMEreinterpret_cast<char const *>("RID_STR_POSTFIX_TIME" "\004"
u8" (Time)")
)
568 };
569
570 for ( size_t i=0; i<2; ++i )
571 {
572 OUString sPurePostfix = comphelper::string::stripStart(aPostfix[i], ' ');
573 sPurePostfix = comphelper::string::stripStart(sPurePostfix, '(');
574 sPurePostfix = comphelper::string::stripEnd(sPurePostfix, ')');
575 OUString sRealName = sFieldName + "_" + sPurePostfix;
576 if (i)
577 xSecondCol->setPropertyValue(FM_PROP_NAME"Name", makeAny(sRealName));
578 else
579 xCol->setPropertyValue(FM_PROP_NAME"Name", makeAny(sRealName));
580 }
581 }
582 else
583 xCol->setPropertyValue(FM_PROP_NAME"Name", makeAny(sFieldName));
584
585 if (bDateNTimeCol)
586 {
587 aElement <<= xSecondCol;
588 xCols->insertByIndex(nPos == sal_uInt16(-1) ? nPos : ++nPos, aElement);
589 }
590
591 // is the component::Form tied to the database?
592 Reference< XFormComponent > xFormCp(xCols, UNO_QUERY);
593 Reference< XPropertySet > xForm(xFormCp->getParent(), UNO_QUERY);
594 if (xForm.is())
595 {
596 if (::comphelper::getString(xForm->getPropertyValue(FM_PROP_DATASOURCE"DataSourceName")).isEmpty())
597 {
598 if ( !sDatasource.isEmpty() )
599 xForm->setPropertyValue(FM_PROP_DATASOURCE"DataSourceName", makeAny(sDatasource));
600 else
601 xForm->setPropertyValue(FM_PROP_URL"URL", makeAny(sURL));
602 }
603
604 if (::comphelper::getString(xForm->getPropertyValue(FM_PROP_COMMAND"Command")).isEmpty())
605 {
606 xForm->setPropertyValue(FM_PROP_COMMAND"Command", makeAny(sCommand));
607 Any aCommandType;
608 switch (nCommandType)
609 {
610 case CommandType::TABLE:
611 aCommandType <<= sal_Int32(CommandType::TABLE);
612 break;
613 case CommandType::QUERY:
614 aCommandType <<= sal_Int32(CommandType::QUERY);
615 break;
616 default:
617 aCommandType <<= sal_Int32(CommandType::COMMAND);
618 xForm->setPropertyValue(FM_PROP_ESCAPE_PROCESSING"EscapeProcessing", css::uno::Any(2 == nCommandType));
619 break;
620 }
621 xForm->setPropertyValue(FM_PROP_COMMANDTYPE"CommandType", aCommandType);
622 }
623 }
624 }
625 catch (Exception&)
626 {
627 TOOLS_WARN_EXCEPTION("svx", "caught an exception while creatin' the column !")do { css::uno::Any tools_warn_exception( DbgGetCaughtException
() ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "svx")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "caught an exception while creatin' the column !"
<< " " << exceptionToString(tools_warn_exception
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), (
"svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "627" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "caught an exception while creatin' the column !"
<< " " << exceptionToString(tools_warn_exception
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "caught an exception while creatin' the column !" <<
" " << exceptionToString(tools_warn_exception); ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "627" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "caught an exception while creatin' the column !"
<< " " << exceptionToString(tools_warn_exception
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), (
"svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "627" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "caught an exception while creatin' the column !"
<< " " << exceptionToString(tools_warn_exception
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "caught an exception while creatin' the column !" <<
" " << exceptionToString(tools_warn_exception); ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "627" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false); } while (false)
;
628 ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
629 ::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
630 return;
631 }
632
633 ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
634 ::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
635}
636
637void FmGridHeader::PreExecuteColumnContextMenu(sal_uInt16 nColId, PopupMenu& rMenu)
638{
639 bool bDesignMode = static_cast<FmGridControl*>(GetParent())->IsDesignMode();
640
641 Reference< css::container::XIndexContainer > xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
642 // Building of the Insert Menu
643 // mark the column if nColId != HEADERBAR_ITEM_NOTFOUND
644 if(nColId > 0)
645 {
646 sal_uInt16 nPos2 = GetModelColumnPos(nColId);
647
648 Reference< css::container::XIndexContainer > xColumns(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
649 Reference< css::beans::XPropertySet> xColumn( xColumns->getByIndex(nPos2), css::uno::UNO_QUERY);
650 Reference< css::view::XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY);
651 if (xSelSupplier.is())
652 xSelSupplier->select(makeAny(xColumn));
653 }
654
655 // insert position, always before the current column
656 sal_uInt16 nPos = GetModelColumnPos(nColId);
657 bool bMarked = nColId && static_cast<FmGridControl*>(GetParent())->isColumnMarked(nColId);
658
659 PopupMenu* pMenu = rMenu.GetPopupMenu(rMenu.GetItemId("insert"));
660 if (pMenu)
661 {
662 SetMenuItem(RID_SVXBMP_EDITBOX"res/sx10599.png", FM_COL_TEXTFIELD"TextField", *pMenu, bDesignMode);
663 SetMenuItem(RID_SVXBMP_CHECKBOX"res/sx10596.png", FM_COL_CHECKBOX"CheckBox", *pMenu, bDesignMode);
664 SetMenuItem(RID_SVXBMP_COMBOBOX"res/sx10600.png", FM_COL_COMBOBOX"ComboBox", *pMenu, bDesignMode);
665 SetMenuItem(RID_SVXBMP_LISTBOX"res/sx10600.png", FM_COL_LISTBOX"ListBox", *pMenu, bDesignMode);
666 SetMenuItem(RID_SVXBMP_DATEFIELD"res/sx10704.png", FM_COL_DATEFIELD"DateField", *pMenu, bDesignMode);
667 SetMenuItem(RID_SVXBMP_TIMEFIELD"res/sx10705.png", FM_COL_TIMEFIELD"TimeField", *pMenu, bDesignMode);
668 SetMenuItem(RID_SVXBMP_NUMERICFIELD"res/sx10706.png", FM_COL_NUMERICFIELD"NumericField", *pMenu, bDesignMode);
669 SetMenuItem(RID_SVXBMP_CURRENCYFIELD"res/sx10707.png", FM_COL_CURRENCYFIELD"CurrencyField", *pMenu, bDesignMode);
670 SetMenuItem(RID_SVXBMP_PATTERNFIELD"res/sx10708.png", FM_COL_PATTERNFIELD"PatternField", *pMenu, bDesignMode);
671 SetMenuItem(RID_SVXBMP_FORMATTEDFIELD"res/sx10728.png", FM_COL_FORMATTEDFIELD"FormattedField", *pMenu, bDesignMode);
672 }
673
674 if (pMenu && xCols.is() && nColId)
675 {
676 Reference< css::beans::XPropertySet > xPropSet( xCols->getByIndex(nPos), css::uno::UNO_QUERY);
677
678 Reference< css::io::XPersistObject > xServiceQuestion(xPropSet, UNO_QUERY);
679 sal_Int32 nColType = xServiceQuestion.is() ? getColumnTypeByModelName(xServiceQuestion->getServiceName()) : 0;
680 if (nColType == TYPE_TEXTFIELD8)
681 { // edit fields and formatted fields have the same service name, thus getColumnTypeByModelName returns TYPE_TEXTFIELD
682 // in both cases. And as columns don't have a css::lang::XServiceInfo interface, we have to distinguish both
683 // types via the existence of special properties
684 if (xPropSet.is())
685 {
686 Reference< css::beans::XPropertySetInfo > xPropsInfo = xPropSet->getPropertySetInfo();
687 if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(FM_PROP_FORMATSSUPPLIER"FormatsSupplier"))
688 nColType = TYPE_FORMATTEDFIELD4;
689 }
690 }
691
692 PopupMenu* pControlMenu = rMenu.GetPopupMenu(rMenu.GetItemId("change"));
693 if (pControlMenu)
694 {
695 SetMenuItem(RID_SVXBMP_EDITBOX"res/sx10599.png", FM_COL_TEXTFIELD"TextField""1", *pControlMenu, bDesignMode && (nColType != TYPE_TEXTFIELD8));
696 SetMenuItem(RID_SVXBMP_CHECKBOX"res/sx10596.png", FM_COL_CHECKBOX"CheckBox""1", *pControlMenu, bDesignMode && (nColType != TYPE_CHECKBOX0));
697 SetMenuItem(RID_SVXBMP_COMBOBOX"res/sx10600.png", FM_COL_COMBOBOX"ComboBox""1", *pControlMenu, bDesignMode && (nColType != TYPE_COMBOBOX1));
698 SetMenuItem(RID_SVXBMP_LISTBOX"res/sx10600.png", FM_COL_LISTBOX"ListBox""1", *pControlMenu, bDesignMode && (nColType != TYPE_LISTBOX5));
699 SetMenuItem(RID_SVXBMP_DATEFIELD"res/sx10704.png", FM_COL_DATEFIELD"DateField""1", *pControlMenu, bDesignMode && (nColType != TYPE_DATEFIELD3));
700 SetMenuItem(RID_SVXBMP_TIMEFIELD"res/sx10705.png", FM_COL_TIMEFIELD"TimeField""1", *pControlMenu, bDesignMode && (nColType != TYPE_TIMEFIELD9));
701 SetMenuItem(RID_SVXBMP_NUMERICFIELD"res/sx10706.png", FM_COL_NUMERICFIELD"NumericField""1", *pControlMenu, bDesignMode && (nColType != TYPE_NUMERICFIELD6));
702 SetMenuItem(RID_SVXBMP_CURRENCYFIELD"res/sx10707.png", FM_COL_CURRENCYFIELD"CurrencyField""1", *pControlMenu, bDesignMode && (nColType != TYPE_CURRENCYFIELD2));
703 SetMenuItem(RID_SVXBMP_PATTERNFIELD"res/sx10708.png", FM_COL_PATTERNFIELD"PatternField""1", *pControlMenu, bDesignMode && (nColType != TYPE_PATTERNFIELD7));
704 SetMenuItem(RID_SVXBMP_FORMATTEDFIELD"res/sx10728.png", FM_COL_FORMATTEDFIELD"FormattedField""1", *pControlMenu, bDesignMode && (nColType != TYPE_FORMATTEDFIELD4));
705 }
706 rMenu.EnableItem(rMenu.GetItemId("change"), bDesignMode && bMarked && xCols.is());
707 }
708 else
709 rMenu.EnableItem(rMenu.GetItemId("change"), false);
710
711 rMenu.EnableItem(rMenu.GetItemId("insert"), bDesignMode && xCols.is());
712 rMenu.EnableItem(rMenu.GetItemId("delete"), bDesignMode && bMarked && xCols.is());
713 rMenu.EnableItem(rMenu.GetItemId("column"), bDesignMode && bMarked && xCols.is());
714
715 PopupMenu* pShowColsMenu = rMenu.GetPopupMenu(rMenu.GetItemId("show"));
716 sal_uInt16 nHiddenCols = 0;
717 if (pShowColsMenu)
718 {
719 if (xCols.is())
720 {
721 // check for hidden cols
722 Reference< css::beans::XPropertySet > xCurCol;
723 Any aHidden,aName;
724 for (sal_Int32 i=0; i<xCols->getCount(); ++i)
725 {
726 xCurCol.set(xCols->getByIndex(i), css::uno::UNO_QUERY);
727 DBG_ASSERT(xCurCol.is(), "FmGridHeader::PreExecuteColumnContextMenu : the Peer has invalid columns !")do { if (true && (!(xCurCol.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "727" ": "), "%s", "FmGridHeader::PreExecuteColumnContextMenu : the Peer has invalid columns !"
); } } while (false)
;
728 aHidden = xCurCol->getPropertyValue(FM_PROP_HIDDEN"Hidden");
729 DBG_ASSERT(aHidden.getValueType().getTypeClass() == TypeClass_BOOLEAN,do { if (true && (!(aHidden.getValueType().getTypeClass
() == TypeClass_BOOLEAN))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "730" ": "), "%s", "FmGridHeader::PreExecuteColumnContextMenu : the property 'hidden' should be boolean !"
); } } while (false)
730 "FmGridHeader::PreExecuteColumnContextMenu : the property 'hidden' should be boolean !")do { if (true && (!(aHidden.getValueType().getTypeClass
() == TypeClass_BOOLEAN))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "730" ": "), "%s", "FmGridHeader::PreExecuteColumnContextMenu : the property 'hidden' should be boolean !"
); } } while (false)
;
731 if (::comphelper::getBOOL(aHidden))
732 {
733 // put the column name into the 'show col' menu
734 if (nHiddenCols < 16)
735 { // (only the first 16 items to keep the menu rather small)
736 aName = xCurCol->getPropertyValue(FM_PROP_LABEL"Label");
737 pShowColsMenu->InsertItem(nHiddenCols + 1, ::comphelper::getString(aName),
738 MenuItemBits::NONE, OString(), nHiddenCols);
739 // the ID is arbitrary, but should be unique within the whole menu
740 }
741 ++nHiddenCols;
742 }
743 }
744 }
745 pShowColsMenu->EnableItem(pShowColsMenu->GetItemId("more"), xCols.is() && (nHiddenCols > 16));
746 pShowColsMenu->EnableItem(pShowColsMenu->GetItemId("all"), xCols.is() && (nHiddenCols > 0));
747 }
748
749 // allow the 'hide column' item ?
750 bool bAllowHide = bMarked; // a column is marked
751 bAllowHide = bAllowHide || (!bDesignMode && (nPos != sal_uInt16(-1))); // OR we are in alive mode and have hit a column
752 bAllowHide = bAllowHide && xCols.is(); // AND we have a column container
753 bAllowHide = bAllowHide && (xCols->getCount()-nHiddenCols > 1); // AND there are at least two visible columns
754 rMenu.EnableItem(rMenu.GetItemId("hide"), bAllowHide);
755
756 if (!bMarked)
757 return;
758
759 SfxViewFrame* pCurrentFrame = SfxViewFrame::Current();
760 // ask the bindings of the current view frame (which should be the one we're residing in) for the state
761 if (pCurrentFrame)
762 {
763 std::unique_ptr<SfxPoolItem> pItem;
764 SfxItemState eState = pCurrentFrame->GetBindings().QueryState(SID_FM_CTL_PROPERTIES( 10000 + 613 ), pItem);
765
766 if (eState >= SfxItemState::DEFAULT && pItem != nullptr)
767 {
768 bool bChecked = dynamic_cast<const SfxBoolItem*>( pItem.get()) != nullptr && static_cast<SfxBoolItem*>(pItem.get())->GetValue();
769 rMenu.CheckItem("column", bChecked);
770 }
771 }
772}
773
774namespace {
775
776enum InspectorAction { eOpenInspector, eCloseInspector, eUpdateInspector, eNone };
777
778}
779
780void FmGridHeader::PostExecuteColumnContextMenu(sal_uInt16 nColId, const PopupMenu& rMenu, sal_uInt16 nExecutionResult)
781{
782 Reference< css::container::XIndexContainer > xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
783 sal_uInt16 nPos = GetModelColumnPos(nColId);
784
785 OUString aFieldType;
786 bool bReplace = false;
787 InspectorAction eInspectorAction = eNone;
788
789 OString sExecutionResult = rMenu.GetCurItemIdent();
790 if (sExecutionResult.isEmpty())
6
Taking false branch
791 {
792 PopupMenu* pMenu = rMenu.GetPopupMenu(rMenu.GetItemId("insert"));
793 if (pMenu)
794 sExecutionResult = pMenu->GetCurItemIdent();
795 }
796 if (sExecutionResult.isEmpty())
7
Taking false branch
797 {
798 PopupMenu* pMenu = rMenu.GetPopupMenu(rMenu.GetItemId("change"));
799 if (pMenu)
800 sExecutionResult = pMenu->GetCurItemIdent();
801 }
802 if (sExecutionResult.isEmpty())
8
Taking false branch
803 {
804 PopupMenu* pMenu = rMenu.GetPopupMenu(rMenu.GetItemId("show"));
805 if (pMenu)
806 sExecutionResult = pMenu->GetCurItemIdent();
807 }
808
809 if (sExecutionResult == "delete")
9
Taking false branch
810 {
811 Reference< XInterface > xCol(
812 xCols->getByIndex(nPos), css::uno::UNO_QUERY);
813 xCols->removeByIndex(nPos);
814 ::comphelper::disposeComponent(xCol);
815 }
816 else if (sExecutionResult == "hide")
10
Taking false branch
817 {
818 Reference< css::beans::XPropertySet > xCurCol( xCols->getByIndex(nPos), css::uno::UNO_QUERY);
819 xCurCol->setPropertyValue(FM_PROP_HIDDEN"Hidden", makeAny(true));
820 }
821 else if (sExecutionResult == "column")
11
Taking false branch
822 {
823 eInspectorAction = rMenu.IsItemChecked(rMenu.GetItemId("column")) ? eOpenInspector : eCloseInspector;
824 }
825 else if (sExecutionResult.startsWith(FM_COL_TEXTFIELD"TextField"))
12
Taking false branch
826 {
827 if (sExecutionResult != FM_COL_TEXTFIELD"TextField")
828 bReplace = true;
829 aFieldType = FM_COL_TEXTFIELD"TextField";
830 }
831 else if (sExecutionResult.startsWith(FM_COL_COMBOBOX"ComboBox"))
13
Taking false branch
832 {
833 if (sExecutionResult != FM_COL_COMBOBOX"ComboBox")
834 bReplace = true;
835 aFieldType = FM_COL_COMBOBOX"ComboBox";
836 }
837 else if (sExecutionResult.startsWith(FM_COL_LISTBOX"ListBox"))
14
Taking false branch
838 {
839 if (sExecutionResult != FM_COL_LISTBOX"ListBox")
840 bReplace = true;
841 aFieldType = FM_COL_LISTBOX"ListBox";
842 }
843 else if (sExecutionResult.startsWith(FM_COL_CHECKBOX"CheckBox"))
15
Taking false branch
844 {
845 if (sExecutionResult != FM_COL_CHECKBOX"CheckBox")
846 bReplace = true;
847 aFieldType = FM_COL_CHECKBOX"CheckBox";
848 }
849 else if (sExecutionResult.startsWith(FM_COL_DATEFIELD"DateField"))
16
Taking false branch
850 {
851 if (sExecutionResult != FM_COL_DATEFIELD"DateField")
852 bReplace = true;
853 aFieldType = FM_COL_DATEFIELD"DateField";
854 }
855 else if (sExecutionResult.startsWith(FM_COL_TIMEFIELD"TimeField"))
17
Taking false branch
856 {
857 if (sExecutionResult != FM_COL_TIMEFIELD"TimeField")
858 bReplace = true;
859 aFieldType = FM_COL_TIMEFIELD"TimeField";
860 }
861 else if (sExecutionResult.startsWith(FM_COL_NUMERICFIELD"NumericField"))
18
Taking false branch
862 {
863 if (sExecutionResult != FM_COL_NUMERICFIELD"NumericField")
864 bReplace = true;
865 aFieldType = FM_COL_NUMERICFIELD"NumericField";
866 }
867 else if (sExecutionResult.startsWith(FM_COL_CURRENCYFIELD"CurrencyField"))
19
Taking false branch
868 {
869 if (sExecutionResult != FM_COL_CURRENCYFIELD"CurrencyField")
870 bReplace = true;
871 aFieldType = FM_COL_CURRENCYFIELD"CurrencyField";
872 }
873 else if (sExecutionResult.startsWith(FM_COL_PATTERNFIELD"PatternField"))
20
Taking false branch
874 {
875 if (sExecutionResult != FM_COL_PATTERNFIELD"PatternField")
876 bReplace = true;
877 aFieldType = FM_COL_PATTERNFIELD"PatternField";
878 }
879 else if (sExecutionResult.startsWith(FM_COL_FORMATTEDFIELD"FormattedField"))
21
Taking false branch
880 {
881 if (sExecutionResult != FM_COL_FORMATTEDFIELD"FormattedField")
882 bReplace = true;
883 aFieldType = FM_COL_FORMATTEDFIELD"FormattedField";
884 }
885 else if (sExecutionResult == "more")
22
Taking true branch
886 {
887 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
888 ScopedVclPtr<AbstractFmShowColsDialog> pDlg(pFact->CreateFmShowColsDialog(GetFrameWeld()));
23
Calling constructor for 'ScopedVclPtr<AbstractFmShowColsDialog>'
30
Returning from constructor for 'ScopedVclPtr<AbstractFmShowColsDialog>'
31
Calling implicit destructor for 'VclPtr<AbstractFmShowColsDialog>'
32
Calling '~Reference'
39
Returning from '~Reference'
40
Returning from destructor for 'VclPtr<AbstractFmShowColsDialog>'
889 pDlg->SetColumns(xCols);
41
Calling 'VclPtr::operator->'
890 pDlg->Execute();
891 }
892 else if (sExecutionResult == "all")
893 {
894 // just iterate through all the cols ...
895 Reference< css::beans::XPropertySet > xCurCol;
896 for (sal_Int32 i=0; i<xCols->getCount(); ++i)
897 {
898 xCurCol.set(xCols->getByIndex(i), css::uno::UNO_QUERY);
899 xCurCol->setPropertyValue(FM_PROP_HIDDEN"Hidden", makeAny(false));
900 }
901 // TODO : there must be a more clever way to do this...
902 // with the above the view is updated after every single model update ...
903 }
904 else if (nExecutionResult>0 && nExecutionResult<=16)
905 { // it was a "show column/<colname>" command (there are at most 16 such items)
906 // search the nExecutionResult'th hidden col
907 Reference< css::beans::XPropertySet > xCurCol;
908 for (sal_Int32 i=0; i<xCols->getCount() && nExecutionResult; ++i)
909 {
910 xCurCol.set(xCols->getByIndex(i), css::uno::UNO_QUERY);
911 Any aHidden = xCurCol->getPropertyValue(FM_PROP_HIDDEN"Hidden");
912 if (::comphelper::getBOOL(aHidden))
913 if (!--nExecutionResult)
914 {
915 xCurCol->setPropertyValue(FM_PROP_HIDDEN"Hidden", makeAny(false));
916 break;
917 }
918 }
919 }
920
921 if ( !aFieldType.isEmpty() )
922 {
923 try
924 {
925 Reference< XGridColumnFactory > xFactory( xCols, UNO_QUERY_THROW );
926 Reference< XPropertySet > xNewCol( xFactory->createColumn( aFieldType ), UNO_SET_THROW );
927
928 if ( bReplace )
929 {
930 // rescue over a few properties
931 Reference< XPropertySet > xReplaced( xCols->getByIndex( nPos ), UNO_QUERY );
932
933 TransferFormComponentProperties(
934 xReplaced, xNewCol, Application::GetSettings().GetUILanguageTag().getLocale() );
935
936 xCols->replaceByIndex( nPos, makeAny( xNewCol ) );
937 ::comphelper::disposeComponent( xReplaced );
938
939 eInspectorAction = eUpdateInspector;
940 }
941 else
942 {
943 FormControlFactory factory;
944
945 OUString sLabel = FormControlFactory::getDefaultUniqueName_ByComponentType(
946 Reference< XNameAccess >( xCols, UNO_QUERY_THROW ), xNewCol );
947 xNewCol->setPropertyValue( FM_PROP_LABEL"Label", makeAny( sLabel ) );
948 xNewCol->setPropertyValue( FM_PROP_NAME"Name", makeAny( sLabel ) );
949
950 factory.initializeControlModel( DocumentClassification::classifyHostDocument( xCols ), xNewCol );
951
952 xCols->insertByIndex( nPos, makeAny( xNewCol ) );
953 }
954 }
955 catch( const Exception& )
956 {
957 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "957" ": ", "svx" );
;
958 }
959 }
960
961 SfxViewFrame* pCurrentFrame = SfxViewFrame::Current();
962 OSL_ENSURE( pCurrentFrame, "FmGridHeader::PostExecuteColumnContextMenu: no view frame -> no bindings -> no property browser!" )do { if (true && (!(pCurrentFrame))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "962" ": "), "%s", "FmGridHeader::PostExecuteColumnContextMenu: no view frame -> no bindings -> no property browser!"
); } } while (false)
;
963 if ( !pCurrentFrame )
964 return;
965
966 if ( eInspectorAction == eUpdateInspector )
967 {
968 if ( !pCurrentFrame->HasChildWindow( SID_FM_SHOW_PROPERTIES( 10000 + 635 ) ) )
969 eInspectorAction = eNone;
970 }
971
972 if ( eInspectorAction != eNone )
973 {
974 SfxBoolItem aShowItem( SID_FM_SHOW_PROPERTIES( 10000 + 635 ), eInspectorAction != eCloseInspector );
975
976 pCurrentFrame->GetBindings().GetDispatcher()->ExecuteList(
977 SID_FM_SHOW_PROPERTY_BROWSER( 10000 + 703 ), SfxCallMode::ASYNCHRON,
978 { &aShowItem });
979 }
980}
981
982void FmGridHeader::triggerColumnContextMenu( const ::Point& _rPreferredPos )
983{
984 // the affected col
985 sal_uInt16 nColId = GetItemId( _rPreferredPos );
986
987 // the menu
988 VclBuilder aBuilder(nullptr, AllSettings::GetUIRootDir(), "svx/ui/colsmenu.ui", "");
989 VclPtr<PopupMenu> aContextMenu(aBuilder.get_menu("menu"));
990
991 // let derivatives modify the menu
992 PreExecuteColumnContextMenu( nColId, *aContextMenu );
993 aContextMenu->RemoveDisabledEntries( true, true );
994
995 // execute the menu
996 sal_uInt16 nResult = aContextMenu->Execute( this, _rPreferredPos );
997
998 // let derivatives handle the result
999 PostExecuteColumnContextMenu( nColId, *aContextMenu, nResult );
5
Calling 'FmGridHeader::PostExecuteColumnContextMenu'
1000}
1001
1002void FmGridHeader::Command(const CommandEvent& rEvt)
1003{
1004 switch (rEvt.GetCommand())
1
Control jumps to 'case ContextMenu:' at line 1006
1005 {
1006 case CommandEventId::ContextMenu:
1007 {
1008 if (!rEvt.IsMouseEvent())
2
Assuming the condition is false
3
Taking false branch
1009 return;
1010
1011 triggerColumnContextMenu( rEvt.GetMousePosPixel() );
4
Calling 'FmGridHeader::triggerColumnContextMenu'
1012 }
1013 break;
1014 default:
1015 EditBrowserHeader::Command(rEvt);
1016 }
1017}
1018
1019FmGridControl::FmGridControl(
1020 const Reference< css::uno::XComponentContext >& _rxContext,
1021 vcl::Window* pParent,
1022 FmXGridPeer* _pPeer,
1023 WinBits nBits)
1024 :DbGridControl(_rxContext, pParent, nBits)
1025 ,m_pPeer(_pPeer)
1026 ,m_nCurrentSelectedColumn(-1)
1027 ,m_nMarkedColumnId(BROWSER_INVALIDID((sal_uInt16) 0xFFFF))
1028 ,m_bSelecting(false)
1029 ,m_bInColumnMove(false)
1030{
1031 EnableInteractiveRowHeight( );
1032}
1033
1034void FmGridControl::Command(const CommandEvent& _rEvt)
1035{
1036 if ( CommandEventId::ContextMenu == _rEvt.GetCommand() )
1037 {
1038 FmGridHeader* pMyHeader = static_cast< FmGridHeader* >( GetHeaderBar() );
1039 if ( pMyHeader && !_rEvt.IsMouseEvent() )
1040 { // context menu requested by keyboard
1041 if ( 1 == GetSelectColumnCount() || IsDesignMode() )
1042 {
1043 sal_uInt16 nSelId = GetColumnId(
1044 sal::static_int_cast< sal_uInt16 >( FirstSelectedColumn() ) );
1045 ::tools::Rectangle aColRect( GetFieldRectPixel( 0, nSelId, false ) );
1046
1047 Point aRelativePos( pMyHeader->ScreenToOutputPixel( OutputToScreenPixel( aColRect.TopCenter() ) ) );
1048 pMyHeader->triggerColumnContextMenu(aRelativePos);
1049
1050 // handled
1051 return;
1052 }
1053 }
1054 }
1055
1056 DbGridControl::Command( _rEvt );
1057}
1058
1059// css::beans::XPropertyChangeListener
1060void FmGridControl::propertyChange(const css::beans::PropertyChangeEvent& evt)
1061{
1062 if (evt.PropertyName == FM_PROP_ROWCOUNT"RowCount")
1063 {
1064 // if we're not in the main thread call AdjustRows asynchronously
1065 implAdjustInSolarThread(true);
1066 return;
1067 }
1068
1069 const DbGridRowRef& xRow = GetCurrentRow();
1070 // no adjustment of the properties is carried out during positioning
1071 Reference<XPropertySet> xSet(evt.Source,UNO_QUERY);
1072 if (!(xRow.is() && (::cppu::any2bool(xSet->getPropertyValue(FM_PROP_ISNEW"IsNew"))|| CompareBookmark(getDataSource()->getBookmark(), xRow->GetBookmark()))))
1073 return;
1074
1075 if (evt.PropertyName == FM_PROP_ISMODIFIED"IsModified")
1076 {
1077 // modified or clean ?
1078 GridRowStatus eStatus = ::comphelper::getBOOL(evt.NewValue) ? GridRowStatus::Modified : GridRowStatus::Clean;
1079 if (eStatus != xRow->GetStatus())
1080 {
1081 xRow->SetStatus(eStatus);
1082 SolarMutexGuard aGuard;
1083 RowModified(GetCurrentPos());
1084 }
1085 }
1086}
1087
1088void FmGridControl::SetDesignMode(bool bMode)
1089{
1090 bool bOldMode = IsDesignMode();
1091 DbGridControl::SetDesignMode(bMode);
1092 if (bOldMode == bMode)
1093 return;
1094
1095 if (!bMode)
1096 {
1097 // cancel selection
1098 markColumn(USHRT_MAX(32767 *2 +1));
1099 }
1100 else
1101 {
1102 Reference< css::container::XIndexContainer > xColumns(GetPeer()->getColumns());
1103 Reference< css::view::XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY);
1104 if (xSelSupplier.is())
1105 {
1106 Any aSelection = xSelSupplier->getSelection();
1107 Reference< css::beans::XPropertySet > xColumn;
1108 if (aSelection.getValueType().getTypeClass() == TypeClass_INTERFACE)
1109 xColumn.set(aSelection, css::uno::UNO_QUERY);
1110 Reference< XInterface > xCurrent;
1111 for (sal_Int32 i=0; i<xColumns->getCount(); ++i)
1112 {
1113 xCurrent.set(xColumns->getByIndex(i), css::uno::UNO_QUERY);
1114 if (xCurrent == xColumn)
1115 {
1116 markColumn(GetColumnIdFromModelPos(i));
1117 break;
1118 }
1119 }
1120 }
1121 }
1122}
1123
1124void FmGridControl::DeleteSelectedRows()
1125{
1126 if (!m_pSeekCursor)
1127 return;
1128
1129 // how many rows are selected?
1130 sal_Int32 nSelectedRows = GetSelectRowCount();
1131
1132 // the current line should be deleted but it is currently in edit mode
1133 if ( IsCurrentAppending() )
1134 return;
1135 // is the insert row selected
1136 if (GetEmptyRow().is() && IsRowSelected(GetRowCount() - 1))
1137 nSelectedRows -= 1;
1138
1139 // nothing to do
1140 if (nSelectedRows <= 0)
1141 return;
1142
1143 // try to confirm the delete
1144 Reference< css::frame::XDispatchProvider > xDispatcher = static_cast<css::frame::XDispatchProvider*>(GetPeer());
1145 if (xDispatcher.is())
1146 {
1147 css::util::URL aUrl;
1148 aUrl.Complete = FMURL_CONFIRM_DELETION".uno:FormSlots/ConfirmDeletion";
1149 Reference< css::util::XURLTransformer > xTransformer(
1150 css::util::URLTransformer::create(::comphelper::getProcessComponentContext()) );
1151 xTransformer->parseStrict( aUrl );
1152
1153 Reference< css::frame::XDispatch > xDispatch = xDispatcher->queryDispatch(aUrl, OUString(), 0);
1154 Reference< css::form::XConfirmDeleteListener > xConfirm(xDispatch, UNO_QUERY);
1155 if (xConfirm.is())
1156 {
1157 css::sdb::RowChangeEvent aEvent;
1158 aEvent.Source = Reference< XInterface >(*getDataSource());
1159 aEvent.Rows = nSelectedRows;
1160 aEvent.Action = css::sdb::RowChangeAction::DELETE;
1161 if (!xConfirm->confirmDelete(aEvent))
1162 return;
1163 }
1164 }
1165
1166 const MultiSelection* pRowSelection = GetSelection();
1167 if ( pRowSelection && pRowSelection->IsAllSelected() )
1168 {
1169 BeginCursorAction();
1170 CursorWrapper* pCursor = getDataSource();
1171 Reference< XResultSetUpdate > xUpdateCursor(Reference< XInterface >(*pCursor), UNO_QUERY);
1172 try
1173 {
1174 pCursor->beforeFirst();
1175 while( pCursor->next() )
1176 xUpdateCursor->deleteRow();
1177
1178 SetUpdateMode(false);
1179 SetNoSelection();
1180
1181 xUpdateCursor->moveToInsertRow();
1182 }
1183 catch(const Exception&)
1184 {
1185 TOOLS_WARN_EXCEPTION("svx", "Exception caught while deleting rows!")do { css::uno::Any tools_warn_exception( DbgGetCaughtException
() ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "svx")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Exception caught while deleting rows!" << " "
<< exceptionToString(tools_warn_exception)) == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1185" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Exception caught while deleting rows!"
<< " " << exceptionToString(tools_warn_exception
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Exception caught while deleting rows!" << " "
<< exceptionToString(tools_warn_exception); ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1185" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Exception caught while deleting rows!" << " "
<< exceptionToString(tools_warn_exception)) == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1185" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Exception caught while deleting rows!"
<< " " << exceptionToString(tools_warn_exception
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Exception caught while deleting rows!" << " "
<< exceptionToString(tools_warn_exception); ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1185" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false); } while (false)
;
1186 }
1187 // adapt to the data cursor
1188 AdjustDataSource(true);
1189 EndCursorAction();
1190 SetUpdateMode(true);
1191 }
1192 else
1193 {
1194 Reference< css::sdbcx::XDeleteRows > xDeleteThem(Reference< XInterface >(*getDataSource()), UNO_QUERY);
1195
1196 // collect the bookmarks of the selected rows
1197 Sequence < Any> aBookmarks = getSelectionBookmarks();
1198
1199 // determine the next row to position after deletion
1200 Any aBookmark;
1201 bool bNewPos = false;
1202 // if the current row isn't selected we take the row as row after deletion
1203 OSL_ENSURE( GetCurrentRow().is(), "FmGridControl::DeleteSelectedRows: no current row here?" )do { if (true && (!(GetCurrentRow().is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1203" ": "), "%s", "FmGridControl::DeleteSelectedRows: no current row here?"
); } } while (false)
;
1204 // crash reports suggest it can happen we don't have a current row - how?
1205 // #154303# / 2008-04-23 / frank.schoenheit@sun.com
1206 if ( !IsRowSelected( GetCurrentPos() ) && !IsCurrentAppending() && GetCurrentRow().is() )
1207 {
1208 aBookmark = GetCurrentRow()->GetBookmark();
1209 bNewPos = true;
1210 }
1211 else
1212 {
1213 // we look for the first row after the selected block for selection
1214 long nIdx = LastSelectedRow() + 1;
1215 if (nIdx < GetRowCount() - 1)
1216 {
1217 // there is a next row to position on
1218 if (SeekCursor(nIdx))
1219 {
1220 GetSeekRow()->SetState(m_pSeekCursor.get(), true);
1221
1222 bNewPos = true;
1223 // if it's not the row for inserting we keep the bookmark
1224 if (!IsInsertionRow(nIdx))
1225 aBookmark = m_pSeekCursor->getBookmark();
1226 }
1227 }
1228 else
1229 {
1230 // we look for the first row before the selected block for selection after deletion
1231 nIdx = FirstSelectedRow() - 1;
1232 if (nIdx >= 0 && SeekCursor(nIdx))
1233 {
1234 GetSeekRow()->SetState(m_pSeekCursor.get(), true);
1235
1236 bNewPos = true;
1237 aBookmark = m_pSeekCursor->getBookmark();
1238 }
1239 }
1240 }
1241
1242 // Are all rows selected?
1243 // Second condition if no insertion line exists
1244 bool bAllSelected = GetTotalCount() == nSelectedRows || GetRowCount() == nSelectedRows;
1245
1246 BeginCursorAction();
1247
1248 // now delete the row
1249 Sequence<sal_Int32> aDeletedRows;
1250 SetUpdateMode( false );
1251 try
1252 {
1253 aDeletedRows = xDeleteThem->deleteRows(aBookmarks);
1254 }
1255 catch(SQLException&)
1256 {
1257 }
1258 SetUpdateMode( true );
1259
1260 // how many rows are deleted?
1261 sal_Int32 nDeletedRows = static_cast<sal_Int32>(std::count_if(aDeletedRows.begin(), aDeletedRows.end(),
1262 [](const sal_Int32 nRow) { return nRow != 0; }));
1263
1264 // have rows been deleted?
1265 if (nDeletedRows)
1266 {
1267 SetUpdateMode(false);
1268 SetNoSelection();
1269 try
1270 {
1271 // did we delete all the rows than try to move to the next possible row
1272 if (nDeletedRows == aDeletedRows.getLength())
1273 {
1274 // there exists a new position to move on
1275 if (bNewPos)
1276 {
1277 if (aBookmark.hasValue())
1278 getDataSource()->moveToBookmark(aBookmark);
1279 // no valid bookmark so move to the insert row
1280 else
1281 {
1282 Reference< XResultSetUpdate > xUpdateCursor(Reference< XInterface >(*m_pDataCursor), UNO_QUERY);
1283 xUpdateCursor->moveToInsertRow();
1284 }
1285 }
1286 else
1287 {
1288 Reference< css::beans::XPropertySet > xSet(Reference< XInterface >(*m_pDataCursor), UNO_QUERY);
1289
1290 sal_Int32 nRecordCount(0);
1291 xSet->getPropertyValue(FM_PROP_ROWCOUNT"RowCount") >>= nRecordCount;
1292 if ( m_pDataCursor->rowDeleted() )
1293 --nRecordCount;
1294
1295 // there are no rows left and we have an insert row
1296 if (!nRecordCount && GetEmptyRow().is())
1297 {
1298 Reference< XResultSetUpdate > xUpdateCursor(Reference< XInterface >(*m_pDataCursor), UNO_QUERY);
1299 xUpdateCursor->moveToInsertRow();
1300 }
1301 else if (nRecordCount)
1302 // move to the first row
1303 getDataSource()->first();
1304 }
1305 }
1306 // not all the rows where deleted, so move to the first row which remained in the resultset
1307 else
1308 {
1309 auto pRow = std::find(aDeletedRows.begin(), aDeletedRows.end(), 0);
1310 if (pRow != aDeletedRows.end())
1311 {
1312 auto i = static_cast<sal_Int32>(std::distance(aDeletedRows.begin(), pRow));
1313 getDataSource()->moveToBookmark(aBookmarks[i]);
1314 }
1315 }
1316 }
1317 catch(const Exception&)
1318 {
1319 try
1320 {
1321 // positioning went wrong so try to move to the first row
1322 getDataSource()->first();
1323 }
1324 catch(const Exception&)
1325 {
1326 }
1327 }
1328
1329 // adapt to the data cursor
1330 AdjustDataSource(true);
1331
1332 // not all rows could be deleted;
1333 // never select again there the ones that could not be deleted
1334 if (nDeletedRows < nSelectedRows)
1335 {
1336 // were all selected
1337 if (bAllSelected)
1338 {
1339 SelectAll();
1340 if (IsInsertionRow(GetRowCount() - 1)) // not the insertion row
1341 SelectRow(GetRowCount() - 1, false);
1342 }
1343 else
1344 {
1345 // select the remaining rows
1346 for (const sal_Int32 nSuccess : aDeletedRows)
1347 {
1348 try
1349 {
1350 if (!nSuccess)
1351 {
1352 m_pSeekCursor->moveToBookmark(m_pDataCursor->getBookmark());
1353 SetSeekPos(m_pSeekCursor->getRow() - 1);
1354 SelectRow(GetSeekPos());
1355 }
1356 }
1357 catch(const Exception&)
1358 {
1359 // keep the seekpos in all cases
1360 SetSeekPos(m_pSeekCursor->getRow() - 1);
1361 }
1362 }
1363 }
1364 }
1365
1366 EndCursorAction();
1367 SetUpdateMode(true);
1368 }
1369 else // row could not be deleted
1370 {
1371 EndCursorAction();
1372 try
1373 {
1374 // currentrow is the insert row?
1375 if (!IsCurrentAppending())
1376 getDataSource()->refreshRow();
1377 }
1378 catch(const Exception&)
1379 {
1380 }
1381 }
1382 }
1383
1384 // if there is no selection anymore we can start editing
1385 if (!GetSelectRowCount())
1386 ActivateCell();
1387}
1388
1389// XCurrentRecordListener
1390void FmGridControl::positioned()
1391{
1392 SAL_INFO("svx.fmcomp", "FmGridControl::positioned")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "FmGridControl::positioned"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1392" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "FmGridControl::positioned"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"FmGridControl::positioned"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1392" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "FmGridControl::positioned") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1392" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "FmGridControl::positioned"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"FmGridControl::positioned"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1392" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1393 // position on the data source (force it to be done in the main thread)
1394 implAdjustInSolarThread(false);
1395}
1396
1397bool FmGridControl::commit()
1398{
1399 // execute commit only if an update is not already executed by the
1400 // css::form::component::GridControl
1401 if (!IsUpdating())
1402 {
1403 if (Controller().is() && Controller()->IsValueChangedFromSaved())
1404 {
1405 if (!SaveModified())
1406 return false;
1407 }
1408 }
1409 return true;
1410}
1411
1412void FmGridControl::inserted()
1413{
1414 const DbGridRowRef& xRow = GetCurrentRow();
1415 if (!xRow.is())
1416 return;
1417
1418 // line has been inserted, then reset the status and mode
1419 xRow->SetState(m_pDataCursor.get(), false);
1420 xRow->SetNew(false);
1421
1422}
1423
1424VclPtr<BrowserHeader> FmGridControl::imp_CreateHeaderBar(BrowseBox* pParent)
1425{
1426 DBG_ASSERT( pParent == this, "FmGridControl::imp_CreateHeaderBar: parent?" )do { if (true && (!(pParent == this))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1426" ": "), "%s", "FmGridControl::imp_CreateHeaderBar: parent?"
); } } while (false)
;
1427 return VclPtr<FmGridHeader>::Create( pParent );
1428}
1429
1430void FmGridControl::markColumn(sal_uInt16 nId)
1431{
1432 if (!(GetHeaderBar() && m_nMarkedColumnId != nId))
1433 return;
1434
1435 // deselect
1436 if (m_nMarkedColumnId != BROWSER_INVALIDID((sal_uInt16) 0xFFFF))
1437 {
1438 HeaderBarItemBits aBits = GetHeaderBar()->GetItemBits(m_nMarkedColumnId) & ~HeaderBarItemBits::FLAT;
1439 GetHeaderBar()->SetItemBits(m_nMarkedColumnId, aBits);
1440 }
1441
1442
1443 if (nId != BROWSER_INVALIDID((sal_uInt16) 0xFFFF))
1444 {
1445 HeaderBarItemBits aBits = GetHeaderBar()->GetItemBits(nId) | HeaderBarItemBits::FLAT;
1446 GetHeaderBar()->SetItemBits(nId, aBits);
1447 }
1448 m_nMarkedColumnId = nId;
1449}
1450
1451bool FmGridControl::isColumnMarked(sal_uInt16 nId) const
1452{
1453 return m_nMarkedColumnId == nId;
1454}
1455
1456long FmGridControl::QueryMinimumRowHeight()
1457{
1458 long const nMinimalLogicHeight = 20; // 0.2 cm
1459 long nMinimalPixelHeight = LogicToPixel(Point(0, nMinimalLogicHeight), MapMode(MapUnit::Map10thMM)).Y();
1460 return CalcZoom( nMinimalPixelHeight );
1461}
1462
1463void FmGridControl::RowHeightChanged()
1464{
1465 DbGridControl::RowHeightChanged();
1466
1467 Reference< XPropertySet > xModel( GetPeer()->getColumns(), UNO_QUERY );
1468 DBG_ASSERT( xModel.is(), "FmGridControl::RowHeightChanged: no model!" )do { if (true && (!(xModel.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1468" ": "), "%s", "FmGridControl::RowHeightChanged: no model!"
); } } while (false)
;
1469 if ( !xModel.is() )
1470 return;
1471
1472 try
1473 {
1474 sal_Int32 nUnzoomedPixelHeight = CalcReverseZoom( GetDataRowHeight() );
1475 Any aProperty = makeAny( static_cast<sal_Int32>(PixelToLogic( Point(0, nUnzoomedPixelHeight), MapMode(MapUnit::Map10thMM)).Y()) );
1476 xModel->setPropertyValue( FM_PROP_ROWHEIGHT"RowHeight", aProperty );
1477 }
1478 catch( const Exception& )
1479 {
1480 TOOLS_WARN_EXCEPTION( "svx", "FmGridControl::RowHeightChanged" )do { css::uno::Any tools_warn_exception( DbgGetCaughtException
() ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "svx")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "FmGridControl::RowHeightChanged" << " " <<
exceptionToString(tools_warn_exception)) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1480" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "FmGridControl::RowHeightChanged" <<
" " << exceptionToString(tools_warn_exception)), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "FmGridControl::RowHeightChanged" << " " <<
exceptionToString(tools_warn_exception); ::sal::detail::log(
(::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1480" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "FmGridControl::RowHeightChanged" << " " <<
exceptionToString(tools_warn_exception)) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1480" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "FmGridControl::RowHeightChanged" <<
" " << exceptionToString(tools_warn_exception)), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "FmGridControl::RowHeightChanged" << " " <<
exceptionToString(tools_warn_exception); ::sal::detail::log(
(::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1480" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false); } while (false)
;
1481 }
1482}
1483
1484void FmGridControl::ColumnResized(sal_uInt16 nId)
1485{
1486 DbGridControl::ColumnResized(nId);
1487
1488 // transfer value to the model
1489 DbGridColumn* pCol = DbGridControl::GetColumns()[ GetModelColumnPos(nId) ].get();
1490 const Reference< css::beans::XPropertySet >& xColModel(pCol->getModel());
1491 if (xColModel.is())
1492 {
1493 Any aWidth;
1494 sal_Int32 nColumnWidth = GetColumnWidth(nId);
1495 nColumnWidth = CalcReverseZoom(nColumnWidth);
1496 // convert to 10THMM
1497 aWidth <<= static_cast<sal_Int32>(PixelToLogic(Point(nColumnWidth, 0), MapMode(MapUnit::Map10thMM)).X());
1498 xColModel->setPropertyValue(FM_PROP_WIDTH"Width", aWidth);
1499 }
1500}
1501
1502void FmGridControl::CellModified()
1503{
1504 DbGridControl::CellModified();
1505 GetPeer()->CellModified();
1506}
1507
1508void FmGridControl::BeginCursorAction()
1509{
1510 DbGridControl::BeginCursorAction();
1511 m_pPeer->stopCursorListening();
1512}
1513
1514void FmGridControl::EndCursorAction()
1515{
1516 m_pPeer->startCursorListening();
1517 DbGridControl::EndCursorAction();
1518}
1519
1520void FmGridControl::ColumnMoved(sal_uInt16 nId)
1521{
1522 m_bInColumnMove = true;
1523
1524 DbGridControl::ColumnMoved(nId);
1525 Reference< css::container::XIndexContainer > xColumns(GetPeer()->getColumns());
1526
1527 if (xColumns.is())
1528 {
1529 // locate the column and move in the model;
1530 // get ColumnPos
1531 DbGridColumn* pCol = DbGridControl::GetColumns()[ GetModelColumnPos(nId) ].get();
1532 Reference< css::beans::XPropertySet > xCol;
1533
1534 // inserting must be based on the column positions
1535 sal_Int32 i;
1536 Reference< XInterface > xCurrent;
1537 for (i = 0; !xCol.is() && i < xColumns->getCount(); i++)
1538 {
1539 xCurrent.set(xColumns->getByIndex(i), css::uno::UNO_QUERY);
1540 if (xCurrent == pCol->getModel())
1541 {
1542 xCol = pCol->getModel();
1543 break;
1544 }
1545 }
1546
1547 DBG_ASSERT(i < xColumns->getCount(), "Wrong css::sdbcx::Index")do { if (true && (!(i < xColumns->getCount())))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1547" ": "), "%s", "Wrong css::sdbcx::Index"); } } while
(false)
;
1548 xColumns->removeByIndex(i);
1549 Any aElement;
1550 aElement <<= xCol;
1551 xColumns->insertByIndex(GetModelColumnPos(nId), aElement);
1552 pCol->setModel(xCol);
1553 // if the column which is shown here is selected ...
1554 if ( isColumnSelected(pCol) )
1555 markColumn(nId); // ... -> mark it
1556 }
1557
1558 m_bInColumnMove = false;
1559}
1560
1561void FmGridControl::InitColumnsByModels(const Reference< css::container::XIndexContainer >& xColumns)
1562{
1563 // reset columns;
1564 // if there is only one HandleColumn, then don't
1565 if (GetModelColCount())
1566 {
1567 RemoveColumns();
1568 InsertHandleColumn();
1569 }
1570
1571 if (!xColumns.is())
1572 return;
1573
1574 SetUpdateMode(false);
1575
1576 // inserting must be based on the column positions
1577 sal_Int32 i;
1578 Any aWidth;
1579 for (i = 0; i < xColumns->getCount(); ++i)
1580 {
1581 Reference< css::beans::XPropertySet > xCol(
1582 xColumns->getByIndex(i), css::uno::UNO_QUERY);
1583
1584 OUString aName(
1585 comphelper::getString(xCol->getPropertyValue(FM_PROP_LABEL"Label")));
1586
1587 aWidth = xCol->getPropertyValue(FM_PROP_WIDTH"Width");
1588 sal_Int32 nWidth = 0;
1589 if (aWidth >>= nWidth)
1590 nWidth = LogicToPixel(Point(nWidth, 0), MapMode(MapUnit::Map10thMM)).X();
1591
1592 AppendColumn(aName, static_cast<sal_uInt16>(nWidth));
1593 DbGridColumn* pCol = DbGridControl::GetColumns()[ i ].get();
1594 pCol->setModel(xCol);
1595 }
1596
1597 // and now remove the hidden columns as well
1598 // (we did not already make it in the upper loop, since we would then have gotten
1599 // problems with the IDs of the columns: AppendColumn allocates them automatically,
1600 // but the column _after_ a hidden one needs an ID increased by one ...)
1601 Any aHidden;
1602 for (i = 0; i < xColumns->getCount(); ++i)
1603 {
1604 Reference< css::beans::XPropertySet > xCol( xColumns->getByIndex(i), css::uno::UNO_QUERY);
1605 aHidden = xCol->getPropertyValue(FM_PROP_HIDDEN"Hidden");
1606 if (::comphelper::getBOOL(aHidden))
1607 HideColumn(GetColumnIdFromModelPos(static_cast<sal_uInt16>(i)));
1608 }
1609
1610 SetUpdateMode(true);
1611}
1612
1613void FmGridControl::InitColumnByField(
1614 DbGridColumn* _pColumn, const Reference< XPropertySet >& _rxColumnModel,
1615 const Reference< XNameAccess >& _rxFieldsByNames, const Reference< XIndexAccess >& _rxFieldsByIndex )
1616{
1617 DBG_ASSERT( _rxFieldsByNames == _rxFieldsByIndex, "FmGridControl::InitColumnByField: invalid container interfaces!" )do { if (true && (!(_rxFieldsByNames == _rxFieldsByIndex
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1617" ": "), "%s", "FmGridControl::InitColumnByField: invalid container interfaces!"
); } } while (false)
;
1618
1619 // lookup the column which belongs to the control source
1620 OUString sFieldName;
1621 _rxColumnModel->getPropertyValue( FM_PROP_CONTROLSOURCE"DataField" ) >>= sFieldName;
1622 Reference< XPropertySet > xField;
1623 _rxColumnModel->getPropertyValue( FM_PROP_BOUNDFIELD"BoundField" ) >>= xField;
1624
1625
1626 if ( !xField.is() && /*sFieldName.getLength() && */_rxFieldsByNames->hasByName( sFieldName ) ) // #i93452# do not check for name length
1627 _rxFieldsByNames->getByName( sFieldName ) >>= xField;
1628
1629 // determine the position of this column
1630 sal_Int32 nFieldPos = -1;
1631 if ( xField.is() )
1632 {
1633 Reference< XPropertySet > xCheck;
1634 sal_Int32 nFieldCount = _rxFieldsByIndex->getCount();
1635 for ( sal_Int32 i = 0; i < nFieldCount; ++i)
1636 {
1637 _rxFieldsByIndex->getByIndex( i ) >>= xCheck;
1638 if ( xField.get() == xCheck.get() )
1639 {
1640 nFieldPos = i;
1641 break;
1642 }
1643 }
1644 }
1645
1646 if ( xField.is() && ( nFieldPos >= 0 ) )
1647 {
1648 // some data types are not allowed
1649 sal_Int32 nDataType = DataType::OTHER;
1650 xField->getPropertyValue( FM_PROP_FIELDTYPE"Type" ) >>= nDataType;
1651
1652 bool bIllegalType = false;
1653 switch ( nDataType )
1654 {
1655 case DataType::BLOB:
1656 case DataType::LONGVARBINARY:
1657 case DataType::BINARY:
1658 case DataType::VARBINARY:
1659 case DataType::OTHER:
1660 bIllegalType = true;
1661 break;
1662 }
1663
1664 if ( bIllegalType )
1665 {
1666 _pColumn->SetObject( static_cast<sal_Int16>(nFieldPos) );
1667 return;
1668 }
1669 }
1670
1671 // the control type is determined by the ColumnServiceName
1672 static const char s_sPropColumnServiceName[] = "ColumnServiceName";
1673 if ( !::comphelper::hasProperty( s_sPropColumnServiceName, _rxColumnModel ) )
1674 return;
1675
1676 _pColumn->setModel( _rxColumnModel );
1677
1678 OUString sColumnServiceName;
1679 _rxColumnModel->getPropertyValue( s_sPropColumnServiceName ) >>= sColumnServiceName;
1680
1681 sal_Int32 nTypeId = getColumnTypeByModelName( sColumnServiceName );
1682 _pColumn->CreateControl( nFieldPos, xField, nTypeId );
1683}
1684
1685void FmGridControl::InitColumnsByFields(const Reference< css::container::XIndexAccess >& _rxFields)
1686{
1687 if ( !_rxFields.is() )
1688 return;
1689
1690 // initialize columns
1691 Reference< XIndexContainer > xColumns( GetPeer()->getColumns() );
1692 Reference< XNameAccess > xFieldsAsNames( _rxFields, UNO_QUERY );
1693
1694 // inserting must be based on the column positions
1695 for (sal_Int32 i = 0; i < xColumns->getCount(); i++)
1696 {
1697 DbGridColumn* pCol = GetColumns()[ i ].get();
1698 OSL_ENSURE(pCol,"No grid column!")do { if (true && (!(pCol))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1698" ": "), "%s", "No grid column!"); } } while (false
)
;
1699 if ( pCol )
1700 {
1701 Reference< XPropertySet > xColumnModel(
1702 xColumns->getByIndex( i ), css::uno::UNO_QUERY);
1703
1704 InitColumnByField( pCol, xColumnModel, xFieldsAsNames, _rxFields );
1705 }
1706 }
1707}
1708
1709void FmGridControl::HideColumn(sal_uInt16 nId)
1710{
1711 DbGridControl::HideColumn(nId);
1712
1713 sal_uInt16 nPos = GetModelColumnPos(nId);
1714 if (nPos == sal_uInt16(-1))
1715 return;
1716
1717 DbGridColumn* pColumn = GetColumns()[ nPos ].get();
1718 if (pColumn->IsHidden())
1719 GetPeer()->columnHidden(pColumn);
1720
1721 if (nId == m_nMarkedColumnId)
1722 m_nMarkedColumnId = sal_uInt16(-1);
1723}
1724
1725bool FmGridControl::isColumnSelected(DbGridColumn const * _pColumn)
1726{
1727 OSL_ENSURE(_pColumn,"Column can not be null!")do { if (true && (!(_pColumn))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1727" ": "), "%s", "Column can not be null!"); } } while
(false)
;
1728 bool bSelected = false;
1729 // if the column which is shown here is selected ...
1730 Reference< css::view::XSelectionSupplier > xSelSupplier(GetPeer()->getColumns(), UNO_QUERY);
1731 if ( xSelSupplier.is() )
1732 {
1733 Reference< css::beans::XPropertySet > xColumn;
1734 xSelSupplier->getSelection() >>= xColumn;
1735 bSelected = (xColumn.get() == _pColumn->getModel().get());
1736 }
1737 return bSelected;
1738}
1739
1740void FmGridControl::ShowColumn(sal_uInt16 nId)
1741{
1742 DbGridControl::ShowColumn(nId);
1743
1744 sal_uInt16 nPos = GetModelColumnPos(nId);
1745 if (nPos == sal_uInt16(-1))
1746 return;
1747
1748 DbGridColumn* pColumn = GetColumns()[ nPos ].get();
1749 if (!pColumn->IsHidden())
1750 GetPeer()->columnVisible(pColumn);
1751
1752 // if the column which is shown here is selected ...
1753 if ( isColumnSelected(pColumn) )
1754 markColumn(nId); // ... -> mark it
1755}
1756
1757bool FmGridControl::selectBookmarks(const Sequence< Any >& _rBookmarks)
1758{
1759 SolarMutexGuard aGuard;
1760 // need to lock the SolarMutex so that no paint call disturbs us ...
1761
1762 if ( !m_pSeekCursor )
1763 {
1764 OSL_FAIL( "FmGridControl::selectBookmarks: no seek cursor!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1764" ": "), "%s", "FmGridControl::selectBookmarks: no seek cursor!"
); } } while (false)
;
1765 return false;
1766 }
1767
1768 SetNoSelection();
1769
1770 bool bAllSuccessfull = true;
1771 try
1772 {
1773 for (const Any& rBookmark : _rBookmarks)
1774 {
1775 // move the seek cursor to the row given
1776 if (m_pSeekCursor->moveToBookmark(rBookmark))
1777 SelectRow( m_pSeekCursor->getRow() - 1);
1778 else
1779 bAllSuccessfull = false;
1780 }
1781 }
1782 catch(Exception&)
1783 {
1784 OSL_FAIL("FmGridControl::selectBookmarks: could not move to one of the bookmarks!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1784" ": "), "%s", "FmGridControl::selectBookmarks: could not move to one of the bookmarks!"
); } } while (false)
;
1785 return false;
1786 }
1787
1788 return bAllSuccessfull;
1789}
1790
1791Sequence< Any> FmGridControl::getSelectionBookmarks()
1792{
1793 // lock our update so no paint-triggered seeks interfere ...
1794 SetUpdateMode(false);
1795
1796 sal_Int32 nSelectedRows = GetSelectRowCount(), i = 0;
1797 Sequence< Any> aBookmarks(nSelectedRows);
1798 if ( nSelectedRows )
1799 {
1800 Any* pBookmarks = aBookmarks.getArray();
1801
1802 // (I'm not sure if the problem isn't deeper: The scenario: a large table displayed by a grid with a
1803 // thread-safe cursor (dBase). On loading the sdb-cursor started a counting thread. While this counting progress
1804 // was running, I tried do delete 3 records from within the grid. Deletion caused a SeekCursor, which made a
1805 // m_pSeekCursor->moveRelative and a m_pSeekCursor->getPosition.
1806 // Unfortunately the first call caused a propertyChanged(RECORDCOUNT) which resulted in a repaint of the
1807 // navigation bar and the grid. The latter itself will result in SeekRow calls. So after (successfully) returning
1808 // from the moveRelative the getPosition returns an invalid value. And so the SeekCursor fails.
1809 // In the consequence ALL parts of code where two calls to the seek cursor are done, while the second call _relies_ on
1810 // the first one, should be secured against recursion, with a broad-minded interpretation of "recursion": if any of these
1811 // code parts is executed, no other should be accessible. But this sounds very difficult to achieve...
1812 // )
1813
1814 // The next problem caused by the same behavior (SeekCursor causes a propertyChanged): when adjusting rows we implicitly
1815 // change our selection. So a "FirstSelected(); SeekCursor(); NextSelected();" may produce unpredictable results.
1816 // That's why we _first_ collect the indices of the selected rows and _then_ their bookmarks.
1817 long nIdx = FirstSelectedRow();
1818 while (nIdx != BROWSER_ENDOFSELECTION(static_cast<long>((-1))))
1819 {
1820 // (we misuse the bookmarks array for this ...)
1821 pBookmarks[i++] <<= static_cast<sal_Int32>(nIdx);
1822 nIdx = NextSelectedRow();
1823 }
1824 DBG_ASSERT(i == nSelectedRows, "FmGridControl::DeleteSelectedRows : could not collect the row indices !")do { if (true && (!(i == nSelectedRows))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1824" ": "), "%s", "FmGridControl::DeleteSelectedRows : could not collect the row indices !"
); } } while (false)
;
1825
1826 for (i=0; i<nSelectedRows; ++i)
1827 {
1828 nIdx = ::comphelper::getINT32(pBookmarks[i]);
1829 if (IsInsertionRow(nIdx))
1830 {
1831 // do not delete empty row
1832 aBookmarks.realloc(--nSelectedRows);
1833 SelectRow(nIdx, false); // cancel selection for empty row
1834 break;
1835 }
1836
1837 // first, position the data cursor on the selected block
1838 if (SeekCursor(nIdx))
1839 {
1840 GetSeekRow()->SetState(m_pSeekCursor.get(), true);
1841
1842 pBookmarks[i] = m_pSeekCursor->getBookmark();
1843 }
1844 #ifdef DBG_UTIL
1845 else
1846 OSL_FAIL("FmGridControl::DeleteSelectedRows : a bookmark could not be determined !")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1846" ": "), "%s", "FmGridControl::DeleteSelectedRows : a bookmark could not be determined !"
); } } while (false)
;
1847 #endif
1848 }
1849 }
1850 SetUpdateMode(true);
1851
1852 // if one of the SeekCursor-calls failed...
1853 aBookmarks.realloc(i);
1854
1855 // (the alternative : while collecting the bookmarks lock our propertyChanged, this should resolve both our problems.
1856 // but this would be incompatible as we need a locking flag, then...)
1857
1858 return aBookmarks;
1859}
1860
1861namespace
1862{
1863 OUString getColumnPropertyFromPeer(FmXGridPeer* _pPeer,sal_Int32 _nPosition,const OUString& _sPropName)
1864 {
1865 OUString sRetText;
1866 if ( _pPeer && _nPosition != -1)
1867 {
1868 Reference<XIndexContainer> xIndex = _pPeer->getColumns();
1869 if ( xIndex.is() && xIndex->getCount() > _nPosition )
1870 {
1871 Reference<XPropertySet> xProp;
1872 xIndex->getByIndex( _nPosition ) >>= xProp;
1873 if ( xProp.is() )
1874 {
1875 try {
1876 xProp->getPropertyValue( _sPropName ) >>= sRetText;
1877 } catch (UnknownPropertyException const&) {
1878 TOOLS_WARN_EXCEPTION("svx.fmcomp", "")do { css::uno::Any tools_warn_exception( DbgGetCaughtException
() ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "svx.fmcomp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "" << " " <<
exceptionToString(tools_warn_exception)) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1878" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "" << " " << exceptionToString
(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "" << " " << exceptionToString
(tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1878" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "" << " " << exceptionToString(tools_warn_exception
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), (
"svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1878" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "" << " " << exceptionToString
(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "" << " " << exceptionToString
(tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("svx.fmcomp"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "1878" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false); } while (false)
;
1879 }
1880 }
1881 }
1882 }
1883 return sRetText;
1884 }
1885}
1886
1887// Object data and state
1888OUString FmGridControl::GetAccessibleObjectName( ::vcl::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition ) const
1889{
1890 OUString sRetText;
1891 switch( _eObjType )
1892 {
1893 case ::vcl::BBTYPE_BROWSEBOX:
1894 if ( GetPeer() )
1895 {
1896 Reference<XPropertySet> xProp(GetPeer()->getColumns(),UNO_QUERY);
1897 if ( xProp.is() )
1898 xProp->getPropertyValue(FM_PROP_NAME"Name") >>= sRetText;
1899 }
1900 break;
1901 case ::vcl::BBTYPE_COLUMNHEADERCELL:
1902 sRetText = getColumnPropertyFromPeer(
1903 GetPeer(),
1904 GetModelColumnPos(
1905 sal::static_int_cast< sal_uInt16 >(_nPosition)),
1906 FM_PROP_LABEL"Label");
1907 break;
1908 default:
1909 sRetText = DbGridControl::GetAccessibleObjectName(_eObjType,_nPosition);
1910 }
1911 return sRetText;
1912}
1913
1914OUString FmGridControl::GetAccessibleObjectDescription( ::vcl::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition ) const
1915{
1916 OUString sRetText;
1917 switch( _eObjType )
1918 {
1919 case ::vcl::BBTYPE_BROWSEBOX:
1920 if ( GetPeer() )
1921 {
1922 Reference<XPropertySet> xProp(GetPeer()->getColumns(),UNO_QUERY);
1923 if ( xProp.is() )
1924 {
1925 xProp->getPropertyValue(FM_PROP_HELPTEXT"HelpText") >>= sRetText;
1926 if ( sRetText.isEmpty() )
1927 xProp->getPropertyValue(FM_PROP_DESCRIPTION"Description") >>= sRetText;
1928 }
1929 }
1930 break;
1931 case ::vcl::BBTYPE_COLUMNHEADERCELL:
1932 sRetText = getColumnPropertyFromPeer(
1933 GetPeer(),
1934 GetModelColumnPos(
1935 sal::static_int_cast< sal_uInt16 >(_nPosition)),
1936 FM_PROP_HELPTEXT"HelpText");
1937 if ( sRetText.isEmpty() )
1938 sRetText = getColumnPropertyFromPeer(
1939 GetPeer(),
1940 GetModelColumnPos(
1941 sal::static_int_cast< sal_uInt16 >(_nPosition)),
1942 FM_PROP_DESCRIPTION"Description");
1943
1944 break;
1945 default:
1946 sRetText = DbGridControl::GetAccessibleObjectDescription(_eObjType,_nPosition);
1947 }
1948 return sRetText;
1949}
1950
1951void FmGridControl::Select()
1952{
1953 DbGridControl::Select();
1954 // ... does it affect our columns?
1955 const MultiSelection* pColumnSelection = GetColumnSelection();
1956
1957 sal_uInt16 nSelectedColumn =
1958 pColumnSelection && pColumnSelection->GetSelectCount()
1959 ? sal::static_int_cast< sal_uInt16 >(
1960 const_cast<MultiSelection*>(pColumnSelection)->FirstSelected())
1961 : SAL_MAX_UINT16((sal_uInt16) 0xFFFF);
1962 // the HandleColumn is not selected
1963 switch (nSelectedColumn)
1964 {
1965 case SAL_MAX_UINT16((sal_uInt16) 0xFFFF): break; // no selection
1966 case 0 : nSelectedColumn = SAL_MAX_UINT16((sal_uInt16) 0xFFFF); break;
1967 // handle col can't be selected
1968 default :
1969 // get the model col pos instead of the view col pos
1970 nSelectedColumn = GetModelColumnPos(GetColumnIdFromViewPos(nSelectedColumn - 1));
1971 break;
1972 }
1973
1974 if (nSelectedColumn == m_nCurrentSelectedColumn)
1975 return;
1976
1977 // BEFORE calling the select at the SelectionSupplier!
1978 m_nCurrentSelectedColumn = nSelectedColumn;
1979
1980 if (m_bSelecting)
1981 return;
1982
1983 m_bSelecting = true;
1984
1985 try
1986 {
1987 Reference< XIndexAccess > xColumns = GetPeer()->getColumns();
1988 Reference< XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY);
1989 if (xSelSupplier.is())
1990 {
1991 if (nSelectedColumn != SAL_MAX_UINT16((sal_uInt16) 0xFFFF))
1992 {
1993 Reference< XPropertySet > xColumn(
1994 xColumns->getByIndex(nSelectedColumn),
1995 css::uno::UNO_QUERY);
1996 xSelSupplier->select(makeAny(xColumn));
1997 }
1998 else
1999 {
2000 xSelSupplier->select(Any());
2001 }
2002 }
2003 }
2004 catch(Exception&)
2005 {
2006 }
2007
2008
2009 m_bSelecting = false;
2010}
2011
2012
2013void FmGridControl::KeyInput( const KeyEvent& rKEvt )
2014{
2015 bool bDone = false;
2016 const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
2017 if ( IsDesignMode()
2018 && !rKeyCode.IsShift()
2019 && !rKeyCode.IsMod1()
2020 && !rKeyCode.IsMod2()
2021 && GetParent() )
2022 {
2023 switch ( rKeyCode.GetCode() )
2024 {
2025 case KEY_ESCAPE:
2026 GetParent()->GrabFocus();
2027 bDone = true;
2028 break;
2029 case KEY_DELETE:
2030 if ( GetSelectColumnCount() && GetPeer() && m_nCurrentSelectedColumn >= 0 )
2031 {
2032 Reference< css::container::XIndexContainer > xCols(GetPeer()->getColumns());
2033 if ( xCols.is() )
2034 {
2035 try
2036 {
2037 if ( m_nCurrentSelectedColumn < xCols->getCount() )
2038 {
2039 Reference< XInterface > xCol;
2040 xCols->getByIndex(m_nCurrentSelectedColumn) >>= xCol;
2041 xCols->removeByIndex(m_nCurrentSelectedColumn);
2042 ::comphelper::disposeComponent(xCol);
2043 }
2044 }
2045 catch(const Exception&)
2046 {
2047 TOOLS_WARN_EXCEPTION("svx", "exception occurred while deleting a column")do { css::uno::Any tools_warn_exception( DbgGetCaughtException
() ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "svx")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "exception occurred while deleting a column" <<
" " << exceptionToString(tools_warn_exception)) == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "2047" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "exception occurred while deleting a column"
<< " " << exceptionToString(tools_warn_exception
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "exception occurred while deleting a column" <<
" " << exceptionToString(tools_warn_exception); ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "2047" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "exception occurred while deleting a column" <<
" " << exceptionToString(tools_warn_exception)) == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "2047" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "exception occurred while deleting a column"
<< " " << exceptionToString(tools_warn_exception
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "exception occurred while deleting a column" <<
" " << exceptionToString(tools_warn_exception); ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/fmcomp/fmgridcl.cxx"
":" "2047" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false); } while (false)
;
2048 }
2049 }
2050 }
2051 bDone = true;
2052 break;
2053 }
2054 }
2055 if ( !bDone )
2056 DbGridControl::KeyInput( rKEvt );
2057}
2058
2059/* 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();
42
Calling 'Reference::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
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)
24
Calling implicit copy constructor for 'VclPtr<AbstractFmShowColsDialog>'
25
Calling copy constructor for 'Reference<AbstractFmShowColsDialog>'
28
Returning from copy constructor for 'Reference<AbstractFmShowColsDialog>'
29
Returning from copy constructor for 'VclPtr<AbstractFmShowColsDialog>'
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)
26
Assuming field 'm_pBody' is non-null
27
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
32.1
Field 'm_pBody' is non-null
32.1
Field 'm_pBody' is non-null
32.1
Field 'm_pBody' is non-null
32.1
Field 'm_pBody' is non-null
)
33
Taking true branch
113 m_pBody->release();
34
Calling 'VclReferenceBase::release'
38
Returning; memory was released
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;
43
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)
35
Assuming the condition is true
36
Taking true branch
40 delete this;
37
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