LCOV - code coverage report
Current view: top level - svtools/source/dialogs - addresstemplate.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1 527 0.2 %
Date: 2014-11-03 Functions: 2 66 3.0 %
Legend: Lines: hit not hit

          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: */

Generated by: LCOV version 1.10