Line data Source code
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 :
21 : #include <stdio.h>
22 : #include <svtools/addresstemplate.hxx>
23 : #include "addresstemplate.hrc"
24 : #include <svtools/svtools.hrc>
25 : #include <svtools/helpid.hrc>
26 : #include <svtools/svtresid.hxx>
27 : #include <tools/debug.hxx>
28 : #include <comphelper/extract.hxx>
29 : #include <comphelper/interaction.hxx>
30 : #include <comphelper/processfactory.hxx>
31 : #include <comphelper/stl_types.hxx>
32 : #include <comphelper/string.hxx>
33 : #include <vcl/stdtext.hxx>
34 : #include <vcl/waitobj.hxx>
35 : #include <vcl/msgbox.hxx>
36 : #include <toolkit/helper/vclunohelper.hxx>
37 : #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
38 : #include <com/sun/star/awt/XWindow.hpp>
39 : #include <com/sun/star/beans/PropertyValue.hpp>
40 : #include <com/sun/star/beans/XPropertySet.hpp>
41 : #include <com/sun/star/sdb/DatabaseContext.hpp>
42 : #include <com/sun/star/sdb/XCompletedConnection.hpp>
43 : #include <com/sun/star/sdb/SQLContext.hpp>
44 : #include <com/sun/star/sdbc/SQLWarning.hpp>
45 : #include <com/sun/star/sdbc/XConnection.hpp>
46 : #include <com/sun/star/task/InteractionHandler.hpp>
47 : #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
48 : #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
49 : #include <com/sun/star/sdb/CommandType.hpp>
50 : #include <svtools/localresaccess.hxx>
51 : #include "svl/filenotation.hxx"
52 : #include <tools/urlobj.hxx>
53 : #include <algorithm>
54 :
55 : // .......................................................................
56 : namespace svt
57 : {
58 : // .......................................................................
59 :
60 : using namespace ::com::sun::star::uno;
61 : using namespace ::com::sun::star::lang;
62 : using namespace ::com::sun::star::container;
63 : using namespace ::com::sun::star::ui::dialogs;
64 : using namespace ::com::sun::star::util;
65 : using namespace ::com::sun::star::beans;
66 : using namespace ::com::sun::star::sdb;
67 : using namespace ::com::sun::star::sdbc;
68 : using namespace ::com::sun::star::sdbcx;
69 : using namespace ::com::sun::star::task;
70 : using namespace ::comphelper;
71 : using namespace ::utl;
72 :
73 : DECLARE_STL_VECTOR( String, StringArray );
74 : DECLARE_STL_STDKEY_SET( ::rtl::OUString, StringBag );
75 : DECLARE_STL_USTRINGACCESS_MAP( ::rtl::OUString, MapString2String );
76 :
77 : namespace
78 : {
79 0 : String lcl_getSelectedDataSource( const ComboBox& _dataSourceCombo )
80 : {
81 0 : String selectedDataSource = _dataSourceCombo.GetText();
82 0 : if ( _dataSourceCombo.GetEntryPos( selectedDataSource ) == LISTBOX_ENTRY_NOTFOUND )
83 : {
84 : // none of the pre-selected entries -> assume a path to a database document
85 0 : OFileNotation aFileNotation( selectedDataSource, OFileNotation::N_SYSTEM );
86 0 : selectedDataSource = aFileNotation.get( OFileNotation::N_URL );
87 : }
88 0 : return selectedDataSource;
89 : }
90 : }
91 :
92 : // ===================================================================
93 : // = IAssigmentData
94 : // ===================================================================
95 0 : class IAssigmentData
96 : {
97 : public:
98 : virtual ~IAssigmentData();
99 :
100 : /// the data source to use for the address book
101 : virtual ::rtl::OUString getDatasourceName() const = 0;
102 :
103 : /// the command to use for the address book
104 : virtual ::rtl::OUString getCommand() const = 0;
105 :
106 : /** the command type to use for the address book
107 : @return
108 : a <type scope="com.sun.star.sdb">CommandType</type> value
109 : */
110 : virtual sal_Int32 getCommandType() const = 0;
111 :
112 : /// checks whether or not there is an assignment for a given logical field
113 : virtual sal_Bool hasFieldAssignment(const ::rtl::OUString& _rLogicalName) = 0;
114 : /// retrieves the assignment for a given logical field
115 : virtual ::rtl::OUString getFieldAssignment(const ::rtl::OUString& _rLogicalName) = 0;
116 :
117 : /// set the assignment for a given logical field
118 : virtual void setFieldAssignment(const ::rtl::OUString& _rLogicalName, const ::rtl::OUString& _rAssignment) = 0;
119 : /// clear the assignment for a given logical field
120 : virtual void clearFieldAssignment(const ::rtl::OUString& _rLogicalName) = 0;
121 :
122 : virtual void setDatasourceName(const ::rtl::OUString& _rName) = 0;
123 : virtual void setCommand(const ::rtl::OUString& _rCommand) = 0;
124 : };
125 :
126 : // -------------------------------------------------------------------
127 0 : IAssigmentData::~IAssigmentData()
128 : {
129 0 : }
130 :
131 : // ===================================================================
132 : // = AssigmentTransientData
133 : // ===================================================================
134 0 : class AssigmentTransientData : public IAssigmentData
135 : {
136 : protected:
137 : Reference< XDataSource > m_xDataSource;
138 : ::rtl::OUString m_sDSName;
139 : ::rtl::OUString m_sTableName;
140 : MapString2String m_aAliases;
141 :
142 : public:
143 : AssigmentTransientData(
144 : const Reference< XDataSource >& _rxDataSource,
145 : const ::rtl::OUString& _rDataSourceName,
146 : const ::rtl::OUString& _rTableName,
147 : const Sequence< AliasProgrammaticPair >& _rFields
148 : );
149 :
150 : // IAssigmentData overridables
151 : virtual ::rtl::OUString getDatasourceName() const;
152 : virtual ::rtl::OUString getCommand() const;
153 : virtual sal_Int32 getCommandType() const;
154 :
155 : virtual sal_Bool hasFieldAssignment(const ::rtl::OUString& _rLogicalName);
156 : virtual ::rtl::OUString getFieldAssignment(const ::rtl::OUString& _rLogicalName);
157 : virtual void setFieldAssignment(const ::rtl::OUString& _rLogicalName, const ::rtl::OUString& _rAssignment);
158 : virtual void clearFieldAssignment(const ::rtl::OUString& _rLogicalName);
159 :
160 : virtual void setDatasourceName(const ::rtl::OUString& _rName);
161 : virtual void setCommand(const ::rtl::OUString& _rCommand);
162 : };
163 :
164 : // -------------------------------------------------------------------
165 0 : AssigmentTransientData::AssigmentTransientData( const Reference< XDataSource >& _rxDataSource,
166 : const ::rtl::OUString& _rDataSourceName, const ::rtl::OUString& _rTableName,
167 : const Sequence< AliasProgrammaticPair >& _rFields )
168 : :m_xDataSource( _rxDataSource )
169 : ,m_sDSName( _rDataSourceName )
170 0 : ,m_sTableName( _rTableName )
171 : {
172 : // fill our aliaes structure
173 : // first collect all known programmatic names
174 0 : StringBag aKnownNames;
175 :
176 0 : rtl::OUString sLogicalFieldNames(SVT_RESSTR(STR_LOGICAL_FIELD_NAMES));
177 0 : sal_Int32 nIndex = 0;
178 0 : do
179 : {
180 0 : rtl::OUString aToken = sLogicalFieldNames.getToken(0, ';', nIndex);
181 0 : aKnownNames.insert(aToken);
182 : }
183 : while ( nIndex >= 0);
184 :
185 : // loop throuzh the given names
186 0 : const AliasProgrammaticPair* pFields = _rFields.getConstArray();
187 0 : const AliasProgrammaticPair* pFieldsEnd = pFields + _rFields.getLength();
188 0 : for (;pFields != pFieldsEnd; ++pFields)
189 : {
190 0 : StringBagIterator aKnownPos = aKnownNames.find( pFields->ProgrammaticName );
191 0 : if ( aKnownNames.end() != aKnownPos )
192 : {
193 0 : m_aAliases[ pFields->ProgrammaticName ] = pFields->Alias;
194 : }
195 : else
196 : {
197 : OSL_FAIL( ( ::rtl::OString("AssigmentTransientData::AssigmentTransientData: unknown programmatic name (")
198 : += ::rtl::OString(pFields->ProgrammaticName.getStr(), pFields->ProgrammaticName.getLength(), RTL_TEXTENCODING_ASCII_US)
199 : += ::rtl::OString(")!")
200 : ).getStr()
201 : );
202 : }
203 0 : }
204 0 : }
205 :
206 : // -------------------------------------------------------------------
207 0 : ::rtl::OUString AssigmentTransientData::getDatasourceName() const
208 : {
209 0 : return m_sDSName;
210 : }
211 :
212 : // -------------------------------------------------------------------
213 0 : ::rtl::OUString AssigmentTransientData::getCommand() const
214 : {
215 0 : return m_sTableName;
216 : }
217 :
218 : // -------------------------------------------------------------------
219 0 : sal_Int32 AssigmentTransientData::getCommandType() const
220 : {
221 0 : return CommandType::TABLE;
222 : }
223 :
224 : // -------------------------------------------------------------------
225 0 : sal_Bool AssigmentTransientData::hasFieldAssignment(const ::rtl::OUString& _rLogicalName)
226 : {
227 0 : ConstMapString2StringIterator aPos = m_aAliases.find( _rLogicalName );
228 0 : return ( m_aAliases.end() != aPos )
229 0 : && ( !aPos->second.isEmpty() );
230 : }
231 :
232 : // -------------------------------------------------------------------
233 0 : ::rtl::OUString AssigmentTransientData::getFieldAssignment(const ::rtl::OUString& _rLogicalName)
234 : {
235 0 : ::rtl::OUString sReturn;
236 0 : ConstMapString2StringIterator aPos = m_aAliases.find( _rLogicalName );
237 0 : if ( m_aAliases.end() != aPos )
238 0 : sReturn = aPos->second;
239 :
240 0 : return sReturn;
241 : }
242 :
243 : // -------------------------------------------------------------------
244 0 : void AssigmentTransientData::setFieldAssignment(const ::rtl::OUString& _rLogicalName, const ::rtl::OUString& _rAssignment)
245 : {
246 0 : m_aAliases[ _rLogicalName ] = _rAssignment;
247 0 : }
248 :
249 : // -------------------------------------------------------------------
250 0 : void AssigmentTransientData::clearFieldAssignment(const ::rtl::OUString& _rLogicalName)
251 : {
252 0 : MapString2StringIterator aPos = m_aAliases.find( _rLogicalName );
253 0 : if ( m_aAliases.end() != aPos )
254 0 : m_aAliases.erase( aPos );
255 0 : }
256 :
257 : // -------------------------------------------------------------------
258 0 : void AssigmentTransientData::setDatasourceName(const ::rtl::OUString&)
259 : {
260 : OSL_FAIL( "AssigmentTransientData::setDatasourceName: cannot be implemented for transient data!" );
261 0 : }
262 :
263 : // -------------------------------------------------------------------
264 0 : void AssigmentTransientData::setCommand(const ::rtl::OUString&)
265 : {
266 : OSL_FAIL( "AssigmentTransientData::setCommand: cannot be implemented for transient data!" );
267 0 : }
268 :
269 : // ===================================================================
270 : // = AssignmentPersistentData
271 : // ===================================================================
272 : class AssignmentPersistentData
273 : :public ::utl::ConfigItem
274 : ,public IAssigmentData
275 : {
276 : protected:
277 : StringBag m_aStoredFields;
278 :
279 : protected:
280 : ::com::sun::star::uno::Any
281 : getProperty(const ::rtl::OUString& _rLocalName) const;
282 : ::com::sun::star::uno::Any
283 : getProperty(const sal_Char* _pLocalName) const;
284 :
285 : ::rtl::OUString getStringProperty(const sal_Char* _pLocalName) const;
286 : sal_Int32 getInt32Property(const sal_Char* _pLocalName) const;
287 :
288 : ::rtl::OUString getStringProperty(const ::rtl::OUString& _rLocalName) const;
289 :
290 : void setStringProperty(const sal_Char* _pLocalName, const ::rtl::OUString& _rValue);
291 :
292 : public:
293 : AssignmentPersistentData();
294 : ~AssignmentPersistentData();
295 :
296 : // IAssigmentData overridables
297 : virtual ::rtl::OUString getDatasourceName() const;
298 : virtual ::rtl::OUString getCommand() const;
299 : virtual sal_Int32 getCommandType() const;
300 :
301 : virtual sal_Bool hasFieldAssignment(const ::rtl::OUString& _rLogicalName);
302 : virtual ::rtl::OUString getFieldAssignment(const ::rtl::OUString& _rLogicalName);
303 : virtual void setFieldAssignment(const ::rtl::OUString& _rLogicalName, const ::rtl::OUString& _rAssignment);
304 : virtual void clearFieldAssignment(const ::rtl::OUString& _rLogicalName);
305 :
306 : virtual void setDatasourceName(const ::rtl::OUString& _rName);
307 : virtual void setCommand(const ::rtl::OUString& _rCommand);
308 :
309 : virtual void Notify( const com::sun::star::uno::Sequence<rtl::OUString>& aPropertyNames);
310 : virtual void Commit();
311 : };
312 :
313 :
314 0 : void AssignmentPersistentData::Notify( const com::sun::star::uno::Sequence<rtl::OUString>& )
315 : {
316 0 : }
317 :
318 0 : void AssignmentPersistentData::Commit()
319 : {
320 0 : }
321 :
322 : // -------------------------------------------------------------------
323 0 : AssignmentPersistentData::AssignmentPersistentData()
324 0 : :ConfigItem( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Office.DataAccess/AddressBook" )))
325 : {
326 0 : Sequence< ::rtl::OUString > aStoredNames = GetNodeNames(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Fields")));
327 0 : const ::rtl::OUString* pStoredNames = aStoredNames.getConstArray();
328 0 : for (sal_Int32 i=0; i<aStoredNames.getLength(); ++i, ++pStoredNames)
329 0 : m_aStoredFields.insert(*pStoredNames);
330 0 : }
331 :
332 : // -------------------------------------------------------------------
333 0 : AssignmentPersistentData::~AssignmentPersistentData()
334 : {
335 0 : }
336 :
337 : // -------------------------------------------------------------------
338 0 : sal_Bool AssignmentPersistentData::hasFieldAssignment(const ::rtl::OUString& _rLogicalName)
339 : {
340 0 : return (m_aStoredFields.end() != m_aStoredFields.find(_rLogicalName));
341 : }
342 :
343 : // -------------------------------------------------------------------
344 0 : ::rtl::OUString AssignmentPersistentData::getFieldAssignment(const ::rtl::OUString& _rLogicalName)
345 : {
346 0 : ::rtl::OUString sAssignment;
347 0 : if (hasFieldAssignment(_rLogicalName))
348 : {
349 0 : ::rtl::OUString sFieldPath(RTL_CONSTASCII_USTRINGPARAM("Fields/"));
350 0 : sFieldPath += _rLogicalName;
351 0 : sFieldPath += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/AssignedFieldName"));
352 0 : sAssignment = getStringProperty(sFieldPath);
353 : }
354 0 : return sAssignment;
355 : }
356 :
357 : // -------------------------------------------------------------------
358 0 : Any AssignmentPersistentData::getProperty(const sal_Char* _pLocalName) const
359 : {
360 0 : return getProperty(::rtl::OUString::createFromAscii(_pLocalName));
361 : }
362 :
363 : // -------------------------------------------------------------------
364 0 : Any AssignmentPersistentData::getProperty(const ::rtl::OUString& _rLocalName) const
365 : {
366 0 : Sequence< ::rtl::OUString > aProperties(&_rLocalName, 1);
367 0 : Sequence< Any > aValues = const_cast<AssignmentPersistentData*>(this)->GetProperties(aProperties);
368 : DBG_ASSERT(aValues.getLength() == 1, "AssignmentPersistentData::getProperty: invalid sequence length!");
369 0 : return aValues[0];
370 : }
371 :
372 : // -------------------------------------------------------------------
373 0 : ::rtl::OUString AssignmentPersistentData::getStringProperty(const ::rtl::OUString& _rLocalName) const
374 : {
375 0 : ::rtl::OUString sReturn;
376 0 : getProperty( _rLocalName ) >>= sReturn;
377 0 : return sReturn;
378 : }
379 :
380 : // -------------------------------------------------------------------
381 0 : ::rtl::OUString AssignmentPersistentData::getStringProperty(const sal_Char* _pLocalName) const
382 : {
383 0 : ::rtl::OUString sReturn;
384 0 : getProperty( _pLocalName ) >>= sReturn;
385 0 : return sReturn;
386 : }
387 :
388 : // -------------------------------------------------------------------
389 0 : sal_Int32 AssignmentPersistentData::getInt32Property(const sal_Char* _pLocalName) const
390 : {
391 0 : sal_Int32 nReturn = 0;
392 0 : getProperty( _pLocalName ) >>= nReturn;
393 0 : return nReturn;
394 : }
395 :
396 : // -------------------------------------------------------------------
397 0 : void AssignmentPersistentData::setStringProperty(const sal_Char* _pLocalName, const ::rtl::OUString& _rValue)
398 : {
399 0 : Sequence< ::rtl::OUString > aNames(1);
400 0 : Sequence< Any > aValues(1);
401 0 : aNames[0] = ::rtl::OUString::createFromAscii(_pLocalName);
402 0 : aValues[0] <<= _rValue;
403 0 : PutProperties(aNames, aValues);
404 0 : }
405 :
406 : // -------------------------------------------------------------------
407 0 : void AssignmentPersistentData::setFieldAssignment(const ::rtl::OUString& _rLogicalName, const ::rtl::OUString& _rAssignment)
408 : {
409 0 : if (_rAssignment.isEmpty())
410 : {
411 0 : if (hasFieldAssignment(_rLogicalName))
412 : // the assignment exists but it should be reset
413 0 : clearFieldAssignment(_rLogicalName);
414 0 : return;
415 : }
416 :
417 : // Fields
418 0 : ::rtl::OUString sDescriptionNodePath(RTL_CONSTASCII_USTRINGPARAM("Fields"));
419 :
420 : // Fields/<field>
421 0 : ::rtl::OUString sFieldElementNodePath(sDescriptionNodePath);
422 0 : sFieldElementNodePath += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"));
423 0 : sFieldElementNodePath += _rLogicalName;
424 :
425 0 : Sequence< PropertyValue > aNewFieldDescription(2);
426 : // Fields/<field>/ProgrammaticFieldName
427 0 : aNewFieldDescription[0].Name = sFieldElementNodePath;
428 0 : aNewFieldDescription[0].Name += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/ProgrammaticFieldName"));
429 0 : aNewFieldDescription[0].Value <<= _rLogicalName;
430 : // Fields/<field>/AssignedFieldName
431 0 : aNewFieldDescription[1].Name = sFieldElementNodePath;
432 0 : aNewFieldDescription[1].Name += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/AssignedFieldName"));
433 0 : aNewFieldDescription[1].Value <<= _rAssignment;
434 :
435 : // just set the new value
436 : #ifdef DBG_UTIL
437 : sal_Bool bSuccess =
438 : #endif
439 0 : SetSetProperties(sDescriptionNodePath, aNewFieldDescription);
440 0 : DBG_ASSERT(bSuccess, "AssignmentPersistentData::setFieldAssignment: could not commit the changes a field!");
441 : }
442 :
443 : // -------------------------------------------------------------------
444 0 : void AssignmentPersistentData::clearFieldAssignment(const ::rtl::OUString& _rLogicalName)
445 : {
446 0 : if (!hasFieldAssignment(_rLogicalName))
447 : // nothing to do
448 0 : return;
449 :
450 0 : ::rtl::OUString sDescriptionNodePath(RTL_CONSTASCII_USTRINGPARAM("Fields"));
451 0 : Sequence< ::rtl::OUString > aNames(&_rLogicalName, 1);
452 0 : ClearNodeElements(sDescriptionNodePath, aNames);
453 : }
454 :
455 : // -------------------------------------------------------------------
456 0 : ::rtl::OUString AssignmentPersistentData::getDatasourceName() const
457 : {
458 0 : return getStringProperty( "DataSourceName" );
459 : }
460 :
461 : // -------------------------------------------------------------------
462 0 : ::rtl::OUString AssignmentPersistentData::getCommand() const
463 : {
464 0 : return getStringProperty( "Command" );
465 : }
466 :
467 : // -------------------------------------------------------------------
468 0 : void AssignmentPersistentData::setDatasourceName(const ::rtl::OUString& _rName)
469 : {
470 0 : setStringProperty( "DataSourceName", _rName );
471 0 : }
472 :
473 : // -------------------------------------------------------------------
474 0 : void AssignmentPersistentData::setCommand(const ::rtl::OUString& _rCommand)
475 : {
476 0 : setStringProperty( "Command", _rCommand );
477 0 : }
478 :
479 : // -------------------------------------------------------------------
480 0 : sal_Int32 AssignmentPersistentData::getCommandType() const
481 : {
482 0 : return getInt32Property( "CommandType" );
483 : }
484 :
485 : // ===================================================================
486 : // = AddressBookSourceDialogData
487 : // ===================================================================
488 : struct AddressBookSourceDialogData
489 : {
490 : FixedText* pFieldLabels[FIELD_PAIRS_VISIBLE * 2];
491 : ListBox* pFields[FIELD_PAIRS_VISIBLE * 2];
492 :
493 : /// when working transient, we need the data source
494 : Reference< XDataSource >
495 : m_xTransientDataSource;
496 : /// current scroll pos in the field list
497 : sal_Int32 nFieldScrollPos;
498 : /// the index within m_pFields of the last visible list box. This is redundant, it could be extracted from other members
499 : sal_Int32 nLastVisibleListIndex;
500 : /// indicates that we've an odd field number. This member is for efficiency only, it's redundant.
501 : sal_Bool bOddFieldNumber : 1;
502 : /// indicates that we're working with the real persistent configuration
503 : sal_Bool bWorkingPersistent : 1;
504 :
505 : /// the strings to use as labels for the field selection listboxes
506 : StringArray aFieldLabels;
507 : // the current field assignment
508 : StringArray aFieldAssignments;
509 : /// the logical field names
510 : StringArray aLogicalFieldNames;
511 :
512 : IAssigmentData* pConfigData;
513 :
514 : // ................................................................
515 0 : AddressBookSourceDialogData( )
516 : :nFieldScrollPos(0)
517 : ,nLastVisibleListIndex(0)
518 : ,bOddFieldNumber(sal_False)
519 : ,bWorkingPersistent( sal_True )
520 0 : ,pConfigData( new AssignmentPersistentData )
521 : {
522 0 : }
523 :
524 : // ................................................................
525 0 : AddressBookSourceDialogData( const Reference< XDataSource >& _rxTransientDS, const ::rtl::OUString& _rDataSourceName,
526 : const ::rtl::OUString& _rTableName, const Sequence< AliasProgrammaticPair >& _rFields )
527 : :m_xTransientDataSource( _rxTransientDS )
528 : ,nFieldScrollPos(0)
529 : ,nLastVisibleListIndex(0)
530 : ,bOddFieldNumber(sal_False)
531 : ,bWorkingPersistent( sal_False )
532 0 : ,pConfigData( new AssigmentTransientData( m_xTransientDataSource, _rDataSourceName, _rTableName, _rFields ) )
533 : {
534 0 : }
535 :
536 0 : ~AddressBookSourceDialogData()
537 0 : {
538 0 : delete pConfigData;
539 0 : }
540 :
541 : };
542 :
543 : // ===================================================================
544 : // = AddressBookSourceDialog
545 : // ===================================================================
546 : #define INIT_FIELDS() \
547 : ModalDialog(_pParent, SvtResId( DLG_ADDRESSBOOKSOURCE ))\
548 : ,m_aDatasourceFrame (this, SvtResId(FL_DATASOURCEFRAME))\
549 : ,m_aDatasourceLabel (this, SvtResId(FT_DATASOURCE))\
550 : ,m_aDatasource (this, SvtResId(CB_DATASOURCE))\
551 : ,m_aAdministrateDatasources (this, SvtResId(PB_ADMINISTATE_DATASOURCES))\
552 : ,m_aTableLabel (this, SvtResId(FT_TABLE))\
553 : ,m_aTable (this, SvtResId(CB_TABLE))\
554 : ,m_aFieldsTitle (this, SvtResId(FT_FIELDS))\
555 : ,m_aFieldsFrame (this, SvtResId(CT_BORDER))\
556 : ,m_aFieldScroller (&m_aFieldsFrame, SvtResId(SB_FIELDSCROLLER))\
557 : ,m_aOK (this, SvtResId(PB_OK))\
558 : ,m_aCancel (this, SvtResId(PB_CANCEL))\
559 : ,m_aHelp (this, SvtResId(PB_HELP))\
560 : ,m_sNoFieldSelection(SVT_RESSTR(STR_NO_FIELD_SELECTION))\
561 : ,m_xORB(_rxORB)
562 :
563 : // -------------------------------------------------------------------
564 0 : AddressBookSourceDialog::AddressBookSourceDialog(Window* _pParent,
565 : const Reference< XMultiServiceFactory >& _rxORB )
566 : :INIT_FIELDS()
567 0 : ,m_pImpl( new AddressBookSourceDialogData )
568 : {
569 0 : implConstruct();
570 0 : }
571 :
572 : // -------------------------------------------------------------------
573 0 : AddressBookSourceDialog::AddressBookSourceDialog( Window* _pParent, const Reference< XMultiServiceFactory >& _rxORB,
574 : const Reference< XDataSource >& _rxTransientDS, const ::rtl::OUString& _rDataSourceName,
575 : const ::rtl::OUString& _rTable, const Sequence< AliasProgrammaticPair >& _rMapping )
576 : :INIT_FIELDS()
577 0 : ,m_pImpl( new AddressBookSourceDialogData( _rxTransientDS, _rDataSourceName, _rTable, _rMapping ) )
578 : {
579 0 : implConstruct();
580 0 : }
581 :
582 : // -------------------------------------------------------------------
583 0 : void AddressBookSourceDialog::implConstruct()
584 : {
585 0 : for (sal_Int32 row=0; row<FIELD_PAIRS_VISIBLE; ++row)
586 : {
587 0 : for (sal_Int32 column=0; column<2; ++column)
588 : {
589 : // the label
590 0 : m_pImpl->pFieldLabels[row * 2 + column] = new FixedText(&m_aFieldsFrame, SvtResId((sal_uInt16)(FT_FIELD_BASE + row * 2 + column)));
591 : // the listbox
592 0 : m_pImpl->pFields[row * 2 + column] = new ListBox(&m_aFieldsFrame, SvtResId((sal_uInt16)(LB_FIELD_BASE + row * 2 + column)));
593 0 : m_pImpl->pFields[row * 2 + column]->SetDropDownLineCount(15);
594 0 : m_pImpl->pFields[row * 2 + column]->SetSelectHdl(LINK(this, AddressBookSourceDialog, OnFieldSelect));
595 :
596 0 : m_pImpl->pFields[row * 2 + column]->SetHelpId(HID_ADDRTEMPL_FIELD_ASSIGNMENT);
597 : }
598 : }
599 :
600 0 : m_aFieldsFrame.SetStyle((m_aFieldsFrame.GetStyle() | WB_TABSTOP | WB_DIALOGCONTROL) & ~WB_NODIALOGCONTROL);
601 :
602 : // correct the z-order
603 0 : m_aFieldScroller.SetZOrder(m_pImpl->pFields[FIELD_CONTROLS_VISIBLE - 1], WINDOW_ZORDER_BEHIND);
604 0 : m_aOK.SetZOrder(&m_aFieldsFrame, WINDOW_ZORDER_BEHIND);
605 0 : m_aCancel.SetZOrder(&m_aOK, WINDOW_ZORDER_BEHIND);
606 :
607 0 : initializeDatasources();
608 :
609 : // for the moment, we have a hard coded list of all known fields.
610 : // A better solution would be to store all known field translations in the configuration, which could be
611 : // extensible by the user in an arbitrary way.
612 : // But for the moment we need a quick solution ...
613 : // (the main thing would be to store the translations to use here in the user interface, besides that, the code
614 : // should be adjustable with a rather small effort.)
615 :
616 : // initialize the strings for the field labels
617 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_FIRSTNAME ));
618 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_LASTNAME ));
619 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_COMPANY));
620 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_DEPARTMENT ));
621 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_STREET ));
622 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_ZIPCODE ));
623 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_CITY ));
624 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_STATE));
625 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_COUNTRY ));
626 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_HOMETEL ));
627 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_WORKTEL ));
628 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_OFFICETEL));
629 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_MOBILE));
630 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_TELOTHER));
631 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_PAGER));
632 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_FAX ));
633 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_EMAIL ));
634 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_URL ));
635 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_TITLE ));
636 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_POSITION ));
637 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_INITIALS ));
638 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_ADDRFORM ));
639 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_SALUTATION ));
640 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_ID));
641 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_CALENDAR));
642 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_INVITE));
643 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_NOTE));
644 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_USER1));
645 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_USER2));
646 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_USER3));
647 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_USER4));
648 :
649 : // force a even number of known fields
650 0 : m_pImpl->bOddFieldNumber = (m_pImpl->aFieldLabels.size() % 2) != 0;
651 0 : if (m_pImpl->bOddFieldNumber)
652 0 : m_pImpl->aFieldLabels.push_back( String() );
653 :
654 : // limit the scrollbar range accordingly
655 0 : sal_Int32 nOverallFieldPairs = m_pImpl->aFieldLabels.size() / 2;
656 0 : m_aFieldScroller.SetRange( Range(0, nOverallFieldPairs - FIELD_PAIRS_VISIBLE) );
657 0 : m_aFieldScroller.SetLineSize(1);
658 0 : m_aFieldScroller.SetPageSize(FIELD_PAIRS_VISIBLE);
659 :
660 : // reset the current field assignments
661 0 : m_pImpl->aFieldAssignments.resize(m_pImpl->aFieldLabels.size());
662 : // (empty strings mean "no assignment")
663 :
664 : // some knittings
665 0 : m_aFieldScroller.SetScrollHdl(LINK(this, AddressBookSourceDialog, OnFieldScroll));
666 0 : m_aAdministrateDatasources.SetClickHdl(LINK(this, AddressBookSourceDialog, OnAdministrateDatasources));
667 0 : m_aDatasource.EnableAutocomplete(sal_True);
668 0 : m_aTable.EnableAutocomplete(sal_True);
669 0 : m_aTable.SetGetFocusHdl(LINK(this, AddressBookSourceDialog, OnComboGetFocus));
670 0 : m_aDatasource.SetGetFocusHdl(LINK(this, AddressBookSourceDialog, OnComboGetFocus));
671 0 : m_aTable.SetLoseFocusHdl(LINK(this, AddressBookSourceDialog, OnComboLoseFocus));
672 0 : m_aDatasource.SetLoseFocusHdl(LINK(this, AddressBookSourceDialog, OnComboLoseFocus));
673 0 : m_aTable.SetSelectHdl(LINK(this, AddressBookSourceDialog, OnComboSelect));
674 0 : m_aDatasource.SetSelectHdl(LINK(this, AddressBookSourceDialog, OnComboSelect));
675 0 : m_aOK.SetClickHdl(LINK(this, AddressBookSourceDialog, OnOkClicked));
676 :
677 0 : m_aDatasource.SetDropDownLineCount(15);
678 :
679 : // initialize the field controls
680 0 : resetFields();
681 0 : m_aFieldScroller.SetThumbPos(0);
682 0 : m_pImpl->nFieldScrollPos = -1;
683 0 : implScrollFields(0, sal_False, sal_False);
684 :
685 : // the logical names
686 0 : rtl::OUString sLogicalFieldNames(SVT_RESSTR(STR_LOGICAL_FIELD_NAMES));
687 0 : sal_Int32 nAdjustedTokenCount = comphelper::string::getTokenCount(sLogicalFieldNames, ';') + (m_pImpl->bOddFieldNumber ? 1 : 0);
688 : DBG_ASSERT(nAdjustedTokenCount == (sal_Int32)m_pImpl->aFieldLabels.size(),
689 : "AddressBookSourceDialog::AddressBookSourceDialog: inconsistence between logical and UI field names!");
690 0 : m_pImpl->aLogicalFieldNames.reserve(nAdjustedTokenCount);
691 0 : for (sal_Int32 i = 0; i<nAdjustedTokenCount; ++i)
692 0 : m_pImpl->aLogicalFieldNames.push_back(comphelper::string::getToken(sLogicalFieldNames, i, ';'));
693 :
694 0 : PostUserEvent(LINK(this, AddressBookSourceDialog, OnDelayedInitialize));
695 : // so the dialog will at least show up before we do the loading of the
696 : // configuration data and the (maybe time consuming) analysis of the data source/table to select
697 :
698 0 : FreeResource();
699 :
700 0 : if ( !m_pImpl->bWorkingPersistent )
701 : {
702 0 : StyleSettings aSystemStyle = GetSettings().GetStyleSettings();
703 0 : const Color& rNewColor = aSystemStyle.GetDialogColor();
704 :
705 0 : m_aDatasource.SetReadOnly( sal_True );
706 0 : m_aDatasource.SetBackground( Wallpaper( rNewColor ) );
707 0 : m_aDatasource.SetControlBackground( rNewColor );
708 :
709 0 : m_aTable.SetReadOnly( sal_True );
710 0 : m_aTable.SetBackground( Wallpaper( rNewColor ) );
711 0 : m_aTable.SetControlBackground( rNewColor );
712 :
713 0 : m_aAdministrateDatasources.Hide( );
714 0 : }
715 0 : }
716 :
717 : // -------------------------------------------------------------------
718 0 : void AddressBookSourceDialog::getFieldMapping(Sequence< AliasProgrammaticPair >& _rMapping) const
719 : {
720 0 : _rMapping.realloc( m_pImpl->aLogicalFieldNames.size() );
721 0 : AliasProgrammaticPair* pPair = _rMapping.getArray();
722 :
723 0 : ::rtl::OUString sCurrent;
724 0 : for ( ConstStringArrayIterator aProgrammatic = m_pImpl->aLogicalFieldNames.begin();
725 0 : aProgrammatic != m_pImpl->aLogicalFieldNames.end();
726 : ++aProgrammatic
727 : )
728 : {
729 0 : sCurrent = *aProgrammatic;
730 0 : if ( m_pImpl->pConfigData->hasFieldAssignment( sCurrent ) )
731 : {
732 : // the user gave us an assignment for this field
733 0 : pPair->ProgrammaticName = *aProgrammatic;
734 0 : pPair->Alias = m_pImpl->pConfigData->getFieldAssignment( *aProgrammatic );
735 0 : ++pPair;
736 : }
737 : }
738 :
739 0 : _rMapping.realloc( pPair - _rMapping.getArray() );
740 0 : }
741 :
742 : // -------------------------------------------------------------------
743 0 : void AddressBookSourceDialog::loadConfiguration()
744 : {
745 0 : ::rtl::OUString sName = m_pImpl->pConfigData->getDatasourceName();
746 0 : INetURLObject aURL( sName );
747 0 : if( aURL.GetProtocol() != INET_PROT_NOT_VALID )
748 : {
749 0 : OFileNotation aFileNotation( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
750 0 : sName = aFileNotation.get(OFileNotation::N_SYSTEM);
751 : }
752 :
753 0 : m_aDatasource.SetText(sName);
754 0 : m_aTable.SetText(m_pImpl->pConfigData->getCommand());
755 : // we ignore the CommandType: only tables are supported
756 :
757 : // the logical names for the fields
758 : DBG_ASSERT(m_pImpl->aLogicalFieldNames.size() == m_pImpl->aFieldAssignments.size(),
759 : "AddressBookSourceDialog::loadConfiguration: inconsistence between field names and field assignments!");
760 :
761 0 : ConstStringArrayIterator aLogical = m_pImpl->aLogicalFieldNames.begin();
762 0 : StringArrayIterator aAssignment = m_pImpl->aFieldAssignments.begin();
763 0 : for ( ;
764 0 : aLogical < m_pImpl->aLogicalFieldNames.end();
765 : ++aLogical, ++aAssignment
766 : )
767 0 : *aAssignment = m_pImpl->pConfigData->getFieldAssignment(*aLogical);
768 0 : }
769 :
770 : // -------------------------------------------------------------------
771 0 : AddressBookSourceDialog::~AddressBookSourceDialog()
772 : {
773 : sal_Int32 i;
774 0 : for (i=0; i<FIELD_CONTROLS_VISIBLE; ++i)
775 : {
776 0 : delete m_pImpl->pFieldLabels[i];
777 0 : delete m_pImpl->pFields[i];
778 : }
779 :
780 0 : delete m_pImpl;
781 0 : }
782 :
783 : // -------------------------------------------------------------------
784 0 : void AddressBookSourceDialog::initializeDatasources()
785 : {
786 0 : if (!m_xDatabaseContext.is())
787 : {
788 : DBG_ASSERT(m_xORB.is(), "AddressBookSourceDialog::initializeDatasources: no service factory!");
789 0 : if (!m_xORB.is())
790 : return;
791 :
792 : try
793 : {
794 0 : m_xDatabaseContext = DatabaseContext::create(comphelper::getComponentContext(m_xORB));
795 : }
796 0 : catch(Exception&) { }
797 0 : if (!m_xDatabaseContext.is())
798 : {
799 0 : const rtl::OUString sContextServiceName("com.sun.star.sdb.DatabaseContext");
800 0 : ShowServiceNotAvailableError( this, sContextServiceName, sal_False);
801 0 : return;
802 : }
803 : }
804 0 : m_aDatasource.Clear();
805 :
806 : // fill the datasources listbox
807 0 : Sequence< ::rtl::OUString > aDatasourceNames;
808 : try
809 : {
810 0 : aDatasourceNames = m_xDatabaseContext->getElementNames();
811 : }
812 0 : catch(Exception&)
813 : {
814 : OSL_FAIL("AddressBookSourceDialog::initializeDatasources: caught an exception while asking for the data source names!");
815 : }
816 0 : const ::rtl::OUString* pDatasourceNames = aDatasourceNames.getConstArray();
817 0 : const ::rtl::OUString* pEnd = pDatasourceNames + aDatasourceNames.getLength();
818 0 : for (; pDatasourceNames < pEnd; ++pDatasourceNames)
819 0 : m_aDatasource.InsertEntry(*pDatasourceNames);
820 : }
821 :
822 : // -------------------------------------------------------------------
823 0 : IMPL_LINK(AddressBookSourceDialog, OnFieldScroll, ScrollBar*, _pScrollBar)
824 : {
825 0 : implScrollFields( _pScrollBar->GetThumbPos(), sal_True, sal_True );
826 0 : return 0L;
827 : }
828 :
829 : // -------------------------------------------------------------------
830 0 : void AddressBookSourceDialog::resetTables()
831 : {
832 0 : if (!m_xDatabaseContext.is())
833 : return;
834 :
835 0 : WaitObject aWaitCursor(this);
836 :
837 : // no matter what we do here, we handled the currently selected data source (no matter if successfull or not)
838 0 : m_aDatasource.SaveValue();
839 :
840 : // create an interaction handler (may be needed for connecting)
841 0 : Reference< XInteractionHandler > xHandler;
842 : try
843 : {
844 : xHandler.set(
845 : InteractionHandler::createWithParent(comphelper::getComponentContext(m_xORB), 0),
846 0 : UNO_QUERY_THROW );
847 : }
848 0 : catch(Exception&) { }
849 0 : if (!xHandler.is())
850 : {
851 0 : const rtl::OUString sInteractionHandlerServiceName("com.sun.star.task.InteractionHandler");
852 0 : ShowServiceNotAvailableError(this, sInteractionHandlerServiceName, sal_True);
853 0 : return;
854 : }
855 :
856 : // the currently selected table
857 0 : ::rtl::OUString sOldTable = m_aTable.GetText();
858 :
859 0 : m_aTable.Clear();
860 :
861 0 : m_xCurrentDatasourceTables= NULL;
862 :
863 : // get the tables of the connection
864 0 : Sequence< ::rtl::OUString > aTableNames;
865 0 : Any aException;
866 : try
867 : {
868 0 : Reference< XCompletedConnection > xDS;
869 0 : if ( m_pImpl->bWorkingPersistent )
870 : {
871 0 : String sSelectedDS = lcl_getSelectedDataSource( m_aDatasource );
872 :
873 : // get the data source the user has chosen and let it build a connection
874 0 : INetURLObject aURL( sSelectedDS );
875 0 : if ( aURL.GetProtocol() != INET_PROT_NOT_VALID || m_xDatabaseContext->hasByName(sSelectedDS) )
876 0 : m_xDatabaseContext->getByName( sSelectedDS ) >>= xDS;
877 : }
878 : else
879 : {
880 0 : xDS = xDS.query( m_pImpl->m_xTransientDataSource );
881 : }
882 :
883 : // build the connection
884 0 : Reference< XConnection > xConn;
885 0 : if (xDS.is())
886 0 : xConn = xDS->connectWithCompletion(xHandler);
887 :
888 : // get the table names
889 0 : Reference< XTablesSupplier > xSupplTables(xConn, UNO_QUERY);
890 0 : if (xSupplTables.is())
891 : {
892 0 : m_xCurrentDatasourceTables = Reference< XNameAccess >(xSupplTables->getTables(), UNO_QUERY);
893 0 : if (m_xCurrentDatasourceTables.is())
894 0 : aTableNames = m_xCurrentDatasourceTables->getElementNames();
895 0 : }
896 : }
897 0 : catch(const SQLContext& e) { aException <<= e; }
898 0 : catch(const SQLWarning& e) { aException <<= e; }
899 0 : catch(const SQLException& e) { aException <<= e; }
900 0 : catch(Exception&)
901 : {
902 : OSL_FAIL("AddressBookSourceDialog::resetTables: could not retrieve the table!");
903 : }
904 :
905 0 : if (aException.hasValue())
906 : {
907 0 : Reference< XInteractionRequest > xRequest = new OInteractionRequest(aException);
908 : try
909 : {
910 0 : xHandler->handle(xRequest);
911 : }
912 0 : catch(Exception&) { }
913 0 : return;
914 : }
915 :
916 0 : sal_Bool bKnowOldTable = sal_False;
917 : // fill the table list
918 0 : const ::rtl::OUString* pTableNames = aTableNames.getConstArray();
919 0 : const ::rtl::OUString* pEnd = pTableNames + aTableNames.getLength();
920 0 : for (;pTableNames != pEnd; ++pTableNames)
921 : {
922 0 : m_aTable.InsertEntry(*pTableNames);
923 0 : if (0 == pTableNames->compareTo(sOldTable))
924 0 : bKnowOldTable = sal_True;
925 : }
926 :
927 : // set the old table, if the new data source knows a table with this name, too. Else reset the tables edit field.
928 0 : if (!bKnowOldTable)
929 0 : sOldTable = ::rtl::OUString();
930 0 : m_aTable.SetText(sOldTable);
931 :
932 0 : resetFields();
933 : }
934 :
935 : // -------------------------------------------------------------------
936 0 : void AddressBookSourceDialog::resetFields()
937 : {
938 0 : WaitObject aWaitCursor(this);
939 :
940 : // no matter what we do here, we handled the currently selected table (no matter if successfull or not)
941 0 : m_aDatasource.SaveValue();
942 :
943 0 : String sSelectedTable = m_aTable.GetText();
944 0 : Sequence< ::rtl::OUString > aColumnNames;
945 : try
946 : {
947 0 : if (m_xCurrentDatasourceTables.is())
948 : {
949 : // get the table and the columns
950 0 : Reference< XColumnsSupplier > xSuppTableCols;
951 0 : if (m_xCurrentDatasourceTables->hasByName(sSelectedTable))
952 0 : ::cppu::extractInterface(xSuppTableCols, m_xCurrentDatasourceTables->getByName(sSelectedTable));
953 0 : Reference< XNameAccess > xColumns;
954 0 : if (xSuppTableCols.is())
955 0 : xColumns = xSuppTableCols->getColumns();
956 0 : if (xColumns.is())
957 0 : aColumnNames = xColumns->getElementNames();
958 : }
959 : }
960 0 : catch(Exception&)
961 : {
962 : OSL_FAIL("AddressBookSourceDialog::resetFields: could not retrieve the table columns!");
963 : }
964 :
965 :
966 0 : const ::rtl::OUString* pColumnNames = aColumnNames.getConstArray();
967 0 : const ::rtl::OUString* pEnd = pColumnNames + aColumnNames.getLength();
968 :
969 : // for quicker access
970 0 : ::std::set< String > aColumnNameSet;
971 0 : for (pColumnNames = aColumnNames.getConstArray(); pColumnNames != pEnd; ++pColumnNames)
972 0 : aColumnNameSet.insert(*pColumnNames);
973 :
974 0 : std::vector<String>::iterator aInitialSelection = m_pImpl->aFieldAssignments.begin() + m_pImpl->nFieldScrollPos;
975 :
976 0 : ListBox** pListbox = m_pImpl->pFields;
977 0 : String sSaveSelection;
978 0 : for (sal_Int32 i=0; i<FIELD_CONTROLS_VISIBLE; ++i, ++pListbox, ++aInitialSelection)
979 : {
980 0 : sSaveSelection = (*pListbox)->GetSelectEntry();
981 :
982 0 : (*pListbox)->Clear();
983 :
984 : // the one entry for "no selection"
985 0 : (*pListbox)->InsertEntry(m_sNoFieldSelection, 0);
986 : // as it's entry data, set the index of the list box in our array
987 0 : (*pListbox)->SetEntryData(0, reinterpret_cast<void*>(i));
988 :
989 : // the field names
990 0 : for (pColumnNames = aColumnNames.getConstArray(); pColumnNames != pEnd; ++pColumnNames)
991 0 : (*pListbox)->InsertEntry(*pColumnNames);
992 :
993 0 : if (aInitialSelection->Len() && (aColumnNameSet.end() != aColumnNameSet.find(*aInitialSelection)))
994 : // we can select the entry as specified in our field assignment array
995 0 : (*pListbox)->SelectEntry(*aInitialSelection);
996 : else
997 : // try to restore the selection
998 0 : if (aColumnNameSet.end() != aColumnNameSet.find(sSaveSelection))
999 : // the old selection is a valid column name
1000 0 : (*pListbox)->SelectEntry(sSaveSelection);
1001 : else
1002 : // select the <none> entry
1003 0 : (*pListbox)->SelectEntryPos(0);
1004 : }
1005 :
1006 : // adjust m_pImpl->aFieldAssignments
1007 0 : for ( StringArrayIterator aAdjust = m_pImpl->aFieldAssignments.begin();
1008 0 : aAdjust != m_pImpl->aFieldAssignments.end();
1009 : ++aAdjust
1010 : )
1011 0 : if (aAdjust->Len())
1012 0 : if (aColumnNameSet.end() == aColumnNameSet.find(*aAdjust))
1013 0 : aAdjust->Erase();
1014 0 : }
1015 :
1016 : // -------------------------------------------------------------------
1017 0 : IMPL_LINK(AddressBookSourceDialog, OnFieldSelect, ListBox*, _pListbox)
1018 : {
1019 : // the index of the affected list box in our array
1020 0 : sal_IntPtr nListBoxIndex = reinterpret_cast<sal_IntPtr>(_pListbox->GetEntryData(0));
1021 : DBG_ASSERT(nListBoxIndex >= 0 && nListBoxIndex < FIELD_CONTROLS_VISIBLE,
1022 : "AddressBookSourceDialog::OnFieldScroll: invalid list box entry!");
1023 :
1024 : // update the array where we remember the field selections
1025 0 : if (0 == _pListbox->GetSelectEntryPos())
1026 : // it's the "no field selection" entry
1027 0 : m_pImpl->aFieldAssignments[m_pImpl->nFieldScrollPos * 2 + nListBoxIndex] = String();
1028 : else
1029 : // it's a regular field entry
1030 0 : m_pImpl->aFieldAssignments[m_pImpl->nFieldScrollPos * 2 + nListBoxIndex] = _pListbox->GetSelectEntry();
1031 :
1032 0 : return 0L;
1033 : }
1034 :
1035 : // -------------------------------------------------------------------
1036 0 : void AddressBookSourceDialog::implScrollFields(sal_Int32 _nPos, sal_Bool _bAdjustFocus, sal_Bool _bAdjustScrollbar)
1037 : {
1038 0 : if (_nPos == m_pImpl->nFieldScrollPos)
1039 : // nothing to do
1040 0 : return;
1041 :
1042 : // loop through our field control rows and do some adjustments
1043 : // for the new texts
1044 0 : FixedText** pLeftLabelControl = m_pImpl->pFieldLabels;
1045 0 : FixedText** pRightLabelControl = pLeftLabelControl + 1;
1046 0 : ConstStringArrayIterator pLeftColumnLabel = m_pImpl->aFieldLabels.begin() + 2 * _nPos;
1047 0 : ConstStringArrayIterator pRightColumnLabel = pLeftColumnLabel + 1;
1048 :
1049 : // for the focus movement and the selection scroll
1050 0 : ListBox** pLeftListControl = m_pImpl->pFields;
1051 0 : ListBox** pRightListControl = pLeftListControl + 1;
1052 :
1053 : // for the focus movement
1054 0 : sal_Int32 nOldFocusRow = -1;
1055 0 : sal_Int32 nOldFocusColumn = 0;
1056 :
1057 : // for the selection scroll
1058 0 : ConstStringArrayIterator pLeftAssignment = m_pImpl->aFieldAssignments.begin() + 2 * _nPos;
1059 0 : ConstStringArrayIterator pRightAssignment = pLeftAssignment + 1;
1060 :
1061 0 : m_pImpl->nLastVisibleListIndex = -1;
1062 : // loop
1063 0 : for (sal_Int32 i=0; i<FIELD_PAIRS_VISIBLE; ++i)
1064 : {
1065 0 : if ((*pLeftListControl)->HasChildPathFocus())
1066 : {
1067 0 : nOldFocusRow = i;
1068 0 : nOldFocusColumn = 0;
1069 : }
1070 0 : else if ((*pRightListControl)->HasChildPathFocus())
1071 : {
1072 0 : nOldFocusRow = i;
1073 0 : nOldFocusColumn = 1;
1074 : }
1075 :
1076 : // the new texts of the label controls
1077 0 : (*pLeftLabelControl)->SetText(*pLeftColumnLabel);
1078 0 : (*pRightLabelControl)->SetText(*pRightColumnLabel);
1079 :
1080 : // we may have to hide the controls in the right column, if we have no label text for it
1081 : // (which means we have an odd number of fields, though we forced our internal arrays to
1082 : // be even-sized for easier handling)
1083 : // (If sometimes we support an arbitrary number of field assignments, we would have to care for
1084 : // an invisible left hand side column, too. But right now, the left hand side controls are always
1085 : // visible)
1086 0 : sal_Bool bHideRightColumn = (0 == pRightColumnLabel->Len());
1087 0 : (*pRightLabelControl)->Show(!bHideRightColumn);
1088 0 : (*pRightListControl)->Show(!bHideRightColumn);
1089 : // the new selections of the listboxes
1090 0 : implSelectField(*pLeftListControl, *pLeftAssignment);
1091 0 : implSelectField(*pRightListControl, *pRightAssignment);
1092 :
1093 : // the index of the last visible list box
1094 0 : ++m_pImpl->nLastVisibleListIndex; // the left hand side box is always visible
1095 0 : if (!bHideRightColumn)
1096 0 : ++m_pImpl->nLastVisibleListIndex;
1097 :
1098 : // increment ...
1099 0 : if ( i < FIELD_PAIRS_VISIBLE - 1 )
1100 : { // (not in the very last round, here the +=2 could result in an invalid
1101 : // iterator position, which causes an abort in a non-product version
1102 0 : pLeftLabelControl += 2;
1103 0 : pRightLabelControl += 2;
1104 0 : pLeftColumnLabel += 2;
1105 0 : pRightColumnLabel += 2;
1106 :
1107 0 : pLeftListControl += 2;
1108 0 : pRightListControl += 2;
1109 0 : pLeftAssignment += 2;
1110 0 : pRightAssignment += 2;
1111 : }
1112 : }
1113 :
1114 0 : if (_bAdjustFocus && (nOldFocusRow >= 0))
1115 : { // we have to adjust the focus and one of the list boxes has the focus
1116 0 : sal_Int32 nDelta = m_pImpl->nFieldScrollPos - _nPos;
1117 : // the new row for the focus
1118 0 : sal_Int32 nNewFocusRow = nOldFocusRow + nDelta;
1119 : // normalize
1120 0 : nNewFocusRow = std::min(nNewFocusRow, (sal_Int32)(FIELD_PAIRS_VISIBLE - 1), ::std::less< sal_Int32 >());
1121 0 : nNewFocusRow = std::max(nNewFocusRow, (sal_Int32)0, ::std::less< sal_Int32 >());
1122 : // set the new focus (in the same column)
1123 0 : m_pImpl->pFields[nNewFocusRow * 2 + nOldFocusColumn]->GrabFocus();
1124 : }
1125 :
1126 0 : m_pImpl->nFieldScrollPos = _nPos;
1127 :
1128 0 : if (_bAdjustScrollbar)
1129 0 : m_aFieldScroller.SetThumbPos(m_pImpl->nFieldScrollPos);
1130 : }
1131 :
1132 : // -------------------------------------------------------------------
1133 0 : void AddressBookSourceDialog::implSelectField(ListBox* _pBox, const String& _rText)
1134 : {
1135 0 : if (_rText.Len())
1136 : // a valid field name
1137 0 : _pBox->SelectEntry(_rText);
1138 : else
1139 : // no selection for this item
1140 0 : _pBox->SelectEntryPos(0);
1141 0 : }
1142 :
1143 : // -------------------------------------------------------------------
1144 0 : IMPL_LINK_NOARG(AddressBookSourceDialog, OnDelayedInitialize)
1145 : {
1146 : // load the initial data from the configuration
1147 0 : loadConfiguration();
1148 0 : resetTables();
1149 : // will reset the tables/fields implicitly
1150 :
1151 0 : if ( !m_pImpl->bWorkingPersistent )
1152 0 : if ( m_pImpl->pFields[0] )
1153 0 : m_pImpl->pFields[0]->GrabFocus();
1154 :
1155 0 : return 0L;
1156 : }
1157 :
1158 : // -------------------------------------------------------------------
1159 0 : IMPL_LINK(AddressBookSourceDialog, OnComboSelect, ComboBox*, _pBox)
1160 : {
1161 0 : if (_pBox == &m_aDatasource)
1162 0 : resetTables();
1163 : else
1164 0 : resetFields();
1165 0 : return 0;
1166 : }
1167 :
1168 : // -------------------------------------------------------------------
1169 0 : IMPL_LINK(AddressBookSourceDialog, OnComboGetFocus, ComboBox*, _pBox)
1170 : {
1171 0 : _pBox->SaveValue();
1172 0 : return 0L;
1173 : }
1174 :
1175 : // -------------------------------------------------------------------
1176 0 : IMPL_LINK(AddressBookSourceDialog, OnComboLoseFocus, ComboBox*, _pBox)
1177 : {
1178 0 : if (_pBox->GetSavedValue() != _pBox->GetText())
1179 : {
1180 0 : if (_pBox == &m_aDatasource)
1181 0 : resetTables();
1182 : else
1183 0 : resetFields();
1184 : }
1185 0 : return 0L;
1186 : }
1187 :
1188 : // -------------------------------------------------------------------
1189 0 : IMPL_LINK_NOARG(AddressBookSourceDialog, OnOkClicked)
1190 : {
1191 0 : String sSelectedDS = lcl_getSelectedDataSource( m_aDatasource );
1192 0 : if ( m_pImpl->bWorkingPersistent )
1193 : {
1194 0 : m_pImpl->pConfigData->setDatasourceName(sSelectedDS);
1195 0 : m_pImpl->pConfigData->setCommand(m_aTable.GetText());
1196 : }
1197 :
1198 : // set the field assignments
1199 0 : ConstStringArrayIterator aLogical = m_pImpl->aLogicalFieldNames.begin();
1200 0 : ConstStringArrayIterator aAssignment = m_pImpl->aFieldAssignments.begin();
1201 0 : for ( ;
1202 0 : aLogical < m_pImpl->aLogicalFieldNames.end();
1203 : ++aLogical, ++aAssignment
1204 : )
1205 0 : m_pImpl->pConfigData->setFieldAssignment(*aLogical, *aAssignment);
1206 :
1207 :
1208 0 : EndDialog(RET_OK);
1209 0 : return 0L;
1210 : }
1211 :
1212 : // -------------------------------------------------------------------
1213 0 : IMPL_LINK_NOARG(AddressBookSourceDialog, OnAdministrateDatasources)
1214 : {
1215 : // collect some initial arguments for the dialog
1216 0 : Sequence< Any > aArgs(1);
1217 0 : aArgs[0] <<= PropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParentWindow")), 0, makeAny(VCLUnoHelper::GetInterface(this)), PropertyState_DIRECT_VALUE);
1218 :
1219 : // create the dialog object
1220 0 : const rtl::OUString sDialogServiceName("com.sun.star.ui.dialogs.AddressBookSourcePilot");
1221 0 : Reference< XExecutableDialog > xAdminDialog;
1222 : try
1223 : {
1224 0 : xAdminDialog = Reference< XExecutableDialog >(m_xORB->createInstanceWithArguments(sDialogServiceName, aArgs), UNO_QUERY);
1225 : }
1226 0 : catch(Exception&) { }
1227 0 : if (!xAdminDialog.is())
1228 : {
1229 0 : ShowServiceNotAvailableError(this, sDialogServiceName, sal_True);
1230 0 : return 1L;
1231 : }
1232 :
1233 : // excute the dialog
1234 : try
1235 : {
1236 0 : if ( xAdminDialog->execute() == RET_OK )
1237 : {
1238 0 : Reference<XPropertySet> xProp(xAdminDialog,UNO_QUERY);
1239 0 : if ( xProp.is() )
1240 : {
1241 0 : ::rtl::OUString sName;
1242 0 : xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSourceName"))) >>= sName;
1243 :
1244 0 : INetURLObject aURL( sName );
1245 0 : if( aURL.GetProtocol() != INET_PROT_NOT_VALID )
1246 : {
1247 0 : OFileNotation aFileNotation( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
1248 0 : sName = aFileNotation.get(OFileNotation::N_SYSTEM);
1249 : }
1250 0 : m_aDatasource.InsertEntry(sName);
1251 0 : delete m_pImpl->pConfigData;
1252 0 : m_pImpl->pConfigData = new AssignmentPersistentData();
1253 0 : loadConfiguration();
1254 0 : resetTables();
1255 : // will reset the fields implicitly
1256 0 : }
1257 : }
1258 : }
1259 0 : catch(Exception&)
1260 : {
1261 : OSL_FAIL("AddressBookSourceDialog::OnAdministrateDatasources: an error occurred while executing the administration dialog!");
1262 : }
1263 :
1264 : // re-fill the data source list
1265 : // try to preserve the current selection
1266 :
1267 : // initializeDatasources();
1268 :
1269 0 : return 0L;
1270 : }
1271 :
1272 : // -------------------------------------------------------------------
1273 0 : long AddressBookSourceDialog::PreNotify( NotifyEvent& _rNEvt )
1274 : {
1275 0 : switch (_rNEvt.GetType())
1276 : {
1277 : case EVENT_KEYINPUT:
1278 : {
1279 0 : const KeyEvent* pKeyEvent = _rNEvt.GetKeyEvent();
1280 0 : sal_uInt16 nCode = pKeyEvent->GetKeyCode().GetCode();
1281 0 : sal_Bool bShift = pKeyEvent->GetKeyCode().IsShift();
1282 0 : sal_Bool bCtrl = pKeyEvent->GetKeyCode().IsMod1();
1283 0 : sal_Bool bAlt = pKeyEvent->GetKeyCode().IsMod2();
1284 :
1285 0 : if (KEY_TAB == nCode)
1286 : { // somebody pressed the tab key
1287 0 : if (!bAlt && !bCtrl && !bShift)
1288 : { // it's really the only the key (no modifiers)
1289 0 : if (m_pImpl->pFields[m_pImpl->nLastVisibleListIndex]->HasChildPathFocus())
1290 : // the last of our visible list boxes has the focus
1291 0 : if (m_pImpl->nFieldScrollPos < m_aFieldScroller.GetRangeMax())
1292 : { // we can still scroll down
1293 0 : sal_Int32 nNextFocusList = m_pImpl->nLastVisibleListIndex + 1 - 2;
1294 : // -> scroll down
1295 0 : implScrollFields(m_pImpl->nFieldScrollPos + 1, sal_False, sal_True);
1296 : // give the left control in the "next" line the focus
1297 0 : m_pImpl->pFields[nNextFocusList]->GrabFocus();
1298 : // return saying "have handled this"
1299 0 : return 1;
1300 0 : }
1301 : }
1302 0 : else if (!bAlt && !bCtrl && bShift)
1303 : { // it's shift-tab
1304 0 : if (m_pImpl->pFields[0]->HasChildPathFocus())
1305 : // our first list box has the focus
1306 0 : if (m_pImpl->nFieldScrollPos > 0)
1307 : { // we can still scroll up
1308 : // -> scroll up
1309 0 : implScrollFields(m_pImpl->nFieldScrollPos - 1, sal_False, sal_True);
1310 : // give the right control in the "prebious" line the focus
1311 0 : m_pImpl->pFields[0 - 1 + 2]->GrabFocus();
1312 : // return saying "have handled this"
1313 0 : return 1;
1314 : }
1315 : }
1316 : }
1317 : }
1318 0 : break;
1319 : }
1320 0 : return ModalDialog::PreNotify(_rNEvt);
1321 : }
1322 :
1323 : // .......................................................................
1324 : } // namespace svt
1325 : // .......................................................................
1326 :
1327 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|