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