Bug Summary

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

/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.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 <browserids.hxx>
21#include <core_resource.hxx>
22#include <strings.hrc>
23#include <strings.hxx>
24#include <query.hrc>
25#include <stringconstants.hxx>
26#include <defaultobjectnamecheck.hxx>
27#include <dlgsave.hxx>
28#include <querycontainerwindow.hxx>
29#include <querycontroller.hxx>
30#include <QueryDesignView.hxx>
31#include <QueryTableView.hxx>
32#include <sqlmessage.hxx>
33#include <TableConnectionData.hxx>
34#include <TableFieldDescription.hxx>
35#include <UITools.hxx>
36#include <QueryPropertiesDialog.hxx>
37
38#include <com/sun/star/beans/PropertyAttribute.hpp>
39#include <com/sun/star/container/XNameContainer.hpp>
40#include <com/sun/star/frame/FrameSearchFlag.hpp>
41#include <com/sun/star/lang/XSingleServiceFactory.hpp>
42#include <com/sun/star/sdb/CommandType.hpp>
43#include <com/sun/star/sdb/SQLContext.hpp>
44#include <com/sun/star/sdb/XQueriesSupplier.hpp>
45#include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp>
46#include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp>
47#include <com/sun/star/sdbcx/XAppend.hpp>
48#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
49#include <com/sun/star/sdbcx/XDrop.hpp>
50#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
51#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
52#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
53#include <com/sun/star/util/XCloseable.hpp>
54#include <com/sun/star/util/VetoException.hpp>
55#include <com/sun/star/ui/XUIElement.hpp>
56
57#include <comphelper/propertysequence.hxx>
58#include <comphelper/processfactory.hxx>
59#include <comphelper/property.hxx>
60#include <comphelper/types.hxx>
61#include <connectivity/dbexception.hxx>
62#include <connectivity/dbtools.hxx>
63#include <cppuhelper/exc_hlp.hxx>
64#include <svl/undo.hxx>
65#include <toolkit/helper/vclunohelper.hxx>
66#include <tools/diagnose_ex.h>
67#include <osl/diagnose.h>
68#include <vcl/stdtext.hxx>
69#include <vcl/svapp.hxx>
70#include <vcl/weld.hxx>
71#include <osl/mutex.hxx>
72#include <memory>
73#include <vector>
74
75extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) css::uno::XInterface*
76org_openoffice_comp_dbu_OQueryDesign_get_implementation(
77 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
78{
79 return cppu::acquire(new ::dbaui::OQueryController(context));
80}
81
82namespace dbaui
83{
84 using namespace ::com::sun::star::uno;
85 using namespace ::com::sun::star::beans;
86 using namespace ::com::sun::star::frame;
87 using namespace ::com::sun::star::util;
88 using namespace ::com::sun::star::lang;
89
90 namespace {
91
92 class OViewController : public OQueryController
93 {
94 virtual OUString SAL_CALL getImplementationName() override
95 {
96 return "org.openoffice.comp.dbu.OViewDesign";
97 }
98 virtual Sequence< OUString> SAL_CALL getSupportedServiceNames() override
99 {
100 return { "com.sun.star.sdb.ViewDesign" };
101 }
102
103 public:
104 explicit OViewController(const Reference< XComponentContext >& _rM) : OQueryController(_rM){}
105 };
106
107 }
108}
109
110extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) css::uno::XInterface*
111org_openoffice_comp_dbu_OViewDesign_get_implementation(
112 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
113{
114 return cppu::acquire(new ::dbaui::OViewController(context));
115}
116
117namespace dbaui
118{
119 using namespace ::connectivity;
120
121 namespace
122 {
123 OUString lcl_getObjectResourceString(const char* pResId, sal_Int32 _nCommandType)
124 {
125 OUString sMessageText = DBA_RES(pResId)::dbaccess::ResourceManager::loadString( pResId );
126 OUString sObjectType = DBA_RES(RSC_QUERY_OBJECT_TYPE[_nCommandType])::dbaccess::ResourceManager::loadString( RSC_QUERY_OBJECT_TYPE
[_nCommandType] )
;
127 sMessageText = sMessageText.replaceFirst( "$object$", sObjectType );
128 return sMessageText;
129 }
130 }
131
132using namespace ::com::sun::star::io;
133using namespace ::com::sun::star::container;
134using namespace ::com::sun::star::sdbcx;
135using namespace ::com::sun::star::sdbc;
136using namespace ::com::sun::star::sdb;
137using namespace ::com::sun::star::ui;
138using namespace ::com::sun::star::ui::dialogs;
139using namespace ::com::sun::star::awt;
140using namespace ::dbtools;
141
142using namespace ::comphelper;
143
144namespace
145{
146 void ensureToolbars( OQueryController& _rController, bool _bDesign )
147 {
148 Reference< css::frame::XLayoutManager > xLayoutManager = OGenericUnoController::getLayoutManager( _rController.getFrame() );
149 if ( !xLayoutManager.is() )
150 return;
151
152 xLayoutManager->lock();
153 static const char s_sDesignToolbar[] = "private:resource/toolbar/designobjectbar";
154 static const char s_sSqlToolbar[] = "private:resource/toolbar/sqlobjectbar";
155 if ( _bDesign )
156 {
157 xLayoutManager->destroyElement( s_sSqlToolbar );
158 xLayoutManager->createElement( s_sDesignToolbar );
159 }
160 else
161 {
162 xLayoutManager->destroyElement( s_sDesignToolbar );
163 xLayoutManager->createElement( s_sSqlToolbar );
164 }
165 xLayoutManager->unlock();
166 xLayoutManager->doLayout();
167 }
168
169 /**
170 * The value of m_nLimit is updated when LimitBox loses its focus
171 * So in those case when execution needs recent data, grab the focus
172 * (e.g. execute SQL statement, change views)
173 */
174 void grabFocusFromLimitBox( OQueryController& _rController )
175 {
176 Reference< XLayoutManager > xLayoutManager = OGenericUnoController::getLayoutManager( _rController.getFrame() );
177 Reference< XUIElement > xUIElement = xLayoutManager->getElement("private:resource/toolbar/designobjectbar");
178 if (xUIElement.is())
179 {
180 Reference< XWindow > xWindow(xUIElement->getRealInterface(), css::uno::UNO_QUERY);
181 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
182 if( pWindow && pWindow->HasChildPathFocus() )
183 {
184 pWindow->GrabFocusToDocument();
185 }
186 }
187 }
188}
189
190OUString SAL_CALL OQueryController::getImplementationName()
191{
192 return "org.openoffice.comp.dbu.OQueryDesign";
193}
194
195Sequence< OUString> SAL_CALL OQueryController::getSupportedServiceNames()
196{
197 return { "com.sun.star.sdb.QueryDesign" };
198}
199
200OQueryController::OQueryController(const Reference< XComponentContext >& _rM)
201 :OJoinController(_rM)
202 ,OQueryController_PBase( getBroadcastHelper() )
203 ,m_pParseContext( new svxform::OSystemParseContext )
204 ,m_aSqlParser( _rM, m_pParseContext.get() )
205 ,m_nLimit(-1)
206 ,m_nVisibleRows(0x400)
207 ,m_nSplitPos(-1)
208 ,m_nCommandType( CommandType::QUERY )
209 ,m_bGraphicalDesign(false)
210 ,m_bDistinct(false)
211 ,m_bEscapeProcessing(true)
212{
213 InvalidateAll();
214
215 registerProperty( PROPERTY_ACTIVECOMMAND"ActiveCommand", PROPERTY_ID_ACTIVECOMMAND56, PropertyAttribute::READONLY | PropertyAttribute::BOUND,
216 &m_sStatement, cppu::UnoType<decltype(m_sStatement)>::get() );
217 registerProperty( PROPERTY_ESCAPE_PROCESSING"EscapeProcessing", PROPERTY_ID_ESCAPE_PROCESSING11, PropertyAttribute::READONLY | PropertyAttribute::BOUND,
218 &m_bEscapeProcessing, cppu::UnoType<decltype(m_bEscapeProcessing)>::get() );
219}
220
221OQueryController::~OQueryController()
222{
223 if ( !getBroadcastHelper().bDisposed && !getBroadcastHelper().bInDispose )
224 {
225 OSL_FAIL("Please check who doesn't dispose this component!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "225" ": "), "%s", "Please check who doesn't dispose this component!"
); } } while (false)
;
226 // increment ref count to prevent double call of Dtor
227 osl_atomic_increment( &m_refCount )__sync_add_and_fetch((&m_refCount), 1);
228 dispose();
229 }
230}
231
232IMPLEMENT_FORWARD_XINTERFACE2( OQueryController, OJoinController, OQueryController_PBase )void OQueryController::acquire() throw() { OJoinController::acquire
(); } void OQueryController::release() throw() { OJoinController
::release(); } css::uno::Any OQueryController::queryInterface
( const css::uno::Type& _rType ) { css::uno::Any aReturn =
OJoinController::queryInterface( _rType ); if ( !aReturn.hasValue
() ) aReturn = OQueryController_PBase::queryInterface( _rType
); return aReturn; }
233IMPLEMENT_FORWARD_XTYPEPROVIDER2( OQueryController, OJoinController, OQueryController_PBase )css::uno::Sequence< css::uno::Type > OQueryController::
getTypes( ) { return ::comphelper::concatSequences( OJoinController
::getTypes(), OQueryController_PBase::getTypes() ); } css::uno
::Sequence< sal_Int8 > OQueryController::getImplementationId
( ) { return css::uno::Sequence<sal_Int8>(); }
234
235Reference< XPropertySetInfo > SAL_CALL OQueryController::getPropertySetInfo()
236{
237 Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
238 return xInfo;
239}
240
241void SAL_CALL OQueryController::getFastPropertyValue( Any& o_rValue, sal_Int32 i_nHandle ) const
242{
243 switch ( i_nHandle )
244 {
245 case PROPERTY_ID_CURRENT_QUERY_DESIGN144:
246 {
247 ::comphelper::NamedValueCollection aCurrentDesign;
248 aCurrentDesign.put( "GraphicalDesign", isGraphicalDesign() );
249 aCurrentDesign.put( OUString(PROPERTY_ESCAPE_PROCESSING"EscapeProcessing"), m_bEscapeProcessing );
250
251 if ( isGraphicalDesign() )
252 {
253 getContainer()->SaveUIConfig();
254 saveViewSettings( aCurrentDesign, true );
255 aCurrentDesign.put( "Statement", m_sStatement );
256 }
257 else
258 {
259 aCurrentDesign.put( "Statement", getContainer()->getStatement() );
260 }
261
262 o_rValue <<= aCurrentDesign.getPropertyValues();
263 }
264 break;
265
266 default:
267 OPropertyContainer::getFastPropertyValue( o_rValue, i_nHandle );
268 break;
269 }
270}
271
272::cppu::IPropertyArrayHelper& OQueryController::getInfoHelper()
273{
274 return *getArrayHelper();
275}
276
277::cppu::IPropertyArrayHelper* OQueryController::createArrayHelper( ) const
278{
279 Sequence< Property > aProps;
280 describeProperties( aProps );
281
282 // one additional property:
283 const sal_Int32 nLength = aProps.getLength();
284 aProps.realloc( nLength + 1 );
285 aProps[ nLength ] = Property(
286 "CurrentQueryDesign",
287 PROPERTY_ID_CURRENT_QUERY_DESIGN144,
288 ::cppu::UnoType< Sequence< PropertyValue > >::get(),
289 PropertyAttribute::READONLY
290 );
291
292 std::sort(
293 aProps.begin(),
294 aProps.end(),
295 ::comphelper::PropertyCompareByName()
296 );
297
298 return new ::cppu::OPropertyArrayHelper(aProps);
299}
300
301void OQueryController::deleteIterator()
302{
303 if(m_pSqlIterator)
304 {
305 delete m_pSqlIterator->getParseTree();
306 m_pSqlIterator->dispose();
307 m_pSqlIterator.reset();
308 }
309}
310
311void OQueryController::disposing()
312{
313 OQueryController_PBase::disposing();
314
315 deleteIterator();
316
317 m_pParseContext.reset();
318
319 clearFields();
320 OTableFields().swap(m_vUnUsedFieldsDesc);
321
322 ::comphelper::disposeComponent(m_xComposer);
323 OJoinController::disposing();
324 OQueryController_PBase::disposing();
325}
326
327void OQueryController::clearFields()
328{
329 OTableFields().swap(m_vTableFieldDesc);
330}
331
332FeatureState OQueryController::GetState(sal_uInt16 _nId) const
333{
334 FeatureState aReturn;
335 aReturn.bEnabled = true;
336 // (disabled automatically)
337
338 switch (_nId)
339 {
340 case ID_BROWSER_EDITDOC(5000 + 1312):
341 if ( editingCommand() )
342 aReturn.bEnabled = false;
343 else if ( editingView() && !m_xAlterView.is() )
344 aReturn.bEnabled = false;
345 else
346 aReturn = OJoinController::GetState( _nId );
347 break;
348
349 case ID_BROWSER_ESCAPEPROCESSING( 10000 + 720 ):
350 aReturn.bChecked = !m_bEscapeProcessing;
351 aReturn.bEnabled = ( m_pSqlIterator != nullptr ) && !m_bGraphicalDesign;
352 break;
353 case SID_RELATION_ADD_RELATION( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 45 )
:
354 aReturn.bEnabled = isEditable() && m_bGraphicalDesign && m_vTableData.size() > 1;
355 break;
356 case ID_BROWSER_SAVEASDOC(5000 + 502):
357 aReturn.bEnabled = !editingCommand() && (!m_bGraphicalDesign || !(m_vTableFieldDesc.empty() || m_vTableData.empty()));
358 break;
359 case ID_BROWSER_SAVEDOC(5000 + 505):
360 aReturn.bEnabled = isEditable() && (!m_bGraphicalDesign || !(m_vTableFieldDesc.empty() || m_vTableData.empty()));
361 break;
362 case SID_PRINTDOCDIRECT(5000 + 509):
363 break;
364 case ID_BROWSER_CUT(5000 + 710):
365 aReturn.bEnabled = isEditable() && getContainer() && getContainer()->isCutAllowed();
366 break;
367 case ID_BROWSER_COPY(5000 + 711):
368 aReturn.bEnabled = getContainer() && getContainer()->isCopyAllowed();
369 break;
370 case ID_BROWSER_PASTE(5000 + 712):
371 aReturn.bEnabled = isEditable() && getContainer() && getContainer()->isPasteAllowed();
372 break;
373 case ID_BROWSER_SQL42:
374 aReturn.bEnabled = m_bEscapeProcessing && m_pSqlIterator;
375 aReturn.bChecked = m_bGraphicalDesign;
376 break;
377 case SID_BROWSER_CLEAR_QUERY( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 44 )
:
378 aReturn.bEnabled = isEditable() && (!m_sStatement.isEmpty() || !m_vTableData.empty());
379 break;
380 case SID_QUERY_VIEW_FUNCTIONS( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 46 )
:
381 case SID_QUERY_VIEW_TABLES( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 47 )
:
382 case SID_QUERY_VIEW_ALIASES( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 48 )
:
383 aReturn.bChecked = getContainer() && getContainer()->isSlotEnabled(_nId);
384 aReturn.bEnabled = m_bGraphicalDesign;
385 break;
386 case SID_QUERY_DISTINCT_VALUES( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 49 )
:
387 aReturn.bEnabled = m_bGraphicalDesign && isEditable();
388 aReturn.bChecked = m_bDistinct;
389 break;
390 case SID_QUERY_LIMIT( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 56 )
:
391 aReturn.bEnabled = m_bGraphicalDesign;
392 if( aReturn.bEnabled )
393 aReturn.aValue <<= m_nLimit;
394 break;
395 case SID_QUERY_PROP_DLG( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 69 )
:
396 aReturn.bEnabled = m_bGraphicalDesign;
397 break;
398 case ID_BROWSER_QUERY_EXECUTE( 10000 + 721 ):
399 aReturn.bEnabled = true;
400 break;
401 case SID_DB_QUERY_PREVIEW( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 52 )
:
402 aReturn.bEnabled = true;
403 aReturn.bChecked = getContainer() && getContainer()->getPreviewFrame().is();
404 break;
405#if OSL_DEBUG_LEVEL1 > 0
406 case ID_EDIT_QUERY_SQL23:
407 break;
408 case ID_EDIT_QUERY_DESIGN21:
409 break;
410#endif
411 case ID_BROWSER_ADDTABLE( 10000 + 722 ):
412 if ( !m_bGraphicalDesign )
413 {
414 aReturn.bEnabled = false;
415 break;
416 }
417 [[fallthrough]];
418 default:
419 aReturn = OJoinController::GetState(_nId);
420 break;
421 }
422 return aReturn;
423}
424
425void OQueryController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs)
426{
427 switch(_nId)
428 {
429 case ID_BROWSER_ESCAPEPROCESSING( 10000 + 720 ):
430 setEscapeProcessing_fireEvent( !m_bEscapeProcessing );
431 if ( !editingView() )
432 setModified(true);
433 InvalidateFeature(ID_BROWSER_SQL42);
434 break;
435 case ID_BROWSER_SAVEASDOC(5000 + 502):
436 case ID_BROWSER_SAVEDOC(5000 + 505):
437 grabFocusFromLimitBox(*this);
438 doSaveAsDoc(ID_BROWSER_SAVEASDOC(5000 + 502) == _nId);
439 break;
440 case SID_RELATION_ADD_RELATION( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 45 )
:
441 {
442 OJoinDesignView* pView = getJoinView();
443 if( pView )
444 static_cast<OQueryTableView*>(pView->getTableView())->createNewConnection();
445 }
446 break;
447 case SID_PRINTDOCDIRECT(5000 + 509):
448 break;
449 case ID_BROWSER_CUT(5000 + 710):
450 getContainer()->cut();
451 break;
452 case ID_BROWSER_COPY(5000 + 711):
453 getContainer()->copy();
454 break;
455 case ID_BROWSER_PASTE(5000 + 712):
456 getContainer()->paste();
457 break;
458 case ID_BROWSER_SQL42:
459 {
460 grabFocusFromLimitBox(*this);
461 if ( !getContainer()->checkStatement() )
462 break;
463 SQLExceptionInfo aError;
464 try
465 {
466 setStatement_fireEvent( getContainer()->getStatement() );
467 if(m_sStatement.isEmpty() && m_pSqlIterator)
468 {
469 // change the view of the data
470 delete m_pSqlIterator->getParseTree();
471 m_pSqlIterator->setParseTree(nullptr);
472 m_bGraphicalDesign = !m_bGraphicalDesign;
473 impl_setViewMode( &aError );
474 }
475 else
476 {
477 OUString aErrorMsg;
478 std::unique_ptr<::connectivity::OSQLParseNode> pNode = m_aSqlParser.parseTree(aErrorMsg,m_sStatement,m_bGraphicalDesign);
479 if ( pNode )
480 {
481 delete m_pSqlIterator->getParseTree();
482 m_pSqlIterator->setParseTree(pNode.release());
483 m_pSqlIterator->traverseAll();
484
485 if ( m_pSqlIterator->hasErrors() )
486 {
487 aError = m_pSqlIterator->getErrors();
488 }
489 else
490 {
491 const OSQLTables& rTabs = m_pSqlIterator->getTables();
492 if ( m_pSqlIterator->getStatementType() != OSQLStatementType::Select || rTabs.empty() )
493 {
494 aError = SQLException(
495 DBA_RES(STR_QRY_NOSELECT)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_QRY_NOSELECT" "\004" u8"Nothing has been selected."
) )
,
496 nullptr,
497 "S1000",
498 1000,
499 Any()
500 );
501 }
502 else
503 {
504 // change the view of the data
505 m_bGraphicalDesign = !m_bGraphicalDesign;
506 OUString sNewStatement;
507 m_pSqlIterator->getParseTree()->parseNodeToStr( sNewStatement, getConnection() );
508 setStatement_fireEvent( sNewStatement );
509 getContainer()->SaveUIConfig();
510 m_vTableConnectionData.clear();
511 impl_setViewMode( &aError );
512 }
513 }
514 }
515 else
516 {
517 aError = SQLException(
518 DBA_RES(STR_QRY_SYNTAX)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_QRY_SYNTAX" "\004" u8"SQL syntax error"
) )
,
519 nullptr,
520 "S1000",
521 1000,
522 Any()
523 );
524 }
525 }
526 }
527 catch(const SQLException&)
528 {
529 aError = ::cppu::getCaughtException();
530 }
531 catch(const Exception&)
532 {
533 DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "533" ": ", "dbaccess" );
;
534 }
535
536 if ( aError.isValid() )
537 showError( aError );
538
539 if(m_bGraphicalDesign)
540 {
541 InvalidateFeature(ID_BROWSER_ADDTABLE( 10000 + 722 ));
542 InvalidateFeature(SID_RELATION_ADD_RELATION( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 45 )
);
543 }
544 }
545 break;
546 case SID_BROWSER_CLEAR_QUERY( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 44 )
:
547 {
548 GetUndoManager().EnterListAction(DBA_RES(STR_QUERY_UNDO_TABWINDELETE)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_QUERY_UNDO_TABWINDELETE" "\004" u8"Delete Table Window"
) )
, OUString(), 0, ViewShellId(-1) );
549 getContainer()->clear();
550 GetUndoManager().LeaveListAction();
551
552 setStatement_fireEvent( OUString() );
553 if(m_bGraphicalDesign)
554 InvalidateFeature(ID_BROWSER_ADDTABLE( 10000 + 722 ));
555 }
556 break;
557 case SID_QUERY_VIEW_FUNCTIONS( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 46 )
:
558 case SID_QUERY_VIEW_TABLES( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 47 )
:
559 case SID_QUERY_VIEW_ALIASES( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 48 )
:
560 getContainer()->setSlotEnabled(_nId,!getContainer()->isSlotEnabled(_nId));
561 setModified(true);
562 break;
563 case SID_QUERY_DISTINCT_VALUES( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 49 )
:
564 m_bDistinct = !m_bDistinct;
565 setModified(true);
566 break;
567 case SID_QUERY_LIMIT( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 56 )
:
568 if ( aArgs.hasElements() && aArgs[0].Name == "DBLimit.Value" )
569 {
570 aArgs[0].Value >>= m_nLimit;
571 setModified(true);
572 }
573 break;
574 case SID_QUERY_PROP_DLG( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 69 )
:
575 grabFocusFromLimitBox(*this);
576 execute_QueryPropDlg();
577 break;
578 case ID_BROWSER_QUERY_EXECUTE( 10000 + 721 ):
579 grabFocusFromLimitBox(*this);
580 if ( getContainer()->checkStatement() )
581 executeQuery();
582 break;
583 case SID_DB_QUERY_PREVIEW( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 52 )
:
584 try
585 {
586 Reference< css::util::XCloseable > xCloseFrame( getContainer()->getPreviewFrame(), UNO_QUERY );
587 if ( xCloseFrame.is() )
588 {
589 try
590 {
591 xCloseFrame->close( true );
592 }
593 catch(const Exception&)
594 {
595 OSL_FAIL( "OQueryController::Execute(SID_DB_QUERY_PREVIEW): *nobody* is expected to veto closing the preview frame!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "595" ": "), "%s", "OQueryController::Execute(SID_DB_QUERY_PREVIEW): *nobody* is expected to veto closing the preview frame!"
); } } while (false)
;
596 }
597 }
598 else
599 Execute(ID_BROWSER_QUERY_EXECUTE( 10000 + 721 ),Sequence< PropertyValue >());
600 }
601 catch(const Exception&)
602 {
603 }
604 break;
605 default:
606 OJoinController::Execute(_nId,aArgs);
607 return; // else we would invalidate twice
608 }
609 InvalidateFeature(_nId);
610}
611
612void OQueryController::impl_showAutoSQLViewError( const css::uno::Any& _rErrorDetails )
613{
614 SQLContext aErrorContext;
615 aErrorContext.Message = lcl_getObjectResourceString( STR_ERROR_PARSING_STATEMENTreinterpret_cast<char const *>("STR_ERROR_PARSING_STATEMENT"
"\004" u8"$object$ is based on an SQL command which could not be parsed."
)
, m_nCommandType );
616 aErrorContext.Context = *this;
617 aErrorContext.Details = lcl_getObjectResourceString( STR_INFO_OPENING_IN_SQL_VIEWreinterpret_cast<char const *>("STR_INFO_OPENING_IN_SQL_VIEW"
"\004" u8"$object$ will be opened in SQL view.")
, m_nCommandType );
618 aErrorContext.NextException = _rErrorDetails;
619 showError( aErrorContext );
620}
621
622void OQueryController::impl_setViewMode( ::dbtools::SQLExceptionInfo* _pErrorInfo )
623{
624 OSL_PRECOND( getContainer(), "OQueryController::impl_setViewMode: illegal call!" )do { if (true && (!(getContainer()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "624" ": "), "%s", "OQueryController::impl_setViewMode: illegal call!"
); } } while (false)
;
625
626 bool wasModified = isModified();
627
628 SQLExceptionInfo aError;
629 bool bSuccess = getContainer()->switchView( &aError );
630 if ( !bSuccess )
631 {
632 m_bGraphicalDesign = !m_bGraphicalDesign;
633 // restore old state
634 getContainer()->switchView( nullptr );
635 // don't pass &aError here, this would overwrite the error which the first switchView call
636 // returned in this location.
637 if ( _pErrorInfo )
638 *_pErrorInfo = aError;
639 else
640 showError( aError );
641 }
642 else
643 {
644 ensureToolbars( *this, m_bGraphicalDesign );
645 }
646
647 setModified( wasModified );
648}
649
650void OQueryController::impl_initialize()
651{
652 OJoinController::impl_initialize();
653
654 const NamedValueCollection& rArguments( getInitParams() );
655
656 OUString sCommand;
657 m_nCommandType = CommandType::QUERY;
658
659 // reading parameters:
660
661 // legacy parameters first (later overwritten by regular parameters)
662 OUString sIndependentSQLCommand;
663 if ( rArguments.get_ensureType( "IndependentSQLCommand", sIndependentSQLCommand ) )
664 {
665 OSL_FAIL( "OQueryController::impl_initialize: IndependentSQLCommand is regognized for compatibility only!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "665" ": "), "%s", "OQueryController::impl_initialize: IndependentSQLCommand is regognized for compatibility only!"
); } } while (false)
;
666 sCommand = sIndependentSQLCommand;
667 m_nCommandType = CommandType::COMMAND;
668 }
669
670 OUString sCurrentQuery;
671 if ( rArguments.get_ensureType( "CurrentQuery", sCurrentQuery ) )
672 {
673 OSL_FAIL( "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "673" ": "), "%s", "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!"
); } } while (false)
;
674 sCommand = sCurrentQuery;
675 m_nCommandType = CommandType::QUERY;
676 }
677
678 bool bCreateView( false );
679 if ( rArguments.get_ensureType( "CreateView", bCreateView ) && bCreateView )
680 {
681 OSL_FAIL( "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "681" ": "), "%s", "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!"
); } } while (false)
;
682 m_nCommandType = CommandType::TABLE;
683 }
684
685 // non-legacy parameters which overwrite the legacy parameters
686 rArguments.get_ensureType( PROPERTY_COMMAND"Command", sCommand );
687 rArguments.get_ensureType( PROPERTY_COMMAND_TYPE"CommandType", m_nCommandType );
688
689 // translate Command/Type into proper members
690 // TODO/Later: all this (including those members) should be hidden behind some abstract interface,
691 // which is implemented for all the three commands
692 switch ( m_nCommandType )
693 {
694 case CommandType::QUERY:
695 m_sName = sCommand;
696 break;
697 case CommandType::TABLE:
698 m_sName = sCommand;
699 break;
700 case CommandType::COMMAND:
701 setStatement_fireEvent( sCommand );
702 m_sName.clear();
703 break;
704 default:
705 OSL_FAIL( "OQueryController::impl_initialize: logic error in code!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "705" ": "), "%s", "OQueryController::impl_initialize: logic error in code!"
); } } while (false)
;
706 throw RuntimeException();
707 }
708
709 // more legacy parameters
710 bool bGraphicalDesign( true );
711 if ( rArguments.get_ensureType( PROPERTY_QUERYDESIGNVIEW"QueryDesignView", bGraphicalDesign ) )
712 {
713 OSL_FAIL( "OQueryController::impl_initialize: QueryDesignView is regognized for compatibility only!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "713" ": "), "%s", "OQueryController::impl_initialize: QueryDesignView is regognized for compatibility only!"
); } } while (false)
;
714 m_bGraphicalDesign = bGraphicalDesign;
715 }
716
717 // more non-legacy
718 rArguments.get_ensureType( PROPERTY_GRAPHICAL_DESIGN"GraphicalDesign", m_bGraphicalDesign );
719
720 bool bEscapeProcessing( true );
721 if ( rArguments.get_ensureType( PROPERTY_ESCAPE_PROCESSING"EscapeProcessing", bEscapeProcessing ) )
722 {
723 setEscapeProcessing_fireEvent( bEscapeProcessing );
724
725 OSL_ENSURE( m_bEscapeProcessing || !m_bGraphicalDesign, "OQueryController::impl_initialize: can't do the graphical design without escape processing!" )do { if (true && (!(m_bEscapeProcessing || !m_bGraphicalDesign
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "725" ": "), "%s", "OQueryController::impl_initialize: can't do the graphical design without escape processing!"
); } } while (false)
;
726 if ( !m_bEscapeProcessing )
727 m_bGraphicalDesign = false;
728 }
729
730 // initial design
731 bool bForceInitialDesign = false;
732 Sequence< PropertyValue > aCurrentQueryDesignProps;
733 aCurrentQueryDesignProps = rArguments.getOrDefault( "CurrentQueryDesign", aCurrentQueryDesignProps );
734
735 if ( aCurrentQueryDesignProps.hasElements() )
736 {
737 ::comphelper::NamedValueCollection aCurrentQueryDesign( aCurrentQueryDesignProps );
738 if ( aCurrentQueryDesign.has( OUString(PROPERTY_GRAPHICAL_DESIGN"GraphicalDesign") ) )
739 {
740 aCurrentQueryDesign.get_ensureType( PROPERTY_GRAPHICAL_DESIGN"GraphicalDesign", m_bGraphicalDesign );
741 }
742 if ( aCurrentQueryDesign.has( OUString(PROPERTY_ESCAPE_PROCESSING"EscapeProcessing") ) )
743 {
744 aCurrentQueryDesign.get_ensureType( PROPERTY_ESCAPE_PROCESSING"EscapeProcessing", m_bEscapeProcessing );
745 }
746 if ( aCurrentQueryDesign.has( "Statement" ) )
747 {
748 OUString sStatement;
749 aCurrentQueryDesign.get_ensureType( "Statement", sStatement );
750 aCurrentQueryDesign.remove( "Statement" );
751 setStatement_fireEvent( sStatement );
752 }
753
754 loadViewSettings( aCurrentQueryDesign );
755
756 bForceInitialDesign = true;
757 }
758
759 if ( !ensureConnected() )
760 { // we have no connection so what else should we do
761 m_bGraphicalDesign = false;
762 if ( editingView() )
763 {
764 connectionLostMessage();
765 throw SQLException();
766 }
767 }
768
769 // check the view capabilities
770 if ( isConnected() && editingView() )
771 {
772 Reference< XViewsSupplier > xViewsSup( getConnection(), UNO_QUERY );
773 Reference< XNameAccess > xViews;
774 if ( xViewsSup.is() )
775 xViews = xViewsSup->getViews();
776
777 if ( !xViews.is() )
778 { // we can't create views so we ask if the user wants to create a query instead
779 m_nCommandType = CommandType::QUERY;
780 bool bClose = false;
781 {
782 OUString aTitle(DBA_RES(STR_QUERYDESIGN_NO_VIEW_SUPPORT)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_QUERYDESIGN_NO_VIEW_SUPPORT" "\004" u8"This database does not support table views."
) )
);
783 OUString aMessage(DBA_RES(STR_QUERYDESIGN_NO_VIEW_ASK)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_QUERYDESIGN_NO_VIEW_ASK" "\004" u8"Do you want to create a query instead?"
) )
);
784 OSQLMessageBox aDlg(getFrameWeld(), aTitle, aMessage, MessBoxStyle::YesNo | MessBoxStyle::DefaultYes, MessageType::Query);
785 bClose = aDlg.run() == RET_NO;
786 }
787 if ( bClose )
788 throw VetoException();
789 }
790
791 // now if we are to edit an existing view, check whether this is possible
792 if ( !m_sName.isEmpty() )
793 {
794 Any aView( xViews->getByName( m_sName ) );
795 // will throw if there is no such view
796 if ( !( aView >>= m_xAlterView ) )
797 {
798 throw IllegalArgumentException(
799 DBA_RES(STR_NO_ALTER_VIEW_SUPPORT)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_NO_ALTER_VIEW_SUPPORT" "\004" u8"This database does not support altering of existing table views."
) )
,
800 *this,
801 1
802 );
803 }
804 }
805 }
806
807 OSL_ENSURE(getDataSource().is(),"OQueryController::impl_initialize: need a datasource!")do { if (true && (!(getDataSource().is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "807" ": "), "%s", "OQueryController::impl_initialize: need a datasource!"
); } } while (false)
;
808
809 try
810 {
811 getContainer()->initialize();
812 impl_reset( bForceInitialDesign );
813
814 SQLExceptionInfo aError;
815 const bool bAttemptedGraphicalDesign = m_bGraphicalDesign;
816
817 if ( bForceInitialDesign )
818 {
819 getContainer()->forceInitialView();
820 }
821 else
822 {
823 impl_setViewMode( &aError );
824 }
825
826 if ( aError.isValid() && bAttemptedGraphicalDesign && !m_bGraphicalDesign )
827 {
828 // we tried initializing the graphical view, this failed, and we were automatically switched to SQL
829 // view => tell this to the user
830 if ( !editingView() )
831 {
832 impl_showAutoSQLViewError( aError.get() );
833 }
834 }
835
836 ClearUndoManager();
837
838 if ( m_bGraphicalDesign
839 && ( ( m_sName.isEmpty() && !editingCommand() )
840 || ( m_sStatement.isEmpty() && editingCommand() )
841 )
842 )
843 {
844 Application::PostUserEvent( LINK( this, OQueryController, OnExecuteAddTable )::tools::detail::makeLink( ::tools::detail::castTo<OQueryController
*>(this), &OQueryController::LinkStubOnExecuteAddTable
)
);
845 }
846
847 setModified(false);
848 }
849 catch(const SQLException& e)
850 {
851 DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "851" ": ", "dbaccess" );
;
852 // we caught an exception so we switch to text only mode
853 {
854 m_bGraphicalDesign = false;
855 getContainer()->initialize();
856 OSQLMessageBox aBox(getFrameWeld(), e);
857 aBox.run();
858 }
859 throw;
860 }
861}
862
863void OQueryController::onLoadedMenu(const Reference< css::frame::XLayoutManager >& /*_xLayoutManager*/)
864{
865 ensureToolbars( *this, m_bGraphicalDesign );
866}
867
868OUString OQueryController::getPrivateTitle( ) const
869{
870 if ( m_sName.isEmpty() )
871 {
872 if ( !editingCommand() )
873 {
874 SolarMutexGuard aSolarGuard;
875 ::osl::MutexGuard aGuard( getMutex() );
876 OUString aDefaultName = DBA_RES(editingView() ? STR_VIEW_TITLE : STR_QRY_TITLE)::dbaccess::ResourceManager::loadString( editingView() ? reinterpret_cast
<char const *>("STR_VIEW_TITLE" "\004" u8"View #") : reinterpret_cast
<char const *>("STR_QRY_TITLE" "\004" u8"Query #") )
;
877 return aDefaultName.getToken(0, ' ') + OUString::number(getCurrentStartNumber());
878 }
879 }
880 return m_sName;
881}
882
883void OQueryController::setQueryComposer()
884{
885 if(!isConnected())
886 return;
887
888 Reference< XSQLQueryComposerFactory > xFactory(getConnection(), UNO_QUERY);
889 OSL_ENSURE(xFactory.is(),"Connection doesn't support a querycomposer")do { if (true && (!(xFactory.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "889" ": "), "%s", "Connection doesn't support a querycomposer"
); } } while (false)
;
890 if ( !(xFactory.is() && getContainer()) )
891 return;
892
893 try
894 {
895 m_xComposer = xFactory->createQueryComposer();
896 getContainer()->setStatement(m_sStatement);
897 }
898 catch(const Exception&)
899 {
900 m_xComposer = nullptr;
901 }
902 OSL_ENSURE(m_xComposer.is(),"No querycomposer available!")do { if (true && (!(m_xComposer.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "902" ": "), "%s", "No querycomposer available!"); } } while
(false)
;
903 Reference<XTablesSupplier> xTablesSup(getConnection(), UNO_QUERY);
904 deleteIterator();
905 m_pSqlIterator.reset(new ::connectivity::OSQLParseTreeIterator( getConnection(), xTablesSup->getTables(), m_aSqlParser ));
906}
907
908bool OQueryController::Construct(vcl::Window* pParent)
909{
910 // TODO: we have to check if we should create the text view or the design view
911
912 setView( VclPtr<OQueryContainerWindow>::Create( pParent, *this, getORB() ) );
1
Calling 'VclPtr::Create'
3
Returned allocated memory
4
Calling implicit destructor for 'VclPtr<dbaui::ODataView>'
5
Calling '~Reference'
12
Returning from '~Reference'
13
Returning from destructor for 'VclPtr<dbaui::ODataView>'
14
Calling implicit destructor for 'VclPtr<dbaui::OQueryContainerWindow>'
15
Calling '~Reference'
913
914 return OJoinController::Construct(pParent);
915}
916
917OJoinDesignView* OQueryController::getJoinView()
918{
919 return getContainer()->getDesignView();
920}
921
922void OQueryController::describeSupportedFeatures()
923{
924 OJoinController::describeSupportedFeatures();
925 implDescribeSupportedFeature( ".uno:SaveAs", ID_BROWSER_SAVEASDOC(5000 + 502), CommandGroup::DOCUMENT );
926 implDescribeSupportedFeature( ".uno:SbaNativeSql", ID_BROWSER_ESCAPEPROCESSING( 10000 + 720 ),CommandGroup::FORMAT );
927 implDescribeSupportedFeature( ".uno:DBViewFunctions", SID_QUERY_VIEW_FUNCTIONS( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 46 )
, CommandGroup::VIEW );
928 implDescribeSupportedFeature( ".uno:DBViewTableNames", SID_QUERY_VIEW_TABLES( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 47 )
, CommandGroup::VIEW );
929 implDescribeSupportedFeature( ".uno:DBViewAliases", SID_QUERY_VIEW_ALIASES( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 48 )
, CommandGroup::VIEW );
930 implDescribeSupportedFeature( ".uno:DBDistinctValues", SID_QUERY_DISTINCT_VALUES( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 49 )
, CommandGroup::FORMAT );
931 implDescribeSupportedFeature( ".uno:DBChangeDesignMode",ID_BROWSER_SQL42, CommandGroup::VIEW );
932 implDescribeSupportedFeature( ".uno:DBClearQuery", SID_BROWSER_CLEAR_QUERY( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 44 )
, CommandGroup::EDIT );
933 implDescribeSupportedFeature( ".uno:SbaExecuteSql", ID_BROWSER_QUERY_EXECUTE( 10000 + 721 ), CommandGroup::VIEW );
934 implDescribeSupportedFeature( ".uno:DBAddRelation", SID_RELATION_ADD_RELATION( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 45 )
, CommandGroup::EDIT );
935 implDescribeSupportedFeature( ".uno:DBQueryPreview", SID_DB_QUERY_PREVIEW( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 52 )
, CommandGroup::VIEW );
936 implDescribeSupportedFeature( ".uno:DBLimit", SID_QUERY_LIMIT( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 56 )
, CommandGroup::FORMAT );
937 implDescribeSupportedFeature( ".uno:DBQueryPropertiesDialog", SID_QUERY_PROP_DLG( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 69 )
, CommandGroup::FORMAT );
938
939#if OSL_DEBUG_LEVEL1 > 0
940 implDescribeSupportedFeature( ".uno:DBShowParseTree", ID_EDIT_QUERY_SQL23 );
941 implDescribeSupportedFeature( ".uno:DBMakeDisjunct", ID_EDIT_QUERY_DESIGN21 );
942#endif
943}
944
945void OQueryController::impl_onModifyChanged()
946{
947 OJoinController::impl_onModifyChanged();
948 InvalidateFeature(SID_BROWSER_CLEAR_QUERY( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 44 )
);
949 InvalidateFeature(ID_BROWSER_SAVEASDOC(5000 + 502));
950 InvalidateFeature(ID_BROWSER_QUERY_EXECUTE( 10000 + 721 ));
951}
952
953void SAL_CALL OQueryController::disposing( const EventObject& Source )
954{
955 SolarMutexGuard aGuard;
956
957 if ( getContainer() && Source.Source.is() )
958 {
959 if ( Source.Source == m_aCurrentFrame.getFrame() )
960 { // our frame is being disposed -> close the preview window (if we have one)
961 Reference< XFrame2 > xPreviewFrame( getContainer()->getPreviewFrame() );
962 ::comphelper::disposeComponent( xPreviewFrame );
963 }
964 else if ( Source.Source == getContainer()->getPreviewFrame() )
965 {
966 getContainer()->disposingPreview();
967 }
968 }
969
970 OJoinController_BASE::disposing(Source);
971}
972
973void OQueryController::reconnect(bool _bUI)
974{
975 deleteIterator();
976 ::comphelper::disposeComponent(m_xComposer);
977
978 OJoinController::reconnect( _bUI );
979
980 if (isConnected())
981 {
982 setQueryComposer();
983 }
984 else
985 {
986 if(m_bGraphicalDesign)
987 {
988 m_bGraphicalDesign = false;
989 // don't call Execute(SQL) because this changes the sql statement
990 impl_setViewMode( nullptr );
991 }
992 InvalidateAll();
993 }
994}
995
996void OQueryController::saveViewSettings( ::comphelper::NamedValueCollection& o_rViewSettings, const bool i_includingCriteria ) const
997{
998 saveTableWindows( o_rViewSettings );
999
1000 ::comphelper::NamedValueCollection aAllFieldsData;
1001 ::comphelper::NamedValueCollection aFieldData;
1002 sal_Int32 i = 1;
1003 for (auto const& fieldDesc : m_vTableFieldDesc)
1004 {
1005 if ( !fieldDesc->IsEmpty() )
1006 {
1007 aFieldData.clear();
1008 fieldDesc->Save( aFieldData, i_includingCriteria );
1009
1010 const OUString sFieldSettingName = "Field" + OUString::number( i );
1011 aAllFieldsData.put( sFieldSettingName, aFieldData.getPropertyValues() );
1012 }
1013 ++i;
1014 }
1015
1016 o_rViewSettings.put( "Fields", aAllFieldsData.getPropertyValues() );
1017 o_rViewSettings.put( "SplitterPosition", m_nSplitPos );
1018 o_rViewSettings.put( "VisibleRows", m_nVisibleRows );
1019}
1020
1021void OQueryController::loadViewSettings( const ::comphelper::NamedValueCollection& o_rViewSettings )
1022{
1023 loadTableWindows( o_rViewSettings );
1024
1025 m_nSplitPos = o_rViewSettings.getOrDefault( "SplitterPosition", m_nSplitPos );
1026 m_nVisibleRows = o_rViewSettings.getOrDefault( "VisibleRows", m_nVisibleRows );
1027 m_aFieldInformation = o_rViewSettings.getOrDefault( "Fields", m_aFieldInformation );
1028}
1029
1030void OQueryController::execute_QueryPropDlg()
1031{
1032 QueryPropertiesDialog aQueryPropDlg(getContainer()->GetFrameWeld(), m_bDistinct, m_nLimit);
1033
1034 if (aQueryPropDlg.run() == RET_OK)
1035 {
1036 m_bDistinct = aQueryPropDlg.getDistinct();
1037 m_nLimit = aQueryPropDlg.getLimit();
1038 InvalidateFeature( SID_QUERY_DISTINCT_VALUES( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 49 )
);
1039 InvalidateFeature( SID_QUERY_LIMIT( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 56 )
, nullptr, true );
1040 }
1041}
1042
1043sal_Int32 OQueryController::getColWidth(sal_uInt16 _nColPos) const
1044{
1045 if ( _nColPos < m_aFieldInformation.getLength() )
1046 {
1047 rtl::Reference<OTableFieldDesc> pField( new OTableFieldDesc());
1048 pField->Load( m_aFieldInformation[ _nColPos ], false );
1049 return pField->GetColWidth();
1050 }
1051 return 0;
1052}
1053
1054Reference<XNameAccess> OQueryController::getObjectContainer() const
1055{
1056 Reference< XNameAccess > xElements;
1057 if ( editingView() )
1058 {
1059 Reference< XViewsSupplier > xViewsSupp( getConnection(), UNO_QUERY );
1060 if ( xViewsSupp.is() )
1061 xElements = xViewsSupp->getViews();
1062 }
1063 else
1064 {
1065 Reference< XQueriesSupplier > xQueriesSupp( getConnection(), UNO_QUERY );
1066 if ( xQueriesSupp.is() )
1067 xElements = xQueriesSupp->getQueries();
1068 else
1069 {
1070 Reference< XQueryDefinitionsSupplier > xQueryDefsSupp( getDataSource(), UNO_QUERY );
1071 if ( xQueryDefsSupp.is() )
1072 xElements = xQueryDefsSupp->getQueryDefinitions();
1073 }
1074 }
1075
1076 OSL_ENSURE( xElements.is(), "OQueryController::getObjectContainer: unable to obtain the container!" )do { if (true && (!(xElements.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "1076" ": "), "%s", "OQueryController::getObjectContainer: unable to obtain the container!"
); } } while (false)
;
1077 return xElements;
1078}
1079
1080void OQueryController::executeQuery()
1081{
1082 // we don't need to check the connection here because we already check the composer
1083 // which can't live without his connection
1084 OUString sTranslatedStmt = translateStatement( false );
1085
1086 OUString sDataSourceName = getDataSourceName();
1087 if ( sDataSourceName.isEmpty() || sTranslatedStmt.isEmpty() )
1088 return;
1089
1090 try
1091 {
1092 getContainer()->showPreview( getFrame() );
1093 InvalidateFeature(SID_DB_QUERY_PREVIEW( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 52 )
);
1094
1095 URL aWantToDispatch;
1096 aWantToDispatch.Complete = ".component:DB/DataSourceBrowser";
1097
1098 OUString sFrameName( FRAME_NAME_QUERY_PREVIEW"QueryPreview" );
1099 sal_Int32 nSearchFlags = FrameSearchFlag::CHILDREN;
1100
1101 Reference< XDispatch> xDisp;
1102 Reference< XDispatchProvider> xProv( getFrame()->findFrame( sFrameName, nSearchFlags ), UNO_QUERY );
1103 if(!xProv.is())
1104 {
1105 xProv.set( getFrame(), UNO_QUERY );
1106 if (xProv.is())
1107 xDisp = xProv->queryDispatch(aWantToDispatch, sFrameName, nSearchFlags);
1108 }
1109 else
1110 {
1111 xDisp = xProv->queryDispatch(aWantToDispatch, sFrameName, FrameSearchFlag::SELF);
1112 }
1113 if (xDisp.is())
1114 {
1115 auto aProps(::comphelper::InitPropertySequence(
1116 {
1117 { PROPERTY_DATASOURCENAME"DataSourceName", makeAny(sDataSourceName) },
1118 { PROPERTY_COMMAND_TYPE"CommandType", makeAny(CommandType::COMMAND) },
1119 { PROPERTY_COMMAND"Command", makeAny(sTranslatedStmt) },
1120 { PROPERTY_ENABLE_BROWSER"EnableBrowser", makeAny(false) },
1121 { PROPERTY_ACTIVE_CONNECTION"ActiveConnection", makeAny(getConnection()) },
1122 { PROPERTY_UPDATE_CATALOGNAME"UpdateCatalogName", makeAny(m_sUpdateCatalogName) },
1123 { PROPERTY_UPDATE_SCHEMANAME"UpdateSchemaName", makeAny(m_sUpdateSchemaName) },
1124 { PROPERTY_UPDATE_TABLENAME"UpdateTableName", makeAny(OUString()) },
1125 { PROPERTY_ESCAPE_PROCESSING"EscapeProcessing", makeAny(m_bEscapeProcessing) }
1126 }));
1127
1128 xDisp->dispatch(aWantToDispatch, aProps);
1129 // check the state of the beamer
1130 // be notified when the beamer frame is closed
1131 Reference< XComponent > xComponent = getFrame()->findFrame( sFrameName, nSearchFlags );
1132 if (xComponent.is())
1133 {
1134 OSL_ENSURE(Reference< XFrame >(xComponent, UNO_QUERY).get() == getContainer()->getPreviewFrame().get(),do { if (true && (!(Reference< XFrame >(xComponent
, UNO_QUERY).get() == getContainer()->getPreviewFrame().get
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "1135" ": "), "%s", "OQueryController::executeQuery: oops ... which window do I have here?"
); } } while (false)
1135 "OQueryController::executeQuery: oops ... which window do I have here?")do { if (true && (!(Reference< XFrame >(xComponent
, UNO_QUERY).get() == getContainer()->getPreviewFrame().get
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "1135" ": "), "%s", "OQueryController::executeQuery: oops ... which window do I have here?"
); } } while (false)
;
1136 Reference< XEventListener> xEvtL(static_cast<cppu::OWeakObject*>(this),UNO_QUERY);
1137 xComponent->addEventListener(xEvtL);
1138 }
1139 }
1140 else
1141 {
1142 OSL_FAIL("Couldn't create a beamer window!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "1142" ": "), "%s", "Couldn't create a beamer window!");
} } while (false)
;
1143 }
1144 }
1145 catch(const Exception&)
1146 {
1147 OSL_FAIL("Couldn't create a beamer window!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "1147" ": "), "%s", "Couldn't create a beamer window!");
} } while (false)
;
1148 }
1149}
1150
1151bool OQueryController::askForNewName(const Reference<XNameAccess>& _xElements, bool _bSaveAs)
1152{
1153 OSL_ENSURE( !editingCommand(), "OQueryController::askForNewName: not to be called when designing an independent statement!" )do { if (true && (!(!editingCommand()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "1153" ": "), "%s", "OQueryController::askForNewName: not to be called when designing an independent statement!"
); } } while (false)
;
1154 if ( editingCommand() )
1155 return false;
1156
1157 OSL_PRECOND( _xElements.is(), "OQueryController::askForNewName: invalid container!" )do { if (true && (!(_xElements.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "1157" ": "), "%s", "OQueryController::askForNewName: invalid container!"
); } } while (false)
;
1158 if ( !_xElements.is() )
1159 return false;
1160
1161 bool bRet = true;
1162 bool bNew = _bSaveAs || !_xElements->hasByName( m_sName );
1163 if(bNew)
1164 {
1165 OUString aDefaultName;
1166 if (!m_sName.isEmpty())
1167 aDefaultName = m_sName;
1168 else
1169 {
1170 OUString sName = DBA_RES(editingView() ? STR_VIEW_TITLE : STR_QRY_TITLE)::dbaccess::ResourceManager::loadString( editingView() ? reinterpret_cast
<char const *>("STR_VIEW_TITLE" "\004" u8"View #") : reinterpret_cast
<char const *>("STR_QRY_TITLE" "\004" u8"Query #") )
;
1171 aDefaultName = ::dbtools::createUniqueName(_xElements, sName.getToken(0, ' '));
1172 }
1173
1174 DynamicTableOrQueryNameCheck aNameChecker( getConnection(), CommandType::QUERY );
1175 OSaveAsDlg aDlg(
1176 getFrameWeld(),
1177 m_nCommandType,
1178 getORB(),
1179 getConnection(),
1180 aDefaultName,
1181 aNameChecker,
1182 SADFlags::NONE );
1183
1184 bRet = ( aDlg.run() == RET_OK );
1185 if ( bRet )
1186 {
1187 m_sName = aDlg.getName();
1188 if ( editingView() )
1189 {
1190 m_sUpdateCatalogName = aDlg.getCatalog();
1191 m_sUpdateSchemaName = aDlg.getSchema();
1192 }
1193 }
1194 }
1195 return bRet;
1196}
1197
1198bool OQueryController::doSaveAsDoc(bool _bSaveAs)
1199{
1200 OSL_ENSURE(isEditable(),"Slot ID_BROWSER_SAVEDOC should not be enabled!")do { if (true && (!(isEditable()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "1200" ": "), "%s", "Slot ID_BROWSER_SAVEDOC should not be enabled!"
); } } while (false)
;
1201 if ( !editingCommand() && !haveDataSource() )
1202 {
1203 OUString aMessage(DBA_RES(STR_DATASOURCE_DELETED)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_DATASOURCE_DELETED" "\004" u8"The corresponding data source has been deleted. Therefore, data relevant to that data source cannot be saved."
) )
);
1204 OSQLWarningBox aBox(getFrameWeld(), aMessage);
1205 aBox.run();
1206 return false;
1207 }
1208
1209 Reference< XNameAccess > xElements = getObjectContainer();
1210 if ( !xElements.is() )
1211 return false;
1212
1213 if ( !getContainer()->checkStatement() )
1214 return false;
1215
1216 OUString sTranslatedStmt = translateStatement();
1217 if ( editingCommand() )
1218 {
1219 setModified( false );
1220 // this is all we need to do here. translateStatement implicitly set our m_sStatement, and
1221 // notified it, and that's all
1222 return true;
1223 }
1224
1225 if ( sTranslatedStmt.isEmpty() )
1226 return false;
1227
1228 // first we need a name for our query so ask the user
1229 // did we get a name
1230 OUString sOriginalName( m_sName );
1231 if ( !askForNewName( xElements, _bSaveAs ) || m_sName.isEmpty() )
1232 return false;
1233
1234 SQLExceptionInfo aInfo;
1235 bool bSuccess = false;
1236 bool bNew = false;
1237 try
1238 {
1239 bNew = _bSaveAs
1240 || ( !xElements->hasByName( m_sName ) );
1241
1242 Reference<XPropertySet> xQuery;
1243 if ( bNew ) // just to make sure the query already exists
1244 {
1245 // drop the query, in case it already exists
1246 if ( xElements->hasByName( m_sName ) )
1247 {
1248 Reference< XDrop > xNameCont( xElements, UNO_QUERY );
1249 if ( xNameCont.is() )
1250 xNameCont->dropByName( m_sName );
1251 else
1252 {
1253 Reference< XNameContainer > xCont( xElements, UNO_QUERY );
1254 if ( xCont.is() )
1255 xCont->removeByName( m_sName );
1256 }
1257 }
1258
1259 // create a new (empty, uninitialized) query resp. view
1260 Reference< XDataDescriptorFactory > xFact( xElements, UNO_QUERY );
1261 if ( xFact.is() )
1262 {
1263 xQuery = xFact->createDataDescriptor();
1264 // to set the name is only allowed when the query is new
1265 xQuery->setPropertyValue( PROPERTY_NAME"Name", makeAny( m_sName ) );
1266 }
1267 else
1268 {
1269 Reference< XSingleServiceFactory > xSingleFac( xElements, UNO_QUERY );
1270 if ( xSingleFac.is() )
1271 xQuery.set(xSingleFac->createInstance(), css::uno::UNO_QUERY);
1272 }
1273 }
1274 else
1275 {
1276 xElements->getByName( m_sName ) >>= xQuery;
1277 }
1278 if ( !xQuery.is() )
1279 throw RuntimeException();
1280
1281 // the new commands
1282 if ( editingView() && !bNew )
1283 {
1284 OSL_ENSURE( xQuery == m_xAlterView, "OQueryController::doSaveAsDoc: already have another alterable view ...!?" )do { if (true && (!(xQuery == m_xAlterView))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "1284" ": "), "%s", "OQueryController::doSaveAsDoc: already have another alterable view ...!?"
); } } while (false)
;
1285 m_xAlterView.set( xQuery, UNO_QUERY_THROW );
1286 m_xAlterView->alterCommand( sTranslatedStmt );
1287 }
1288 else
1289 { // we're creating a query, or a *new* view
1290 xQuery->setPropertyValue( PROPERTY_COMMAND"Command", makeAny( sTranslatedStmt ) );
1291
1292 if ( editingView() )
1293 {
1294 xQuery->setPropertyValue( PROPERTY_CATALOGNAME"CatalogName", makeAny( m_sUpdateCatalogName ) );
1295 xQuery->setPropertyValue( PROPERTY_SCHEMANAME"SchemaName", makeAny( m_sUpdateSchemaName ) );
1296 }
1297
1298 if ( editingQuery() )
1299 {
1300 xQuery->setPropertyValue( PROPERTY_UPDATE_TABLENAME"UpdateTableName", makeAny( OUString() ) );
1301 xQuery->setPropertyValue( PROPERTY_ESCAPE_PROCESSING"EscapeProcessing", css::uno::makeAny( m_bEscapeProcessing ) );
1302
1303 xQuery->setPropertyValue( PROPERTY_LAYOUTINFORMATION"LayoutInformation", getViewData() );
1304 }
1305 }
1306
1307 if ( bNew )
1308 {
1309 Reference< XAppend > xAppend( xElements, UNO_QUERY );
1310 if ( xAppend.is() )
1311 {
1312 xAppend->appendByDescriptor( xQuery );
1313 }
1314 else
1315 {
1316 Reference< XNameContainer > xCont( xElements, UNO_QUERY );
1317 if ( xCont.is() )
1318 xCont->insertByName( m_sName, makeAny( xQuery ) );
1319 }
1320
1321 if ( editingView() )
1322 {
1323 Reference< XPropertySet > xViewProps;
1324 if ( xElements->hasByName( m_sName ) )
1325 xViewProps.set( xElements->getByName( m_sName ), UNO_QUERY );
1326
1327 if ( !xViewProps.is() ) // correct name and try again
1328 m_sName = ::dbtools::composeTableName( getMetaData(), xQuery, ::dbtools::EComposeRule::InDataManipulation, false );
1329
1330 OSL_ENSURE( xElements->hasByName( m_sName ), "OQueryController::doSaveAsDoc: newly created view does not exist!" )do { if (true && (!(xElements->hasByName( m_sName )
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "1330" ": "), "%s", "OQueryController::doSaveAsDoc: newly created view does not exist!"
); } } while (false)
;
1331
1332 if ( xElements->hasByName( m_sName ) )
1333 m_xAlterView.set( xElements->getByName( m_sName ), UNO_QUERY );
1334
1335 // now check if our datasource has set a tablefilter and if so, append the new table name to it
1336 ::dbaui::appendToFilter(getConnection(), m_sName, getORB(), getFrameWeld());
1337 }
1338 Reference< XTitleChangeListener> xEventListener(impl_getTitleHelper_throw(),UNO_QUERY);
1339 if ( xEventListener.is() )
1340 {
1341 TitleChangedEvent aEvent;
1342 xEventListener->titleChanged(aEvent);
1343 }
1344 releaseNumberForComponent();
1345 }
1346
1347 setModified( false );
1348 bSuccess = true;
1349
1350 }
1351 catch(const SQLException&)
1352 {
1353 if ( !bNew )
1354 m_sName = sOriginalName;
1355 aInfo = SQLExceptionInfo( ::cppu::getCaughtException() );
1356 }
1357 catch(const Exception&)
1358 {
1359 DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "1359" ": ", "dbaccess" );
;
1360 if ( !bNew )
1361 m_sName = sOriginalName;
1362 }
1363
1364 showError( aInfo );
1365
1366 // if we successfully saved a view we were creating, then close the designer
1367 if ( bSuccess && editingView() && !m_xAlterView.is() )
1368 {
1369 closeTask();
1370 }
1371
1372 if ( bSuccess && editingView() )
1373 InvalidateFeature( ID_BROWSER_EDITDOC(5000 + 1312) );
1374
1375 return bSuccess;
1376}
1377
1378namespace {
1379struct CommentStrip
1380{
1381 OUString maComment;
1382 bool mbLastOnLine;
1383 CommentStrip( const OUString& rComment, bool bLastOnLine )
1384 : maComment( rComment), mbLastOnLine( bLastOnLine) {}
1385};
1386
1387}
1388
1389/** Obtain all comments in a query.
1390
1391 See also delComment() implementation for OSQLParser::parseTree().
1392 */
1393static std::vector< CommentStrip > getComment( const OUString& rQuery )
1394{
1395 std::vector< CommentStrip > aRet;
1396 // First a quick search if there is any "--" or "//" or "/*", if not then
1397 // the whole copying loop is pointless.
1398 if (rQuery.indexOf( "--" ) < 0 && rQuery.indexOf( "//" ) < 0 &&
1399 rQuery.indexOf( "/*" ) < 0)
1400 return aRet;
1401
1402 const sal_Unicode* pCopy = rQuery.getStr();
1403 const sal_Int32 nQueryLen = rQuery.getLength();
1404 bool bIsText1 = false; // "text"
1405 bool bIsText2 = false; // 'text'
1406 bool bComment2 = false; // /* comment */
1407 bool bComment = false; // -- or // comment
1408 OUStringBuffer aBuf;
1409 for (sal_Int32 i=0; i < nQueryLen; ++i)
1410 {
1411 if (bComment2)
1412 {
1413 aBuf.append( &pCopy[i], 1);
1414 if ((i+1) < nQueryLen)
1415 {
1416 if (pCopy[i]=='*' && pCopy[i+1]=='/')
1417 {
1418 bComment2 = false;
1419 aBuf.append( &pCopy[++i], 1);
1420 aRet.emplace_back( aBuf.makeStringAndClear(), false);
1421 }
1422 }
1423 else
1424 {
1425 // comment can't close anymore, actually an error, but...
1426 aRet.emplace_back( aBuf.makeStringAndClear(), false);
1427 }
1428 continue;
1429 }
1430 if (pCopy[i] == '\n' || i == nQueryLen-1)
1431 {
1432 if (bComment)
1433 {
1434 if (i == nQueryLen-1 && pCopy[i] != '\n')
1435 aBuf.append( &pCopy[i], 1);
1436 aRet.emplace_back( aBuf.makeStringAndClear(), true);
1437 bComment = false;
1438 }
1439 else if (!aRet.empty())
1440 aRet.back().mbLastOnLine = true;
1441 }
1442 else if (!bComment)
1443 {
1444 if (pCopy[i] == '\"' && !bIsText2)
1445 bIsText1 = !bIsText1;
1446 else if (pCopy[i] == '\'' && !bIsText1)
1447 bIsText2 = !bIsText2;
1448 if (!bIsText1 && !bIsText2 && (i+1) < nQueryLen)
1449 {
1450 if ((pCopy[i]=='-' && pCopy[i+1]=='-') || (pCopy[i]=='/' && pCopy[i+1]=='/'))
1451 bComment = true;
1452 else if (pCopy[i]=='/' && pCopy[i+1]=='*')
1453 bComment2 = true;
1454 }
1455 }
1456 if (bComment || bComment2)
1457 aBuf.append( &pCopy[i], 1);
1458 }
1459 return aRet;
1460}
1461
1462/** Concat/insert comments that were previously obtained with getComment().
1463
1464 NOTE: The current parser implementation does not preserve newlines, so all
1465 comments are always appended to the entire query, also inline comments
1466 that would need positioning anyway that can't be obtained after
1467 recomposition. This is ugly but at least allows commented queries while
1468 preserving the comments _somehow_.
1469 */
1470static OUString concatComment( const OUString& rQuery, const std::vector< CommentStrip >& rComments )
1471{
1472 // No comments => return query.
1473 if (rComments.empty())
1474 return rQuery;
1475
1476 const sal_Unicode* pBeg = rQuery.getStr();
1477 const sal_Int32 nLen = rQuery.getLength();
1478 const size_t nComments = rComments.size();
1479 // Obtaining the needed size once should be faster than reallocating.
1480 // Also add a blank or linefeed for each comment.
1481 sal_Int32 nBufSize = nLen + nComments;
1482 for (auto const& comment : rComments)
1483 nBufSize += comment.maComment.getLength();
1484 OUStringBuffer aBuf( nBufSize );
1485 sal_Int32 nIndBeg = 0;
1486 sal_Int32 nIndLF = rQuery.indexOf('\n');
1487 size_t i = 0;
1488 while (nIndLF >= 0 && i < nComments)
1489 {
1490 aBuf.append( pBeg + nIndBeg, nIndLF - nIndBeg);
1491 do
1492 {
1493 aBuf.append( rComments[i].maComment);
1494 } while (!rComments[i++].mbLastOnLine && i < nComments);
1495 aBuf.append( pBeg + nIndLF, 1); // the LF
1496 nIndBeg = nIndLF + 1;
1497 nIndLF = (nIndBeg < nLen ? rQuery.indexOf( '\n', nIndBeg) : -1);
1498 }
1499 // Append remainder of query.
1500 if (nIndBeg < nLen)
1501 aBuf.append( pBeg + nIndBeg, nLen - nIndBeg);
1502 // Append all remaining comments, preserve lines.
1503 bool bNewLine = false;
1504 for ( ; i < nComments; ++i)
1505 {
1506 if (!bNewLine)
1507 aBuf.append( ' ');
1508 aBuf.append( rComments[i].maComment);
1509 if (rComments[i].mbLastOnLine)
1510 {
1511 aBuf.append( '\n');
1512 bNewLine = true;
1513 }
1514 else
1515 bNewLine = false;
1516 }
1517 return aBuf.makeStringAndClear();
1518}
1519
1520OUString OQueryController::translateStatement( bool _bFireStatementChange )
1521{
1522 // now set the properties
1523 setStatement_fireEvent( getContainer()->getStatement(), _bFireStatementChange );
1524 OUString sTranslatedStmt;
1525 if(!m_sStatement.isEmpty() && m_xComposer.is() && m_bEscapeProcessing)
1526 {
1527 try
1528 {
1529 OUString aErrorMsg;
1530
1531 std::vector< CommentStrip > aComments = getComment( m_sStatement);
1532
1533 std::unique_ptr<::connectivity::OSQLParseNode> pNode = m_aSqlParser.parseTree( aErrorMsg, m_sStatement, m_bGraphicalDesign );
1534 if(pNode)
1535 {
1536 pNode->parseNodeToStr( sTranslatedStmt, getConnection() );
1537 }
1538
1539 m_xComposer->setQuery(sTranslatedStmt);
1540 sTranslatedStmt = m_xComposer->getComposedQuery();
1541 sTranslatedStmt = concatComment( sTranslatedStmt, aComments);
1542 }
1543 catch(const SQLException& e)
1544 {
1545 ::dbtools::SQLExceptionInfo aInfo(e);
1546 showError(aInfo);
1547 // an error occurred so we clear the statement
1548 sTranslatedStmt.clear();
1549 }
1550 }
1551 else if(m_sStatement.isEmpty())
1552 {
1553 showError(SQLException(DBA_RES(STR_QRY_NOSELECT)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_QRY_NOSELECT" "\004" u8"Nothing has been selected."
) )
, nullptr, "S1000", 1000, Any()));
1554 }
1555 else
1556 sTranslatedStmt = m_sStatement;
1557
1558 return sTranslatedStmt;
1559}
1560
1561short OQueryController::saveModified()
1562{
1563 SolarMutexGuard aSolarGuard;
1564 ::osl::MutexGuard aGuard( getMutex() );
1565 short nRet = RET_YES;
1566 if ( !isConnected() || !isModified() )
1567 return nRet;
1568
1569 if ( !m_bGraphicalDesign
1570 || ( !m_vTableFieldDesc.empty()
1571 && !m_vTableData.empty()
1572 )
1573 )
1574 {
1575 OUString sMessageText( lcl_getObjectResourceString( STR_QUERY_SAVEMODIFIEDreinterpret_cast<char const *>("STR_QUERY_SAVEMODIFIED"
"\004" u8"$object$ has been changed.\nDo you want to save the changes?"
)
, m_nCommandType ) );
1576
1577 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(getFrameWeld(),
1578 VclMessageType::Question, VclButtonsType::YesNo,
1579 sMessageText));
1580 xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL);
1581 xQueryBox->set_default_response(RET_YES);
1582
1583 nRet = xQueryBox->run();
1584 if ( ( nRet == RET_YES )
1585 && !doSaveAsDoc( false )
1586 )
1587 {
1588 nRet = RET_CANCEL;
1589 }
1590 }
1591 return nRet;
1592}
1593
1594void OQueryController::impl_reset( const bool i_bForceCurrentControllerSettings )
1595{
1596 bool bValid = false;
1597
1598 Sequence< PropertyValue > aLayoutInformation;
1599 // get command from the query if a query name was supplied
1600 if ( !i_bForceCurrentControllerSettings && !editingCommand() )
1601 {
1602 if ( !m_sName.isEmpty() )
1603 {
1604 Reference< XNameAccess > xQueries = getObjectContainer();
1605 if ( xQueries.is() )
1606 {
1607 Reference< XPropertySet > xProp;
1608 if( xQueries->hasByName( m_sName ) && ( xQueries->getByName( m_sName ) >>= xProp ) && xProp.is() )
1609 {
1610 OUString sNewStatement;
1611 xProp->getPropertyValue( PROPERTY_COMMAND"Command" ) >>= sNewStatement;
1612 setStatement_fireEvent( sNewStatement );
1613
1614 if ( editingQuery() )
1615 {
1616 bool bNewEscapeProcessing( true );
1617 xProp->getPropertyValue( PROPERTY_ESCAPE_PROCESSING"EscapeProcessing" ) >>= bNewEscapeProcessing;
1618 setEscapeProcessing_fireEvent( bNewEscapeProcessing );
1619 }
1620
1621 m_bGraphicalDesign = m_bGraphicalDesign && m_bEscapeProcessing;
1622 bValid = true;
1623
1624 try
1625 {
1626 if ( editingQuery() )
1627 xProp->getPropertyValue( PROPERTY_LAYOUTINFORMATION"LayoutInformation" ) >>= aLayoutInformation;
1628 }
1629 catch( const Exception& )
1630 {
1631 OSL_FAIL( "OQueryController::impl_reset: could not retrieve the layout information from the query!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "1631" ": "), "%s", "OQueryController::impl_reset: could not retrieve the layout information from the query!"
); } } while (false)
;
1632 }
1633 }
1634 }
1635 }
1636 }
1637 else
1638 {
1639 bValid = true;
1640 // assume that we got all necessary information during initialization
1641 }
1642
1643 if ( bValid )
1644 {
1645 // load the layoutInformation
1646 if ( aLayoutInformation.hasElements() )
1647 {
1648 try
1649 {
1650 loadViewSettings( aLayoutInformation );
1651 }
1652 catch( const Exception& )
1653 {
1654 DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "1654" ": ", "dbaccess" );
;
1655 }
1656 }
1657
1658 if ( !m_sStatement.isEmpty() )
1659 {
1660 setQueryComposer();
1661
1662 bool bError( false );
1663
1664 if ( !m_pSqlIterator )
1665 {
1666 bError = true;
1667 }
1668 else if ( m_bEscapeProcessing )
1669 {
1670 OUString aErrorMsg;
1671 std::unique_ptr< ::connectivity::OSQLParseNode > pNode(
1672 m_aSqlParser.parseTree( aErrorMsg, m_sStatement, m_bGraphicalDesign ) );
1673
1674 if (pNode)
1675 {
1676 delete m_pSqlIterator->getParseTree();
1677 m_pSqlIterator->setParseTree( pNode.release() );
1678 m_pSqlIterator->traverseAll();
1679 if ( m_pSqlIterator->hasErrors() )
1680 {
1681 if ( !i_bForceCurrentControllerSettings && m_bGraphicalDesign && !editingView() )
1682 {
1683 impl_showAutoSQLViewError( makeAny( m_pSqlIterator->getErrors() ) );
1684 }
1685 bError = true;
1686 }
1687 }
1688 else
1689 {
1690 if ( !i_bForceCurrentControllerSettings && !editingView() )
1691 {
1692 OUString aTitle(DBA_RES(STR_SVT_SQL_SYNTAX_ERROR)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_SVT_SQL_SYNTAX_ERROR" "\004" u8"Syntax error in SQL statement"
) )
);
1693 OSQLMessageBox aDlg(getFrameWeld(), aTitle, aErrorMsg);
1694 aDlg.run();
1695 }
1696 bError = true;
1697 }
1698 }
1699
1700 if ( bError )
1701 {
1702 m_bGraphicalDesign = false;
1703 if ( editingView() )
1704 // if we're editing a view whose statement could not be parsed, default to "no escape processing"
1705 setEscapeProcessing_fireEvent( false );
1706 }
1707 }
1708 }
1709
1710 if(!m_pSqlIterator)
1711 setQueryComposer();
1712 OSL_ENSURE(m_pSqlIterator,"No SQLIterator set!")do { if (true && (!(m_pSqlIterator))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "1712" ": "), "%s", "No SQLIterator set!"); } } while (false
)
;
1713
1714 getContainer()->setNoneVisibleRow(m_nVisibleRows);
1715}
1716
1717void OQueryController::reset()
1718{
1719 impl_reset();
1720 getContainer()->reset();
1721 ClearUndoManager();
1722}
1723
1724void OQueryController::setStatement_fireEvent( const OUString& _rNewStatement, bool _bFireStatementChange )
1725{
1726 Any aOldValue = makeAny( m_sStatement );
1727 m_sStatement = _rNewStatement;
1728 Any aNewValue = makeAny( m_sStatement );
1729
1730 sal_Int32 nHandle = PROPERTY_ID_ACTIVECOMMAND56;
1731 if ( _bFireStatementChange )
1732 fire( &nHandle, &aNewValue, &aOldValue, 1, false );
1733}
1734
1735void OQueryController::setEscapeProcessing_fireEvent( const bool _bEscapeProcessing )
1736{
1737 if ( _bEscapeProcessing == m_bEscapeProcessing )
1738 return;
1739
1740 Any aOldValue = makeAny( m_bEscapeProcessing );
1741 m_bEscapeProcessing = _bEscapeProcessing;
1742 Any aNewValue = makeAny( m_bEscapeProcessing );
1743
1744 sal_Int32 nHandle = PROPERTY_ID_ESCAPE_PROCESSING11;
1745 fire( &nHandle, &aNewValue, &aOldValue, 1, false );
1746}
1747
1748IMPL_LINK_NOARG( OQueryController, OnExecuteAddTable, void*, void )void OQueryController::LinkStubOnExecuteAddTable(void * instance
, void* data) { return static_cast<OQueryController *>(
instance)->OnExecuteAddTable(data); } void OQueryController
::OnExecuteAddTable(__attribute__ ((unused)) void*)
1749{
1750 Execute( ID_BROWSER_ADDTABLE( 10000 + 722 ),Sequence<PropertyValue>() );
1751}
1752
1753bool OQueryController::allowViews() const
1754{
1755 return true;
1756}
1757
1758bool OQueryController::allowQueries() const
1759{
1760 OSL_ENSURE( getSdbMetaData().isConnected(), "OQueryController::allowQueries: illegal call!" )do { if (true && (!(getSdbMetaData().isConnected())))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/querydesign/querycontroller.cxx"
":" "1760" ": "), "%s", "OQueryController::allowQueries: illegal call!"
); } } while (false)
;
1761 if ( !getSdbMetaData().supportsSubqueriesInFrom() )
1762 return false;
1763
1764 const NamedValueCollection& rArguments( getInitParams() );
1765 sal_Int32 nCommandType = rArguments.getOrDefault( PROPERTY_COMMAND_TYPE"CommandType", sal_Int32(CommandType::QUERY) );
1766 bool bCreatingView = ( nCommandType == CommandType::TABLE );
1767 return !bCreatingView;
1768}
1769
1770Any SAL_CALL OQueryController::getViewData()
1771{
1772 ::osl::MutexGuard aGuard( getMutex() );
1773
1774 getContainer()->SaveUIConfig();
1775
1776 ::comphelper::NamedValueCollection aViewSettings;
1777 saveViewSettings( aViewSettings, false );
1778
1779 return makeAny( aViewSettings.getPropertyValues() );
1780}
1781
1782void SAL_CALL OQueryController::restoreViewData(const Any& /*Data*/)
1783{
1784 // TODO
1785}
1786
1787} // namespace dbaui
1788
1789/* 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 );
2
Memory is allocated
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
205 if (aTmp.get()) {
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

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

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
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
5.1
Field 'm_pBody' is non-null
15.1
Field 'm_pBody' is non-null
5.1
Field 'm_pBody' is non-null
15.1
Field 'm_pBody' is non-null
5.1
Field 'm_pBody' is non-null
15.1
Field 'm_pBody' is non-null
5.1
Field 'm_pBody' is non-null
15.1
Field 'm_pBody' is non-null
)
6
Taking true branch
16
Taking true branch
113 m_pBody->release();
7
Calling 'VclReferenceBase::release'
11
Returning; memory was released
17
Use of memory after it is freed
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody)
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
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)
8
Assuming the condition is true
9
Taking true branch
40 delete this;
10
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