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_extensions.hxx"
30 #include "abspilot.hxx"
31 #include "abpilot.hrc"
32 #include "abpresid.hrc"
33 #include "componentmodule.hxx"
34 #include <tools/debug.hxx>
35 #include <svtools/localresaccess.hxx>
36 #include "typeselectionpage.hxx"
37 #include "admininvokationpage.hxx"
38 #include "tableselectionpage.hxx"
39 #include <vcl/waitobj.hxx>
40 #include <vcl/msgbox.hxx>
41 #include "abpfinalpage.hxx"
42 #include "fieldmappingpage.hxx"
43 #include "fieldmappingimpl.hxx"
44 
45 //.........................................................................
46 namespace abp
47 {
48 //.........................................................................
49 
50 #define STATE_SELECT_ABTYPE         0
51 #define STATE_INVOKE_ADMIN_DIALOG   1
52 #define STATE_TABLE_SELECTION       2
53 #define STATE_MANUAL_FIELD_MAPPING  3
54 #define STATE_FINAL_CONFIRM         4
55 
56 #define PATH_COMPLETE               1
57 #define PATH_NO_SETTINGS            2
58 #define PATH_NO_FIELDS              3
59 #define PATH_NO_SETTINGS_NO_FIELDS  4
60 
61 	using namespace ::svt;
62 	using namespace ::com::sun::star::uno;
63 	using namespace ::com::sun::star::lang;
64 
65 	//=====================================================================
66 	//= OAddessBookSourcePilot
67 	//=====================================================================
68 	//---------------------------------------------------------------------
69 	OAddessBookSourcePilot::OAddessBookSourcePilot(Window* _pParent, const Reference< XMultiServiceFactory >& _rxORB)
70 		:OAddessBookSourcePilot_Base( _pParent, ModuleRes( RID_DLG_ADDRESSBOOKSOURCEPILOT ),
71             WZB_HELP | WZB_FINISH | WZB_CANCEL | WZB_NEXT | WZB_PREVIOUS )
72 		,m_xORB(_rxORB)
73 		,m_aNewDataSource(_rxORB)
74 		,m_eNewDataSourceType( AST_INVALID )
75 	{
76 		SetPageSizePixel(LogicToPixel(Size(WINDOW_SIZE_X, WINDOW_SIZE_Y), MAP_APPFONT));
77 
78 		ShowButtonFixedLine(sal_True);
79 
80         declarePath( PATH_COMPLETE,
81             STATE_SELECT_ABTYPE,
82             STATE_INVOKE_ADMIN_DIALOG,
83             STATE_TABLE_SELECTION,
84             STATE_MANUAL_FIELD_MAPPING,
85             STATE_FINAL_CONFIRM,
86             WZS_INVALID_STATE
87         );
88         declarePath( PATH_NO_SETTINGS,
89             STATE_SELECT_ABTYPE,
90             STATE_TABLE_SELECTION,
91             STATE_MANUAL_FIELD_MAPPING,
92             STATE_FINAL_CONFIRM,
93             WZS_INVALID_STATE
94         );
95         declarePath( PATH_NO_FIELDS,
96             STATE_SELECT_ABTYPE,
97             STATE_INVOKE_ADMIN_DIALOG,
98             STATE_TABLE_SELECTION,
99             STATE_FINAL_CONFIRM,
100             WZS_INVALID_STATE
101         );
102         declarePath( PATH_NO_SETTINGS_NO_FIELDS,
103             STATE_SELECT_ABTYPE,
104             STATE_TABLE_SELECTION,
105             STATE_FINAL_CONFIRM,
106             WZS_INVALID_STATE
107         );
108 
109 		m_pPrevPage->SetHelpId(HID_ABSPILOT_PREVIOUS);
110 		m_pNextPage->SetHelpId(HID_ABSPILOT_NEXT);
111 		m_pCancel->SetHelpId(HID_ABSPILOT_CANCEL);
112 		m_pFinish->SetHelpId(HID_ABSPILOT_FINISH);
113 		m_pHelp->SetUniqueId(UID_ABSPILOT_HELP);
114 
115 		m_pCancel->SetClickHdl( LINK( this, OAddessBookSourcePilot, OnCancelClicked) );
116 
117 		// some initial settings
118 #ifdef MACOSX
119         m_aSettings.eType = AST_MACAB;
120 #elif WITH_MOZILLA
121 #ifdef UNX
122 		m_aSettings.eType = AST_MORK;
123 #else
124 		m_aSettings.eType = AST_OE;
125 #endif
126 #else
127 		m_aSettings.eType = AST_OTHER;
128 #endif
129 		m_aSettings.sDataSourceName = String(ModuleRes(RID_STR_DEFAULT_NAME));
130 		m_aSettings.bRegisterDataSource = false;
131 		m_aSettings.bIgnoreNoTable = false;
132 
133 		defaultButton(WZB_NEXT);
134 		enableButtons(WZB_FINISH, sal_False);
135 		ActivatePage();
136 
137         typeSelectionChanged( m_aSettings.eType );
138 	}
139 
140 	//---------------------------------------------------------------------
141 	String OAddessBookSourcePilot::getStateDisplayName( WizardState _nState ) const
142     {
143         sal_uInt16 nResId = 0;
144         switch ( _nState )
145         {
146             case STATE_SELECT_ABTYPE:        nResId = STR_SELECT_ABTYPE; break;
147             case STATE_INVOKE_ADMIN_DIALOG:  nResId = STR_INVOKE_ADMIN_DIALOG; break;
148             case STATE_TABLE_SELECTION:      nResId = STR_TABLE_SELECTION; break;
149             case STATE_MANUAL_FIELD_MAPPING: nResId = STR_MANUAL_FIELD_MAPPING; break;
150             case STATE_FINAL_CONFIRM:        nResId = STR_FINAL_CONFIRM; break;
151         }
152         DBG_ASSERT( nResId, "OAddessBookSourcePilot::getStateDisplayName: don't know this state!" );
153 
154         String sDisplayName;
155         if ( nResId )
156         {
157             svt::OLocalResourceAccess aAccess( ModuleRes( RID_DLG_ADDRESSBOOKSOURCEPILOT ), RSC_MODALDIALOG );
158             sDisplayName = String( ModuleRes( nResId ) );
159         }
160 
161         return sDisplayName;
162     }
163 
164 	//---------------------------------------------------------------------
165 	void OAddessBookSourcePilot::implCommitAll()
166 	{
167 		// in real, the data source already exists in the data source context
168 		// Thus, if the user changed the name, we have to rename the data source
169 		if ( m_aSettings.sDataSourceName != m_aNewDataSource.getName() )
170 			m_aNewDataSource.rename( m_aSettings.sDataSourceName );
171 
172 		// 1. the data source
173 		m_aNewDataSource.store();
174 
175 		// 2. check if we need to register the data source
176 		if ( m_aSettings.bRegisterDataSource )
177 			m_aNewDataSource.registerDataSource(m_aSettings.sRegisteredDataSourceName);
178 
179 		// 3. write the data source / table names into the configuration
180 		addressconfig::writeTemplateAddressSource( getORB(), m_aSettings.bRegisterDataSource ? m_aSettings.sRegisteredDataSourceName : m_aSettings.sDataSourceName, m_aSettings.sSelectedTable );
181 
182 		// 4. write the field mapping
183 		fieldmapping::writeTemplateAddressFieldMapping( getORB(), m_aSettings.aFieldMapping );
184 	}
185 
186 	//---------------------------------------------------------------------
187 	void OAddessBookSourcePilot::implCleanup()
188 	{
189 		if ( m_aNewDataSource.isValid() )
190 			m_aNewDataSource.remove();
191 	}
192 
193 	//---------------------------------------------------------------------
194 	IMPL_LINK( OAddessBookSourcePilot, OnCancelClicked, void*, /*NOTINTERESTEDIN*/ )
195 	{
196 		// do cleanups
197 		implCleanup();
198 
199 		// reset the click hdl
200 		m_pCancel->SetClickHdl( Link() );
201 		// simulate the click again - this time, the default handling of the button will strike ....
202 		m_pCancel->Click();
203 
204 		return 0L;
205 	}
206 
207 	//---------------------------------------------------------------------
208 	sal_Bool OAddessBookSourcePilot::Close()
209 	{
210 		implCleanup();
211 
212 		return OAddessBookSourcePilot_Base::Close();
213 	}
214 
215 	//---------------------------------------------------------------------
216 	sal_Bool OAddessBookSourcePilot::onFinish()
217 	{
218 		if ( !OAddessBookSourcePilot_Base::onFinish() )
219 			return sal_False;
220 
221 		implCommitAll();
222 
223 		addressconfig::markPilotSuccess( getORB() );
224 
225 		return sal_True;
226 	}
227 
228 	//---------------------------------------------------------------------
229 	void OAddessBookSourcePilot::enterState( WizardState _nState )
230 	{
231 		switch ( _nState )
232 		{
233 			case STATE_SELECT_ABTYPE:
234                 impl_updateRoadmap( static_cast< TypeSelectionPage* >( GetPage( STATE_SELECT_ABTYPE ) )->getSelectedType() );
235                 break;
236 
237 			case STATE_FINAL_CONFIRM:
238 				if ( !needManualFieldMapping( ) )
239 					implDoAutoFieldMapping();
240 				break;
241 
242 			case STATE_TABLE_SELECTION:
243 				implDefaultTableName();
244 				break;
245 		}
246 
247 		OAddessBookSourcePilot_Base::enterState(_nState);
248 	}
249 
250     //---------------------------------------------------------------------
251     sal_Bool OAddessBookSourcePilot::prepareLeaveCurrentState( CommitPageReason _eReason )
252     {
253         if ( !OAddessBookSourcePilot_Base::prepareLeaveCurrentState( _eReason ) )
254             return sal_False;
255 
256         if ( _eReason == eTravelBackward )
257             return sal_True;
258 
259         sal_Bool bAllow = sal_True;
260 
261         switch ( getCurrentState() )
262         {
263         case STATE_SELECT_ABTYPE:
264             implCreateDataSource();
265             if ( needAdminInvokationPage() )
266                 break;
267             // no break here
268 
269         case STATE_INVOKE_ADMIN_DIALOG:
270     		if ( !connectToDataSource( sal_False ) )
271             {
272 	    		// connecting did not succeed -> do not allow proceeding
273                 bAllow = sal_False;
274 		    	break;
275             }
276 
277             // ........................................................
278             // now that we connected to the data source, check whether we need the "table selection" page
279             const StringBag& aTables = m_aNewDataSource.getTableNames();
280 
281 			if ( aTables.empty() )
282             {
283                 if ( RET_YES != QueryBox( this, ModuleRes( RID_QRY_NOTABLES ) ).Execute() )
284                 {
285                     // cannot ask the user, or the user chose to use this data source, though there are no tables
286                     bAllow = sal_False;
287                     break;
288                 }
289 
290 		        m_aSettings.bIgnoreNoTable = true;
291 			}
292 
293             if ( aTables.size() == 1 )
294 			    // remember the one and only table we have
295 			    m_aSettings.sSelectedTable = *aTables.begin();
296 
297             break;
298         }
299 
300         impl_updateRoadmap( m_aSettings.eType );
301         return bAllow;
302     }
303 
304 	//---------------------------------------------------------------------
305 	void OAddessBookSourcePilot::implDefaultTableName()
306 	{
307 		const StringBag& rTableNames = getDataSource().getTableNames();
308 		if ( rTableNames.end() != rTableNames.find( getSettings().sSelectedTable ) )
309 			// already a valid table selected
310 			return;
311 
312 		const sal_Char* pGuess = NULL;
313 		switch ( getSettings().eType )
314 		{
315 			case AST_MORK		        :
316 			case AST_THUNDERBIRD        : pGuess = "Personal Address book"; break;
317 			case AST_LDAP		        : pGuess = "LDAP Directory"; break;
318 			case AST_EVOLUTION          :
319 			case AST_EVOLUTION_GROUPWISE:
320 			case AST_EVOLUTION_LDAP     : pGuess = "Personal"; break;
321             default:
322                 DBG_ERROR( "OAddessBookSourcePilot::implDefaultTableName: unhandled case!" );
323                 return;
324 		}
325 		const ::rtl::OUString sGuess = ::rtl::OUString::createFromAscii( pGuess );
326 		if ( rTableNames.end() != rTableNames.find( sGuess ) )
327 			getSettings().sSelectedTable = sGuess;
328 	}
329 
330 	//---------------------------------------------------------------------
331 	void OAddessBookSourcePilot::implDoAutoFieldMapping()
332 	{
333 		DBG_ASSERT( !needManualFieldMapping( ), "OAddessBookSourcePilot::implDoAutoFieldMapping: invalid call!" );
334 
335 		fieldmapping::defaultMapping( getORB(), m_aSettings.aFieldMapping );
336 	}
337 
338 	//---------------------------------------------------------------------
339 	void OAddessBookSourcePilot::implCreateDataSource()
340 	{
341 		if (m_aNewDataSource.isValid())
342 		{	// we already have a data source object
343 			if ( m_aSettings.eType == m_eNewDataSourceType )
344 				// and it already has the correct type
345 				return;
346 
347 			// it has a wrong type -> remove it
348 			m_aNewDataSource.remove();
349 		}
350 
351 		ODataSourceContext aContext( getORB() );
352 		aContext.disambiguate( m_aSettings.sDataSourceName );
353 
354 		switch (m_aSettings.eType)
355 		{
356 			case AST_MORK:
357 				m_aNewDataSource = aContext.createNewMORK( m_aSettings.sDataSourceName );
358 				break;
359 
360 			case AST_THUNDERBIRD:
361 				m_aNewDataSource = aContext.createNewThunderbird( m_aSettings.sDataSourceName );
362 				break;
363 
364 			case AST_EVOLUTION:
365 				m_aNewDataSource = aContext.createNewEvolution( m_aSettings.sDataSourceName );
366 				break;
367 
368 			case AST_EVOLUTION_GROUPWISE:
369 				m_aNewDataSource = aContext.createNewEvolutionGroupwise( m_aSettings.sDataSourceName );
370 				break;
371 
372 			case AST_EVOLUTION_LDAP:
373 				m_aNewDataSource = aContext.createNewEvolutionLdap( m_aSettings.sDataSourceName );
374 				break;
375 
376 			case AST_KAB:
377 				m_aNewDataSource = aContext.createNewKab( m_aSettings.sDataSourceName );
378 				break;
379 
380 			case AST_MACAB:
381 				m_aNewDataSource = aContext.createNewMacab( m_aSettings.sDataSourceName );
382 				break;
383 
384 			case AST_LDAP:
385 				m_aNewDataSource = aContext.createNewLDAP( m_aSettings.sDataSourceName );
386 				break;
387 
388 			case AST_OUTLOOK:
389 				m_aNewDataSource = aContext.createNewOutlook( m_aSettings.sDataSourceName );
390 				break;
391 
392 			case AST_OE:
393 				m_aNewDataSource = aContext.createNewOE( m_aSettings.sDataSourceName );
394 				break;
395 
396 			case AST_OTHER:
397 				m_aNewDataSource = aContext.createNewDBase( m_aSettings.sDataSourceName );
398 				break;
399 
400             case AST_INVALID:
401                 DBG_ERROR( "OAddessBookSourcePilot::implCreateDataSource: illegal data source type!" );
402                 break;
403 		}
404 		m_eNewDataSourceType = m_aSettings.eType;
405 	}
406 
407 	//---------------------------------------------------------------------
408 	sal_Bool OAddessBookSourcePilot::connectToDataSource( sal_Bool _bForceReConnect )
409 	{
410 		DBG_ASSERT( m_aNewDataSource.isValid(), "OAddessBookSourcePilot::implConnect: invalid current data source!" );
411 
412 		WaitObject aWaitCursor( this );
413 		if ( _bForceReConnect && m_aNewDataSource.isConnected( ) )
414 			m_aNewDataSource.disconnect( );
415 
416 		return m_aNewDataSource.connect( this );
417 	}
418 
419 	//---------------------------------------------------------------------
420 	OWizardPage* OAddessBookSourcePilot::createPage(WizardState _nState)
421 	{
422 		switch (_nState)
423 		{
424 			case STATE_SELECT_ABTYPE:
425 				return new TypeSelectionPage( this );
426 
427 			case STATE_INVOKE_ADMIN_DIALOG:
428 				return new AdminDialogInvokationPage( this );
429 
430 			case STATE_TABLE_SELECTION:
431 				return new TableSelectionPage( this );
432 
433 			case STATE_MANUAL_FIELD_MAPPING:
434 				return new FieldMappingPage( this );
435 
436 			case STATE_FINAL_CONFIRM:
437 				return new FinalPage( this );
438 
439 			default:
440 				DBG_ERROR("OAddessBookSourcePilot::createPage: invalid state!");
441 				return NULL;
442 		}
443 	}
444 
445     //---------------------------------------------------------------------
446     void OAddessBookSourcePilot::impl_updateRoadmap( AddressSourceType _eType )
447     {
448         bool bSettingsPage = needAdminInvokationPage( _eType );
449         bool bTablesPage   = needTableSelection( _eType );
450         bool bFieldsPage   = needManualFieldMapping( _eType );
451 
452         bool bConnected = m_aNewDataSource.isConnected();
453         bool bCanSkipTables =
454                 (   m_aNewDataSource.hasTable( m_aSettings.sSelectedTable )
455                 ||  m_aSettings.bIgnoreNoTable
456                 );
457 
458         enableState( STATE_INVOKE_ADMIN_DIALOG, bSettingsPage );
459 
460         enableState( STATE_TABLE_SELECTION,
461             bTablesPage &&  ( bConnected ? !bCanSkipTables : !bSettingsPage )
462             // if we do not need a settings page, we connect upon "Next" on the first page
463         );
464 
465         enableState( STATE_MANUAL_FIELD_MAPPING,
466                 bFieldsPage && bConnected && m_aNewDataSource.hasTable( m_aSettings.sSelectedTable )
467         );
468 
469         enableState( STATE_FINAL_CONFIRM,
470             bConnected && bCanSkipTables
471         );
472     }
473 
474     //---------------------------------------------------------------------
475     void OAddessBookSourcePilot::typeSelectionChanged( AddressSourceType _eType )
476     {
477         PathId nCurrentPathID( PATH_COMPLETE );
478         bool bSettingsPage = needAdminInvokationPage( _eType );
479         bool bFieldsPage = needManualFieldMapping( _eType );
480         if ( !bSettingsPage )
481             if ( !bFieldsPage )
482                 nCurrentPathID = PATH_NO_SETTINGS_NO_FIELDS;
483             else
484                 nCurrentPathID = PATH_NO_SETTINGS;
485         else
486             if ( !bFieldsPage )
487                 nCurrentPathID = PATH_NO_FIELDS;
488             else
489                 nCurrentPathID = PATH_COMPLETE;
490         activatePath( nCurrentPathID, true );
491 
492         m_aNewDataSource.disconnect();
493         m_aSettings.bIgnoreNoTable = false;
494         impl_updateRoadmap( _eType );
495     }
496 
497 //.........................................................................
498 }	// namespace abp
499 //.........................................................................
500 
501