Add embedded database selector to db setup dialog.

This allows for choosing between the HSQLDB driver (currently default)
and the firebird driver for embedded databases.

Change-Id: I3734440fedf9f07b28f9cfd806dafbe6610393f7
Reviewed-on: https://gerrit.libreoffice.org/5199
Reviewed-by: Luboš Luňák <l.lunak@suse.cz>
Tested-by: Luboš Luňák <l.lunak@suse.cz>
diff --git a/dbaccess/source/ui/dlg/dbwizsetup.cxx b/dbaccess/source/ui/dlg/dbwizsetup.cxx
index e14fedf..86b2c99 100644
--- a/dbaccess/source/ui/dlg/dbwizsetup.cxx
+++ b/dbaccess/source/ui/dlg/dbwizsetup.cxx
@@ -337,7 +337,7 @@ void ODbTypeWizDialogSetup::activateDatabasePath()
    {
    case OGeneralPageWizard::eCreateNew:
    {
        sal_Int32 nCreateNewDBIndex = m_pCollection->getIndexOf( m_pCollection->getEmbeddedDatabase() );
        sal_Int32 nCreateNewDBIndex = m_pCollection->getIndexOf( m_pGeneralPage->GetSelectedType() );
        if ( nCreateNewDBIndex == -1 )
            nCreateNewDBIndex = m_pCollection->getIndexOf( OUString("sdbc:dbase:") );
        OSL_ENSURE( nCreateNewDBIndex != -1, "ODbTypeWizDialogSetup::activateDatabasePath: the GeneralPage should have prevented this!" );
@@ -802,28 +802,10 @@ sal_Bool ODbTypeWizDialogSetup::SaveDatabaseDocument()
    }

    //-------------------------------------------------------------------------
    OUString ODbTypeWizDialogSetup::getDefaultDatabaseType() const
    {
        OUString sEmbeddedURL = m_pCollection->getEmbeddedDatabase();
        ::connectivity::DriversConfig aDriverConfig(getORB());
        try
        {
        if ( aDriverConfig.getDriverFactoryName(sEmbeddedURL).isEmpty() || !m_pImpl->getDriver(sEmbeddedURL).is() )
            sEmbeddedURL = OUString("sdbc:dbase:");
        }
        catch(const Exception&)
        {
            sEmbeddedURL = OUString("sdbc:dbase:");
        }

        return sEmbeddedURL;
    }

    //-------------------------------------------------------------------------
    void ODbTypeWizDialogSetup::CreateDatabase()
    {
        OUString sUrl;
        OUString eType = getDefaultDatabaseType();
        OUString eType = m_pGeneralPage->GetSelectedType();
        if ( m_pCollection->isEmbeddedDatabase(eType) )
        {
            sUrl = eType;
diff --git a/dbaccess/source/ui/dlg/generalpage.cxx b/dbaccess/source/ui/dlg/generalpage.cxx
index 2d2044e..ad09e8d 100644
--- a/dbaccess/source/ui/dlg/generalpage.cxx
+++ b/dbaccess/source/ui/dlg/generalpage.cxx
@@ -65,20 +65,24 @@ namespace dbaui
        ,m_eLastMessage                 ( smNone )
        ,m_bDisplayingInvalid           ( sal_False )
        ,m_bInitTypeList                ( true )
        ,m_bInitEmbeddedDBList          ( true )
        ,m_pDatasourceType              ( NULL )
        ,m_pEmbeddedDBType              ( NULL )
        ,m_pCollection                  ( NULL )
    {
        get( m_pDatasourceType, "datasourceType" );
        get( m_pEmbeddedDBType, "embeddeddbList" );
        get( m_pSpecialMessage, "specialMessage" );

        // extract the datasource type collection from the item set
        DbuTypeCollectionItem* pCollectionItem = PTR_CAST(DbuTypeCollectionItem, _rItems.GetItem(DSID_TYPECOLLECTION));
        if (pCollectionItem)
            m_pCollection = pCollectionItem->getCollection();
        OSL_ENSURE(m_pCollection, "OGeneralPage::OGeneralPage : really need a DSN type collection !");
        SAL_WARN_IF(!m_pCollection, "dbaaccess", "OGeneralPage::OGeneralPage : really need a DSN type collection !");

        // do some knittings
        m_pDatasourceType->SetSelectHdl(LINK(this, OGeneralPage, OnDatasourceTypeSelected));
        m_pEmbeddedDBType->SetSelectHdl(LINK(this, OGeneralPage, OnEmbeddedDBTypeSelected));
    }

    //-------------------------------------------------------------------------
@@ -148,6 +152,46 @@ namespace dbaui
    }

    //-------------------------------------------------------------------------
    void OGeneralPage::initializeEmbeddedDBList()
    {
        if ( m_bInitEmbeddedDBList )
        {
            m_bInitEmbeddedDBList = false;
             m_pEmbeddedDBType->Clear();

            if ( m_pCollection )
            {
                DisplayedTypes aDisplayedTypes;

                ::dbaccess::ODsnTypeCollection::TypeIterator aEnd = m_pCollection->end();
                for (   ::dbaccess::ODsnTypeCollection::TypeIterator aTypeLoop =  m_pCollection->begin();
                        aTypeLoop != aEnd;
                        ++aTypeLoop
                    )
                {
                    const OUString sURLPrefix = aTypeLoop.getURLPrefix();
                    if ( !sURLPrefix.isEmpty() )
                    {
                        OUString sDisplayName = aTypeLoop.getDisplayName();
                        if ( m_pEmbeddedDBType->GetEntryPos( sDisplayName ) == LISTBOX_ENTRY_NOTFOUND
                            && m_pCollection->isEmbeddedDatabase( sURLPrefix ) )
                        {
                            aDisplayedTypes.push_back( DisplayedTypes::value_type( sURLPrefix, sDisplayName ) );
                        }
                    }
                }
                ::std::sort( aDisplayedTypes.begin(), aDisplayedTypes.end(), DisplayedTypeLess() );
                DisplayedTypes::const_iterator aDisplayEnd = aDisplayedTypes.end();
                for (   DisplayedTypes::const_iterator loop = aDisplayedTypes.begin();
                        loop != aDisplayEnd;
                        ++loop
                    )
                    insertEmbeddedDBTypeEntryData( loop->eType, loop->sDisplayName );
            }
        }
    }

    //-------------------------------------------------------------------------
    void OGeneralPage::setParentTitle(const OUString&)
    {
    }
@@ -192,8 +236,10 @@ namespace dbaui
    void OGeneralPage::implInitControls( const SfxItemSet& _rSet, sal_Bool _bSaveValue )
    {
        initializeTypeList();
        initializeEmbeddedDBList();

        m_pDatasourceType->SelectEntry( getDatasourceName( _rSet ) );
        m_pEmbeddedDBType->SelectEntry( getEmbeddedDBName( _rSet ) );

        // notify our listener that our type selection has changed (if so)
        // FIXME: how to detect that it did not changed? (fdo#62937)
@@ -207,6 +253,55 @@ namespace dbaui
    }

    //-------------------------------------------------------------------------
    OUString OGeneralPage::getEmbeddedDBName( const SfxItemSet& _rSet )
    {
        // first check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
        sal_Bool bValid, bReadonly;
        getFlags( _rSet, bValid, bReadonly );

        // if the selection is invalid, disable everything
        String sName,sConnectURL;
        m_bDisplayingInvalid = !bValid;
        if ( bValid )
        {
            // collect some items and some values
            SFX_ITEMSET_GET( _rSet, pNameItem, SfxStringItem, DSID_NAME, sal_True );
            SFX_ITEMSET_GET( _rSet, pUrlItem, SfxStringItem, DSID_CONNECTURL, sal_True );
            assert( pUrlItem );
            assert( pNameItem );
            sName = pNameItem->GetValue();
            sConnectURL = pUrlItem->GetValue();
        }

        m_eNotSupportedKnownType =  ::dbaccess::DST_UNKNOWN;
        implSetCurrentType(  OUString() );

        // compare the DSN prefix with the registered ones
        OUString sDisplayName;

        if (m_pCollection && bValid)
        {
            implSetCurrentType( m_pCollection->getEmbeddedDatabase() );
            sDisplayName = m_pCollection->getTypeDisplayName( m_eCurrentSelection );
        }

        // select the correct datasource type
        if  (  m_pCollection->isEmbeddedDatabase( m_eCurrentSelection )
            &&  ( LISTBOX_ENTRY_NOTFOUND == m_pEmbeddedDBType->GetEntryPos( sDisplayName ) )
            )
        {   // this indicates it's really a type which is known in general, but not supported on the current platform
            // show a message saying so
            //  eSpecialMessage = smUnsupportedType;
            insertDatasourceTypeEntryData( m_eCurrentSelection, sDisplayName );
            // remember this type so we can show the special message again if the user selects this
            // type again (without changing the data source)
            m_eNotSupportedKnownType = m_pCollection->determineType( m_eCurrentSelection );
        }

        return sDisplayName;
    }

    //-------------------------------------------------------------------------
    OUString OGeneralPage::getDatasourceName( const SfxItemSet& _rSet )
    {
        // first check whether or not the selection is invalid or readonly (invalid implies readonly, but not vice versa)
@@ -221,8 +316,8 @@ namespace dbaui
            // collect some items and some values
            SFX_ITEMSET_GET( _rSet, pNameItem, SfxStringItem, DSID_NAME, sal_True );
            SFX_ITEMSET_GET( _rSet, pUrlItem, SfxStringItem, DSID_CONNECTURL, sal_True );
            OSL_ENSURE( pUrlItem, "OGeneralPage::getDatasourceName: missing the type attribute !" );
            OSL_ENSURE( pNameItem, "OGeneralPage::getDatasourceName: missing the type attribute !" );
            assert( pUrlItem );
            assert( pNameItem );
            sName = pNameItem->GetValue();
            sConnectURL = pUrlItem->GetValue();
        }
@@ -295,6 +390,16 @@ namespace dbaui
    }

    // -----------------------------------------------------------------------
    void OGeneralPage::insertEmbeddedDBTypeEntryData(const OUString& _sType, String sDisplayName)
    {
        // insert a (temporary) entry
        sal_uInt16 nPos = m_pEmbeddedDBType->InsertEntry(sDisplayName);
        if ( nPos >= m_aEmbeddedURLPrefixes.size() )
            m_aEmbeddedURLPrefixes.resize(nPos+1);
        m_aEmbeddedURLPrefixes[nPos] = _sType;
    }

    // -----------------------------------------------------------------------
    void OGeneralPage::fillWindows(::std::vector< ISaveValueWrapper* >& _rControlList)
    {
        _rControlList.push_back( new ODisableWrapper<FixedText>( m_pSpecialMessage ) );
@@ -326,6 +431,27 @@ namespace dbaui
    }

    //-------------------------------------------------------------------------
    IMPL_LINK( OGeneralPage, OnEmbeddedDBTypeSelected, ListBox*, _pBox )
    {
        // get the type from the entry data
        sal_uInt16 nSelected = _pBox->GetSelectEntryPos();
        if (nSelected >= m_aEmbeddedURLPrefixes.size() )
        {
            SAL_WARN("dbaui.OGeneralPage", "Got out-of-range value '" << nSelected <<  "' from the DatasourceType selection ListBox's GetSelectEntryPos(): no corresponding URL prefix");
            return 0L;
        }
        const OUString sURLPrefix = m_aEmbeddedURLPrefixes[ nSelected ];

        setParentTitle( sURLPrefix );
        // let the impl method do all the stuff
        onTypeSelected( sURLPrefix );
        // tell the listener we were modified
        callModifiedHdl();
        // outta here
        return 0L;
    }

    //-------------------------------------------------------------------------
    IMPL_LINK( OGeneralPage, OnDatasourceTypeSelected, ListBox*, _pBox )
    {
        // get the type from the entry data
@@ -406,6 +532,7 @@ namespace dbaui
        ,m_pRB_CreateDatabase           ( NULL )
        ,m_pRB_OpenExistingDatabase     ( NULL )
        ,m_pRB_ConnectDatabase          ( NULL )
        ,m_pFT_EmbeddedDBLabel          ( NULL )
        ,m_pFT_DocListLabel             ( NULL )
        ,m_pLB_DocumentList             ( NULL )
        ,m_pPB_OpenDatabase             ( NULL )
@@ -416,6 +543,7 @@ namespace dbaui
        get( m_pRB_CreateDatabase, "createDatabase" );
        get( m_pRB_OpenExistingDatabase, "openExistingDatabase" );
        get( m_pRB_ConnectDatabase, "connectDatabase" );
        get( m_pFT_EmbeddedDBLabel, "embeddeddbLabel" );
        get( m_pFT_DocListLabel, "docListLabel" );
        get( m_pLB_DocumentList, "documentList" );
        get( m_pPB_OpenDatabase, "openDatabase" );
@@ -445,7 +573,7 @@ namespace dbaui
            m_pRB_CreateDatabase->Check();

        // do some knittings
        m_pRB_CreateDatabase->SetClickHdl( LINK( this, OGeneralPageWizard, OnSetupModeSelected ) );
        m_pRB_CreateDatabase->SetClickHdl( LINK( this, OGeneralPageWizard, OnCreateDatabaseModeSelected ) );
        m_pRB_ConnectDatabase->SetClickHdl( LINK( this, OGeneralPageWizard, OnSetupModeSelected ) );
        m_pRB_OpenExistingDatabase->SetClickHdl( LINK( this, OGeneralPageWizard, OnSetupModeSelected ) );
        m_pLB_DocumentList->SetSelectHdl( LINK( this, OGeneralPageWizard, OnDocumentSelected ) );
@@ -487,6 +615,7 @@ namespace dbaui

        if ( !bValid || bReadonly )
        {
            m_pFT_EmbeddedDBLabel->Enable( false );
            m_pDatasourceType->Enable( false );
            m_pPB_OpenDatabase->Enable( false );
            m_pFT_DocListLabel->Enable( false );
@@ -494,6 +623,7 @@ namespace dbaui
        }
        else
        {
            m_aControlDependencies.enableOnRadioCheck( *m_pRB_CreateDatabase, *m_pEmbeddedDBType, *m_pFT_EmbeddedDBLabel );
            m_aControlDependencies.enableOnRadioCheck( *m_pRB_ConnectDatabase, *m_pDatasourceType );
            m_aControlDependencies.enableOnRadioCheck( *m_pRB_OpenExistingDatabase, *m_pPB_OpenDatabase, *m_pFT_DocListLabel, *m_pLB_DocumentList );
        }
@@ -508,6 +638,7 @@ namespace dbaui
    //-------------------------------------------------------------------------
    OUString OGeneralPageWizard::getDatasourceName(const SfxItemSet& _rSet)
    {
        // Sets jdbc as the default selected databse on startup.
        if (m_pRB_CreateDatabase->IsChecked() )
            return m_pCollection->getTypeDisplayName( OUString( "jdbc:" ) );

@@ -590,6 +721,15 @@ namespace dbaui
    }

    //-------------------------------------------------------------------------
    IMPL_LINK( OGeneralPageWizard, OnCreateDatabaseModeSelected, RadioButton*, /*_pBox*/ )
    {
        if ( m_aCreationModeHandler.IsSet() )
            m_aCreationModeHandler.Call( this );
        OnEmbeddedDBTypeSelected(m_pEmbeddedDBType);
        return 1L;
    }

    //-------------------------------------------------------------------------
    IMPL_LINK( OGeneralPageWizard, OnSetupModeSelected, RadioButton*, /*_pBox*/ )
    {
        if ( m_aCreationModeHandler.IsSet() )
diff --git a/dbaccess/source/ui/dlg/generalpage.hxx b/dbaccess/source/ui/dlg/generalpage.hxx
index 197b1bc..719aa47 100644
--- a/dbaccess/source/ui/dlg/generalpage.hxx
+++ b/dbaccess/source/ui/dlg/generalpage.hxx
@@ -58,17 +58,22 @@ namespace dbaui
        Link                m_aTypeSelectHandler;   /// to be called if a new type is selected
        sal_Bool            m_bDisplayingInvalid : 1;   // the currently displayed data source is deleted
        bool                m_bInitTypeList : 1;
        bool                m_bInitEmbeddedDBList : 1;
        bool                approveDatasourceType( const OUString& _sURLPrefix, OUString& _inout_rDisplayName );
        void                insertDatasourceTypeEntryData( const OUString& _sType, String sDisplayName );
        void                insertEmbeddedDBTypeEntryData( const OUString& _sType, String sDisplayName );

    protected:
        ListBox*            m_pDatasourceType;
        ListBox*            m_pEmbeddedDBType;

        ::dbaccess::ODsnTypeCollection*
                            m_pCollection;  /// the DSN type collection instance

        ::std::vector< OUString>
                            m_aURLPrefixes;
        ::std::vector< OUString>
                            m_aEmbeddedURLPrefixes;

    public:
        /// set a handler which gets called every time the user selects a new type
@@ -83,6 +88,7 @@ namespace dbaui

        virtual void implInitControls( const SfxItemSet& _rSet, sal_Bool _bSaveValue );
        virtual OUString getDatasourceName( const SfxItemSet& _rSet );
        virtual OUString getEmbeddedDBName( const SfxItemSet& _rSet );
        virtual bool approveDatasourceType( ::dbaccess::DATASOURCE_TYPE eType, OUString& _inout_rDisplayName );

        // <method>OGenericAdministrationPage::fillControls</method>
@@ -92,6 +98,7 @@ namespace dbaui

        void onTypeSelected(const OUString& _sURLPrefix);
        void initializeTypeList();
        void initializeEmbeddedDBList();

        void implSetCurrentType( const OUString& _eType );

@@ -101,6 +108,7 @@ namespace dbaui
        virtual void setParentTitle( const OUString& _sURLPrefix );

        DECL_LINK(OnDatasourceTypeSelected, ListBox*);
        DECL_LINK(OnEmbeddedDBTypeSelected, ListBox*);
    };

    //=========================================================================
@@ -149,6 +157,7 @@ namespace dbaui
        RadioButton*            m_pRB_OpenExistingDatabase;
        RadioButton*            m_pRB_ConnectDatabase;

        FixedText*              m_pFT_EmbeddedDBLabel;
        FixedText*              m_pFT_DocListLabel;
        OpenDocumentListBox*    m_pLB_DocumentList;
        OpenDocumentButton*     m_pPB_OpenDatabase;
@@ -182,6 +191,7 @@ namespace dbaui
        virtual bool approveDatasourceType( ::dbaccess::DATASOURCE_TYPE eType, OUString& _inout_rDisplayName );

    protected:
        DECL_LINK( OnCreateDatabaseModeSelected, RadioButton* );
        DECL_LINK( OnSetupModeSelected, RadioButton* );
        DECL_LINK( OnDocumentSelected, ListBox* );
        DECL_LINK( OnOpenDocument, PushButton* );
diff --git a/dbaccess/source/ui/inc/dbwizsetup.hxx b/dbaccess/source/ui/inc/dbwizsetup.hxx
index f9360c8..706abdc 100644
--- a/dbaccess/source/ui/inc/dbwizsetup.hxx
+++ b/dbaccess/source/ui/inc/dbwizsetup.hxx
@@ -177,8 +177,6 @@ private:
    void createUniqueFolderName(INetURLObject* pURL);
    ::dbaccess::DATASOURCE_TYPE VerifyDataSourceType(const ::dbaccess::DATASOURCE_TYPE _DatabaseType) const;

    OUString getDefaultDatabaseType() const;

    void updateTypeDependentStates();
    sal_Bool callSaveAsDialog();
    sal_Bool IsConnectionUrlRequired();
diff --git a/dbaccess/uiconfig/ui/generalpagewizard.ui b/dbaccess/uiconfig/ui/generalpagewizard.ui
index 0e41080..0fcd591 100644
--- a/dbaccess/uiconfig/ui/generalpagewizard.ui
+++ b/dbaccess/uiconfig/ui/generalpagewizard.ui
@@ -59,10 +59,12 @@
    <child>
      <object class="GtkRadioButton" id="createDatabase">
        <property name="label" translatable="yes">Create a n_ew database</property>
        <property name="use_action_appearance">False</property>
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <property name="receives_default">False</property>
        <property name="margin_left">12</property>
        <property name="use_action_appearance">False</property>
        <property name="use_underline">True</property>
        <property name="xalign">0</property>
        <property name="active">True</property>
@@ -75,12 +77,53 @@
      </packing>
    </child>
    <child>
      <object class="GtkBox" id="embeddeddbBox">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="margin_left">48</property>
        <property name="spacing">8</property>
        <child>
          <object class="GtkLabel" id="embeddeddbLabel">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="xalign">0</property>
            <property name="label" translatable="yes">_Embedded Database:</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkComboBoxText" id="embeddeddbList">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="entry_text_column">0</property>
            <property name="id_column">1</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">4</property>
      </packing>
    </child>
    <child>
      <object class="GtkRadioButton" id="openExistingDatabase">
        <property name="label" translatable="yes">Open an existing database _file</property>
        <property name="use_action_appearance">False</property>
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <property name="receives_default">False</property>
        <property name="margin_left">12</property>
        <property name="use_action_appearance">False</property>
        <property name="use_underline">True</property>
        <property name="xalign">0</property>
        <property name="active">True</property>
@@ -90,7 +133,7 @@
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">4</property>
        <property name="position">5</property>
      </packing>
    </child>
    <child>
@@ -131,32 +174,36 @@
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">5</property>
        <property name="position">6</property>
      </packing>
    </child>
    <child>
      <object class="dbulo-OpenDocumentButton" id="openDatabase">
        <property name="label" translatable="yes">Open</property>
        <property name="use_action_appearance">False</property>
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <property name="receives_default">True</property>
        <property name="halign">start</property>
        <property name="margin_left">48</property>
        <property name="use_action_appearance">False</property>
        <property name="always_show_image">True</property>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">6</property>
        <property name="position">7</property>
      </packing>
    </child>
    <child>
      <object class="GtkRadioButton" id="connectDatabase">
        <property name="label" translatable="yes">Connect to an e_xisting database</property>
        <property name="use_action_appearance">False</property>
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <property name="receives_default">False</property>
        <property name="margin_left">12</property>
        <property name="use_action_appearance">False</property>
        <property name="use_underline">True</property>
        <property name="xalign">0</property>
        <property name="active">True</property>
@@ -166,7 +213,7 @@
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">7</property>
        <property name="position">8</property>
      </packing>
    </child>
    <child>
@@ -181,7 +228,7 @@
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">8</property>
        <property name="position">9</property>
      </packing>
    </child>
    <child>
@@ -192,7 +239,7 @@
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">9</property>
        <property name="position">10</property>
      </packing>
    </child>
  </object>