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 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 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 : 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 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 : 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 : 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 : bool bOddFieldNumber : 1;
464 : /// indicates that we're working with the real persistent configuration
465 : 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(false)
481 : ,bWorkingPersistent( true )
482 0 : ,pConfigData( new AssignmentPersistentData )
483 : {
484 0 : memset(pFieldLabels, 0, sizeof(pFieldLabels));
485 0 : memset(pFields, 0, sizeof(pFields));
486 0 : }
487 :
488 0 : AddressBookSourceDialogData( const Reference< XDataSource >& _rxTransientDS, const OUString& _rDataSourceName,
489 : const OUString& _rTableName, const Sequence< AliasProgrammaticPair >& _rFields )
490 : :m_xTransientDataSource( _rxTransientDS )
491 : ,nFieldScrollPos(0)
492 : ,nLastVisibleListIndex(0)
493 : ,bOddFieldNumber(false)
494 : ,bWorkingPersistent( false )
495 0 : ,pConfigData( new AssigmentTransientData( m_xTransientDataSource, _rDataSourceName, _rTableName, _rFields ) )
496 : {
497 0 : memset(pFieldLabels, 0, sizeof(pFieldLabels));
498 0 : memset(pFields, 0, sizeof(pFields));
499 0 : }
500 :
501 0 : ~AddressBookSourceDialogData()
502 0 : {
503 0 : delete pConfigData;
504 0 : }
505 :
506 : };
507 :
508 :
509 : // = AddressBookSourceDialog
510 :
511 :
512 :
513 0 : AddressBookSourceDialog::AddressBookSourceDialog(vcl::Window* _pParent,
514 : const Reference< XComponentContext >& _rxORB )
515 : : ModalDialog(_pParent, "AddressTemplateDialog", "svt/ui/addresstemplatedialog.ui")
516 : , m_sNoFieldSelection(SVT_RESSTR(STR_NO_FIELD_SELECTION))
517 : , m_xORB(_rxORB)
518 0 : , m_pImpl( new AddressBookSourceDialogData )
519 : {
520 0 : implConstruct();
521 0 : }
522 :
523 :
524 0 : AddressBookSourceDialog::AddressBookSourceDialog( vcl::Window* _pParent, const Reference< XComponentContext >& _rxORB,
525 : const Reference< XDataSource >& _rxTransientDS, const OUString& _rDataSourceName,
526 : const OUString& _rTable, const Sequence< AliasProgrammaticPair >& _rMapping )
527 : : ModalDialog(_pParent, "AddressTemplateDialog", "svt/ui/addresstemplatedialog.ui")
528 : , m_sNoFieldSelection(SVT_RESSTR(STR_NO_FIELD_SELECTION))
529 : , m_xORB(_rxORB)
530 0 : , m_pImpl( new AddressBookSourceDialogData( _rxTransientDS, _rDataSourceName, _rTable, _rMapping ) )
531 : {
532 0 : implConstruct();
533 0 : }
534 :
535 :
536 0 : void AddressBookSourceDialog::implConstruct()
537 : {
538 0 : get(m_pDatasource, "datasource");
539 0 : get(m_pAdministrateDatasources, "admin");
540 0 : get(m_pTable, "datatable");
541 0 : VclScrolledWindow *pScrollWindow = get<VclScrolledWindow>("scrollwindow");
542 0 : pScrollWindow->setUserManagedScrolling(true);
543 0 : m_pFieldScroller = &pScrollWindow->getVertScrollBar();
544 :
545 0 : for (sal_Int32 row=0; row<FIELD_PAIRS_VISIBLE; ++row)
546 : {
547 0 : for (sal_Int32 column=0; column<2; ++column)
548 : {
549 : // the label
550 0 : m_pImpl->pFieldLabels[row * 2 + column] = get<FixedText>(OString("label") + OString::number(row * 2 + column));
551 : // the listbox
552 0 : m_pImpl->pFields[row * 2 + column] = get<ListBox>(OString("box") + OString::number(row * 2 + column));
553 0 : m_pImpl->pFields[row * 2 + column]->SetSelectHdl(LINK(this, AddressBookSourceDialog, OnFieldSelect));
554 :
555 : }
556 : }
557 :
558 0 : initializeDatasources();
559 :
560 : // for the moment, we have a hard coded list of all known fields.
561 : // A better solution would be to store all known field translations in the configuration, which could be
562 : // extensible by the user in an arbitrary way.
563 : // But for the moment we need a quick solution ...
564 : // (the main thing would be to store the translations to use here in the user interface, besides that, the code
565 : // should be adjustable with a rather small effort.)
566 :
567 : // initialize the strings for the field labels
568 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_FIRSTNAME ));
569 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_LASTNAME ));
570 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_COMPANY));
571 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_DEPARTMENT ));
572 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_STREET ));
573 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_ZIPCODE ));
574 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_CITY ));
575 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_STATE));
576 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_COUNTRY ));
577 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_HOMETEL ));
578 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_WORKTEL ));
579 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_OFFICETEL));
580 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_MOBILE));
581 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_TELOTHER));
582 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_PAGER));
583 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_FAX ));
584 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_EMAIL ));
585 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_URL ));
586 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_TITLE ));
587 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_POSITION ));
588 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_INITIALS ));
589 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_ADDRFORM ));
590 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_SALUTATION ));
591 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_ID));
592 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_CALENDAR));
593 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_INVITE));
594 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_NOTE));
595 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_USER1));
596 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_USER2));
597 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_USER3));
598 0 : m_pImpl->aFieldLabels.push_back( SVT_RESSTR( STR_FIELD_USER4));
599 :
600 0 : long nLabelWidth = 0;
601 0 : long nListBoxWidth = m_pImpl->pFields[0]->approximate_char_width() * 20;
602 0 : for (StringArray::const_iterator aI = m_pImpl->aFieldLabels.begin(), aEnd = m_pImpl->aFieldLabels.end(); aI != aEnd; ++aI)
603 : {
604 0 : nLabelWidth = std::max(nLabelWidth, FixedText::getTextDimensions(m_pImpl->pFieldLabels[0], *aI, 0x7FFFFFFF).Width());
605 : }
606 0 : for (sal_Int32 row=0; row<FIELD_PAIRS_VISIBLE; ++row)
607 : {
608 0 : for (sal_Int32 column=0; column<2; ++column)
609 : {
610 0 : m_pImpl->pFieldLabels[row * 2 + column]->set_width_request(nLabelWidth);
611 0 : m_pImpl->pFields[row * 2 + column]->set_width_request(nListBoxWidth);
612 : }
613 : }
614 :
615 :
616 : // force a even number of known fields
617 0 : m_pImpl->bOddFieldNumber = (m_pImpl->aFieldLabels.size() % 2) != 0;
618 0 : if (m_pImpl->bOddFieldNumber)
619 0 : m_pImpl->aFieldLabels.push_back( OUString() );
620 :
621 : // limit the scrollbar range accordingly
622 0 : sal_Int32 nOverallFieldPairs = m_pImpl->aFieldLabels.size() / 2;
623 0 : m_pFieldScroller->SetRange( Range(0, nOverallFieldPairs - FIELD_PAIRS_VISIBLE) );
624 0 : m_pFieldScroller->SetLineSize(1);
625 0 : m_pFieldScroller->SetPageSize(FIELD_PAIRS_VISIBLE);
626 :
627 : // reset the current field assignments
628 0 : m_pImpl->aFieldAssignments.resize(m_pImpl->aFieldLabels.size());
629 : // (empty strings mean "no assignment")
630 :
631 : // some knittings
632 0 : m_pFieldScroller->SetScrollHdl(LINK(this, AddressBookSourceDialog, OnFieldScroll));
633 0 : m_pAdministrateDatasources->SetClickHdl(LINK(this, AddressBookSourceDialog, OnAdministrateDatasources));
634 0 : m_pDatasource->EnableAutocomplete(true);
635 0 : m_pTable->EnableAutocomplete(true);
636 0 : m_pTable->SetGetFocusHdl(LINK(this, AddressBookSourceDialog, OnComboGetFocus));
637 0 : m_pDatasource->SetGetFocusHdl(LINK(this, AddressBookSourceDialog, OnComboGetFocus));
638 0 : m_pTable->SetLoseFocusHdl(LINK(this, AddressBookSourceDialog, OnComboLoseFocus));
639 0 : m_pDatasource->SetLoseFocusHdl(LINK(this, AddressBookSourceDialog, OnComboLoseFocus));
640 0 : m_pTable->SetSelectHdl(LINK(this, AddressBookSourceDialog, OnComboSelect));
641 0 : m_pDatasource->SetSelectHdl(LINK(this, AddressBookSourceDialog, OnComboSelect));
642 0 : get<OKButton>("ok")->SetClickHdl(LINK(this, AddressBookSourceDialog, OnOkClicked));
643 :
644 : // initialize the field controls
645 0 : resetFields();
646 0 : m_pFieldScroller->SetThumbPos(0);
647 0 : m_pImpl->nFieldScrollPos = -1;
648 0 : implScrollFields(0, false, false);
649 :
650 : // the logical names
651 0 : OUString sLogicalFieldNames(SVT_RESSTR(STR_LOGICAL_FIELD_NAMES));
652 0 : sal_Int32 nAdjustedTokenCount = comphelper::string::getTokenCount(sLogicalFieldNames, ';') + (m_pImpl->bOddFieldNumber ? 1 : 0);
653 : DBG_ASSERT(nAdjustedTokenCount == (sal_Int32)m_pImpl->aFieldLabels.size(),
654 : "AddressBookSourceDialog::AddressBookSourceDialog: inconsistence between logical and UI field names!");
655 0 : m_pImpl->aLogicalFieldNames.reserve(nAdjustedTokenCount);
656 0 : for (sal_Int32 i = 0; i<nAdjustedTokenCount; ++i)
657 0 : m_pImpl->aLogicalFieldNames.push_back(comphelper::string::getToken(sLogicalFieldNames, i, ';'));
658 :
659 0 : PostUserEvent(LINK(this, AddressBookSourceDialog, OnDelayedInitialize));
660 : // so the dialog will at least show up before we do the loading of the
661 : // configuration data and the (maybe time consuming) analysis of the data source/table to select
662 :
663 0 : if ( !m_pImpl->bWorkingPersistent )
664 : {
665 0 : StyleSettings aSystemStyle = GetSettings().GetStyleSettings();
666 0 : const ::Color& rNewColor = aSystemStyle.GetDialogColor();
667 :
668 0 : m_pDatasource->SetReadOnly( true );
669 0 : m_pDatasource->SetBackground( Wallpaper( rNewColor ) );
670 0 : m_pDatasource->SetControlBackground( rNewColor );
671 :
672 0 : m_pTable->SetReadOnly( true );
673 0 : m_pTable->SetBackground( Wallpaper( rNewColor ) );
674 0 : m_pTable->SetControlBackground( rNewColor );
675 :
676 0 : m_pAdministrateDatasources->Hide( );
677 0 : }
678 0 : }
679 :
680 :
681 0 : void AddressBookSourceDialog::getFieldMapping(Sequence< AliasProgrammaticPair >& _rMapping) const
682 : {
683 0 : _rMapping.realloc( m_pImpl->aLogicalFieldNames.size() );
684 0 : AliasProgrammaticPair* pPair = _rMapping.getArray();
685 :
686 0 : OUString sCurrent;
687 0 : for ( StringArray::const_iterator aProgrammatic = m_pImpl->aLogicalFieldNames.begin();
688 0 : aProgrammatic != m_pImpl->aLogicalFieldNames.end();
689 : ++aProgrammatic
690 : )
691 : {
692 0 : sCurrent = *aProgrammatic;
693 0 : if ( m_pImpl->pConfigData->hasFieldAssignment( sCurrent ) )
694 : {
695 : // the user gave us an assignment for this field
696 0 : pPair->ProgrammaticName = *aProgrammatic;
697 0 : pPair->Alias = m_pImpl->pConfigData->getFieldAssignment( *aProgrammatic );
698 0 : ++pPair;
699 : }
700 : }
701 :
702 0 : _rMapping.realloc( pPair - _rMapping.getArray() );
703 0 : }
704 :
705 :
706 0 : void AddressBookSourceDialog::loadConfiguration()
707 : {
708 0 : OUString sName = m_pImpl->pConfigData->getDatasourceName();
709 0 : INetURLObject aURL( sName );
710 0 : if( aURL.GetProtocol() != INET_PROT_NOT_VALID )
711 : {
712 0 : OFileNotation aFileNotation( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
713 0 : sName = aFileNotation.get(OFileNotation::N_SYSTEM);
714 : }
715 :
716 0 : m_pDatasource->SetText(sName);
717 0 : m_pTable->SetText(m_pImpl->pConfigData->getCommand());
718 : // we ignore the CommandType: only tables are supported
719 :
720 : // the logical names for the fields
721 : // AddressBookSourceDialog::loadConfiguration: inconsistence between field names and field assignments!
722 : assert(m_pImpl->aLogicalFieldNames.size() == m_pImpl->aFieldAssignments.size());
723 :
724 0 : StringArray::const_iterator aLogical = m_pImpl->aLogicalFieldNames.begin();
725 0 : StringArray::iterator aAssignment = m_pImpl->aFieldAssignments.begin();
726 0 : for ( ;
727 0 : aLogical != m_pImpl->aLogicalFieldNames.end();
728 : ++aLogical, ++aAssignment
729 : )
730 0 : *aAssignment = m_pImpl->pConfigData->getFieldAssignment(*aLogical);
731 0 : }
732 :
733 :
734 0 : AddressBookSourceDialog::~AddressBookSourceDialog()
735 : {
736 0 : delete m_pImpl;
737 0 : }
738 :
739 :
740 0 : void AddressBookSourceDialog::initializeDatasources()
741 : {
742 0 : if (!m_xDatabaseContext.is())
743 : {
744 : DBG_ASSERT(m_xORB.is(), "AddressBookSourceDialog::initializeDatasources: no service factory!");
745 0 : if (!m_xORB.is())
746 0 : return;
747 :
748 : try
749 : {
750 0 : m_xDatabaseContext = DatabaseContext::create(m_xORB);
751 : }
752 0 : catch(const Exception&) { }
753 0 : if (!m_xDatabaseContext.is())
754 : {
755 0 : const OUString sContextServiceName("com.sun.star.sdb.DatabaseContext");
756 0 : ShowServiceNotAvailableError( this, sContextServiceName, false);
757 0 : return;
758 : }
759 : }
760 0 : m_pDatasource->Clear();
761 :
762 : // fill the datasources listbox
763 0 : Sequence< OUString > aDatasourceNames;
764 : try
765 : {
766 0 : aDatasourceNames = m_xDatabaseContext->getElementNames();
767 : }
768 0 : catch(Exception&)
769 : {
770 : OSL_FAIL("AddressBookSourceDialog::initializeDatasources: caught an exception while asking for the data source names!");
771 : }
772 0 : const OUString* pDatasourceNames = aDatasourceNames.getConstArray();
773 0 : const OUString* pEnd = pDatasourceNames + aDatasourceNames.getLength();
774 0 : for (; pDatasourceNames < pEnd; ++pDatasourceNames)
775 0 : m_pDatasource->InsertEntry(*pDatasourceNames);
776 : }
777 :
778 :
779 0 : IMPL_LINK(AddressBookSourceDialog, OnFieldScroll, ScrollBar*, _pScrollBar)
780 : {
781 0 : implScrollFields( _pScrollBar->GetThumbPos(), true, true );
782 0 : return 0L;
783 : }
784 :
785 :
786 0 : void AddressBookSourceDialog::resetTables()
787 : {
788 0 : if (!m_xDatabaseContext.is())
789 0 : return;
790 :
791 0 : WaitObject aWaitCursor(this);
792 :
793 : // no matter what we do here, we handled the currently selected data source (no matter if successful or not)
794 0 : m_pDatasource->SaveValue();
795 :
796 : // create an interaction handler (may be needed for connecting)
797 0 : Reference< XInteractionHandler > xHandler;
798 : try
799 : {
800 : xHandler.set(
801 : InteractionHandler::createWithParent(m_xORB, 0),
802 0 : UNO_QUERY_THROW );
803 : }
804 0 : catch(const Exception&) { }
805 0 : if (!xHandler.is())
806 : {
807 0 : const OUString sInteractionHandlerServiceName("com.sun.star.task.InteractionHandler");
808 0 : ShowServiceNotAvailableError(this, sInteractionHandlerServiceName, true);
809 0 : return;
810 : }
811 :
812 : // the currently selected table
813 0 : OUString sOldTable = m_pTable->GetText();
814 :
815 0 : m_pTable->Clear();
816 :
817 0 : m_xCurrentDatasourceTables= NULL;
818 :
819 : // get the tables of the connection
820 0 : Sequence< OUString > aTableNames;
821 0 : Any aException;
822 : try
823 : {
824 0 : Reference< XCompletedConnection > xDS;
825 0 : if ( m_pImpl->bWorkingPersistent )
826 : {
827 0 : OUString sSelectedDS = lcl_getSelectedDataSource(*m_pDatasource);
828 :
829 : // get the data source the user has chosen and let it build a connection
830 0 : INetURLObject aURL( sSelectedDS );
831 0 : if ( aURL.GetProtocol() != INET_PROT_NOT_VALID || m_xDatabaseContext->hasByName(sSelectedDS) )
832 0 : m_xDatabaseContext->getByName( sSelectedDS ) >>= xDS;
833 : }
834 : else
835 : {
836 0 : xDS.set(m_pImpl->m_xTransientDataSource, css::uno::UNO_QUERY);
837 : }
838 :
839 : // build the connection
840 0 : Reference< XConnection > xConn;
841 0 : if (xDS.is())
842 0 : xConn = xDS->connectWithCompletion(xHandler);
843 :
844 : // get the table names
845 0 : Reference< XTablesSupplier > xSupplTables(xConn, UNO_QUERY);
846 0 : if (xSupplTables.is())
847 : {
848 0 : m_xCurrentDatasourceTables = Reference< XNameAccess >(xSupplTables->getTables(), UNO_QUERY);
849 0 : if (m_xCurrentDatasourceTables.is())
850 0 : aTableNames = m_xCurrentDatasourceTables->getElementNames();
851 0 : }
852 : }
853 0 : catch(const SQLContext& e) { aException <<= e; }
854 0 : catch(const SQLWarning& e) { aException <<= e; }
855 0 : catch(const SQLException& e) { aException <<= e; }
856 0 : catch(Exception&)
857 : {
858 : OSL_FAIL("AddressBookSourceDialog::resetTables: could not retrieve the table!");
859 : }
860 :
861 0 : if (aException.hasValue())
862 : {
863 0 : Reference< XInteractionRequest > xRequest = new OInteractionRequest(aException);
864 : try
865 : {
866 0 : xHandler->handle(xRequest);
867 : }
868 0 : catch(Exception&) { }
869 0 : return;
870 : }
871 :
872 0 : bool bKnowOldTable = false;
873 : // fill the table list
874 0 : const OUString* pTableNames = aTableNames.getConstArray();
875 0 : const OUString* pEnd = pTableNames + aTableNames.getLength();
876 0 : for (;pTableNames != pEnd; ++pTableNames)
877 : {
878 0 : m_pTable->InsertEntry(*pTableNames);
879 0 : if (0 == pTableNames->compareTo(sOldTable))
880 0 : bKnowOldTable = true;
881 : }
882 :
883 : // set the old table, if the new data source knows a table with this name, too. Else reset the tables edit field.
884 0 : if (!bKnowOldTable)
885 0 : sOldTable = OUString();
886 0 : m_pTable->SetText(sOldTable);
887 :
888 0 : resetFields();
889 : }
890 :
891 :
892 0 : void AddressBookSourceDialog::resetFields()
893 : {
894 0 : WaitObject aWaitCursor(this);
895 :
896 : // no matter what we do here, we handled the currently selected table (no matter if successful or not)
897 0 : m_pDatasource->SaveValue();
898 :
899 0 : OUString sSelectedTable = m_pTable->GetText();
900 0 : Sequence< OUString > aColumnNames;
901 : try
902 : {
903 0 : if (m_xCurrentDatasourceTables.is())
904 : {
905 : // get the table and the columns
906 0 : Reference< XColumnsSupplier > xSuppTableCols;
907 0 : if (m_xCurrentDatasourceTables->hasByName(sSelectedTable))
908 : xSuppTableCols.set(
909 0 : m_xCurrentDatasourceTables->getByName(sSelectedTable),
910 0 : css::uno::UNO_QUERY);
911 0 : Reference< XNameAccess > xColumns;
912 0 : if (xSuppTableCols.is())
913 0 : xColumns = xSuppTableCols->getColumns();
914 0 : if (xColumns.is())
915 0 : aColumnNames = xColumns->getElementNames();
916 : }
917 : }
918 0 : catch (const Exception&)
919 : {
920 : OSL_FAIL("AddressBookSourceDialog::resetFields: could not retrieve the table columns!");
921 : }
922 :
923 :
924 0 : const OUString* pColumnNames = aColumnNames.getConstArray();
925 0 : const OUString* pEnd = pColumnNames + aColumnNames.getLength();
926 :
927 : // for quicker access
928 0 : ::std::set< OUString > aColumnNameSet;
929 0 : for (pColumnNames = aColumnNames.getConstArray(); pColumnNames != pEnd; ++pColumnNames)
930 0 : aColumnNameSet.insert(*pColumnNames);
931 :
932 0 : std::vector<OUString>::iterator aInitialSelection = m_pImpl->aFieldAssignments.begin() + m_pImpl->nFieldScrollPos;
933 :
934 0 : ListBox** pListbox = m_pImpl->pFields;
935 0 : OUString sSaveSelection;
936 0 : for (sal_Int32 i=0; i<FIELD_CONTROLS_VISIBLE; ++i, ++pListbox, ++aInitialSelection)
937 : {
938 0 : sSaveSelection = (*pListbox)->GetSelectEntry();
939 :
940 0 : (*pListbox)->Clear();
941 :
942 : // the one entry for "no selection"
943 0 : (*pListbox)->InsertEntry(m_sNoFieldSelection, 0);
944 : // as it's entry data, set the index of the list box in our array
945 0 : (*pListbox)->SetEntryData(0, reinterpret_cast<void*>(i));
946 :
947 : // the field names
948 0 : for (pColumnNames = aColumnNames.getConstArray(); pColumnNames != pEnd; ++pColumnNames)
949 0 : (*pListbox)->InsertEntry(*pColumnNames);
950 :
951 0 : if (!aInitialSelection->isEmpty() && (aColumnNameSet.end() != aColumnNameSet.find(*aInitialSelection)))
952 : // we can select the entry as specified in our field assignment array
953 0 : (*pListbox)->SelectEntry(*aInitialSelection);
954 : else
955 : // try to restore the selection
956 0 : if (aColumnNameSet.end() != aColumnNameSet.find(sSaveSelection))
957 : // the old selection is a valid column name
958 0 : (*pListbox)->SelectEntry(sSaveSelection);
959 : else
960 : // select the <none> entry
961 0 : (*pListbox)->SelectEntryPos(0);
962 : }
963 :
964 : // adjust m_pImpl->aFieldAssignments
965 0 : for ( StringArray::iterator aAdjust = m_pImpl->aFieldAssignments.begin();
966 0 : aAdjust != m_pImpl->aFieldAssignments.end();
967 : ++aAdjust
968 : )
969 0 : if (!aAdjust->isEmpty())
970 0 : if (aColumnNameSet.end() == aColumnNameSet.find(*aAdjust))
971 0 : (*aAdjust) = "";
972 0 : }
973 :
974 :
975 0 : IMPL_LINK(AddressBookSourceDialog, OnFieldSelect, ListBox*, _pListbox)
976 : {
977 : // the index of the affected list box in our array
978 0 : sal_IntPtr nListBoxIndex = reinterpret_cast<sal_IntPtr>(_pListbox->GetEntryData(0));
979 : DBG_ASSERT(nListBoxIndex >= 0 && nListBoxIndex < FIELD_CONTROLS_VISIBLE,
980 : "AddressBookSourceDialog::OnFieldScroll: invalid list box entry!");
981 :
982 : // update the array where we remember the field selections
983 0 : if (0 == _pListbox->GetSelectEntryPos())
984 : // it's the "no field selection" entry
985 0 : m_pImpl->aFieldAssignments[m_pImpl->nFieldScrollPos * 2 + nListBoxIndex] = "";
986 : else
987 : // it's a regular field entry
988 0 : m_pImpl->aFieldAssignments[m_pImpl->nFieldScrollPos * 2 + nListBoxIndex] = _pListbox->GetSelectEntry();
989 :
990 0 : return 0L;
991 : }
992 :
993 :
994 0 : void AddressBookSourceDialog::implScrollFields(sal_Int32 _nPos, bool _bAdjustFocus, bool _bAdjustScrollbar)
995 : {
996 0 : if (_nPos == m_pImpl->nFieldScrollPos)
997 : // nothing to do
998 0 : return;
999 :
1000 : // loop through our field control rows and do some adjustments
1001 : // for the new texts
1002 0 : FixedText** pLeftLabelControl = m_pImpl->pFieldLabels;
1003 0 : FixedText** pRightLabelControl = pLeftLabelControl + 1;
1004 0 : StringArray::const_iterator pLeftColumnLabel = m_pImpl->aFieldLabels.begin() + 2 * _nPos;
1005 0 : StringArray::const_iterator pRightColumnLabel = pLeftColumnLabel + 1;
1006 :
1007 : // for the focus movement and the selection scroll
1008 0 : ListBox** pLeftListControl = m_pImpl->pFields;
1009 0 : ListBox** pRightListControl = pLeftListControl + 1;
1010 :
1011 : // for the focus movement
1012 0 : sal_Int32 nOldFocusRow = -1;
1013 0 : sal_Int32 nOldFocusColumn = 0;
1014 :
1015 : // for the selection scroll
1016 0 : StringArray::const_iterator pLeftAssignment = m_pImpl->aFieldAssignments.begin() + 2 * _nPos;
1017 0 : StringArray::const_iterator pRightAssignment = pLeftAssignment + 1;
1018 :
1019 0 : m_pImpl->nLastVisibleListIndex = -1;
1020 : // loop
1021 0 : for (sal_Int32 i=0; i<FIELD_PAIRS_VISIBLE; ++i)
1022 : {
1023 0 : if ((*pLeftListControl)->HasChildPathFocus())
1024 : {
1025 0 : nOldFocusRow = i;
1026 0 : nOldFocusColumn = 0;
1027 : }
1028 0 : else if ((*pRightListControl)->HasChildPathFocus())
1029 : {
1030 0 : nOldFocusRow = i;
1031 0 : nOldFocusColumn = 1;
1032 : }
1033 :
1034 : // the new texts of the label controls
1035 0 : (*pLeftLabelControl)->SetText(*pLeftColumnLabel);
1036 0 : (*pRightLabelControl)->SetText(*pRightColumnLabel);
1037 :
1038 : // we may have to hide the controls in the right column, if we have no label text for it
1039 : // (which means we have an odd number of fields, though we forced our internal arrays to
1040 : // be even-sized for easier handling)
1041 : // (If sometimes we support an arbitrary number of field assignments, we would have to care for
1042 : // an invisible left hand side column, too. But right now, the left hand side controls are always
1043 : // visible)
1044 0 : bool bHideRightColumn = pRightColumnLabel->isEmpty();
1045 0 : (*pRightLabelControl)->Show(!bHideRightColumn);
1046 0 : (*pRightListControl)->Show(!bHideRightColumn);
1047 : // the new selections of the listboxes
1048 0 : implSelectField(*pLeftListControl, *pLeftAssignment);
1049 0 : implSelectField(*pRightListControl, *pRightAssignment);
1050 :
1051 : // the index of the last visible list box
1052 0 : ++m_pImpl->nLastVisibleListIndex; // the left hand side box is always visible
1053 0 : if (!bHideRightColumn)
1054 0 : ++m_pImpl->nLastVisibleListIndex;
1055 :
1056 : // increment ...
1057 0 : if ( i < FIELD_PAIRS_VISIBLE - 1 )
1058 : { // (not in the very last round, here the +=2 could result in an invalid
1059 : // iterator position, which causes an abort in a non-product version
1060 0 : pLeftLabelControl += 2;
1061 0 : pRightLabelControl += 2;
1062 0 : pLeftColumnLabel += 2;
1063 0 : pRightColumnLabel += 2;
1064 :
1065 0 : pLeftListControl += 2;
1066 0 : pRightListControl += 2;
1067 0 : pLeftAssignment += 2;
1068 0 : pRightAssignment += 2;
1069 : }
1070 : }
1071 :
1072 0 : if (_bAdjustFocus && (nOldFocusRow >= 0))
1073 : { // we have to adjust the focus and one of the list boxes has the focus
1074 0 : sal_Int32 nDelta = m_pImpl->nFieldScrollPos - _nPos;
1075 : // the new row for the focus
1076 0 : sal_Int32 nNewFocusRow = nOldFocusRow + nDelta;
1077 : // normalize
1078 0 : nNewFocusRow = std::min(nNewFocusRow, (sal_Int32)(FIELD_PAIRS_VISIBLE - 1), ::std::less< sal_Int32 >());
1079 0 : nNewFocusRow = std::max(nNewFocusRow, (sal_Int32)0, ::std::less< sal_Int32 >());
1080 : // set the new focus (in the same column)
1081 0 : m_pImpl->pFields[nNewFocusRow * 2 + nOldFocusColumn]->GrabFocus();
1082 : }
1083 :
1084 0 : m_pImpl->nFieldScrollPos = _nPos;
1085 :
1086 0 : if (_bAdjustScrollbar)
1087 0 : m_pFieldScroller->SetThumbPos(m_pImpl->nFieldScrollPos);
1088 : }
1089 :
1090 :
1091 0 : void AddressBookSourceDialog::implSelectField(ListBox* _pBox, const OUString& _rText)
1092 : {
1093 0 : if (!_rText.isEmpty())
1094 : // a valid field name
1095 0 : _pBox->SelectEntry(_rText);
1096 : else
1097 : // no selection for this item
1098 0 : _pBox->SelectEntryPos(0);
1099 0 : }
1100 :
1101 :
1102 0 : IMPL_LINK_NOARG(AddressBookSourceDialog, OnDelayedInitialize)
1103 : {
1104 : // load the initial data from the configuration
1105 0 : loadConfiguration();
1106 0 : resetTables();
1107 : // will reset the tables/fields implicitly
1108 :
1109 0 : if ( !m_pImpl->bWorkingPersistent )
1110 0 : if ( m_pImpl->pFields[0] )
1111 0 : m_pImpl->pFields[0]->GrabFocus();
1112 :
1113 0 : return 0L;
1114 : }
1115 :
1116 :
1117 0 : IMPL_LINK(AddressBookSourceDialog, OnComboSelect, ComboBox*, _pBox)
1118 : {
1119 0 : if (_pBox == m_pDatasource)
1120 0 : resetTables();
1121 : else
1122 0 : resetFields();
1123 0 : return 0;
1124 : }
1125 :
1126 :
1127 0 : IMPL_LINK(AddressBookSourceDialog, OnComboGetFocus, ComboBox*, _pBox)
1128 : {
1129 0 : _pBox->SaveValue();
1130 0 : return 0L;
1131 : }
1132 :
1133 :
1134 0 : IMPL_LINK(AddressBookSourceDialog, OnComboLoseFocus, ComboBox*, _pBox)
1135 : {
1136 0 : if ( _pBox->IsValueChangedFromSaved() )
1137 : {
1138 0 : if (_pBox == m_pDatasource)
1139 0 : resetTables();
1140 : else
1141 0 : resetFields();
1142 : }
1143 0 : return 0L;
1144 : }
1145 :
1146 :
1147 0 : IMPL_LINK_NOARG(AddressBookSourceDialog, OnOkClicked)
1148 : {
1149 0 : OUString sSelectedDS = lcl_getSelectedDataSource(*m_pDatasource);
1150 0 : if ( m_pImpl->bWorkingPersistent )
1151 : {
1152 0 : m_pImpl->pConfigData->setDatasourceName(sSelectedDS);
1153 0 : m_pImpl->pConfigData->setCommand(m_pTable->GetText());
1154 : }
1155 :
1156 : // AddressBookSourceDialog::loadConfiguration: inconsistence between field names and field assignments!
1157 : assert(m_pImpl->aLogicalFieldNames.size() == m_pImpl->aFieldAssignments.size());
1158 :
1159 : // set the field assignments
1160 0 : StringArray::const_iterator aLogical = m_pImpl->aLogicalFieldNames.begin();
1161 0 : StringArray::const_iterator aAssignment = m_pImpl->aFieldAssignments.begin();
1162 0 : for ( ;
1163 0 : aLogical != m_pImpl->aLogicalFieldNames.end();
1164 : ++aLogical, ++aAssignment
1165 : )
1166 0 : m_pImpl->pConfigData->setFieldAssignment(*aLogical, *aAssignment);
1167 :
1168 :
1169 0 : EndDialog(RET_OK);
1170 0 : return 0L;
1171 : }
1172 :
1173 :
1174 0 : IMPL_LINK_NOARG(AddressBookSourceDialog, OnAdministrateDatasources)
1175 : {
1176 : // create the dialog object
1177 0 : Reference< XExecutableDialog > xAdminDialog;
1178 : try
1179 : {
1180 0 : xAdminDialog = AddressBookSourcePilot::createWithParent( m_xORB, VCLUnoHelper::GetInterface(this) );
1181 : }
1182 0 : catch(const Exception&) { }
1183 0 : if (!xAdminDialog.is())
1184 : {
1185 0 : ShowServiceNotAvailableError(this, OUString("com.sun.star.ui.dialogs.AddressBookSourcePilot"), true);
1186 0 : return 1L;
1187 : }
1188 :
1189 : // excute the dialog
1190 : try
1191 : {
1192 0 : if ( xAdminDialog->execute() == RET_OK )
1193 : {
1194 0 : Reference<XPropertySet> xProp(xAdminDialog,UNO_QUERY);
1195 0 : if ( xProp.is() )
1196 : {
1197 0 : OUString sName;
1198 0 : xProp->getPropertyValue("DataSourceName") >>= sName;
1199 :
1200 0 : INetURLObject aURL( sName );
1201 0 : if( aURL.GetProtocol() != INET_PROT_NOT_VALID )
1202 : {
1203 0 : OFileNotation aFileNotation( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
1204 0 : sName = aFileNotation.get(OFileNotation::N_SYSTEM);
1205 : }
1206 0 : m_pDatasource->InsertEntry(sName);
1207 0 : delete m_pImpl->pConfigData;
1208 0 : m_pImpl->pConfigData = new AssignmentPersistentData();
1209 0 : loadConfiguration();
1210 0 : resetTables();
1211 : // will reset the fields implicitly
1212 0 : }
1213 : }
1214 : }
1215 0 : catch(const Exception&)
1216 : {
1217 : OSL_FAIL("AddressBookSourceDialog::OnAdministrateDatasources: an error occurred while executing the administration dialog!");
1218 : }
1219 :
1220 : // re-fill the data source list
1221 : // try to preserve the current selection
1222 :
1223 : // initializeDatasources();
1224 :
1225 0 : return 0L;
1226 : }
1227 :
1228 :
1229 0 : bool AddressBookSourceDialog::PreNotify( NotifyEvent& _rNEvt )
1230 : {
1231 0 : switch (_rNEvt.GetType())
1232 : {
1233 : case EVENT_KEYINPUT:
1234 : {
1235 0 : const KeyEvent* pKeyEvent = _rNEvt.GetKeyEvent();
1236 0 : sal_uInt16 nCode = pKeyEvent->GetKeyCode().GetCode();
1237 0 : bool bShift = pKeyEvent->GetKeyCode().IsShift();
1238 0 : bool bCtrl = pKeyEvent->GetKeyCode().IsMod1();
1239 0 : bool bAlt = pKeyEvent->GetKeyCode().IsMod2();
1240 :
1241 0 : if (KEY_TAB == nCode)
1242 : { // somebody pressed the tab key
1243 0 : if (!bAlt && !bCtrl && !bShift)
1244 : { // it's really the only the key (no modifiers)
1245 0 : if (m_pImpl->pFields[m_pImpl->nLastVisibleListIndex]->HasChildPathFocus())
1246 : // the last of our visible list boxes has the focus
1247 0 : if (m_pImpl->nFieldScrollPos < m_pFieldScroller->GetRangeMax())
1248 : { // we can still scroll down
1249 0 : sal_Int32 nNextFocusList = m_pImpl->nLastVisibleListIndex + 1 - 2;
1250 : // -> scroll down
1251 0 : implScrollFields(m_pImpl->nFieldScrollPos + 1, false, true);
1252 : // give the left control in the "next" line the focus
1253 0 : m_pImpl->pFields[nNextFocusList]->GrabFocus();
1254 : // return saying "have handled this"
1255 0 : return true;
1256 0 : }
1257 : }
1258 0 : else if (!bAlt && !bCtrl && bShift)
1259 : { // it's shift-tab
1260 0 : if (m_pImpl->pFields[0]->HasChildPathFocus())
1261 : // our first list box has the focus
1262 0 : if (m_pImpl->nFieldScrollPos > 0)
1263 : { // we can still scroll up
1264 : // -> scroll up
1265 0 : implScrollFields(m_pImpl->nFieldScrollPos - 1, false, true);
1266 : // give the right control in the "prebious" line the focus
1267 0 : m_pImpl->pFields[0 - 1 + 2]->GrabFocus();
1268 : // return saying "have handled this"
1269 0 : return true;
1270 : }
1271 : }
1272 : }
1273 : }
1274 0 : break;
1275 : }
1276 0 : return ModalDialog::PreNotify(_rNEvt);
1277 : }
1278 :
1279 :
1280 1227 : } // namespace svt
1281 :
1282 :
1283 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|