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(const Exception&)
797 : {
798 0 : const rtl::OUString sContextServiceName("com.sun.star.sdb.DatabaseContext");
799 0 : ShowServiceNotAvailableError( this, sContextServiceName, sal_False);
800 0 : return;
801 : }
802 : }
803 0 : m_aDatasource.Clear();
804 :
805 : // fill the datasources listbox
806 0 : Sequence< ::rtl::OUString > aDatasourceNames;
807 : try
808 : {
809 0 : aDatasourceNames = m_xDatabaseContext->getElementNames();
810 : }
811 0 : catch(Exception&)
812 : {
813 : OSL_FAIL("AddressBookSourceDialog::initializeDatasources: caught an exception while asking for the data source names!");
814 : }
815 0 : const ::rtl::OUString* pDatasourceNames = aDatasourceNames.getConstArray();
816 0 : const ::rtl::OUString* pEnd = pDatasourceNames + aDatasourceNames.getLength();
817 0 : for (; pDatasourceNames < pEnd; ++pDatasourceNames)
818 0 : m_aDatasource.InsertEntry(*pDatasourceNames);
819 : }
820 :
821 : // -------------------------------------------------------------------
822 0 : IMPL_LINK(AddressBookSourceDialog, OnFieldScroll, ScrollBar*, _pScrollBar)
823 : {
824 0 : implScrollFields( _pScrollBar->GetThumbPos(), sal_True, sal_True );
825 0 : return 0L;
826 : }
827 :
828 : // -------------------------------------------------------------------
829 0 : void AddressBookSourceDialog::resetTables()
830 : {
831 0 : if (!m_xDatabaseContext.is())
832 : return;
833 :
834 0 : WaitObject aWaitCursor(this);
835 :
836 : // no matter what we do here, we handled the currently selected data source (no matter if successfull or not)
837 0 : m_aDatasource.SaveValue();
838 :
839 : // create an interaction handler (may be needed for connecting)
840 0 : Reference< XInteractionHandler > xHandler;
841 : try
842 : {
843 : xHandler.set(
844 : InteractionHandler::createWithParent(comphelper::getComponentContext(m_xORB), 0),
845 0 : UNO_QUERY_THROW );
846 : }
847 0 : catch(Exception&) { }
848 0 : if (!xHandler.is())
849 : {
850 0 : const rtl::OUString sInteractionHandlerServiceName("com.sun.star.task.InteractionHandler");
851 0 : ShowServiceNotAvailableError(this, sInteractionHandlerServiceName, sal_True);
852 0 : return;
853 : }
854 :
855 : // the currently selected table
856 0 : ::rtl::OUString sOldTable = m_aTable.GetText();
857 :
858 0 : m_aTable.Clear();
859 :
860 0 : m_xCurrentDatasourceTables= NULL;
861 :
862 : // get the tables of the connection
863 0 : Sequence< ::rtl::OUString > aTableNames;
864 0 : Any aException;
865 : try
866 : {
867 0 : Reference< XCompletedConnection > xDS;
868 0 : if ( m_pImpl->bWorkingPersistent )
869 : {
870 0 : String sSelectedDS = lcl_getSelectedDataSource( m_aDatasource );
871 :
872 : // get the data source the user has chosen and let it build a connection
873 0 : INetURLObject aURL( sSelectedDS );
874 0 : if ( aURL.GetProtocol() != INET_PROT_NOT_VALID || m_xDatabaseContext->hasByName(sSelectedDS) )
875 0 : m_xDatabaseContext->getByName( sSelectedDS ) >>= xDS;
876 : }
877 : else
878 : {
879 0 : xDS = xDS.query( m_pImpl->m_xTransientDataSource );
880 : }
881 :
882 : // build the connection
883 0 : Reference< XConnection > xConn;
884 0 : if (xDS.is())
885 0 : xConn = xDS->connectWithCompletion(xHandler);
886 :
887 : // get the table names
888 0 : Reference< XTablesSupplier > xSupplTables(xConn, UNO_QUERY);
889 0 : if (xSupplTables.is())
890 : {
891 0 : m_xCurrentDatasourceTables = Reference< XNameAccess >(xSupplTables->getTables(), UNO_QUERY);
892 0 : if (m_xCurrentDatasourceTables.is())
893 0 : aTableNames = m_xCurrentDatasourceTables->getElementNames();
894 0 : }
895 : }
896 0 : catch(const SQLContext& e) { aException <<= e; }
897 0 : catch(const SQLWarning& e) { aException <<= e; }
898 0 : catch(const SQLException& e) { aException <<= e; }
899 0 : catch(Exception&)
900 : {
901 : OSL_FAIL("AddressBookSourceDialog::resetTables: could not retrieve the table!");
902 : }
903 :
904 0 : if (aException.hasValue())
905 : {
906 0 : Reference< XInteractionRequest > xRequest = new OInteractionRequest(aException);
907 : try
908 : {
909 0 : xHandler->handle(xRequest);
910 : }
911 0 : catch(Exception&) { }
912 0 : return;
913 : }
914 :
915 0 : sal_Bool bKnowOldTable = sal_False;
916 : // fill the table list
917 0 : const ::rtl::OUString* pTableNames = aTableNames.getConstArray();
918 0 : const ::rtl::OUString* pEnd = pTableNames + aTableNames.getLength();
919 0 : for (;pTableNames != pEnd; ++pTableNames)
920 : {
921 0 : m_aTable.InsertEntry(*pTableNames);
922 0 : if (0 == pTableNames->compareTo(sOldTable))
923 0 : bKnowOldTable = sal_True;
924 : }
925 :
926 : // set the old table, if the new data source knows a table with this name, too. Else reset the tables edit field.
927 0 : if (!bKnowOldTable)
928 0 : sOldTable = ::rtl::OUString();
929 0 : m_aTable.SetText(sOldTable);
930 :
931 0 : resetFields();
932 : }
933 :
934 : // -------------------------------------------------------------------
935 0 : void AddressBookSourceDialog::resetFields()
936 : {
937 0 : WaitObject aWaitCursor(this);
938 :
939 : // no matter what we do here, we handled the currently selected table (no matter if successfull or not)
940 0 : m_aDatasource.SaveValue();
941 :
942 0 : String sSelectedTable = m_aTable.GetText();
943 0 : Sequence< ::rtl::OUString > aColumnNames;
944 : try
945 : {
946 0 : if (m_xCurrentDatasourceTables.is())
947 : {
948 : // get the table and the columns
949 0 : Reference< XColumnsSupplier > xSuppTableCols;
950 0 : if (m_xCurrentDatasourceTables->hasByName(sSelectedTable))
951 0 : ::cppu::extractInterface(xSuppTableCols, m_xCurrentDatasourceTables->getByName(sSelectedTable));
952 0 : Reference< XNameAccess > xColumns;
953 0 : if (xSuppTableCols.is())
954 0 : xColumns = xSuppTableCols->getColumns();
955 0 : if (xColumns.is())
956 0 : aColumnNames = xColumns->getElementNames();
957 : }
958 : }
959 0 : catch(Exception&)
960 : {
961 : OSL_FAIL("AddressBookSourceDialog::resetFields: could not retrieve the table columns!");
962 : }
963 :
964 :
965 0 : const ::rtl::OUString* pColumnNames = aColumnNames.getConstArray();
966 0 : const ::rtl::OUString* pEnd = pColumnNames + aColumnNames.getLength();
967 :
968 : // for quicker access
969 0 : ::std::set< String > aColumnNameSet;
970 0 : for (pColumnNames = aColumnNames.getConstArray(); pColumnNames != pEnd; ++pColumnNames)
971 0 : aColumnNameSet.insert(*pColumnNames);
972 :
973 0 : std::vector<String>::iterator aInitialSelection = m_pImpl->aFieldAssignments.begin() + m_pImpl->nFieldScrollPos;
974 :
975 0 : ListBox** pListbox = m_pImpl->pFields;
976 0 : String sSaveSelection;
977 0 : for (sal_Int32 i=0; i<FIELD_CONTROLS_VISIBLE; ++i, ++pListbox, ++aInitialSelection)
978 : {
979 0 : sSaveSelection = (*pListbox)->GetSelectEntry();
980 :
981 0 : (*pListbox)->Clear();
982 :
983 : // the one entry for "no selection"
984 0 : (*pListbox)->InsertEntry(m_sNoFieldSelection, 0);
985 : // as it's entry data, set the index of the list box in our array
986 0 : (*pListbox)->SetEntryData(0, reinterpret_cast<void*>(i));
987 :
988 : // the field names
989 0 : for (pColumnNames = aColumnNames.getConstArray(); pColumnNames != pEnd; ++pColumnNames)
990 0 : (*pListbox)->InsertEntry(*pColumnNames);
991 :
992 0 : if (aInitialSelection->Len() && (aColumnNameSet.end() != aColumnNameSet.find(*aInitialSelection)))
993 : // we can select the entry as specified in our field assignment array
994 0 : (*pListbox)->SelectEntry(*aInitialSelection);
995 : else
996 : // try to restore the selection
997 0 : if (aColumnNameSet.end() != aColumnNameSet.find(sSaveSelection))
998 : // the old selection is a valid column name
999 0 : (*pListbox)->SelectEntry(sSaveSelection);
1000 : else
1001 : // select the <none> entry
1002 0 : (*pListbox)->SelectEntryPos(0);
1003 : }
1004 :
1005 : // adjust m_pImpl->aFieldAssignments
1006 0 : for ( StringArrayIterator aAdjust = m_pImpl->aFieldAssignments.begin();
1007 0 : aAdjust != m_pImpl->aFieldAssignments.end();
1008 : ++aAdjust
1009 : )
1010 0 : if (aAdjust->Len())
1011 0 : if (aColumnNameSet.end() == aColumnNameSet.find(*aAdjust))
1012 0 : aAdjust->Erase();
1013 0 : }
1014 :
1015 : // -------------------------------------------------------------------
1016 0 : IMPL_LINK(AddressBookSourceDialog, OnFieldSelect, ListBox*, _pListbox)
1017 : {
1018 : // the index of the affected list box in our array
1019 0 : sal_IntPtr nListBoxIndex = reinterpret_cast<sal_IntPtr>(_pListbox->GetEntryData(0));
1020 : DBG_ASSERT(nListBoxIndex >= 0 && nListBoxIndex < FIELD_CONTROLS_VISIBLE,
1021 : "AddressBookSourceDialog::OnFieldScroll: invalid list box entry!");
1022 :
1023 : // update the array where we remember the field selections
1024 0 : if (0 == _pListbox->GetSelectEntryPos())
1025 : // it's the "no field selection" entry
1026 0 : m_pImpl->aFieldAssignments[m_pImpl->nFieldScrollPos * 2 + nListBoxIndex] = String();
1027 : else
1028 : // it's a regular field entry
1029 0 : m_pImpl->aFieldAssignments[m_pImpl->nFieldScrollPos * 2 + nListBoxIndex] = _pListbox->GetSelectEntry();
1030 :
1031 0 : return 0L;
1032 : }
1033 :
1034 : // -------------------------------------------------------------------
1035 0 : void AddressBookSourceDialog::implScrollFields(sal_Int32 _nPos, sal_Bool _bAdjustFocus, sal_Bool _bAdjustScrollbar)
1036 : {
1037 0 : if (_nPos == m_pImpl->nFieldScrollPos)
1038 : // nothing to do
1039 0 : return;
1040 :
1041 : // loop through our field control rows and do some adjustments
1042 : // for the new texts
1043 0 : FixedText** pLeftLabelControl = m_pImpl->pFieldLabels;
1044 0 : FixedText** pRightLabelControl = pLeftLabelControl + 1;
1045 0 : ConstStringArrayIterator pLeftColumnLabel = m_pImpl->aFieldLabels.begin() + 2 * _nPos;
1046 0 : ConstStringArrayIterator pRightColumnLabel = pLeftColumnLabel + 1;
1047 :
1048 : // for the focus movement and the selection scroll
1049 0 : ListBox** pLeftListControl = m_pImpl->pFields;
1050 0 : ListBox** pRightListControl = pLeftListControl + 1;
1051 :
1052 : // for the focus movement
1053 0 : sal_Int32 nOldFocusRow = -1;
1054 0 : sal_Int32 nOldFocusColumn = 0;
1055 :
1056 : // for the selection scroll
1057 0 : ConstStringArrayIterator pLeftAssignment = m_pImpl->aFieldAssignments.begin() + 2 * _nPos;
1058 0 : ConstStringArrayIterator pRightAssignment = pLeftAssignment + 1;
1059 :
1060 0 : m_pImpl->nLastVisibleListIndex = -1;
1061 : // loop
1062 0 : for (sal_Int32 i=0; i<FIELD_PAIRS_VISIBLE; ++i)
1063 : {
1064 0 : if ((*pLeftListControl)->HasChildPathFocus())
1065 : {
1066 0 : nOldFocusRow = i;
1067 0 : nOldFocusColumn = 0;
1068 : }
1069 0 : else if ((*pRightListControl)->HasChildPathFocus())
1070 : {
1071 0 : nOldFocusRow = i;
1072 0 : nOldFocusColumn = 1;
1073 : }
1074 :
1075 : // the new texts of the label controls
1076 0 : (*pLeftLabelControl)->SetText(*pLeftColumnLabel);
1077 0 : (*pRightLabelControl)->SetText(*pRightColumnLabel);
1078 :
1079 : // we may have to hide the controls in the right column, if we have no label text for it
1080 : // (which means we have an odd number of fields, though we forced our internal arrays to
1081 : // be even-sized for easier handling)
1082 : // (If sometimes we support an arbitrary number of field assignments, we would have to care for
1083 : // an invisible left hand side column, too. But right now, the left hand side controls are always
1084 : // visible)
1085 0 : sal_Bool bHideRightColumn = (0 == pRightColumnLabel->Len());
1086 0 : (*pRightLabelControl)->Show(!bHideRightColumn);
1087 0 : (*pRightListControl)->Show(!bHideRightColumn);
1088 : // the new selections of the listboxes
1089 0 : implSelectField(*pLeftListControl, *pLeftAssignment);
1090 0 : implSelectField(*pRightListControl, *pRightAssignment);
1091 :
1092 : // the index of the last visible list box
1093 0 : ++m_pImpl->nLastVisibleListIndex; // the left hand side box is always visible
1094 0 : if (!bHideRightColumn)
1095 0 : ++m_pImpl->nLastVisibleListIndex;
1096 :
1097 : // increment ...
1098 0 : if ( i < FIELD_PAIRS_VISIBLE - 1 )
1099 : { // (not in the very last round, here the +=2 could result in an invalid
1100 : // iterator position, which causes an abort in a non-product version
1101 0 : pLeftLabelControl += 2;
1102 0 : pRightLabelControl += 2;
1103 0 : pLeftColumnLabel += 2;
1104 0 : pRightColumnLabel += 2;
1105 :
1106 0 : pLeftListControl += 2;
1107 0 : pRightListControl += 2;
1108 0 : pLeftAssignment += 2;
1109 0 : pRightAssignment += 2;
1110 : }
1111 : }
1112 :
1113 0 : if (_bAdjustFocus && (nOldFocusRow >= 0))
1114 : { // we have to adjust the focus and one of the list boxes has the focus
1115 0 : sal_Int32 nDelta = m_pImpl->nFieldScrollPos - _nPos;
1116 : // the new row for the focus
1117 0 : sal_Int32 nNewFocusRow = nOldFocusRow + nDelta;
1118 : // normalize
1119 0 : nNewFocusRow = std::min(nNewFocusRow, (sal_Int32)(FIELD_PAIRS_VISIBLE - 1), ::std::less< sal_Int32 >());
1120 0 : nNewFocusRow = std::max(nNewFocusRow, (sal_Int32)0, ::std::less< sal_Int32 >());
1121 : // set the new focus (in the same column)
1122 0 : m_pImpl->pFields[nNewFocusRow * 2 + nOldFocusColumn]->GrabFocus();
1123 : }
1124 :
1125 0 : m_pImpl->nFieldScrollPos = _nPos;
1126 :
1127 0 : if (_bAdjustScrollbar)
1128 0 : m_aFieldScroller.SetThumbPos(m_pImpl->nFieldScrollPos);
1129 : }
1130 :
1131 : // -------------------------------------------------------------------
1132 0 : void AddressBookSourceDialog::implSelectField(ListBox* _pBox, const String& _rText)
1133 : {
1134 0 : if (_rText.Len())
1135 : // a valid field name
1136 0 : _pBox->SelectEntry(_rText);
1137 : else
1138 : // no selection for this item
1139 0 : _pBox->SelectEntryPos(0);
1140 0 : }
1141 :
1142 : // -------------------------------------------------------------------
1143 0 : IMPL_LINK_NOARG(AddressBookSourceDialog, OnDelayedInitialize)
1144 : {
1145 : // load the initial data from the configuration
1146 0 : loadConfiguration();
1147 0 : resetTables();
1148 : // will reset the tables/fields implicitly
1149 :
1150 0 : if ( !m_pImpl->bWorkingPersistent )
1151 0 : if ( m_pImpl->pFields[0] )
1152 0 : m_pImpl->pFields[0]->GrabFocus();
1153 :
1154 0 : return 0L;
1155 : }
1156 :
1157 : // -------------------------------------------------------------------
1158 0 : IMPL_LINK(AddressBookSourceDialog, OnComboSelect, ComboBox*, _pBox)
1159 : {
1160 0 : if (_pBox == &m_aDatasource)
1161 0 : resetTables();
1162 : else
1163 0 : resetFields();
1164 0 : return 0;
1165 : }
1166 :
1167 : // -------------------------------------------------------------------
1168 0 : IMPL_LINK(AddressBookSourceDialog, OnComboGetFocus, ComboBox*, _pBox)
1169 : {
1170 0 : _pBox->SaveValue();
1171 0 : return 0L;
1172 : }
1173 :
1174 : // -------------------------------------------------------------------
1175 0 : IMPL_LINK(AddressBookSourceDialog, OnComboLoseFocus, ComboBox*, _pBox)
1176 : {
1177 0 : if (_pBox->GetSavedValue() != _pBox->GetText())
1178 : {
1179 0 : if (_pBox == &m_aDatasource)
1180 0 : resetTables();
1181 : else
1182 0 : resetFields();
1183 : }
1184 0 : return 0L;
1185 : }
1186 :
1187 : // -------------------------------------------------------------------
1188 0 : IMPL_LINK_NOARG(AddressBookSourceDialog, OnOkClicked)
1189 : {
1190 0 : String sSelectedDS = lcl_getSelectedDataSource( m_aDatasource );
1191 0 : if ( m_pImpl->bWorkingPersistent )
1192 : {
1193 0 : m_pImpl->pConfigData->setDatasourceName(sSelectedDS);
1194 0 : m_pImpl->pConfigData->setCommand(m_aTable.GetText());
1195 : }
1196 :
1197 : // set the field assignments
1198 0 : ConstStringArrayIterator aLogical = m_pImpl->aLogicalFieldNames.begin();
1199 0 : ConstStringArrayIterator aAssignment = m_pImpl->aFieldAssignments.begin();
1200 0 : for ( ;
1201 0 : aLogical < m_pImpl->aLogicalFieldNames.end();
1202 : ++aLogical, ++aAssignment
1203 : )
1204 0 : m_pImpl->pConfigData->setFieldAssignment(*aLogical, *aAssignment);
1205 :
1206 :
1207 0 : EndDialog(RET_OK);
1208 0 : return 0L;
1209 : }
1210 :
1211 : // -------------------------------------------------------------------
1212 0 : IMPL_LINK_NOARG(AddressBookSourceDialog, OnAdministrateDatasources)
1213 : {
1214 : // collect some initial arguments for the dialog
1215 0 : Sequence< Any > aArgs(1);
1216 0 : aArgs[0] <<= PropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParentWindow")), 0, makeAny(VCLUnoHelper::GetInterface(this)), PropertyState_DIRECT_VALUE);
1217 :
1218 : // create the dialog object
1219 0 : const rtl::OUString sDialogServiceName("com.sun.star.ui.dialogs.AddressBookSourcePilot");
1220 0 : Reference< XExecutableDialog > xAdminDialog;
1221 : try
1222 : {
1223 0 : xAdminDialog = Reference< XExecutableDialog >(m_xORB->createInstanceWithArguments(sDialogServiceName, aArgs), UNO_QUERY);
1224 : }
1225 0 : catch(Exception&) { }
1226 0 : if (!xAdminDialog.is())
1227 : {
1228 0 : ShowServiceNotAvailableError(this, sDialogServiceName, sal_True);
1229 0 : return 1L;
1230 : }
1231 :
1232 : // excute the dialog
1233 : try
1234 : {
1235 0 : if ( xAdminDialog->execute() == RET_OK )
1236 : {
1237 0 : Reference<XPropertySet> xProp(xAdminDialog,UNO_QUERY);
1238 0 : if ( xProp.is() )
1239 : {
1240 0 : ::rtl::OUString sName;
1241 0 : xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSourceName"))) >>= sName;
1242 :
1243 0 : INetURLObject aURL( sName );
1244 0 : if( aURL.GetProtocol() != INET_PROT_NOT_VALID )
1245 : {
1246 0 : OFileNotation aFileNotation( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
1247 0 : sName = aFileNotation.get(OFileNotation::N_SYSTEM);
1248 : }
1249 0 : m_aDatasource.InsertEntry(sName);
1250 0 : delete m_pImpl->pConfigData;
1251 0 : m_pImpl->pConfigData = new AssignmentPersistentData();
1252 0 : loadConfiguration();
1253 0 : resetTables();
1254 : // will reset the fields implicitly
1255 0 : }
1256 : }
1257 : }
1258 0 : catch(Exception&)
1259 : {
1260 : OSL_FAIL("AddressBookSourceDialog::OnAdministrateDatasources: an error occurred while executing the administration dialog!");
1261 : }
1262 :
1263 : // re-fill the data source list
1264 : // try to preserve the current selection
1265 :
1266 : // initializeDatasources();
1267 :
1268 0 : return 0L;
1269 : }
1270 :
1271 : // -------------------------------------------------------------------
1272 0 : long AddressBookSourceDialog::PreNotify( NotifyEvent& _rNEvt )
1273 : {
1274 0 : switch (_rNEvt.GetType())
1275 : {
1276 : case EVENT_KEYINPUT:
1277 : {
1278 0 : const KeyEvent* pKeyEvent = _rNEvt.GetKeyEvent();
1279 0 : sal_uInt16 nCode = pKeyEvent->GetKeyCode().GetCode();
1280 0 : sal_Bool bShift = pKeyEvent->GetKeyCode().IsShift();
1281 0 : sal_Bool bCtrl = pKeyEvent->GetKeyCode().IsMod1();
1282 0 : sal_Bool bAlt = pKeyEvent->GetKeyCode().IsMod2();
1283 :
1284 0 : if (KEY_TAB == nCode)
1285 : { // somebody pressed the tab key
1286 0 : if (!bAlt && !bCtrl && !bShift)
1287 : { // it's really the only the key (no modifiers)
1288 0 : if (m_pImpl->pFields[m_pImpl->nLastVisibleListIndex]->HasChildPathFocus())
1289 : // the last of our visible list boxes has the focus
1290 0 : if (m_pImpl->nFieldScrollPos < m_aFieldScroller.GetRangeMax())
1291 : { // we can still scroll down
1292 0 : sal_Int32 nNextFocusList = m_pImpl->nLastVisibleListIndex + 1 - 2;
1293 : // -> scroll down
1294 0 : implScrollFields(m_pImpl->nFieldScrollPos + 1, sal_False, sal_True);
1295 : // give the left control in the "next" line the focus
1296 0 : m_pImpl->pFields[nNextFocusList]->GrabFocus();
1297 : // return saying "have handled this"
1298 0 : return 1;
1299 0 : }
1300 : }
1301 0 : else if (!bAlt && !bCtrl && bShift)
1302 : { // it's shift-tab
1303 0 : if (m_pImpl->pFields[0]->HasChildPathFocus())
1304 : // our first list box has the focus
1305 0 : if (m_pImpl->nFieldScrollPos > 0)
1306 : { // we can still scroll up
1307 : // -> scroll up
1308 0 : implScrollFields(m_pImpl->nFieldScrollPos - 1, sal_False, sal_True);
1309 : // give the right control in the "prebious" line the focus
1310 0 : m_pImpl->pFields[0 - 1 + 2]->GrabFocus();
1311 : // return saying "have handled this"
1312 0 : return 1;
1313 : }
1314 : }
1315 : }
1316 : }
1317 0 : break;
1318 : }
1319 0 : return ModalDialog::PreNotify(_rNEvt);
1320 : }
1321 :
1322 : // .......................................................................
1323 : } // namespace svt
1324 : // .......................................................................
1325 :
1326 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|