LibreOffice Module extensions (master) 1
sqlcommanddesign.cxx
Go to the documentation of this file.
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 "sqlcommanddesign.hxx"
21#include "formstrings.hxx"
22#include <command.hrc>
23#include "modulepcr.hxx"
24#include "unourl.hxx"
25
26#include <com/sun/star/awt/XWindow.hpp>
27#include <com/sun/star/awt/XTopWindow.hpp>
28#include <com/sun/star/uno/Sequence.hxx>
29#include <com/sun/star/frame/Desktop.hpp>
30#include <com/sun/star/frame/XTitle.hpp>
31#include <com/sun/star/frame/XComponentLoader.hpp>
32#include <com/sun/star/lang/NullPointerException.hpp>
33#include <com/sun/star/lang/DisposedException.hpp>
34#include <com/sun/star/frame/FrameSearchFlag.hpp>
35#include <com/sun/star/sdbc/XConnection.hpp>
36#include <com/sun/star/util/XCloseable.hpp>
37#include <com/sun/star/frame/XDispatchProvider.hpp>
38#include <com/sun/star/sdb/CommandType.hpp>
39
41#include <utility>
43#include <osl/diagnose.h>
44
45
46namespace pcr
47{
48
49
50 using ::com::sun::star::uno::Reference;
51 using ::com::sun::star::beans::PropertyChangeEvent;
52 using ::com::sun::star::uno::RuntimeException;
53 using ::com::sun::star::frame::XFrame;
54 using ::com::sun::star::awt::XTopWindow;
55 using ::com::sun::star::awt::XWindow;
56 using ::com::sun::star::uno::Exception;
57 using ::com::sun::star::uno::UNO_QUERY_THROW;
58 using ::com::sun::star::uno::UNO_QUERY;
59 using ::com::sun::star::beans::PropertyValue;
60 using ::com::sun::star::uno::Sequence;
61 using ::com::sun::star::lang::XComponent;
62 using ::com::sun::star::frame::XComponentLoader;
63 using ::com::sun::star::beans::XPropertySet;
64 using ::com::sun::star::frame::XTitle;
65 using ::com::sun::star::lang::EventObject;
66 using ::com::sun::star::lang::NullPointerException;
67 using ::com::sun::star::lang::DisposedException;
68 using ::com::sun::star::uno::XComponentContext;
69 using ::com::sun::star::frame::XFrames;
70 using ::com::sun::star::util::XCloseable;
71 using ::com::sun::star::lang::XMultiServiceFactory;
72 using ::com::sun::star::frame::XDispatchProvider;
73 using ::com::sun::star::frame::XDispatch;
74 using ::com::sun::star::frame::Desktop;
75 using ::com::sun::star::frame::XDesktop2;
76
77 namespace FrameSearchFlag = ::com::sun::star::frame::FrameSearchFlag;
78 namespace CommandType = ::com::sun::star::sdb::CommandType;
79
80
81 //= ISQLCommandAdapter
82
83
85 {
86 }
87
88
89 //= SQLCommandDesigner
90
91
92 SQLCommandDesigner::SQLCommandDesigner( const Reference< XComponentContext >& _rxContext,
93 const ::rtl::Reference< ISQLCommandAdapter >& _rxPropertyAdapter,
94 ::dbtools::SharedConnection _aConnection, const Link<SQLCommandDesigner&,void>& _rCloseLink )
95 :m_xContext( _rxContext )
96 ,m_xConnection(std::move( _aConnection ))
97 ,m_xObjectAdapter( _rxPropertyAdapter )
98 ,m_aCloseLink( _rCloseLink )
99 {
100 if ( m_xContext.is() )
101 m_xORB = m_xContext->getServiceManager();
102 if ( !m_xORB.is() || !_rxPropertyAdapter.is() || !m_xConnection.is() )
103 throw NullPointerException();
104
105 impl_doOpenDesignerFrame_nothrow();
106 }
107
108
110 {
111 }
112
113
114 void SAL_CALL SQLCommandDesigner::propertyChange( const PropertyChangeEvent& Event )
115 {
116 OSL_ENSURE( m_xDesigner.is() && ( Event.Source == m_xDesigner ), "SQLCommandDesigner::propertyChange: where did this come from?" );
117
118 if ( !(m_xDesigner.is() && ( Event.Source == m_xDesigner )) )
119 return;
120
121 try
122 {
123 if ( PROPERTY_ACTIVECOMMAND == Event.PropertyName )
124 {
125 OUString sCommand;
126 OSL_VERIFY( Event.NewValue >>= sCommand );
127 m_xObjectAdapter->setSQLCommand( sCommand );
128 }
129 else if ( PROPERTY_ESCAPE_PROCESSING == Event.PropertyName )
130 {
131 bool bEscapeProcessing( false );
132 OSL_VERIFY( Event.NewValue >>= bEscapeProcessing );
133 m_xObjectAdapter->setEscapeProcessing( bEscapeProcessing );
134 }
135 }
136 catch( const RuntimeException& ) { throw; }
137 catch( const Exception& )
138 {
139 // not allowed to leave, so silence it
140 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
141 }
142 }
143
144
145 void SAL_CALL SQLCommandDesigner::disposing( const EventObject& Source )
146 {
147 if ( m_xDesigner.is() && ( Source.Source == m_xDesigner ) )
148 {
149 m_aCloseLink.Call( *this );
150 m_xDesigner.clear();
151 }
152 }
153
154
156 {
157 if ( impl_isDisposed() )
158 return;
159
160 if ( isActive() )
162
164 m_xContext.clear();
165 m_xORB.clear();
166 }
167
168
170 {
171 if ( impl_isDisposed() )
172 throw DisposedException();
173 }
174
175
177 {
180 }
181
182
184 {
187 }
188
189
191 {
192 OSL_PRECOND( isActive(), "SQLCommandDesigner::impl_raise_nothrow: not active!" );
193 if ( !isActive() )
194 return;
195
196 try
197 {
198 // activate the frame for this component
199 Reference< XFrame > xFrame( m_xDesigner->getFrame(), css::uno::UNO_SET_THROW );
200 Reference< XWindow > xWindow( xFrame->getContainerWindow(), css::uno::UNO_SET_THROW );
201 Reference< XTopWindow > xTopWindow( xWindow, UNO_QUERY_THROW );
202
203 xTopWindow->toFront();
204 xWindow->setFocus();
205 }
206 catch( const Exception& )
207 {
208 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
209 }
210 }
211
212
214 {
215 OSL_PRECOND( !isActive(),
216 "SQLCommandDesigner::impl_doOpenDesignerFrame_nothrow: already active!" );
217 OSL_PRECOND( m_xConnection.is(), "SQLCommandDesigner::impl_doOpenDesignerFrame_nothrow: this will crash!" );
218 osl_atomic_increment(&m_refCount);
219
220 try
221 {
222 // for various reasons, we don't want the new frame to appear in the desktop's frame list
223 // thus, we create a blank frame at the desktop, remove it from the desktop's frame list
224 // immediately, and then load the component into this blank (and now parent-less) frame
225 Reference< XComponentLoader > xLoader( impl_createEmptyParentlessTask_nothrow(), UNO_QUERY_THROW );
226 const bool bEscapeProcessing = m_xObjectAdapter->getEscapeProcessing();
227 Sequence< PropertyValue > aArgs{
232 comphelper::makePropertyValue("GraphicalDesign", bEscapeProcessing)
233 };
234
235 Reference< XComponent > xQueryDesign = xLoader->loadComponentFromURL(
236 ".component:DB/QueryDesign",
237 "_self",
238 FrameSearchFlag::TASKS | FrameSearchFlag::CREATE,
239 aArgs
240 );
241
242 // remember this newly loaded component - we need to care for it e.g. when we're suspended
243 m_xDesigner.set(xQueryDesign, css::uno::UNO_QUERY);
244 OSL_ENSURE( m_xDesigner.is() || !xQueryDesign.is(), "SQLCommandDesigner::impl_doOpenDesignerFrame_nothrow: the component is expected to be a controller!" );
245 if ( m_xDesigner.is() )
246 {
247 Reference< XPropertySet > xQueryDesignProps( m_xDesigner, UNO_QUERY );
248 OSL_ENSURE( xQueryDesignProps.is(), "SQLCommandDesigner::impl_doOpenDesignerFrame_nothrow: the controller should have properties!" );
249 if ( xQueryDesignProps.is() )
250 {
251 xQueryDesignProps->addPropertyChangeListener( PROPERTY_ACTIVECOMMAND, this );
252 xQueryDesignProps->addPropertyChangeListener( PROPERTY_ESCAPE_PROCESSING, this );
253 }
254 }
255
256 // get the frame which we just opened and set its title
257 Reference< XTitle> xTitle(xQueryDesign,UNO_QUERY);
258 if ( xTitle.is() )
259 {
260 OUString sDisplayName = PcrRes(RID_RSC_ENUM_COMMAND_TYPE[CommandType::COMMAND]);
261 xTitle->setTitle(sDisplayName);
262 }
263 }
264 catch( const Exception& )
265 {
266 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
267 m_xDesigner.clear();
268 }
269 osl_atomic_decrement(&m_refCount);
270 }
271
272
274 {
275 OSL_PRECOND( m_xORB.is(), "SQLCommandDesigner::impl_createEmptyParentlessTask_nothrow: this will crash!" );
276
277 Reference< XFrame > xFrame;
278 try
279 {
280 Reference< XDesktop2 > xDesktop = Desktop::create(m_xContext);
281
282 Reference< XFrames > xDesktopFramesCollection( xDesktop->getFrames(), css::uno::UNO_SET_THROW );
283 xFrame = xDesktop->findFrame( "_blank", FrameSearchFlag::CREATE );
284 OSL_ENSURE( xFrame.is(), "SQLCommandDesigner::impl_createEmptyParentlessTask_nothrow: could not create an empty frame!" );
285 xDesktopFramesCollection->remove( xFrame );
286 }
287 catch( const Exception& )
288 {
289 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
290 }
291 return xFrame;
292 }
293
294
296 {
297 OSL_PRECOND( isActive(), "SQLCommandDesigner::impl_closeDesigner_nothrow: invalid call!" );
298 // close it
299 try
300 {
301 // do not listen anymore...
302 Reference< XPropertySet > xProps( m_xDesigner, UNO_QUERY );
303 if ( xProps.is() )
304 xProps->removePropertyChangeListener( PROPERTY_ACTIVECOMMAND, this );
305
306 // we need to close the frame via the "user interface", by dispatching a close command,
307 // instead of calling XCloseable::close directly. The latter method would also close
308 // the frame, but not care for things like shutting down the office when the last
309 // frame is gone ...
310 const UnoURL aCloseURL( ".uno:CloseDoc",
312
313 Reference< XDispatchProvider > xProvider( m_xDesigner->getFrame(), UNO_QUERY_THROW );
314 Reference< XDispatch > xDispatch( xProvider->queryDispatch( aCloseURL, "_top", FrameSearchFlag::SELF ) );
315 OSL_ENSURE( xDispatch.is(), "SQLCommandDesigner::impl_closeDesigner_nothrow: no dispatcher for the CloseDoc command!" );
316 if ( xDispatch.is() )
317 {
318 xDispatch->dispatch( aCloseURL, Sequence< PropertyValue >( ) );
319 }
320 else
321 {
322 // fallback: use the XCloseable::close (with all possible disadvantages)
323 Reference< XCloseable > xClose( m_xDesigner->getFrame(), UNO_QUERY );
324 if ( xClose.is() )
325 xClose->close( true );
326 }
327 }
328 catch( const Exception& )
329 {
330 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
331 }
332
333 m_xDesigner.clear();
334 }
335
336
338 {
339 OSL_PRECOND( isActive(), "SQLCommandDesigner::impl_trySuspendDesigner_nothrow: no active designer, this will crash!" );
340 bool bAllow = true;
341 try
342 {
343 bAllow = m_xDesigner->suspend( true );
344 }
345 catch( const Exception& )
346 {
347 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
348 }
349 return bAllow;
350 }
351
352
353} // namespace pcr
354
355
356/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual ~ISQLCommandAdapter() override
css::uno::Reference< css::frame::XFrame > impl_createEmptyParentlessTask_nothrow() const
create an empty top-level frame, which does not belong to the desktop's frame list @precond ->m_xORB ...
css::uno::Reference< css::frame::XController > m_xDesigner
void impl_checkDisposed_throw() const
checks whether we are already disposed
virtual ~SQLCommandDesigner() override
::dbtools::SharedConnection m_xConnection
void impl_closeDesigner_nothrow()
closes the component denoted by m_xDesigner @precond our designer component is actually active (->isA...
bool impl_trySuspendDesigner_nothrow() const
suspends our designer component @precond the designer component is actually active (->isActive)
css::uno::Reference< css::lang::XMultiComponentFactory > m_xORB
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
void impl_doOpenDesignerFrame_nothrow()
opens a new frame for interactively designing an SQL command @precond the designer is not currently a...
::rtl::Reference< ISQLCommandAdapter > m_xObjectAdapter
Link< SQLCommandDesigner &, void > m_aCloseLink
SQLCommandDesigner(const css::uno::Reference< css::uno::XComponentContext > &_rxContext, const ::rtl::Reference< ISQLCommandAdapter > &_rxPropertyAdapter, ::dbtools::SharedConnection _aConnection, const Link< SQLCommandDesigner &, void > &_rCloseLink)
creates the instance, and immediately opens the SQL command design frame
bool impl_isDisposed() const
determines whether we are already disposed
virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent &evt) override
bool suspend() const
suspends the designer @precond the designer is active (->isActive) @precond the instance is not dispo...
void impl_raise_nothrow() const
impl-version of ->raise
css::uno::Reference< css::uno::XComponentContext > m_xContext
void raise() const
raises the designer window to top @precond the designer is active (->isActive) @precond the instance ...
bool isActive() const
determines whether the SQL Command designer is currently active, i.e.
void dispose()
disposes the instance so that it becomes non-functional
const css::uno::Reference< INTERFACE > & getTyped() const
#define DBG_UNHANDLED_EXCEPTION(...)
Reference< XDispatch > xDispatch
ULONG m_refCount
Reference< XComponentContext > m_xContext
Definition: filehandler.cxx:78
constexpr OUStringLiteral PROPERTY_COMMAND
constexpr OUStringLiteral PROPERTY_COMMANDTYPE
constexpr OUStringLiteral PROPERTY_ACTIVECOMMAND
constexpr OUStringLiteral PROPERTY_ESCAPE_PROCESSING
constexpr OUStringLiteral PROPERTY_ACTIVE_CONNECTION
OUString sDisplayName
@ Exception
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
a property handler for any virtual string properties
Definition: browserline.cxx:39
OUString PcrRes(TranslateId aId)
Definition: modulepcr.cxx:26
Reference< XConnection > m_xConnection
Reference< XFrame > xFrame