1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 
31 #include "svx/databaselocationinput.hxx"
32 #include "svx/dialmgr.hxx"
33 
34 #include "svx/fmresids.hrc"
35 
36 /** === begin UNO includes === **/
37 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
38 /** === end UNO includes === **/
39 
40 #include <comphelper/componentcontext.hxx>
41 #include <comphelper/namedvaluecollection.hxx>
42 #include <rtl/ustrbuf.hxx>
43 #include <sfx2/filedlghelper.hxx>
44 #include <svtools/urlcontrol.hxx>
45 #include <svl/filenotation.hxx>
46 #include <tools/diagnose_ex.h>
47 #include <unotools/confignode.hxx>
48 #include <unotools/ucbhelper.hxx>
49 #include <vcl/button.hxx>
50 #include <vcl/msgbox.hxx>
51 
52 //........................................................................
53 namespace svx
54 {
55 //........................................................................
56 
57 	/** === begin UNO using === **/
58     using ::com::sun::star::uno::Sequence;
59     using ::com::sun::star::uno::Reference;
60     using ::com::sun::star::container::XNameAccess;
61     using ::com::sun::star::uno::UNO_QUERY_THROW;
62     using ::com::sun::star::uno::Exception;
63 	/** === end UNO using === **/
64     namespace TemplateDescription = ::com::sun::star::ui::dialogs::TemplateDescription;
65 
66 	//====================================================================
67 	//= DatabaseLocationInputController_Impl
68 	//====================================================================
69     class DatabaseLocationInputController_Impl
70     {
71     public:
72         DatabaseLocationInputController_Impl(
73             const ::comphelper::ComponentContext&   _rContext,
74             ::svt::OFileURLControl&                 _rLocationInput,
75             PushButton&                             _rBrowseButton
76         );
77         ~DatabaseLocationInputController_Impl();
78 
79         bool    prepareCommit();
80         void    setURL( const String& _rURL );
81         String  getURL() const;
82 
83     private:
84         void    impl_initFilterProperties_nothrow();
85         void    impl_onBrowseButtonClicked();
86         void    impl_onLocationModified();
87         String  impl_getCurrentURL() const;
88 
89         DECL_LINK( OnControlAction, VclWindowEvent* );
90 
91     private:
92         const ::comphelper::ComponentContext    m_aContext;
93         ::svt::OFileURLControl&                 m_rLocationInput;
94         PushButton&                             m_rBrowseButton;
95         Sequence< ::rtl::OUString >             m_aFilterExtensions;
96         ::rtl::OUString                         m_sFilterUIName;
97         bool                                    m_bNeedExistenceCheck;
98     };
99 
100 	//--------------------------------------------------------------------
101     DatabaseLocationInputController_Impl::DatabaseLocationInputController_Impl( const ::comphelper::ComponentContext& _rContext,
102             ::svt::OFileURLControl& _rLocationInput, PushButton& _rBrowseButton )
103         :m_aContext( _rContext )
104         ,m_rLocationInput( _rLocationInput )
105         ,m_rBrowseButton( _rBrowseButton )
106         ,m_aFilterExtensions()
107         ,m_sFilterUIName()
108         ,m_bNeedExistenceCheck( true )
109     {
110         impl_initFilterProperties_nothrow();
111 
112         // forward the allowed extensions to the input control
113         ::rtl::OUStringBuffer aExtensionList;
114         for (   const ::rtl::OUString* pExtension = m_aFilterExtensions.getConstArray();
115                 pExtension != m_aFilterExtensions.getConstArray() + m_aFilterExtensions.getLength();
116                 ++pExtension
117             )
118         {
119             aExtensionList.append( *pExtension );
120             aExtensionList.append( (sal_Unicode)';' );
121         }
122         m_rLocationInput.SetFilter( aExtensionList.makeStringAndClear() );
123 
124         m_rBrowseButton.AddEventListener( LINK( this, DatabaseLocationInputController_Impl, OnControlAction ) );
125         m_rLocationInput.AddEventListener( LINK( this, DatabaseLocationInputController_Impl, OnControlAction ) );
126     }
127 
128     //--------------------------------------------------------------------
129     DatabaseLocationInputController_Impl::~DatabaseLocationInputController_Impl()
130     {
131         m_rBrowseButton.RemoveEventListener( LINK( this, DatabaseLocationInputController_Impl, OnControlAction ) );
132         m_rLocationInput.RemoveEventListener( LINK( this, DatabaseLocationInputController_Impl, OnControlAction ) );
133     }
134 
135 	//--------------------------------------------------------------------
136     bool DatabaseLocationInputController_Impl::prepareCommit()
137     {
138 		::rtl::OUString sURL( impl_getCurrentURL() );
139         if ( !sURL.getLength() )
140             return false;
141 
142         // check if the name exists
143 		if ( m_bNeedExistenceCheck )
144 		{
145 			if ( ::utl::UCBContentHelper::Exists( sURL ) )
146 			{
147 				QueryBox aBox( m_rLocationInput.GetSystemWindow(), WB_YES_NO, SVX_RES( RID_STR_ALREADYEXISTOVERWRITE ) );
148 				if ( aBox.Execute() != RET_YES )
149 					return false;
150 			}
151 		}
152 
153         return true;
154     }
155 
156 	//--------------------------------------------------------------------
157     void DatabaseLocationInputController_Impl::setURL( const String& _rURL )
158     {
159         ::svt::OFileNotation aTransformer( _rURL );
160         m_rLocationInput.SetText( aTransformer.get( ::svt::OFileNotation::N_SYSTEM ) );
161     }
162 
163 	//--------------------------------------------------------------------
164     String DatabaseLocationInputController_Impl::getURL() const
165     {
166         return impl_getCurrentURL();
167     }
168 
169 	//--------------------------------------------------------------------
170     void DatabaseLocationInputController_Impl::impl_initFilterProperties_nothrow()
171     {
172         try
173         {
174             // get the name of the default filter for database documents
175             ::utl::OConfigurationTreeRoot aConfig(
176                 ::utl::OConfigurationTreeRoot::createWithServiceFactory(
177                     m_aContext.getLegacyServiceFactory(),
178                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Setup/Office/Factories/com.sun.star.sdb.OfficeDatabaseDocument" ) )
179             ) );
180             ::rtl::OUString sDatabaseFilter;
181             OSL_VERIFY( aConfig.getNodeValue( "ooSetupFactoryActualFilter" ) >>= sDatabaseFilter );
182 
183             // get the type this filter is responsible for
184             Reference< XNameAccess > xFilterFactory(
185                 m_aContext.createComponent( "com.sun.star.document.FilterFactory" ),
186                 UNO_QUERY_THROW );
187             ::comphelper::NamedValueCollection aFilterProperties( xFilterFactory->getByName( sDatabaseFilter ) );
188             ::rtl::OUString sDocumentType = aFilterProperties.getOrDefault( "Type", ::rtl::OUString() );
189 
190             // get the extension(s) for this type
191             Reference< XNameAccess > xTypeDetection(
192                 m_aContext.createComponent( "com.sun.star.document.TypeDetection" ),
193                 UNO_QUERY_THROW );
194 
195             ::comphelper::NamedValueCollection aTypeProperties( xTypeDetection->getByName( sDocumentType ) );
196             m_aFilterExtensions = aTypeProperties.getOrDefault( "Extensions", m_aFilterExtensions );
197             m_sFilterUIName = aTypeProperties.getOrDefault( "UIName", m_sFilterUIName );
198         }
199         catch( const Exception& )
200         {
201         	DBG_UNHANDLED_EXCEPTION();
202         }
203 
204         // ensure we have at least one extension
205         OSL_ENSURE( m_aFilterExtensions.getLength(),
206             "DatabaseLocationInputController_Impl::impl_initFilterProperties_nothrow: unable to determine the file extension(s)!" );
207         if ( m_aFilterExtensions.getLength() == 0 )
208         {
209             m_aFilterExtensions.realloc(1);
210             m_aFilterExtensions[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*.odb" ) );
211         }
212     }
213 
214     // -----------------------------------------------------------------------------
215     IMPL_LINK( DatabaseLocationInputController_Impl, OnControlAction, VclWindowEvent*, _pEvent )
216     {
217         if  (   ( _pEvent->GetWindow() == &m_rBrowseButton )
218             &&  ( _pEvent->GetId() == VCLEVENT_BUTTON_CLICK )
219             )
220         {
221             impl_onBrowseButtonClicked();
222         }
223 
224         if  (   ( _pEvent->GetWindow() == &m_rLocationInput )
225             &&  ( _pEvent->GetId() == VCLEVENT_EDIT_MODIFY )
226             )
227         {
228             impl_onLocationModified();
229         }
230 
231         return 0L;
232     }
233 
234     // -----------------------------------------------------------------------------
235     String DatabaseLocationInputController_Impl::impl_getCurrentURL() const
236     {
237         String sCurrentFile( m_rLocationInput.GetText() );
238         if ( sCurrentFile.Len() )
239         {
240             ::svt::OFileNotation aCurrentFile( sCurrentFile );
241             sCurrentFile = aCurrentFile.get( ::svt::OFileNotation::N_URL );
242         }
243         return sCurrentFile;
244     }
245 
246     // -----------------------------------------------------------------------------
247     void DatabaseLocationInputController_Impl::impl_onBrowseButtonClicked()
248     {
249         ::sfx2::FileDialogHelper aFileDlg(
250             TemplateDescription::FILESAVE_AUTOEXTENSION,
251             WB_STDMODAL | WB_SAVEAS,
252             m_rLocationInput.GetSystemWindow()
253         );
254         aFileDlg.SetDisplayDirectory( impl_getCurrentURL() );
255 
256         aFileDlg.AddFilter( m_sFilterUIName, ::rtl::OUStringBuffer().appendAscii( "*." ).append( m_aFilterExtensions[0] ).makeStringAndClear() );
257         aFileDlg.SetCurrentFilter( m_sFilterUIName );
258 
259         if ( aFileDlg.Execute() == ERRCODE_NONE )
260         {
261             INetURLObject aURL( aFileDlg.GetPath() );
262             if( aURL.GetProtocol() != INET_PROT_NOT_VALID )
263             {
264                 ::svt::OFileNotation aFileNotation( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
265                 m_rLocationInput.SetText( aFileNotation.get( ::svt::OFileNotation::N_SYSTEM ) );
266                 m_rLocationInput.GetModifyHdl().Call( &m_rLocationInput );
267                 // the dialog already checked for the file's existence, so we don't need to, again
268                 m_bNeedExistenceCheck = false;
269             }
270         }
271     }
272 
273     // -----------------------------------------------------------------------------
274     void DatabaseLocationInputController_Impl::impl_onLocationModified()
275     {
276         m_bNeedExistenceCheck = true;
277     }
278 
279     //====================================================================
280 	//= DatabaseLocationInputController
281 	//====================================================================
282 	//--------------------------------------------------------------------
283     DatabaseLocationInputController::DatabaseLocationInputController( const ::comphelper::ComponentContext& _rContext,
284             ::svt::OFileURLControl& _rLocationInput, PushButton& _rBrowseButton )
285         :m_pImpl( new DatabaseLocationInputController_Impl( _rContext, _rLocationInput, _rBrowseButton ) )
286     {
287     }
288 
289 	//--------------------------------------------------------------------
290     DatabaseLocationInputController::~DatabaseLocationInputController()
291     {
292     }
293 
294 	//--------------------------------------------------------------------
295     bool DatabaseLocationInputController::prepareCommit()
296     {
297         return m_pImpl->prepareCommit();
298     }
299 
300 	//--------------------------------------------------------------------
301     void DatabaseLocationInputController::setURL( const String& _rURL )
302     {
303         m_pImpl->setURL( _rURL );
304     }
305 
306 	//--------------------------------------------------------------------
307     String DatabaseLocationInputController::getURL() const
308     {
309         return m_pImpl->getURL();
310     }
311 
312 //........................................................................
313 } // namespace svx
314 //........................................................................
315