merge the formfield patch from ooo-build
[ooovba.git] / svtools / source / dialogs / addresstemplate.cxx
blobeb76402d7c2e4874400bf783588c2cbbf1f7b9e9
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: addresstemplate.cxx,v $
10 * $Revision: 1.28 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #include <stdio.h>
37 #include "addresstemplate.hxx"
38 #ifndef _SVT_ADDRESSTEMPLATE_HRC_
39 #include "addresstemplate.hrc"
40 #endif
41 #ifndef _SVTOOLS_HRC
42 #include <svtools/svtools.hrc>
43 #endif
44 #ifndef _SVT_HELPID_HRC
45 #include <svtools/helpid.hrc>
46 #endif
47 #include <svtools/svtdata.hxx>
48 #include <tools/debug.hxx>
49 #include <comphelper/processfactory.hxx>
50 #include <comphelper/stl_types.hxx>
51 #include <vcl/stdtext.hxx>
52 #include <vcl/waitobj.hxx>
53 #include <vcl/msgbox.hxx>
54 #include <toolkit/helper/vclunohelper.hxx>
55 #ifndef _CPPUHELPER_EXTRACT_HXX_
56 #include <cppuhelper/extract.hxx>
57 #endif
58 #include <comphelper/interaction.hxx>
59 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
60 #include <com/sun/star/awt/XWindow.hpp>
61 #include <com/sun/star/beans/PropertyValue.hpp>
62 #include <com/sun/star/beans/XPropertySet.hpp>
63 #include <com/sun/star/sdb/XCompletedConnection.hpp>
64 #include <com/sun/star/sdb/SQLContext.hpp>
65 #include <com/sun/star/sdbc/SQLWarning.hpp>
66 #include <com/sun/star/sdbc/XConnection.hpp>
67 #include <com/sun/star/task/XInteractionHandler.hpp>
68 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
69 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
70 #include <com/sun/star/sdb/CommandType.hpp>
71 #include "localresaccess.hxx"
72 #ifndef SVTOOLS_FILENOTATION_HXX_
73 #include "filenotation.hxx"
74 #endif
75 #include <tools/urlobj.hxx>
77 #include <algorithm>
79 // .......................................................................
80 namespace svt
82 // .......................................................................
84 using namespace ::com::sun::star::uno;
85 using namespace ::com::sun::star::lang;
86 using namespace ::com::sun::star::container;
87 using namespace ::com::sun::star::ui::dialogs;
88 using namespace ::com::sun::star::util;
89 using namespace ::com::sun::star::beans;
90 using namespace ::com::sun::star::sdb;
91 using namespace ::com::sun::star::sdbc;
92 using namespace ::com::sun::star::sdbcx;
93 using namespace ::com::sun::star::task;
94 using namespace ::comphelper;
95 using namespace ::utl;
97 DECLARE_STL_VECTOR( String, StringArray );
98 DECLARE_STL_STDKEY_SET( ::rtl::OUString, StringBag );
99 DECLARE_STL_USTRINGACCESS_MAP( ::rtl::OUString, MapString2String );
101 namespace
103 String lcl_getSelectedDataSource( const ComboBox& _dataSourceCombo )
105 String selectedDataSource = _dataSourceCombo.GetText();
106 if ( _dataSourceCombo.GetEntryPos( selectedDataSource ) == LISTBOX_ENTRY_NOTFOUND )
108 // none of the pre-selected entries -> assume a path to a database document
109 OFileNotation aFileNotation( selectedDataSource, OFileNotation::N_SYSTEM );
110 selectedDataSource = aFileNotation.get( OFileNotation::N_URL );
112 return selectedDataSource;
116 // ===================================================================
117 // = IAssigmentData
118 // ===================================================================
119 class IAssigmentData
121 public:
122 virtual ~IAssigmentData();
124 /// the data source to use for the address book
125 virtual ::rtl::OUString getDatasourceName() const = 0;
127 /// the command to use for the address book
128 virtual ::rtl::OUString getCommand() const = 0;
130 /** the command type to use for the address book
131 @return
132 a <type scope="com.sun.star.sdb">CommandType</type> value
134 virtual sal_Int32 getCommandType() const = 0;
136 /// checks whether or not there is an assignment for a given logical field
137 virtual sal_Bool hasFieldAssignment(const ::rtl::OUString& _rLogicalName) = 0;
138 /// retrieves the assignment for a given logical field
139 virtual ::rtl::OUString getFieldAssignment(const ::rtl::OUString& _rLogicalName) = 0;
141 /// set the assignment for a given logical field
142 virtual void setFieldAssignment(const ::rtl::OUString& _rLogicalName, const ::rtl::OUString& _rAssignment) = 0;
143 /// clear the assignment for a given logical field
144 virtual void clearFieldAssignment(const ::rtl::OUString& _rLogicalName) = 0;
146 virtual void setDatasourceName(const ::rtl::OUString& _rName) = 0;
147 virtual void setCommand(const ::rtl::OUString& _rCommand) = 0;
150 // -------------------------------------------------------------------
151 IAssigmentData::~IAssigmentData()
155 // ===================================================================
156 // = AssigmentTransientData
157 // ===================================================================
158 class AssigmentTransientData : public IAssigmentData
160 protected:
161 Reference< XDataSource > m_xDataSource;
162 ::rtl::OUString m_sDSName;
163 ::rtl::OUString m_sTableName;
164 MapString2String m_aAliases;
166 public:
167 AssigmentTransientData(
168 const Reference< XDataSource >& _rxDataSource,
169 const ::rtl::OUString& _rDataSourceName,
170 const ::rtl::OUString& _rTableName,
171 const Sequence< AliasProgrammaticPair >& _rFields
174 // IAssigmentData overridables
175 virtual ::rtl::OUString getDatasourceName() const;
176 virtual ::rtl::OUString getCommand() const;
177 virtual sal_Int32 getCommandType() const;
179 virtual sal_Bool hasFieldAssignment(const ::rtl::OUString& _rLogicalName);
180 virtual ::rtl::OUString getFieldAssignment(const ::rtl::OUString& _rLogicalName);
181 virtual void setFieldAssignment(const ::rtl::OUString& _rLogicalName, const ::rtl::OUString& _rAssignment);
182 virtual void clearFieldAssignment(const ::rtl::OUString& _rLogicalName);
184 virtual void setDatasourceName(const ::rtl::OUString& _rName);
185 virtual void setCommand(const ::rtl::OUString& _rCommand);
188 // -------------------------------------------------------------------
189 AssigmentTransientData::AssigmentTransientData( const Reference< XDataSource >& _rxDataSource,
190 const ::rtl::OUString& _rDataSourceName, const ::rtl::OUString& _rTableName,
191 const Sequence< AliasProgrammaticPair >& _rFields )
192 :m_xDataSource( _rxDataSource )
193 ,m_sDSName( _rDataSourceName )
194 ,m_sTableName( _rTableName )
196 // fill our aliaes structure
197 // first collect all known programmatic names
198 StringBag aKnownNames;
200 String sLogicalFieldNames( SvtResId( STR_LOCAGICAL_FIELD_NAMES ) );
201 sal_Int32 nTokenCount = sLogicalFieldNames.GetTokenCount(';');
202 for (sal_Int32 i = 0; i<nTokenCount; ++i)
203 aKnownNames.insert(sLogicalFieldNames.GetToken((sal_uInt16)i, ';'));
205 // loop throuzh the given names
206 const AliasProgrammaticPair* pFields = _rFields.getConstArray();
207 for (;pFields != pFields; ++pFields)
209 StringBagIterator aKnownPos = aKnownNames.find( pFields->ProgrammaticName );
210 if ( aKnownNames.end() != aKnownPos )
212 m_aAliases[ pFields->ProgrammaticName ] = pFields->Alias;
214 else
216 DBG_ERROR ( ( ::rtl::OString("AssigmentTransientData::AssigmentTransientData: unknown programmatic name (")
217 += ::rtl::OString(pFields->ProgrammaticName.getStr(), pFields->ProgrammaticName.getLength(), RTL_TEXTENCODING_ASCII_US)
218 += ::rtl::OString(")!")
219 ).getStr()
225 // -------------------------------------------------------------------
226 ::rtl::OUString AssigmentTransientData::getDatasourceName() const
228 return m_sDSName;
231 // -------------------------------------------------------------------
232 ::rtl::OUString AssigmentTransientData::getCommand() const
234 return m_sTableName;
237 // -------------------------------------------------------------------
238 sal_Int32 AssigmentTransientData::getCommandType() const
240 return CommandType::TABLE;
243 // -------------------------------------------------------------------
244 sal_Bool AssigmentTransientData::hasFieldAssignment(const ::rtl::OUString& _rLogicalName)
246 ConstMapString2StringIterator aPos = m_aAliases.find( _rLogicalName );
247 return ( m_aAliases.end() != aPos )
248 && ( aPos->second.getLength() );
251 // -------------------------------------------------------------------
252 ::rtl::OUString AssigmentTransientData::getFieldAssignment(const ::rtl::OUString& _rLogicalName)
254 ::rtl::OUString sReturn;
255 ConstMapString2StringIterator aPos = m_aAliases.find( _rLogicalName );
256 if ( m_aAliases.end() != aPos )
257 sReturn = aPos->second;
259 return sReturn;
262 // -------------------------------------------------------------------
263 void AssigmentTransientData::setFieldAssignment(const ::rtl::OUString& _rLogicalName, const ::rtl::OUString& _rAssignment)
265 m_aAliases[ _rLogicalName ] = _rAssignment;
268 // -------------------------------------------------------------------
269 void AssigmentTransientData::clearFieldAssignment(const ::rtl::OUString& _rLogicalName)
271 MapString2StringIterator aPos = m_aAliases.find( _rLogicalName );
272 if ( m_aAliases.end() != aPos )
273 m_aAliases.erase( aPos );
276 // -------------------------------------------------------------------
277 void AssigmentTransientData::setDatasourceName(const ::rtl::OUString&)
279 DBG_ERROR( "AssigmentTransientData::setDatasourceName: cannot be implemented for transient data!" );
282 // -------------------------------------------------------------------
283 void AssigmentTransientData::setCommand(const ::rtl::OUString&)
285 DBG_ERROR( "AssigmentTransientData::setCommand: cannot be implemented for transient data!" );
288 // ===================================================================
289 // = AssignmentPersistentData
290 // ===================================================================
291 class AssignmentPersistentData
292 :public ::utl::ConfigItem
293 ,public IAssigmentData
295 protected:
296 StringBag m_aStoredFields;
298 protected:
299 ::com::sun::star::uno::Any
300 getProperty(const ::rtl::OUString& _rLocalName) const;
301 ::com::sun::star::uno::Any
302 getProperty(const sal_Char* _pLocalName) const;
304 ::rtl::OUString getStringProperty(const sal_Char* _pLocalName) const;
305 sal_Int32 getInt32Property(const sal_Char* _pLocalName) const;
307 ::rtl::OUString getStringProperty(const ::rtl::OUString& _rLocalName) const;
309 void setStringProperty(const sal_Char* _pLocalName, const ::rtl::OUString& _rValue);
311 public:
312 AssignmentPersistentData();
313 ~AssignmentPersistentData();
315 // IAssigmentData overridables
316 virtual ::rtl::OUString getDatasourceName() const;
317 virtual ::rtl::OUString getCommand() const;
318 virtual sal_Int32 getCommandType() const;
320 virtual sal_Bool hasFieldAssignment(const ::rtl::OUString& _rLogicalName);
321 virtual ::rtl::OUString getFieldAssignment(const ::rtl::OUString& _rLogicalName);
322 virtual void setFieldAssignment(const ::rtl::OUString& _rLogicalName, const ::rtl::OUString& _rAssignment);
323 virtual void clearFieldAssignment(const ::rtl::OUString& _rLogicalName);
325 virtual void setDatasourceName(const ::rtl::OUString& _rName);
326 virtual void setCommand(const ::rtl::OUString& _rCommand);
329 // -------------------------------------------------------------------
330 AssignmentPersistentData::AssignmentPersistentData()
331 :ConfigItem( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Office.DataAccess/AddressBook" )))
333 Sequence< ::rtl::OUString > aStoredNames = GetNodeNames(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Fields")));
334 const ::rtl::OUString* pStoredNames = aStoredNames.getConstArray();
335 for (sal_Int32 i=0; i<aStoredNames.getLength(); ++i, ++pStoredNames)
336 m_aStoredFields.insert(*pStoredNames);
339 // -------------------------------------------------------------------
340 AssignmentPersistentData::~AssignmentPersistentData()
344 // -------------------------------------------------------------------
345 sal_Bool AssignmentPersistentData::hasFieldAssignment(const ::rtl::OUString& _rLogicalName)
347 return (m_aStoredFields.end() != m_aStoredFields.find(_rLogicalName));
350 // -------------------------------------------------------------------
351 ::rtl::OUString AssignmentPersistentData::getFieldAssignment(const ::rtl::OUString& _rLogicalName)
353 ::rtl::OUString sAssignment;
354 if (hasFieldAssignment(_rLogicalName))
356 ::rtl::OUString sFieldPath(RTL_CONSTASCII_USTRINGPARAM("Fields/"));
357 sFieldPath += _rLogicalName;
358 sFieldPath += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/AssignedFieldName"));
359 sAssignment = getStringProperty(sFieldPath);
361 return sAssignment;
364 // -------------------------------------------------------------------
365 Any AssignmentPersistentData::getProperty(const sal_Char* _pLocalName) const
367 return getProperty(::rtl::OUString::createFromAscii(_pLocalName));
370 // -------------------------------------------------------------------
371 Any AssignmentPersistentData::getProperty(const ::rtl::OUString& _rLocalName) const
373 Sequence< ::rtl::OUString > aProperties(&_rLocalName, 1);
374 Sequence< Any > aValues = const_cast<AssignmentPersistentData*>(this)->GetProperties(aProperties);
375 DBG_ASSERT(aValues.getLength() == 1, "AssignmentPersistentData::getProperty: invalid sequence length!");
376 return aValues[0];
379 // -------------------------------------------------------------------
380 ::rtl::OUString AssignmentPersistentData::getStringProperty(const ::rtl::OUString& _rLocalName) const
382 ::rtl::OUString sReturn;
383 getProperty( _rLocalName ) >>= sReturn;
384 return sReturn;
387 // -------------------------------------------------------------------
388 ::rtl::OUString AssignmentPersistentData::getStringProperty(const sal_Char* _pLocalName) const
390 ::rtl::OUString sReturn;
391 getProperty( _pLocalName ) >>= sReturn;
392 return sReturn;
395 // -------------------------------------------------------------------
396 sal_Int32 AssignmentPersistentData::getInt32Property(const sal_Char* _pLocalName) const
398 sal_Int32 nReturn = 0;
399 getProperty( _pLocalName ) >>= nReturn;
400 return nReturn;
403 // -------------------------------------------------------------------
404 void AssignmentPersistentData::setStringProperty(const sal_Char* _pLocalName, const ::rtl::OUString& _rValue)
406 Sequence< ::rtl::OUString > aNames(1);
407 Sequence< Any > aValues(1);
408 aNames[0] = ::rtl::OUString::createFromAscii(_pLocalName);
409 aValues[0] <<= _rValue;
410 PutProperties(aNames, aValues);
413 // -------------------------------------------------------------------
414 void AssignmentPersistentData::setFieldAssignment(const ::rtl::OUString& _rLogicalName, const ::rtl::OUString& _rAssignment)
416 if (!_rAssignment.getLength())
418 if (hasFieldAssignment(_rLogicalName))
419 // the assignment exists but it should be reset
420 clearFieldAssignment(_rLogicalName);
421 return;
424 // Fields
425 ::rtl::OUString sDescriptionNodePath(RTL_CONSTASCII_USTRINGPARAM("Fields"));
427 // Fields/<field>
428 ::rtl::OUString sFieldElementNodePath(sDescriptionNodePath);
429 sFieldElementNodePath += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"));
430 sFieldElementNodePath += _rLogicalName;
432 Sequence< PropertyValue > aNewFieldDescription(2);
433 // Fields/<field>/ProgrammaticFieldName
434 aNewFieldDescription[0].Name = sFieldElementNodePath;
435 aNewFieldDescription[0].Name += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/ProgrammaticFieldName"));
436 aNewFieldDescription[0].Value <<= _rLogicalName;
437 // Fields/<field>/AssignedFieldName
438 aNewFieldDescription[1].Name = sFieldElementNodePath;
439 aNewFieldDescription[1].Name += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/AssignedFieldName"));
440 aNewFieldDescription[1].Value <<= _rAssignment;
442 // just set the new value
443 #ifdef DBG_UTIL
444 sal_Bool bSuccess =
445 #endif
446 SetSetProperties(sDescriptionNodePath, aNewFieldDescription);
447 DBG_ASSERT(bSuccess, "AssignmentPersistentData::setFieldAssignment: could not commit the changes a field!");
450 // -------------------------------------------------------------------
451 void AssignmentPersistentData::clearFieldAssignment(const ::rtl::OUString& _rLogicalName)
453 if (!hasFieldAssignment(_rLogicalName))
454 // nothing to do
455 return;
457 ::rtl::OUString sDescriptionNodePath(RTL_CONSTASCII_USTRINGPARAM("Fields"));
458 Sequence< ::rtl::OUString > aNames(&_rLogicalName, 1);
459 ClearNodeElements(sDescriptionNodePath, aNames);
462 // -------------------------------------------------------------------
463 ::rtl::OUString AssignmentPersistentData::getDatasourceName() const
465 return getStringProperty( "DataSourceName" );
468 // -------------------------------------------------------------------
469 ::rtl::OUString AssignmentPersistentData::getCommand() const
471 return getStringProperty( "Command" );
474 // -------------------------------------------------------------------
475 void AssignmentPersistentData::setDatasourceName(const ::rtl::OUString& _rName)
477 setStringProperty( "DataSourceName", _rName );
480 // -------------------------------------------------------------------
481 void AssignmentPersistentData::setCommand(const ::rtl::OUString& _rCommand)
483 setStringProperty( "Command", _rCommand );
486 // -------------------------------------------------------------------
487 sal_Int32 AssignmentPersistentData::getCommandType() const
489 return getInt32Property( "CommandType" );
492 // ===================================================================
493 // = AddressBookSourceDialogData
494 // ===================================================================
495 struct AddressBookSourceDialogData
497 FixedText* pFieldLabels[FIELD_PAIRS_VISIBLE * 2];
498 ListBox* pFields[FIELD_PAIRS_VISIBLE * 2];
500 /// when working transient, we need the data source
501 Reference< XDataSource >
502 m_xTransientDataSource;
503 /// current scroll pos in the field list
504 sal_Int32 nFieldScrollPos;
505 /// the index within m_pFields of the last visible list box. This is redundant, it could be extracted from other members
506 sal_Int32 nLastVisibleListIndex;
507 /// indicates that we've an odd field number. This member is for efficiency only, it's redundant.
508 sal_Bool bOddFieldNumber : 1;
509 /// indicates that we're working with the real persistent configuration
510 sal_Bool bWorkingPersistent : 1;
512 /// the strings to use as labels for the field selection listboxes
513 StringArray aFieldLabels;
514 // the current field assignment
515 StringArray aFieldAssignments;
516 /// the logical field names
517 StringArray aLogicalFieldNames;
519 IAssigmentData* pConfigData;
521 // ................................................................
522 AddressBookSourceDialogData( )
523 :nFieldScrollPos(0)
524 ,nLastVisibleListIndex(0)
525 ,bOddFieldNumber(sal_False)
526 ,bWorkingPersistent( sal_True )
527 ,pConfigData( new AssignmentPersistentData )
531 // ................................................................
532 AddressBookSourceDialogData( const Reference< XDataSource >& _rxTransientDS, const ::rtl::OUString& _rDataSourceName,
533 const ::rtl::OUString& _rTableName, const Sequence< AliasProgrammaticPair >& _rFields )
534 :m_xTransientDataSource( _rxTransientDS )
535 ,nFieldScrollPos(0)
536 ,nLastVisibleListIndex(0)
537 ,bOddFieldNumber(sal_False)
538 ,bWorkingPersistent( sal_False )
539 ,pConfigData( new AssigmentTransientData( m_xTransientDataSource, _rDataSourceName, _rTableName, _rFields ) )
543 ~AddressBookSourceDialogData()
545 delete pConfigData;
550 // ===================================================================
551 // = AddressBookSourceDialog
552 // ===================================================================
553 #define INIT_FIELDS() \
554 ModalDialog(_pParent, SvtResId( DLG_ADDRESSBOOKSOURCE ))\
555 ,m_aDatasourceFrame (this, SvtResId(FL_DATASOURCEFRAME))\
556 ,m_aDatasourceLabel (this, SvtResId(FT_DATASOURCE))\
557 ,m_aDatasource (this, SvtResId(CB_DATASOURCE))\
558 ,m_aAdministrateDatasources (this, SvtResId(PB_ADMINISTATE_DATASOURCES))\
559 ,m_aTableLabel (this, SvtResId(FT_TABLE))\
560 ,m_aTable (this, SvtResId(CB_TABLE))\
561 ,m_aFieldsTitle (this, SvtResId(FT_FIELDS))\
562 ,m_aFieldsFrame (this, SvtResId(CT_BORDER))\
563 ,m_aFieldScroller (&m_aFieldsFrame, SvtResId(SB_FIELDSCROLLER))\
564 ,m_aOK (this, SvtResId(PB_OK))\
565 ,m_aCancel (this, SvtResId(PB_CANCEL))\
566 ,m_aHelp (this, SvtResId(PB_HELP))\
567 ,m_sNoFieldSelection(SvtResId(STR_NO_FIELD_SELECTION))\
568 ,m_xORB(_rxORB)
570 // -------------------------------------------------------------------
571 AddressBookSourceDialog::AddressBookSourceDialog(Window* _pParent,
572 const Reference< XMultiServiceFactory >& _rxORB )
573 :INIT_FIELDS()
574 ,m_pImpl( new AddressBookSourceDialogData )
576 implConstruct();
579 // -------------------------------------------------------------------
580 AddressBookSourceDialog::AddressBookSourceDialog( Window* _pParent, const Reference< XMultiServiceFactory >& _rxORB,
581 const Reference< XDataSource >& _rxTransientDS, const ::rtl::OUString& _rDataSourceName,
582 const ::rtl::OUString& _rTable, const Sequence< AliasProgrammaticPair >& _rMapping )
583 :INIT_FIELDS()
584 ,m_pImpl( new AddressBookSourceDialogData( _rxTransientDS, _rDataSourceName, _rTable, _rMapping ) )
586 implConstruct();
589 // -------------------------------------------------------------------
590 void AddressBookSourceDialog::implConstruct()
592 for (sal_Int32 row=0; row<FIELD_PAIRS_VISIBLE; ++row)
594 for (sal_Int32 column=0; column<2; ++column)
596 // the label
597 m_pImpl->pFieldLabels[row * 2 + column] = new FixedText(&m_aFieldsFrame, SvtResId((USHORT)(FT_FIELD_BASE + row * 2 + column)));
598 // the listbox
599 m_pImpl->pFields[row * 2 + column] = new ListBox(&m_aFieldsFrame, SvtResId((USHORT)(LB_FIELD_BASE + row * 2 + column)));
600 m_pImpl->pFields[row * 2 + column]->SetDropDownLineCount(15);
601 m_pImpl->pFields[row * 2 + column]->SetSelectHdl(LINK(this, AddressBookSourceDialog, OnFieldSelect));
603 m_pImpl->pFields[row * 2 + column]->SetHelpId(HID_ADDRTEMPL_FIELD_ASSIGNMENT);
607 m_aFieldsFrame.SetStyle((m_aFieldsFrame.GetStyle() | WB_TABSTOP | WB_DIALOGCONTROL) & ~WB_NODIALOGCONTROL);
609 // correct the z-order
610 m_aFieldScroller.SetZOrder(m_pImpl->pFields[FIELD_CONTROLS_VISIBLE - 1], WINDOW_ZORDER_BEHIND);
611 m_aOK.SetZOrder(&m_aFieldsFrame, WINDOW_ZORDER_BEHIND);
612 m_aCancel.SetZOrder(&m_aOK, WINDOW_ZORDER_BEHIND);
614 initializeDatasources();
616 // for the moment, we have a hard coded list of all known fields.
617 // A better solution would be to store all known field translations in the configuration, which could be
618 // extensible by the user in an arbitrary way.
619 // But for the moment we need a quick solution ...
620 // (the main thing would be to store the translations to use here in the user interface, besides that, the code
621 // should be adjustable with a rather small effort.)
623 // initialize the strings for the field labels
624 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_FIRSTNAME )) );
625 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_LASTNAME )) );
626 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_COMPANY)) );
627 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_DEPARTMENT )) );
628 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_STREET )) );
629 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_ZIPCODE )) );
630 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_CITY )) );
631 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_STATE)) );
632 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_COUNTRY )) );
633 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_HOMETEL )) );
634 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_WORKTEL )) );
635 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_OFFICETEL)) );
636 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_MOBILE)) );
637 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_TELOTHER)) );
638 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_PAGER)) );
639 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_FAX )) );
640 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_EMAIL )) );
641 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_URL )) );
642 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_TITLE )) );
643 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_POSITION )) );
644 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_INITIALS )) );
645 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_ADDRFORM )) );
646 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_SALUTATION )) );
647 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_ID)) );
648 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_CALENDAR)) );
649 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_INVITE)) );
650 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_NOTE)) );
651 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_USER1)) );
652 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_USER2)) );
653 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_USER3)) );
654 m_pImpl->aFieldLabels.push_back( String(SvtResId( STR_FIELD_USER4)) );
656 // force a even number of known fields
657 m_pImpl->bOddFieldNumber = (m_pImpl->aFieldLabels.size() % 2) != 0;
658 if (m_pImpl->bOddFieldNumber)
659 m_pImpl->aFieldLabels.push_back( String() );
661 // limit the scrollbar range accordingly
662 sal_Int32 nOverallFieldPairs = m_pImpl->aFieldLabels.size() / 2;
663 m_aFieldScroller.SetRange( Range(0, nOverallFieldPairs - FIELD_PAIRS_VISIBLE) );
664 m_aFieldScroller.SetLineSize(1);
665 m_aFieldScroller.SetPageSize(FIELD_PAIRS_VISIBLE);
667 // reset the current field assignments
668 m_pImpl->aFieldAssignments.resize(m_pImpl->aFieldLabels.size());
669 // (empty strings mean "no assignment")
671 // some knittings
672 m_aFieldScroller.SetScrollHdl(LINK(this, AddressBookSourceDialog, OnFieldScroll));
673 m_aAdministrateDatasources.SetClickHdl(LINK(this, AddressBookSourceDialog, OnAdministrateDatasources));
674 m_aDatasource.EnableAutocomplete(sal_True);
675 m_aTable.EnableAutocomplete(sal_True);
676 m_aTable.SetGetFocusHdl(LINK(this, AddressBookSourceDialog, OnComboGetFocus));
677 m_aDatasource.SetGetFocusHdl(LINK(this, AddressBookSourceDialog, OnComboGetFocus));
678 m_aTable.SetLoseFocusHdl(LINK(this, AddressBookSourceDialog, OnComboLoseFocus));
679 m_aDatasource.SetLoseFocusHdl(LINK(this, AddressBookSourceDialog, OnComboLoseFocus));
680 m_aTable.SetSelectHdl(LINK(this, AddressBookSourceDialog, OnComboSelect));
681 m_aDatasource.SetSelectHdl(LINK(this, AddressBookSourceDialog, OnComboSelect));
682 m_aOK.SetClickHdl(LINK(this, AddressBookSourceDialog, OnOkClicked));
684 m_aDatasource.SetDropDownLineCount(15);
686 // initialize the field controls
687 resetFields();
688 m_aFieldScroller.SetThumbPos(0);
689 m_pImpl->nFieldScrollPos = -1;
690 implScrollFields(0, sal_False, sal_False);
692 // the logical names
693 String sLogicalFieldNames(SvtResId(STR_LOCAGICAL_FIELD_NAMES));
694 sal_Int32 nAdjustedTokenCount = sLogicalFieldNames.GetTokenCount(';') + (m_pImpl->bOddFieldNumber ? 1 : 0);
695 DBG_ASSERT(nAdjustedTokenCount == (sal_Int32)m_pImpl->aFieldLabels.size(),
696 "AddressBookSourceDialog::AddressBookSourceDialog: inconsistence between logical and UI field names!");
697 m_pImpl->aLogicalFieldNames.reserve(nAdjustedTokenCount);
698 for (sal_Int32 i = 0; i<nAdjustedTokenCount; ++i)
699 m_pImpl->aLogicalFieldNames.push_back(sLogicalFieldNames.GetToken((sal_uInt16)i, ';'));
701 PostUserEvent(LINK(this, AddressBookSourceDialog, OnDelayedInitialize));
702 // so the dialog will at least show up before we do the loading of the
703 // configuration data and the (maybe time consuming) analysis of the data source/table to select
705 FreeResource();
707 if ( !m_pImpl->bWorkingPersistent )
709 StyleSettings aSystemStyle = GetSettings().GetStyleSettings();
710 const Color& rNewColor = aSystemStyle.GetDialogColor();
712 m_aDatasource.SetReadOnly( sal_True );
713 m_aDatasource.SetBackground( Wallpaper( rNewColor ) );
714 m_aDatasource.SetControlBackground( rNewColor );
716 m_aTable.SetReadOnly( sal_True );
717 m_aTable.SetBackground( Wallpaper( rNewColor ) );
718 m_aTable.SetControlBackground( rNewColor );
720 m_aAdministrateDatasources.Hide( );
724 // -------------------------------------------------------------------
725 void AddressBookSourceDialog::getFieldMapping(Sequence< AliasProgrammaticPair >& _rMapping) const
727 _rMapping.realloc( m_pImpl->aLogicalFieldNames.size() );
728 AliasProgrammaticPair* pPair = _rMapping.getArray();
730 ::rtl::OUString sCurrent;
731 for ( ConstStringArrayIterator aProgrammatic = m_pImpl->aLogicalFieldNames.begin();
732 aProgrammatic != m_pImpl->aLogicalFieldNames.end();
733 ++aProgrammatic
736 sCurrent = *aProgrammatic;
737 if ( m_pImpl->pConfigData->hasFieldAssignment( sCurrent ) )
739 // the user gave us an assignment for this field
740 pPair->ProgrammaticName = *aProgrammatic;
741 pPair->Alias = m_pImpl->pConfigData->getFieldAssignment( *aProgrammatic );
742 ++pPair;
746 _rMapping.realloc( pPair - _rMapping.getArray() );
749 // -------------------------------------------------------------------
750 void AddressBookSourceDialog::loadConfiguration()
752 ::rtl::OUString sName = m_pImpl->pConfigData->getDatasourceName();
753 INetURLObject aURL( sName );
754 if( aURL.GetProtocol() != INET_PROT_NOT_VALID )
756 OFileNotation aFileNotation( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
757 sName = aFileNotation.get(OFileNotation::N_SYSTEM);
760 m_aDatasource.SetText(sName);
761 m_aTable.SetText(m_pImpl->pConfigData->getCommand());
762 // we ignore the CommandType: only tables are supported
764 // the logical names for the fields
765 DBG_ASSERT(m_pImpl->aLogicalFieldNames.size() == m_pImpl->aFieldAssignments.size(),
766 "AddressBookSourceDialog::loadConfiguration: inconsistence between field names and field assignments!");
768 ConstStringArrayIterator aLogical = m_pImpl->aLogicalFieldNames.begin();
769 StringArrayIterator aAssignment = m_pImpl->aFieldAssignments.begin();
770 for ( ;
771 aLogical < m_pImpl->aLogicalFieldNames.end();
772 ++aLogical, ++aAssignment
774 *aAssignment = m_pImpl->pConfigData->getFieldAssignment(*aLogical);
777 // -------------------------------------------------------------------
778 AddressBookSourceDialog::~AddressBookSourceDialog()
780 sal_Int32 i;
781 for (i=0; i<FIELD_CONTROLS_VISIBLE; ++i)
783 delete m_pImpl->pFieldLabels[i];
784 delete m_pImpl->pFields[i];
787 delete m_pImpl;
790 // -------------------------------------------------------------------
791 void AddressBookSourceDialog::initializeDatasources()
793 if (!m_xDatabaseContext.is())
795 DBG_ASSERT(m_xORB.is(), "AddressBookSourceDialog::initializeDatasources: no service factory!");
796 if (!m_xORB.is())
797 return;
799 const String sContextServiceName = String::CreateFromAscii("com.sun.star.sdb.DatabaseContext");
802 m_xDatabaseContext = Reference< XNameAccess >(m_xORB->createInstance(sContextServiceName), UNO_QUERY);
804 catch(Exception&) { }
805 if (!m_xDatabaseContext.is())
807 ShowServiceNotAvailableError( this, sContextServiceName, sal_False);
808 return;
811 m_aDatasource.Clear();
813 // fill the datasources listbox
814 Sequence< ::rtl::OUString > aDatasourceNames;
817 aDatasourceNames = m_xDatabaseContext->getElementNames();
819 catch(Exception&)
821 DBG_ERROR("AddressBookSourceDialog::initializeDatasources: caught an exception while asking for the data source names!");
823 const ::rtl::OUString* pDatasourceNames = aDatasourceNames.getConstArray();
824 const ::rtl::OUString* pEnd = pDatasourceNames + aDatasourceNames.getLength();
825 for (; pDatasourceNames < pEnd; ++pDatasourceNames)
826 m_aDatasource.InsertEntry(*pDatasourceNames);
829 // -------------------------------------------------------------------
830 IMPL_LINK(AddressBookSourceDialog, OnFieldScroll, ScrollBar*, _pScrollBar)
832 implScrollFields( _pScrollBar->GetThumbPos(), sal_True, sal_True );
833 return 0L;
836 // -------------------------------------------------------------------
837 void AddressBookSourceDialog::resetTables()
839 if (!m_xDatabaseContext.is())
840 return;
842 WaitObject aWaitCursor(this);
844 // no matter what we do here, we handled the currently selected data source (no matter if successfull or not)
845 m_aDatasource.SaveValue();
847 // create an interaction handler (may be needed for connecting)
848 const String sInteractionHandlerServiceName = String::CreateFromAscii("com.sun.star.sdb.InteractionHandler");
849 Reference< XInteractionHandler > xHandler;
852 xHandler = Reference< XInteractionHandler >(m_xORB->createInstance(sInteractionHandlerServiceName), UNO_QUERY);
854 catch(Exception&) { }
855 if (!xHandler.is())
857 ShowServiceNotAvailableError(this, sInteractionHandlerServiceName, sal_True);
858 return;
861 // the currently selected table
862 ::rtl::OUString sOldTable = m_aTable.GetText();
864 m_aTable.Clear();
866 m_xCurrentDatasourceTables= NULL;
868 // get the tables of the connection
869 Sequence< ::rtl::OUString > aTableNames;
870 Any aException;
873 Reference< XCompletedConnection > xDS;
874 if ( m_pImpl->bWorkingPersistent )
876 String sSelectedDS = lcl_getSelectedDataSource( m_aDatasource );
878 // get the data source the user has chosen and let it build a connection
879 INetURLObject aURL( sSelectedDS );
880 if ( aURL.GetProtocol() != INET_PROT_NOT_VALID || m_xDatabaseContext->hasByName(sSelectedDS) )
881 m_xDatabaseContext->getByName( sSelectedDS ) >>= xDS;
883 else
885 xDS = xDS.query( m_pImpl->m_xTransientDataSource );
888 // build the connection
889 Reference< XConnection > xConn;
890 if (xDS.is())
891 xConn = xDS->connectWithCompletion(xHandler);
893 // get the table names
894 Reference< XTablesSupplier > xSupplTables(xConn, UNO_QUERY);
895 if (xSupplTables.is())
897 m_xCurrentDatasourceTables = Reference< XNameAccess >(xSupplTables->getTables(), UNO_QUERY);
898 if (m_xCurrentDatasourceTables.is())
899 aTableNames = m_xCurrentDatasourceTables->getElementNames();
902 catch(SQLContext& e) { aException <<= e; }
903 catch(SQLWarning& e) { aException <<= e; }
904 catch(SQLException& e) { aException <<= e; }
905 catch(Exception&)
907 DBG_ERROR("AddressBookSourceDialog::resetTables: could not retrieve the table!");
910 if (aException.hasValue())
912 Reference< XInteractionRequest > xRequest = new OInteractionRequest(aException);
915 xHandler->handle(xRequest);
917 catch(Exception&) { }
918 return;
921 sal_Bool bKnowOldTable = sal_False;
922 // fill the table list
923 const ::rtl::OUString* pTableNames = aTableNames.getConstArray();
924 const ::rtl::OUString* pEnd = pTableNames + aTableNames.getLength();
925 for (;pTableNames != pEnd; ++pTableNames)
927 m_aTable.InsertEntry(*pTableNames);
928 if (0 == pTableNames->compareTo(sOldTable))
929 bKnowOldTable = sal_True;
932 // set the old table, if the new data source knows a table with this name, too. Else reset the tables edit field.
933 if (!bKnowOldTable)
934 sOldTable = ::rtl::OUString();
935 m_aTable.SetText(sOldTable);
937 resetFields();
940 // -------------------------------------------------------------------
941 void AddressBookSourceDialog::resetFields()
943 WaitObject aWaitCursor(this);
945 // no matter what we do here, we handled the currently selected table (no matter if successfull or not)
946 m_aDatasource.SaveValue();
948 String sSelectedTable = m_aTable.GetText();
949 Sequence< ::rtl::OUString > aColumnNames;
952 if (m_xCurrentDatasourceTables.is())
954 // get the table and the columns
955 Reference< XColumnsSupplier > xSuppTableCols;
956 if (m_xCurrentDatasourceTables->hasByName(sSelectedTable))
957 ::cppu::extractInterface(xSuppTableCols, m_xCurrentDatasourceTables->getByName(sSelectedTable));
958 Reference< XNameAccess > xColumns;
959 if (xSuppTableCols.is())
960 xColumns = xSuppTableCols->getColumns();
961 if (xColumns.is())
962 aColumnNames = xColumns->getElementNames();
965 catch(Exception&)
967 DBG_ERROR("AddressBookSourceDialog::resetFields: could not retrieve the table columns!");
971 const ::rtl::OUString* pColumnNames = aColumnNames.getConstArray();
972 const ::rtl::OUString* pEnd = pColumnNames + aColumnNames.getLength();
974 // for quicker access
975 ::std::set< String > aColumnNameSet;
976 for (pColumnNames = aColumnNames.getConstArray(); pColumnNames != pEnd; ++pColumnNames)
977 aColumnNameSet.insert(*pColumnNames);
979 std::vector<String>::iterator aInitialSelection = m_pImpl->aFieldAssignments.begin() + m_pImpl->nFieldScrollPos;
981 ListBox** pListbox = m_pImpl->pFields;
982 String sSaveSelection;
983 for (sal_Int32 i=0; i<FIELD_CONTROLS_VISIBLE; ++i, ++pListbox, ++aInitialSelection)
985 sSaveSelection = (*pListbox)->GetSelectEntry();
987 (*pListbox)->Clear();
989 // the one entry for "no selection"
990 (*pListbox)->InsertEntry(m_sNoFieldSelection, 0);
991 // as it's entry data, set the index of the list box in our array
992 (*pListbox)->SetEntryData(0, reinterpret_cast<void*>(i));
994 // the field names
995 for (pColumnNames = aColumnNames.getConstArray(); pColumnNames != pEnd; ++pColumnNames)
996 (*pListbox)->InsertEntry(*pColumnNames);
998 if (aInitialSelection->Len() && (aColumnNameSet.end() != aColumnNameSet.find(*aInitialSelection)))
999 // we can select the entry as specified in our field assignment array
1000 (*pListbox)->SelectEntry(*aInitialSelection);
1001 else
1002 // try to restore the selection
1003 if (aColumnNameSet.end() != aColumnNameSet.find(sSaveSelection))
1004 // the old selection is a valid column name
1005 (*pListbox)->SelectEntry(sSaveSelection);
1006 else
1007 // select the <none> entry
1008 (*pListbox)->SelectEntryPos(0);
1011 // adjust m_pImpl->aFieldAssignments
1012 for ( StringArrayIterator aAdjust = m_pImpl->aFieldAssignments.begin();
1013 aAdjust != m_pImpl->aFieldAssignments.end();
1014 ++aAdjust
1016 if (aAdjust->Len())
1017 if (aColumnNameSet.end() == aColumnNameSet.find(*aAdjust))
1018 aAdjust->Erase();
1021 // -------------------------------------------------------------------
1022 IMPL_LINK(AddressBookSourceDialog, OnFieldSelect, ListBox*, _pListbox)
1024 // the index of the affected list box in our array
1025 sal_IntPtr nListBoxIndex = reinterpret_cast<sal_IntPtr>(_pListbox->GetEntryData(0));
1026 DBG_ASSERT(nListBoxIndex >= 0 && nListBoxIndex < FIELD_CONTROLS_VISIBLE,
1027 "AddressBookSourceDialog::OnFieldScroll: invalid list box entry!");
1029 // update the array where we remember the field selections
1030 if (0 == _pListbox->GetSelectEntryPos())
1031 // it's the "no field selection" entry
1032 m_pImpl->aFieldAssignments[m_pImpl->nFieldScrollPos * 2 + nListBoxIndex] = String();
1033 else
1034 // it's a regular field entry
1035 m_pImpl->aFieldAssignments[m_pImpl->nFieldScrollPos * 2 + nListBoxIndex] = _pListbox->GetSelectEntry();
1037 return 0L;
1040 // -------------------------------------------------------------------
1041 void AddressBookSourceDialog::implScrollFields(sal_Int32 _nPos, sal_Bool _bAdjustFocus, sal_Bool _bAdjustScrollbar)
1043 if (_nPos == m_pImpl->nFieldScrollPos)
1044 // nothing to do
1045 return;
1047 // loop through our field control rows and do some adjustments
1048 // for the new texts
1049 FixedText** pLeftLabelControl = m_pImpl->pFieldLabels;
1050 FixedText** pRightLabelControl = pLeftLabelControl + 1;
1051 ConstStringArrayIterator pLeftColumnLabel = m_pImpl->aFieldLabels.begin() + 2 * _nPos;
1052 ConstStringArrayIterator pRightColumnLabel = pLeftColumnLabel + 1;
1054 // for the focus movement and the selection scroll
1055 ListBox** pLeftListControl = m_pImpl->pFields;
1056 ListBox** pRightListControl = pLeftListControl + 1;
1058 // for the focus movement
1059 sal_Int32 nOldFocusRow = -1;
1060 sal_Int32 nOldFocusColumn = 0;
1062 // for the selection scroll
1063 ConstStringArrayIterator pLeftAssignment = m_pImpl->aFieldAssignments.begin() + 2 * _nPos;
1064 ConstStringArrayIterator pRightAssignment = pLeftAssignment + 1;
1066 m_pImpl->nLastVisibleListIndex = -1;
1067 // loop
1068 for (sal_Int32 i=0; i<FIELD_PAIRS_VISIBLE; ++i)
1070 if ((*pLeftListControl)->HasChildPathFocus())
1072 nOldFocusRow = i;
1073 nOldFocusColumn = 0;
1075 else if ((*pRightListControl)->HasChildPathFocus())
1077 nOldFocusRow = i;
1078 nOldFocusColumn = 1;
1081 // the new texts of the label controls
1082 (*pLeftLabelControl)->SetText(*pLeftColumnLabel);
1083 (*pRightLabelControl)->SetText(*pRightColumnLabel);
1085 // we may have to hide the controls in the right column, if we have no label text for it
1086 // (which means we have an odd number of fields, though we forced our internal arrays to
1087 // be even-sized for easier handling)
1088 // (If sometimes we support an arbitrary number of field assignments, we would have to care for
1089 // an invisible left hand side column, too. But right now, the left hand side controls are always
1090 // visible)
1091 sal_Bool bHideRightColumn = (0 == pRightColumnLabel->Len());
1092 (*pRightLabelControl)->Show(!bHideRightColumn);
1093 (*pRightListControl)->Show(!bHideRightColumn);
1094 // the new selections of the listboxes
1095 implSelectField(*pLeftListControl, *pLeftAssignment);
1096 implSelectField(*pRightListControl, *pRightAssignment);
1098 // the index of the last visible list box
1099 ++m_pImpl->nLastVisibleListIndex; // the left hand side box is always visible
1100 if (!bHideRightColumn)
1101 ++m_pImpl->nLastVisibleListIndex;
1103 // increment ...
1104 if ( i < FIELD_PAIRS_VISIBLE - 1 )
1105 { // (not in the very last round, here the +=2 could result in an invalid
1106 // iterator position, which causes an abort in a non-product version
1107 pLeftLabelControl += 2;
1108 pRightLabelControl += 2;
1109 pLeftColumnLabel += 2;
1110 pRightColumnLabel += 2;
1112 pLeftListControl += 2;
1113 pRightListControl += 2;
1114 pLeftAssignment += 2;
1115 pRightAssignment += 2;
1119 if (_bAdjustFocus && (nOldFocusRow >= 0))
1120 { // we have to adjust the focus and one of the list boxes has the focus
1121 sal_Int32 nDelta = m_pImpl->nFieldScrollPos - _nPos;
1122 // the new row for the focus
1123 sal_Int32 nNewFocusRow = nOldFocusRow + nDelta;
1124 // normalize
1125 nNewFocusRow = std::min(nNewFocusRow, (sal_Int32)(FIELD_PAIRS_VISIBLE - 1), ::std::less< sal_Int32 >());
1126 nNewFocusRow = std::max(nNewFocusRow, (sal_Int32)0, ::std::less< sal_Int32 >());
1127 // set the new focus (in the same column)
1128 m_pImpl->pFields[nNewFocusRow * 2 + nOldFocusColumn]->GrabFocus();
1131 m_pImpl->nFieldScrollPos = _nPos;
1133 if (_bAdjustScrollbar)
1134 m_aFieldScroller.SetThumbPos(m_pImpl->nFieldScrollPos);
1137 // -------------------------------------------------------------------
1138 void AddressBookSourceDialog::implSelectField(ListBox* _pBox, const String& _rText)
1140 if (_rText.Len())
1141 // a valid field name
1142 _pBox->SelectEntry(_rText);
1143 else
1144 // no selection for this item
1145 _pBox->SelectEntryPos(0);
1148 // -------------------------------------------------------------------
1149 IMPL_LINK(AddressBookSourceDialog, OnDelayedInitialize, void*, EMPTYARG)
1151 // load the initial data from the configuration
1152 loadConfiguration();
1153 resetTables();
1154 // will reset the tables/fields implicitly
1156 if ( !m_pImpl->bWorkingPersistent )
1157 if ( m_pImpl->pFields[0] )
1158 m_pImpl->pFields[0]->GrabFocus();
1160 return 0L;
1163 // -------------------------------------------------------------------
1164 IMPL_LINK(AddressBookSourceDialog, OnComboSelect, ComboBox*, _pBox)
1166 if (_pBox == &m_aDatasource)
1167 resetTables();
1168 else
1169 resetFields();
1170 return 0;
1173 // -------------------------------------------------------------------
1174 IMPL_LINK(AddressBookSourceDialog, OnComboGetFocus, ComboBox*, _pBox)
1176 _pBox->SaveValue();
1177 return 0L;
1180 // -------------------------------------------------------------------
1181 IMPL_LINK(AddressBookSourceDialog, OnComboLoseFocus, ComboBox*, _pBox)
1183 if (_pBox->GetSavedValue() != _pBox->GetText())
1185 if (_pBox == &m_aDatasource)
1186 resetTables();
1187 else
1188 resetFields();
1190 return 0L;
1193 // -------------------------------------------------------------------
1194 IMPL_LINK(AddressBookSourceDialog, OnOkClicked, Button*, EMPTYARG)
1196 String sSelectedDS = lcl_getSelectedDataSource( m_aDatasource );
1197 if ( m_pImpl->bWorkingPersistent )
1199 m_pImpl->pConfigData->setDatasourceName(sSelectedDS);
1200 m_pImpl->pConfigData->setCommand(m_aTable.GetText());
1203 // set the field assignments
1204 ConstStringArrayIterator aLogical = m_pImpl->aLogicalFieldNames.begin();
1205 ConstStringArrayIterator aAssignment = m_pImpl->aFieldAssignments.begin();
1206 for ( ;
1207 aLogical < m_pImpl->aLogicalFieldNames.end();
1208 ++aLogical, ++aAssignment
1210 m_pImpl->pConfigData->setFieldAssignment(*aLogical, *aAssignment);
1213 EndDialog(RET_OK);
1214 return 0L;
1217 // -------------------------------------------------------------------
1218 IMPL_LINK(AddressBookSourceDialog, OnAdministrateDatasources, void*, EMPTYARG)
1220 // collect some initial arguments for the dialog
1221 Sequence< Any > aArgs(1);
1222 aArgs[0] <<= PropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParentWindow")), 0, makeAny(VCLUnoHelper::GetInterface(this)), PropertyState_DIRECT_VALUE);
1224 // create the dialog object
1225 const String sDialogServiceName = String::CreateFromAscii("com.sun.star.ui.dialogs.AddressBookSourcePilot");
1226 Reference< XExecutableDialog > xAdminDialog;
1229 xAdminDialog = Reference< XExecutableDialog >(m_xORB->createInstanceWithArguments(sDialogServiceName, aArgs), UNO_QUERY);
1231 catch(Exception&) { }
1232 if (!xAdminDialog.is())
1234 ShowServiceNotAvailableError(this, sDialogServiceName, sal_True);
1235 return 1L;
1238 // excute the dialog
1241 if ( xAdminDialog->execute() == RET_OK )
1243 Reference<XPropertySet> xProp(xAdminDialog,UNO_QUERY);
1244 if ( xProp.is() )
1246 ::rtl::OUString sName;
1247 xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSourceName"))) >>= sName;
1249 INetURLObject aURL( sName );
1250 if( aURL.GetProtocol() != INET_PROT_NOT_VALID )
1252 OFileNotation aFileNotation( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
1253 sName = aFileNotation.get(OFileNotation::N_SYSTEM);
1255 m_aDatasource.InsertEntry(sName);
1256 delete m_pImpl->pConfigData;
1257 m_pImpl->pConfigData = new AssignmentPersistentData();
1258 loadConfiguration();
1259 resetTables();
1260 // will reset the fields implicitly
1264 catch(Exception&)
1266 DBG_ERROR("AddressBookSourceDialog::OnAdministrateDatasources: an error occured while executing the administration dialog!");
1269 // re-fill the data source list
1270 // try to preserve the current selection
1272 // initializeDatasources();
1274 return 0L;
1277 // -------------------------------------------------------------------
1278 long AddressBookSourceDialog::PreNotify( NotifyEvent& _rNEvt )
1280 switch (_rNEvt.GetType())
1282 case EVENT_KEYINPUT:
1284 const KeyEvent* pKeyEvent = _rNEvt.GetKeyEvent();
1285 sal_uInt16 nCode = pKeyEvent->GetKeyCode().GetCode();
1286 sal_Bool bShift = pKeyEvent->GetKeyCode().IsShift();
1287 sal_Bool bCtrl = pKeyEvent->GetKeyCode().IsMod1();
1288 sal_Bool bAlt = pKeyEvent->GetKeyCode().IsMod2();
1290 if (KEY_TAB == nCode)
1291 { // somebody pressed the tab key
1292 if (!bAlt && !bCtrl && !bShift)
1293 { // it's really the only the key (no modifiers)
1294 if (m_pImpl->pFields[m_pImpl->nLastVisibleListIndex]->HasChildPathFocus())
1295 // the last of our visible list boxes has the focus
1296 if (m_pImpl->nFieldScrollPos < m_aFieldScroller.GetRangeMax())
1297 { // we can still scroll down
1298 sal_Int32 nNextFocusList = m_pImpl->nLastVisibleListIndex + 1 - 2;
1299 // -> scroll down
1300 implScrollFields(m_pImpl->nFieldScrollPos + 1, sal_False, sal_True);
1301 // give the left control in the "next" line the focus
1302 m_pImpl->pFields[nNextFocusList]->GrabFocus();
1303 // return saying "have handled this"
1304 return 1;
1307 else if (!bAlt && !bCtrl && bShift)
1308 { // it's shift-tab
1309 if (m_pImpl->pFields[0]->HasChildPathFocus())
1310 // our first list box has the focus
1311 if (m_pImpl->nFieldScrollPos > 0)
1312 { // we can still scroll up
1313 // -> scroll up
1314 implScrollFields(m_pImpl->nFieldScrollPos - 1, sal_False, sal_True);
1315 // give the right control in the "prebious" line the focus
1316 m_pImpl->pFields[0 - 1 + 2]->GrabFocus();
1317 // return saying "have handled this"
1318 return 1;
1323 break;
1325 return ModalDialog::PreNotify(_rNEvt);
1328 // .......................................................................
1329 } // namespace svt
1330 // .......................................................................