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