2496 lines
98 KiB
C++
2496 lines
98 KiB
C++
/*************************************************************************
|
|
*
|
|
* $RCSfile: dbadmin.cxx,v $
|
|
*
|
|
* $Revision: 1.40 $
|
|
*
|
|
* last change: $Author: oj $ $Date: 2001-03-27 08:05:56 $
|
|
*
|
|
* The Contents of this file are made available subject to the terms of
|
|
* either of the following licenses
|
|
*
|
|
* - GNU Lesser General Public License Version 2.1
|
|
* - Sun Industry Standards Source License Version 1.1
|
|
*
|
|
* Sun Microsystems Inc., October, 2000
|
|
*
|
|
* GNU Lesser General Public License Version 2.1
|
|
* =============================================
|
|
* Copyright 2000 by Sun Microsystems, Inc.
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License version 2.1, as published by the Free Software Foundation.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307 USA
|
|
*
|
|
*
|
|
* Sun Industry Standards Source License Version 1.1
|
|
* =================================================
|
|
* The contents of this file are subject to the Sun Industry Standards
|
|
* Source License Version 1.1 (the "License"); You may not use this file
|
|
* except in compliance with the License. You may obtain a copy of the
|
|
* License at http://www.openoffice.org/license.html.
|
|
*
|
|
* Software provided under this License is provided on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
|
|
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
|
|
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
|
|
* See the License for the specific provisions governing your rights and
|
|
* obligations concerning the Software.
|
|
*
|
|
* The Initial Developer of the Original Code is: Sun Microsystems, Inc..
|
|
*
|
|
* Copyright: 2000 by Sun Microsystems, Inc.
|
|
*
|
|
* All Rights Reserved.
|
|
*
|
|
* Contributor(s): _______________________________________
|
|
*
|
|
*
|
|
************************************************************************/
|
|
|
|
#ifndef _DBAUI_DBADMIN_HXX_
|
|
#include "dbadmin.hxx"
|
|
#endif
|
|
#ifndef _DBAUI_DBADMIN_HRC_
|
|
#include "dbadmin.hrc"
|
|
#endif
|
|
#ifndef _DBU_RESOURCE_HRC_
|
|
#include "dbu_resource.hrc"
|
|
#endif
|
|
#ifndef _DBAUI_MODULE_DBU_HXX_
|
|
#include "moduledbu.hxx"
|
|
#endif
|
|
#ifndef _DBAUI_DATASOURCEITEMS_HXX_
|
|
#include "dsitems.hxx"
|
|
#endif
|
|
#ifndef _SFXSTRITEM_HXX
|
|
#include <svtools/stritem.hxx>
|
|
#endif
|
|
#ifndef _SFXENUMITEM_HXX
|
|
#include <svtools/eitem.hxx>
|
|
#endif
|
|
#ifndef _SFXINTITEM_HXX
|
|
#include <svtools/intitem.hxx>
|
|
#endif
|
|
#ifndef _VCL_STDTEXT_HXX
|
|
#include <vcl/stdtext.hxx>
|
|
#endif
|
|
#ifndef _SV_MSGBOX_HXX
|
|
#include <vcl/msgbox.hxx>
|
|
#endif
|
|
#ifndef _SVTOOLS_LOGINDLG_HXX_
|
|
#include <svtools/logindlg.hxx>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
|
|
#include <com/sun/star/beans/PropertyAttribute.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_UNO_XNAMINGSERVICE_HPP_
|
|
#include <com/sun/star/uno/XNamingService.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_UTIL_XFLUSHABLE_HPP_
|
|
#include <com/sun/star/util/XFlushable.hpp>
|
|
#endif
|
|
#ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
|
|
#include "dbustrings.hrc"
|
|
#endif
|
|
#ifndef _COMPHELPER_EXTRACT_HXX_
|
|
#include <comphelper/extract.hxx>
|
|
#endif
|
|
#ifndef _DBAUI_ADMINPAGES_HXX_
|
|
#include "adminpages.hxx"
|
|
#endif
|
|
#ifndef _DBAUI_DETAILPAGES_HXX_
|
|
#include "detailpages.hxx"
|
|
#endif
|
|
#ifndef _DBAUI_COMMONPAGES_HXX_
|
|
#include "commonpages.hxx"
|
|
#endif
|
|
#ifndef _DBAUI_LOCALRESACCESS_HXX_
|
|
#include "localresaccess.hxx"
|
|
#endif
|
|
#ifndef _DBAUI_STRINGLISTITEM_HXX_
|
|
#include "stringlistitem.hxx"
|
|
#endif
|
|
#ifndef _TYPELIB_TYPEDESCRIPTION_HXX_
|
|
#include <typelib/typedescription.hxx>
|
|
#endif
|
|
#ifndef _COMPHELPER_PROPERTY_HXX_
|
|
#include <comphelper/property.hxx>
|
|
#endif
|
|
#ifndef _COMPHELPER_SEQUENCE_HXX_
|
|
#include <comphelper/sequence.hxx>
|
|
#endif
|
|
#ifndef _DBAUI_PROPERTYSETITEM_HXX_
|
|
#include "propertysetitem.hxx"
|
|
#endif
|
|
#ifndef DBAUI_ADABASPAGE_HXX
|
|
#include "AdabasPage.hxx"
|
|
#endif
|
|
#ifndef _DBHELPER_DBEXCEPTION_HXX_
|
|
#include <connectivity/dbexception.hxx>
|
|
#endif
|
|
#ifndef DBAUI_TOOLS_HXX
|
|
#include "UITools.hxx"
|
|
#endif
|
|
#ifndef _SV_WAITOBJ_HXX
|
|
#include <vcl/waitobj.hxx>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_SDBC_XDRIVERACCESS_HPP_
|
|
#include <com/sun/star/sdbc/XDriverAccess.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_SDBC_XDRIVER_HPP_
|
|
#include <com/sun/star/sdbc/XDriver.hpp>
|
|
#endif
|
|
//.........................................................................
|
|
namespace dbaui
|
|
{
|
|
//.........................................................................
|
|
using namespace dbtools;
|
|
using namespace com::sun::star::uno;
|
|
using namespace com::sun::star::sdbc;
|
|
using namespace com::sun::star::sdb;
|
|
using namespace com::sun::star::lang;
|
|
using namespace com::sun::star::util;
|
|
using namespace com::sun::star::beans;
|
|
using namespace com::sun::star::container;
|
|
|
|
//=========================================================================
|
|
//= ODatasourceMap
|
|
//=========================================================================
|
|
//-------------------------------------------------------------------------
|
|
ODatasourceMap::ODatasourceMap(const Reference< XMultiServiceFactory > _rxORB)
|
|
:m_xORB(_rxORB)
|
|
{
|
|
// create the DatabaseContext service
|
|
DBG_ASSERT(m_xORB.is(), "ODatasourceMap::ODatasourceMap: need a service factory !");
|
|
try
|
|
{
|
|
m_xDatabaseContext = Reference< XNameAccess >(m_xORB->createInstance(SERVICE_SDB_DATABASECONTEXT), UNO_QUERY);
|
|
}
|
|
catch(Exception&)
|
|
{
|
|
}
|
|
|
|
// initialize our map
|
|
if (m_xDatabaseContext.is())
|
|
{
|
|
Sequence< ::rtl::OUString > aDatasources = m_xDatabaseContext->getElementNames();
|
|
const ::rtl::OUString* pDatasources = aDatasources.getConstArray();
|
|
for (sal_Int32 i=0; i<aDatasources.getLength(); ++i, ++pDatasources)
|
|
m_aDatasources[*pDatasources] = DatasourceInfo();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
ODatasourceMap::Iterator ODatasourceMap::begin()
|
|
{
|
|
return Iterator(this, m_aDatasources.begin());
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
ODatasourceMap::Iterator ODatasourceMap::end()
|
|
{
|
|
return Iterator(this, m_aDatasources.end());
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
ODatasourceMap::Iterator ODatasourceMap::beginDeleted()
|
|
{
|
|
return Iterator(this, m_aDeletedDatasources.begin());
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
ODatasourceMap::Iterator ODatasourceMap::endDeleted()
|
|
{
|
|
return Iterator(this, m_aDeletedDatasources.end());
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceMap::update(const ::rtl::OUString& _rName, SfxItemSet& _rSet)
|
|
{
|
|
DatasourceInfosIterator aPos = m_aDatasources.find(_rName);
|
|
DBG_ASSERT(aPos != m_aDatasources.end(), "ODatasourceMap::update: invalid name!!");
|
|
if (aPos == m_aDatasources.end())
|
|
return;
|
|
|
|
if (aPos->second.pModifications)
|
|
// already had modifications for this datasource
|
|
// -> simply update them
|
|
aPos->second.pModifications->Put(_rSet);
|
|
else
|
|
{
|
|
// this is the first time this data source is modified -> create a new set and initialize it
|
|
aPos->second.pModifications = new SfxItemSet(_rSet);
|
|
aPos->second.pModifications->Put(SfxStringItem(DSID_ORIGINALNAME, _rName));
|
|
aPos->second.pModifications->Put(SfxBoolItem(DSID_NEWDATASOURCE, sal_False));
|
|
aPos->second.pModifications->Put(SfxBoolItem(DSID_DELETEDDATASOURCE, sal_False));
|
|
|
|
// and reset the original name in the source set, it may contain an old one
|
|
_rSet.Put(SfxStringItem(DSID_ORIGINALNAME, _rName));
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceMap::deleted(const ::rtl::OUString& _rName)
|
|
{
|
|
DatasourceInfosIterator aPos = m_aDatasources.find(_rName);
|
|
DBG_ASSERT(aPos != m_aDeletedDatasources.end(), "ODatasourceMap::deleted: invalid access key!");
|
|
if (aPos == m_aDeletedDatasources.end())
|
|
return;
|
|
|
|
delete aPos->second.pModifications;
|
|
m_aDatasources.erase(aPos);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
sal_Bool ODatasourceMap::restoreDeleted(sal_Int32 _nAccessId, ::rtl::OUString& _rName)
|
|
{
|
|
MapInt2InfoIterator aPos = m_aDeletedDatasources.find(_nAccessId);
|
|
if (m_aDeletedDatasources.end() == aPos)
|
|
{
|
|
DBG_ERROR("ODatasourceSelector::restoreDeleted: invalid access id!");
|
|
return sal_False;
|
|
}
|
|
|
|
// the name (not the original name) of the data source
|
|
Iterator aEasyNameAccess(this, aPos);
|
|
::rtl::OUString sName = aEasyNameAccess->getName();
|
|
|
|
// check if we have a not-deleted data source with that name
|
|
ConstDatasourceInfosIterator aExistentPos = m_aDatasources.find(sName);
|
|
if (m_aDatasources.end() != aExistentPos)
|
|
// yes -> too bad ...
|
|
return sal_False;
|
|
|
|
m_aDatasources[sName] = aPos->second;
|
|
m_aDeletedDatasources.erase(aPos);
|
|
_rName = sName;
|
|
return sal_True;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
sal_Int32 ODatasourceMap::markDeleted(const ::rtl::OUString& _rName)
|
|
{
|
|
DatasourceInfosIterator aPos = m_aDatasources.find(_rName);
|
|
DBG_ASSERT(aPos != m_aDatasources.end(), "ODatasourceMap::markDeleted: invalid name!!");
|
|
if (aPos == m_aDatasources.end())
|
|
return -1;
|
|
|
|
// after the DatasourceInfo moved from m_aDatasources to m_aDeletedDatasources, we loose the info
|
|
// of the name of the ds (which in m_aDatasources is the key). So later we need an modifications item set
|
|
// or the real object itself to obtain that name.
|
|
if (NULL == aPos->second.pModifications)
|
|
ensureObject(_rName);
|
|
|
|
// search a free access key
|
|
const sal_uInt32 nPrime = 65521;
|
|
sal_uInt32 nAccessKey = rand() % nPrime; // the engendering
|
|
|
|
for (sal_uInt32 nLoop=0; nLoop<nPrime; ++nLoop, nAccessKey = (nAccessKey * nAccessKey) % nPrime)
|
|
{
|
|
::std::pair< MapInt2InfoIterator, bool > aInsertPos
|
|
= m_aDeletedDatasources.insert(MapInt2Info::value_type(nAccessKey, aPos->second));
|
|
if (aInsertPos.second)
|
|
// a new entry was inserted into m_aDeletedDatasources, which means the key wasn't used yet
|
|
break;
|
|
}
|
|
if (nAccessKey<nPrime)
|
|
{ // we found a free key ...
|
|
// delete the DatasourceInfo from the other map
|
|
m_aDatasources.erase(aPos);
|
|
return nAccessKey;
|
|
}
|
|
|
|
DBG_ERROR("ODatasourceMap::markDeleted: could not find a free key (tried 65521 different ones ...)!");
|
|
return -1;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceMap::clearModifiedFlag(const ::rtl::OUString& _rName)
|
|
{
|
|
DatasourceInfosIterator aPos = m_aDatasources.find(_rName);
|
|
DBG_ASSERT(aPos != m_aDatasources.end(), "ODatasourceMap::clearModifiedFlag: invalid name!!");
|
|
if (aPos == m_aDatasources.end())
|
|
return;
|
|
|
|
if (aPos->second.pModifications)
|
|
{
|
|
delete aPos->second.pModifications;
|
|
aPos->second.pModifications = NULL;
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceMap::clearDeleted()
|
|
{
|
|
for ( ConstMapInt2InfoIterator aLoopDeleted = m_aDeletedDatasources.begin();
|
|
aLoopDeleted != m_aDeletedDatasources.end();
|
|
++aLoopDeleted
|
|
)
|
|
{
|
|
if (aLoopDeleted->second.pModifications)
|
|
delete aLoopDeleted->second.pModifications;
|
|
}
|
|
m_aDeletedDatasources.clear();
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceMap::clear()
|
|
{
|
|
// the "ordinary" data sources
|
|
for ( ConstDatasourceInfosIterator aLoop = m_aDatasources.begin();
|
|
aLoop != m_aDatasources.end();
|
|
++aLoop
|
|
)
|
|
{
|
|
if (aLoop->second.pModifications)
|
|
delete aLoop->second.pModifications;
|
|
}
|
|
m_aDatasources.clear();
|
|
|
|
// the deleted ones
|
|
clearDeleted();
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceMap::ensureObject(const ::rtl::OUString& _rName)
|
|
{
|
|
DatasourceInfosIterator aPos = m_aDatasources.find(_rName);
|
|
DBG_ASSERT(aPos != m_aDatasources.end(), "ODatasourceMap::ensureObject: invalid name!!");
|
|
if (aPos == m_aDatasources.end())
|
|
return;
|
|
|
|
if (aPos->second.xDatasource.is())
|
|
// nothing to do, the object already exists
|
|
return;
|
|
|
|
try
|
|
{
|
|
if (m_xDatabaseContext.is() && _rName.getLength())
|
|
::cppu::extractInterface(aPos->second.xDatasource, m_xDatabaseContext->getByName(_rName));
|
|
DBG_ASSERT(aPos->second.xDatasource.is(), "ODatasourceMap::ensureObject: could not retrieve the object!");
|
|
}
|
|
catch(NoSuchElementException&)
|
|
{
|
|
DBG_ERROR("ODatasourceMap::ensureObject: did not find the element with the given name!");
|
|
}
|
|
catch(WrappedTargetException&)
|
|
{
|
|
DBG_ERROR("ODatasourceMap::ensureObject: caught a WrappedTargetException!");
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
::rtl::OUString ODatasourceMap::adjustRealName(const ::rtl::OUString& _rName)
|
|
{
|
|
DatasourceInfosIterator aPos = m_aDatasources.find(_rName);
|
|
DBG_ASSERT(aPos != m_aDatasources.end(), "ODatasourceMap::adjustRealName: invalid name!!");
|
|
if (aPos == m_aDatasources.end())
|
|
return _rName;
|
|
|
|
if (!aPos->second.pModifications)
|
|
return _rName;
|
|
|
|
SFX_ITEMSET_GET(*aPos->second.pModifications, pRealName, SfxStringItem, DSID_NAME, sal_True);
|
|
if (!pRealName)
|
|
return _rName;
|
|
|
|
::rtl::OUString sRealName = pRealName->GetValue().GetBuffer();
|
|
if (sRealName.equals(_rName))
|
|
// all fine
|
|
return _rName;
|
|
|
|
DBG_ASSERT(m_aDatasources.end() == m_aDatasources.find(sRealName), "ODatasourceMap::adjustRealName: have an invalid real name!");
|
|
|
|
renamed(_rName, sRealName);
|
|
return sRealName;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceMap::renamed(const ::rtl::OUString& _rOldName, const ::rtl::OUString& _rNewName)
|
|
{
|
|
DatasourceInfosIterator aPos = m_aDatasources.find(_rOldName);
|
|
DBG_ASSERT(aPos != m_aDatasources.end(), "ODatasourceMap::renamed: invalid name!!");
|
|
if (aPos == m_aDatasources.end())
|
|
return;
|
|
|
|
// insert the DatasourceInfo under the new name
|
|
DatasourceInfo aInfo = aPos->second;
|
|
m_aDatasources.erase(aPos);
|
|
m_aDatasources[_rNewName] = aInfo;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
sal_Bool ODatasourceMap::exists(const ::rtl::OUString& _rName) const
|
|
{
|
|
return isValid() && (m_aDatasources.end() != m_aDatasources.find(_rName));
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
Reference< XPropertySet > ODatasourceMap::createNew(const ::rtl::OUString& _rName, SfxItemPool* _pPool, const USHORT* _pRanges)
|
|
{
|
|
Reference< XPropertySet > xReturn;
|
|
try
|
|
{
|
|
xReturn = Reference< XPropertySet >(m_xORB->createInstance(SERVICE_SDB_DATASOURCE), UNO_QUERY);
|
|
}
|
|
catch(Exception&)
|
|
{
|
|
}
|
|
|
|
if (xReturn.is())
|
|
{
|
|
// create a new item set
|
|
SfxItemSet* pItems = new SfxItemSet(*_pPool, _pRanges);
|
|
pItems->Put(SfxBoolItem(DSID_NEWDATASOURCE, sal_True));
|
|
pItems->Put(SfxStringItem(DSID_NAME, _rName));
|
|
pItems->Put(OPropertySetItem(DSID_DATASOURCE_UNO, xReturn));
|
|
m_aDatasources[_rName] = DatasourceInfo(xReturn, pItems);
|
|
}
|
|
return xReturn;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
ODatasourceMap::ODatasourceInfo ODatasourceMap::operator[](const ::rtl::OUString _rName)
|
|
{
|
|
ConstDatasourceInfosIterator aPos = m_aDatasources.find(_rName);
|
|
DBG_ASSERT(aPos != m_aDatasources.end(), "ODatasourceMap::operator[]: invalid name!!");
|
|
if (aPos == m_aDatasources.end())
|
|
{
|
|
// just prevent crashes, the result here is completely nonsense
|
|
static ODatasourceMap::DatasourceInfo aFallback;
|
|
return ODatasourceInfo(NULL, ::rtl::OUString(), aFallback, -1);
|
|
}
|
|
|
|
return ODatasourceInfo(this, aPos->first, aPos->second, -1);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//- ODatasourceMap::ODatasourceInfo
|
|
//-------------------------------------------------------------------------
|
|
Reference< XPropertySet > ODatasourceMap::ODatasourceInfo::getDatasource() const
|
|
{
|
|
if (!m_rInfoImpl.xDatasource.is())
|
|
{ // the object has not been accessed yet -> create it
|
|
DBG_ASSERT(m_pOwner, "ODatasourceInfo::getDatasource: no owner which could provide the object!");
|
|
DBG_ASSERT(!isNew(), "ODatasourceInfo::getDatasource: new object without property set!");
|
|
|
|
if (m_pOwner)
|
|
m_pOwner->ensureObject(getName());
|
|
}
|
|
return m_rInfoImpl.xDatasource;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
::rtl::OUString ODatasourceMap::ODatasourceInfo::getRealName() const
|
|
{
|
|
if (!isModified())
|
|
return getName();
|
|
|
|
::rtl::OUString sReturn;
|
|
if (m_rInfoImpl.pModifications)
|
|
{
|
|
SFX_ITEMSET_GET(*m_rInfoImpl.pModifications, pRealName, SfxStringItem, DSID_NAME, sal_True);
|
|
if (pRealName)
|
|
sReturn = pRealName->GetValue().GetBuffer();
|
|
}
|
|
return sReturn;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
::rtl::OUString ODatasourceMap::ODatasourceInfo::getOriginalName() const
|
|
{
|
|
if (!isModified())
|
|
return getName();
|
|
|
|
::rtl::OUString sReturn;
|
|
if (m_rInfoImpl.pModifications)
|
|
{
|
|
SFX_ITEMSET_GET(*m_rInfoImpl.pModifications, pOriginalName, SfxStringItem, DSID_ORIGINALNAME, sal_True);
|
|
if (pOriginalName)
|
|
sReturn = pOriginalName->GetValue().GetBuffer();
|
|
}
|
|
return sReturn;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
sal_Bool ODatasourceMap::ODatasourceInfo::isModified() const
|
|
{
|
|
return NULL != m_rInfoImpl.pModifications;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
sal_Bool ODatasourceMap::ODatasourceInfo::isNew() const
|
|
{
|
|
if (!m_rInfoImpl.pModifications)
|
|
return sal_False;
|
|
SFX_ITEMSET_GET(*m_rInfoImpl.pModifications, pIsNew, SfxBoolItem, DSID_NEWDATASOURCE, sal_True);
|
|
return pIsNew && pIsNew->GetValue();
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//- ODatasourceMap::Iterator
|
|
//-------------------------------------------------------------------------
|
|
ODatasourceMap::Iterator::Iterator(ODatasourceMap* _pOwner, ODatasourceMap::ConstDatasourceInfosIterator _rPos)
|
|
:m_pOwner(_pOwner)
|
|
,m_aPos(_rPos)
|
|
,m_aPosDeleted(_pOwner->m_aDeletedDatasources.end())
|
|
,m_bLoopingDeleted(sal_False)
|
|
{
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
ODatasourceMap::Iterator::Iterator(ODatasourceMap* _pOwner, ODatasourceMap::ConstMapInt2InfoIterator _rPos)
|
|
:m_pOwner(_pOwner)
|
|
,m_aPos(_pOwner->m_aDatasources.end())
|
|
,m_aPosDeleted(_rPos)
|
|
,m_bLoopingDeleted(sal_True)
|
|
{
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
ODatasourceMap::Iterator::Iterator(const ODatasourceMap::Iterator& _rSource)
|
|
:m_pOwner(_rSource.m_pOwner)
|
|
,m_aPos(_rSource.m_aPos)
|
|
,m_aPosDeleted(_rSource.m_aPosDeleted)
|
|
,m_bLoopingDeleted(_rSource.m_bLoopingDeleted)
|
|
{
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
const ODatasourceMap::Iterator& ODatasourceMap::Iterator::operator++()
|
|
{
|
|
if (m_bLoopingDeleted)
|
|
++m_aPosDeleted;
|
|
else
|
|
++m_aPos;
|
|
return *this;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
const ODatasourceMap::Iterator& ODatasourceMap::Iterator::operator--()
|
|
{
|
|
if (m_bLoopingDeleted)
|
|
--m_aPosDeleted;
|
|
else
|
|
--m_aPos;
|
|
return *this;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
::rtl::OUString ODatasourceMap::Iterator::implGetName(const ODatasourceMap::DatasourceInfo& _rInfo) const
|
|
{
|
|
::rtl::OUString sName;
|
|
if (_rInfo.pModifications)
|
|
{
|
|
SFX_ITEMSET_GET(*_rInfo.pModifications, pName, SfxStringItem, DSID_NAME, sal_True);
|
|
sName = pName->GetValue();
|
|
}
|
|
else
|
|
{
|
|
DBG_ASSERT(_rInfo.xDatasource.is(), "ODatasourceMap::Iterator::implGetName: no modifications, no object ... How am I supposed to get the name?");
|
|
if (_rInfo.xDatasource.is())
|
|
{
|
|
try
|
|
{
|
|
_rInfo.xDatasource->getPropertyValue(PROPERTY_NAME) >>= sName;
|
|
}
|
|
catch(Exception&)
|
|
{
|
|
DBG_ERROR("ODatasourceMap::operator->: could not obtain the data source name!");
|
|
}
|
|
}
|
|
}
|
|
return sName;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
ODatasourceMap::ODatasourceInfo ODatasourceMap::Iterator::operator->() const
|
|
{
|
|
if (!m_bLoopingDeleted)
|
|
return ODatasourceInfo(m_pOwner, m_aPos->first, m_aPos->second, -1);
|
|
else
|
|
return ODatasourceInfo(m_pOwner, implGetName(m_aPosDeleted->second), m_aPosDeleted->second, m_aPosDeleted->first);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
ODatasourceMap::ODatasourceInfo ODatasourceMap::Iterator::operator*() const
|
|
{
|
|
if (!m_bLoopingDeleted)
|
|
return ODatasourceInfo(m_pOwner, m_aPos->first, m_aPos->second, -1);
|
|
else
|
|
return ODatasourceInfo(m_pOwner, implGetName(m_aPosDeleted->second), m_aPosDeleted->second, m_aPosDeleted->first);
|
|
}
|
|
|
|
//=========================================================================
|
|
//= ODbAdminDialog
|
|
//=========================================================================
|
|
//-------------------------------------------------------------------------
|
|
ODbAdminDialog::ODbAdminDialog(Window* _pParent, SfxItemSet* _pItems, const Reference< XMultiServiceFactory >& _rxORB)
|
|
:SfxTabDialog(_pParent, ModuleRes(DLG_DATABASE_ADMINISTRATION), _pItems)
|
|
,m_aSelector(this, ResId(WND_DATASOURCESELECTOR))
|
|
,m_bResetting(sal_False)
|
|
,m_aDatasources(_rxORB)
|
|
,m_xORB(_rxORB)
|
|
{
|
|
// add the initial tab pages
|
|
AddTabPage(PAGE_GENERAL, String(ResId(STR_PAGETITLE_GENERAL)), OGeneralPage::Create, NULL);
|
|
AddTabPage(PAGE_TABLESUBSCRIPTION, String(ResId(STR_PAGETITLE_TABLESUBSCRIPTION)), OTableSubscriptionPage::Create, NULL);
|
|
AddTabPage(PAGE_QUERYADMINISTRATION, String(ResId(STR_PAGETITLE_QUERIES)), OQueryAdministrationPage::Create, NULL);
|
|
|
|
// no local resources needed anymore
|
|
FreeResource();
|
|
|
|
/// initialize the property translation map
|
|
// direct properties of a data source
|
|
m_aDirectPropTranslator.insert(MapInt2String::value_type(DSID_CONNECTURL, PROPERTY_URL));
|
|
m_aDirectPropTranslator.insert(MapInt2String::value_type(DSID_NAME, PROPERTY_NAME));
|
|
m_aDirectPropTranslator.insert(MapInt2String::value_type(DSID_USER, PROPERTY_USER));
|
|
m_aDirectPropTranslator.insert(MapInt2String::value_type(DSID_PASSWORD, PROPERTY_PASSWORD));
|
|
m_aDirectPropTranslator.insert(MapInt2String::value_type(DSID_PASSWORDREQUIRED, PROPERTY_ISPASSWORDREQUIRED));
|
|
m_aDirectPropTranslator.insert(MapInt2String::value_type(DSID_TABLEFILTER, PROPERTY_TABLEFILTER));
|
|
m_aDirectPropTranslator.insert(MapInt2String::value_type(DSID_READONLY, PROPERTY_ISREADONLY));
|
|
m_aDirectPropTranslator.insert(MapInt2String::value_type(DSID_SUPPRESSVERSIONCL, PROPERTY_SUPPRESSVERSIONCL));
|
|
|
|
// implicit properties, to be found in the direct property "Info"
|
|
m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_JDBCDRIVERCLASS, ::rtl::OUString::createFromAscii("JavaDriverClass")));
|
|
m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_TEXTFILEEXTENSION, ::rtl::OUString::createFromAscii("Extension")));
|
|
m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CHARSET, ::rtl::OUString::createFromAscii("CharSet")));
|
|
m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_TEXTFILEHEADER, ::rtl::OUString::createFromAscii("HeaderLine")));
|
|
m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_FIELDDELIMITER, ::rtl::OUString::createFromAscii("FieldDelimiter")));
|
|
m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_TEXTDELIMITER, ::rtl::OUString::createFromAscii("StringDelimiter")));
|
|
m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_DECIMALDELIMITER, ::rtl::OUString::createFromAscii("DecimalDelimiter")));
|
|
m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_THOUSANDSDELIMITER, ::rtl::OUString::createFromAscii("ThousandDelimiter")));
|
|
m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_SHOWDELETEDROWS, ::rtl::OUString::createFromAscii("ShowDeleted")));
|
|
m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_ALLOWLONGTABLENAMES, ::rtl::OUString::createFromAscii("NoNameLengthLimit")));
|
|
m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_ADDITIONALOPTIONS, ::rtl::OUString::createFromAscii("SystemDriverSettings")));
|
|
|
|
// special settings for adabas
|
|
m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CONN_SHUTSERVICE, ::rtl::OUString::createFromAscii("ShutdownDatabase")));
|
|
m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CONN_DATAINC, ::rtl::OUString::createFromAscii("DataCacheSizeIncrement")));
|
|
m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CONN_CACHESIZE, ::rtl::OUString::createFromAscii("DataCacheSize")));
|
|
m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CONN_CTRLUSER, ::rtl::OUString::createFromAscii("ControlUser")));
|
|
m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CONN_CTRLPWD, ::rtl::OUString::createFromAscii("ControlPassword")));
|
|
|
|
// remove the reset button - it's meaning is much too ambiguous in this dialog
|
|
RemoveResetButton();
|
|
|
|
// enable an apply button
|
|
EnableApplyButton(sal_True);
|
|
SetApplyHandler(LINK(this, ODbAdminDialog, OnApplyChanges));
|
|
// disable the apply button
|
|
GetApplyButton()->Enable(sal_False);
|
|
|
|
// register the view window
|
|
SetViewWindow(&m_aSelector);
|
|
SetViewAlign(WINDOWALIGN_LEFT);
|
|
|
|
// do some knittings
|
|
m_aSelector.setSelectHandler(LINK(this, ODbAdminDialog, OnDatasourceSelected));
|
|
m_aSelector.setNewHandler(LINK(this, ODbAdminDialog, OnNewDatasource));
|
|
m_aSelector.setDeleteHandler(LINK(this, ODbAdminDialog, OnDeleteDatasource));
|
|
m_aSelector.setRestoreHandler(LINK(this, ODbAdminDialog, OnRestoreDatasource));
|
|
|
|
::rtl::OUString sInitialSelection; // will be the initial selection
|
|
|
|
if (!m_aDatasources.isValid())
|
|
{
|
|
ShowServiceNotAvailableError(_pParent, String(SERVICE_SDB_DATABASECONTEXT), sal_True);
|
|
m_aSelector.Disable();
|
|
}
|
|
else
|
|
{
|
|
m_xDatabaseContext = m_aDatasources.getContext();
|
|
m_xDynamicContext = Reference< XNamingService >(m_xDatabaseContext, UNO_QUERY);
|
|
DBG_ASSERT(m_xDynamicContext.is(), "ODbAdminDialog::ODbAdminDialog : no XNamingService interface !");
|
|
|
|
// fill the listbox with the names of the registered datasources
|
|
ODatasourceMap::Iterator aDatasourceLoop = m_aDatasources.begin();
|
|
while (aDatasourceLoop != m_aDatasources.end())
|
|
{
|
|
m_aSelector.insert(*aDatasourceLoop);
|
|
m_aValidDatasources.insert(*aDatasourceLoop);
|
|
|
|
++aDatasourceLoop;
|
|
}
|
|
|
|
if (!m_aDatasources.size())
|
|
{
|
|
WarningBox(_pParent, ModuleRes(ERR_NOREGISTEREDDATASOURCES)).Execute();
|
|
}
|
|
else
|
|
sInitialSelection = *m_aDatasources.begin();
|
|
}
|
|
|
|
implSelectDatasource(sInitialSelection);
|
|
|
|
GetApplyButton()->Enable(sal_False);
|
|
// nothing modified 'til now -> now apply
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
ODbAdminDialog::~ODbAdminDialog()
|
|
{
|
|
SetInputSet(NULL);
|
|
DELETEZ(pExampleSet);
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
Reference<XConnection> ODbAdminDialog::createConnection()
|
|
{
|
|
Reference<XConnection> xConnection;
|
|
// // if (bValid)
|
|
{ // get the current table list from the connection for the current settings
|
|
// the PropertyValues for the current dialog settings
|
|
Sequence< PropertyValue > aConnectionParams;
|
|
if (getCurrentSettings(aConnectionParams))
|
|
{
|
|
// the current DSN
|
|
String sConnectionURL;
|
|
SFX_ITEMSET_GET(*GetExampleSet(), pUrlItem, SfxStringItem, DSID_CONNECTURL, sal_True);
|
|
sConnectionURL = pUrlItem->GetValue();
|
|
|
|
// fill the table list with this connection information
|
|
SQLExceptionInfo aErrorInfo;
|
|
try
|
|
{
|
|
WaitObject aWaitCursor(this);
|
|
// get the global DriverManager
|
|
Reference< XDriverAccess > xDriverManager;
|
|
String sCurrentActionError = String(ModuleRes(STR_COULDNOTCREATE_DRIVERMANAGER));
|
|
// in case an error occures
|
|
sCurrentActionError.SearchAndReplaceAscii("#servicename#", (::rtl::OUString)SERVICE_SDBC_DRIVERMANAGER);
|
|
try
|
|
{
|
|
xDriverManager = Reference< XDriverAccess >(getORB()->createInstance(SERVICE_SDBC_DRIVERMANAGER), UNO_QUERY);
|
|
DBG_ASSERT(xDriverManager.is(), "OTableTreeListBox::UpdateTableList : could not instantiate the driver manager, or it does not provide the necessary interface!");
|
|
}
|
|
catch (Exception& e)
|
|
{
|
|
// wrap the exception into an SQLException
|
|
SQLException aSQLWrapper(e.Message, getORB(), ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("S1000")), 0, Any());
|
|
throw aSQLWrapper;
|
|
}
|
|
if (!xDriverManager.is())
|
|
throw Exception();
|
|
|
|
|
|
sCurrentActionError = String(ModuleRes(STR_NOREGISTEREDDRIVER));
|
|
Reference< XDriver > xDriver = xDriverManager->getDriverByURL(sConnectionURL);
|
|
if (!xDriver.is())
|
|
// will be caught and translated into an SQLContext exception
|
|
throw Exception();
|
|
|
|
xConnection = xDriver->connect(sConnectionURL, aConnectionParams);
|
|
}
|
|
catch (SQLContext& e) { aErrorInfo = SQLExceptionInfo(e); }
|
|
catch (SQLWarning& e) { aErrorInfo = SQLExceptionInfo(e); }
|
|
catch (SQLException& e) { aErrorInfo = SQLExceptionInfo(e); }
|
|
|
|
showError(aErrorInfo,this,getORB());
|
|
}
|
|
}
|
|
|
|
return xConnection;
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
short ODbAdminDialog::Execute()
|
|
{
|
|
short nResult = SfxTabDialog::Execute();
|
|
|
|
// within it's dtor, the SfxTabDialog saves (amongst others) the currently selected tab page and
|
|
// reads it upon the next Execute (dependent on the resource id, which thus has to be globally unique,
|
|
// though our's isn't)
|
|
// As this is not wanted if e.g. the table subscription page is selected, we show the GeneralPage here
|
|
ShowPage(PAGE_GENERAL);
|
|
|
|
// clear the temporary SfxItemSets we created
|
|
m_aDatasources.clear();
|
|
|
|
return nResult;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODbAdminDialog::selectDataSource(const ::rtl::OUString& _rName)
|
|
{
|
|
if (m_aDatasources.exists(_rName))
|
|
implSelectDatasource(_rName);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
sal_Bool ODbAdminDialog::getCurrentSettings(Sequence< PropertyValue >& _rDriverParam)
|
|
{
|
|
DBG_ASSERT(GetExampleSet(), "ODbAdminDialog::getCurrentSettings : not to be called without an example set!");
|
|
if (!GetExampleSet())
|
|
return sal_False;
|
|
|
|
::std::vector< PropertyValue > aReturn;
|
|
// collecting this in a vector because it has a push_back, in opposite to sequences
|
|
|
|
// user: DSID_USER -> "user"
|
|
SFX_ITEMSET_GET(*GetExampleSet(), pUser, SfxStringItem, DSID_USER, sal_True);
|
|
if (pUser && pUser->GetValue().Len())
|
|
aReturn.push_back(
|
|
PropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("user")), 0,
|
|
makeAny(::rtl::OUString(pUser->GetValue())), PropertyState_DIRECT_VALUE));
|
|
|
|
// check if the connection type requires a password
|
|
if (hasAuthentication(*GetExampleSet()))
|
|
{
|
|
// password: DSID_PASSWORD -> "password"
|
|
SFX_ITEMSET_GET(*GetExampleSet(), pPassword, SfxStringItem, DSID_PASSWORD, sal_True);
|
|
String sPassword = pPassword ? pPassword->GetValue() : String();
|
|
SFX_ITEMSET_GET(*GetExampleSet(), pPasswordRequired, SfxBoolItem, DSID_PASSWORDREQUIRED, sal_True);
|
|
// if the set does not contain a password, but the item set says it requires one, ask the user
|
|
if ((!pPassword || !pPassword->GetValue().Len()) && (pPasswordRequired && pPasswordRequired->GetValue()))
|
|
{
|
|
SFX_ITEMSET_GET(*GetExampleSet(), pName, SfxStringItem, DSID_NAME, sal_True);
|
|
|
|
::svt::LoginDialog aDlg(this,
|
|
LF_NO_PATH | LF_NO_ACCOUNT | LF_NO_ERRORTEXT | LF_USERNAME_READONLY,
|
|
String(), NULL);
|
|
|
|
aDlg.SetName(pUser ? pUser->GetValue() : String());
|
|
aDlg.ClearPassword(); // this will give the password field the focus
|
|
|
|
String sLoginRequest(ModuleRes(STR_ENTER_CONNECTION_PASSWORD));
|
|
sLoginRequest.SearchAndReplaceAscii("$name$", pName ? pName->GetValue() : String()),
|
|
aDlg.SetLoginRequestText(sLoginRequest);
|
|
aDlg.SetSavePasswordText(ModuleRes(STR_REMEMBERPASSWORD_SESSION));
|
|
aDlg.SetSavePassword(sal_True);
|
|
|
|
sal_Int32 nResult = aDlg.Execute();
|
|
if (nResult != RET_OK)
|
|
return sal_False;
|
|
|
|
sPassword = aDlg.GetPassword();
|
|
if (aDlg.IsSavePassword())
|
|
pExampleSet->Put(SfxStringItem(DSID_PASSWORD, sPassword));
|
|
}
|
|
|
|
if (sPassword.Len())
|
|
aReturn.push_back(
|
|
PropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("password")), 0,
|
|
makeAny(::rtl::OUString(sPassword)), PropertyState_DIRECT_VALUE));
|
|
}
|
|
|
|
_rDriverParam = Sequence< PropertyValue >(aReturn.begin(), aReturn.size());
|
|
|
|
// append all the other stuff (charset etc.)
|
|
fillDatasourceInfo(*GetExampleSet(), _rDriverParam);
|
|
|
|
return sal_True;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
sal_Bool ODbAdminDialog::isApplyable()
|
|
{
|
|
return GetApplyButton()->IsEnabled();
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODbAdminDialog::applyChangesAsync()
|
|
{
|
|
DBG_ASSERT(isApplyable(), "ODbAdminDialog::applyChangesAsync: invalid call!");
|
|
PostUserEvent(LINK(this, ODbAdminDialog, OnAsyncApplyChanges));
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
short ODbAdminDialog::Ok()
|
|
{
|
|
short nResult = SfxTabDialog::Ok();
|
|
return (AR_LEAVE_MODIFIED == implApplyChanges(sal_False)) ? RET_OK : RET_CANCEL;
|
|
// TODO : AR_ERROR is not handled correctly, we always close the dialog here
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODbAdminDialog::PageCreated(USHORT _nId, SfxTabPage& _rPage)
|
|
{
|
|
// register ourself as modified listener
|
|
static_cast<OGenericAdministrationPage&>(_rPage).SetModifiedHandler(LINK(this, ODbAdminDialog, OnDatasourceModifed));
|
|
|
|
// some registrations which depend on the type of the page
|
|
switch (_nId)
|
|
{
|
|
case PAGE_GENERAL:
|
|
static_cast<OGeneralPage&>(_rPage).SetTypeSelectHandler(LINK(this, ODbAdminDialog, OnTypeSelected));
|
|
static_cast<OGeneralPage&>(_rPage).SetNameModifyHandler(LINK(this, ODbAdminDialog, OnNameModified));
|
|
static_cast<OGeneralPage&>(_rPage).SetAdminDialog(this);
|
|
break;
|
|
case PAGE_TABLESUBSCRIPTION:
|
|
static_cast<OTableSubscriptionPage&>(_rPage).setServiceFactory(m_xORB);
|
|
static_cast<OTableSubscriptionPage&>(_rPage).SetAdminDialog(this);
|
|
break;
|
|
case PAGE_QUERYADMINISTRATION:
|
|
static_cast<OQueryAdministrationPage&>(_rPage).setServiceFactory(m_xORB);
|
|
static_cast<OQueryAdministrationPage&>(_rPage).SetAdminDialog(this);
|
|
break;
|
|
case TAB_PAG_ADABAS_SETTINGS:
|
|
static_cast<OAdabasAdminSettings&>(_rPage).SetAdminDialog(this);
|
|
break;
|
|
}
|
|
|
|
SfxTabDialog::PageCreated(_nId, _rPage);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
SfxItemSet* ODbAdminDialog::createItemSet(SfxItemSet*& _rpSet, SfxItemPool*& _rpPool, SfxPoolItem**& _rppDefaults, ODsnTypeCollection* _pTypeCollection)
|
|
{
|
|
// just to be sure ....
|
|
_rpSet = NULL;
|
|
_rpPool = NULL;
|
|
_rppDefaults = NULL;
|
|
|
|
// create and initialize the defaults
|
|
_rppDefaults = new SfxPoolItem*[DSID_LAST_ITEM_ID - DSID_FIRST_ITEM_ID + 1];
|
|
SfxPoolItem** pCounter = _rppDefaults; // want to modify this without affecting the out param _rppDefaults
|
|
*pCounter++ = new SfxStringItem(DSID_NAME, String());
|
|
*pCounter++ = new SfxStringItem(DSID_ORIGINALNAME, String());
|
|
*pCounter++ = new SfxStringItem(DSID_CONNECTURL, _pTypeCollection ? _pTypeCollection->getDatasourcePrefix(DST_JDBC) : String());
|
|
*pCounter++ = new OStringListItem(DSID_TABLEFILTER, Sequence< ::rtl::OUString >(&::rtl::OUString("%", 1, RTL_TEXTENCODING_ASCII_US), 1));
|
|
*pCounter++ = new DbuTypeCollectionItem(DSID_TYPECOLLECTION, _pTypeCollection);
|
|
*pCounter++ = new SfxBoolItem(DSID_INVALID_SELECTION, sal_False);
|
|
*pCounter++ = new SfxBoolItem(DSID_READONLY, sal_False);
|
|
*pCounter++ = new SfxStringItem(DSID_USER, String());
|
|
*pCounter++ = new SfxStringItem(DSID_PASSWORD, String());
|
|
*pCounter++ = new SfxStringItem(DSID_ADDITIONALOPTIONS, String());
|
|
*pCounter++ = new SfxStringItem(DSID_CHARSET, String());
|
|
*pCounter++ = new SfxBoolItem(DSID_PASSWORDREQUIRED, sal_False);
|
|
*pCounter++ = new SfxBoolItem(DSID_SHOWDELETEDROWS, sal_False);
|
|
*pCounter++ = new SfxBoolItem(DSID_ALLOWLONGTABLENAMES, sal_False);
|
|
*pCounter++ = new SfxStringItem(DSID_JDBCDRIVERCLASS, String());
|
|
*pCounter++ = new SfxStringItem(DSID_FIELDDELIMITER, ';');
|
|
*pCounter++ = new SfxStringItem(DSID_TEXTDELIMITER, '"');
|
|
*pCounter++ = new SfxStringItem(DSID_DECIMALDELIMITER, '.');
|
|
*pCounter++ = new SfxStringItem(DSID_THOUSANDSDELIMITER, ',');
|
|
*pCounter++ = new SfxStringItem(DSID_TEXTFILEEXTENSION, String::CreateFromAscii("txt"));
|
|
*pCounter++ = new SfxBoolItem(DSID_TEXTFILEHEADER, sal_True);
|
|
*pCounter++ = new SfxBoolItem(DSID_NEWDATASOURCE, sal_False);
|
|
*pCounter++ = new SfxBoolItem(DSID_DELETEDDATASOURCE, sal_False);
|
|
*pCounter++ = new SfxBoolItem(DSID_SUPPRESSVERSIONCL, sal_True);
|
|
*pCounter++ = new OPropertySetItem(DSID_DATASOURCE_UNO);
|
|
*pCounter++ = new SfxBoolItem(DSID_CONN_SHUTSERVICE, sal_False);
|
|
*pCounter++ = new SfxInt32Item(DSID_CONN_DATAINC, 20);
|
|
*pCounter++ = new SfxInt32Item(DSID_CONN_CACHESIZE, 20);
|
|
*pCounter++ = new SfxStringItem(DSID_CONN_CTRLUSER, String());
|
|
*pCounter++ = new SfxStringItem(DSID_CONN_CTRLPWD, String());
|
|
|
|
|
|
// create the pool
|
|
static SfxItemInfo __READONLY_DATA aItemInfos[DSID_LAST_ITEM_ID - DSID_FIRST_ITEM_ID + 1] =
|
|
{
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
{0,0},
|
|
};
|
|
|
|
_rpPool = new SfxItemPool(String::CreateFromAscii("DSAItemPool"), DSID_FIRST_ITEM_ID, DSID_LAST_ITEM_ID,
|
|
aItemInfos, _rppDefaults);
|
|
_rpPool->FreezeIdRanges();
|
|
|
|
// and, finally, the set
|
|
_rpSet = new SfxItemSet(*_rpPool, sal_True);
|
|
|
|
return _rpSet;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODbAdminDialog::destroyItemSet(SfxItemSet*& _rpSet, SfxItemPool*& _rpPool, SfxPoolItem**& _rppDefaults)
|
|
{
|
|
// _first_ delete the set (refering the pool)
|
|
if (_rpSet)
|
|
{
|
|
delete _rpSet;
|
|
_rpSet = NULL;
|
|
}
|
|
|
|
// delete the pool
|
|
if (_rpPool)
|
|
{
|
|
_rpPool->ReleaseDefaults(sal_True);
|
|
// the "true" means delete the items, too
|
|
delete _rpPool;
|
|
_rpPool = NULL;
|
|
}
|
|
|
|
// reset the defaults ptr
|
|
_rppDefaults = NULL;
|
|
// no need to explicitly delete the defaults, this has been done by the ReleaseDefaults
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
IMPL_LINK(ODbAdminDialog, OnDatasourceSelected, ListBox*, _pBox)
|
|
{
|
|
// first ask the current page if it is allowed to leave
|
|
if (!PrepareLeaveCurrentPage())
|
|
{ // the page did not allow us to leave -> restore the old selection
|
|
if (m_sCurrentDatasource.getLength())
|
|
m_aSelector.select(m_sCurrentDatasource);
|
|
else
|
|
m_aSelector.select(m_nCurrentDeletedDataSource);
|
|
return 1L;
|
|
}
|
|
|
|
// if the old data source is not a to-be-deleted one, save the modifications made in the tabpages
|
|
if (m_sCurrentDatasource.getLength())
|
|
{
|
|
// remember the settings for this data source
|
|
ODatasourceMap::ODatasourceInfo aPreviouslySelected = m_aDatasources[m_sCurrentDatasource];
|
|
if (aPreviouslySelected.isModified())
|
|
m_aDatasources.update(m_sCurrentDatasource, *pExampleSet);
|
|
// (The modified flag is set as soon as any UI element has any change (e.g. a single new character in a edit line).
|
|
// But when this flag is set, and other changes occur, no items are transfered.
|
|
// That's why the above statement "if (isModified()) update()" makes sense, though it may not seem so :)
|
|
|
|
// need a special handling for the name property
|
|
if (aPreviouslySelected.isModified())
|
|
{
|
|
String sName = aPreviouslySelected.getName().getStr();
|
|
DBG_ASSERT(m_sCurrentDatasource.equals(sName.GetBuffer()), "ODbAdminDialog::OnDatasourceSelected: inconsistent names!");
|
|
|
|
// first adjust the name which the datasource is stored under in our map.
|
|
String sNewName = m_aDatasources.adjustRealName(sName);
|
|
// if this was a real change ('cause the ds was stored under name "A", but the modifications set already contained
|
|
// an DSID_NAME item "B", which has been corrected by the previous call), tell the selector window that
|
|
// something changed
|
|
if (!sNewName.Equals(sName))
|
|
{
|
|
// tell our selector window that the name has changed
|
|
m_aSelector.renamed(sName, sNewName);
|
|
// update our "current database"
|
|
m_sCurrentDatasource = sNewName;
|
|
}
|
|
}
|
|
}
|
|
|
|
// switch the content of the pages
|
|
if (DELETED == m_aSelector.getSelectedState())
|
|
implSelectDeleted(m_aSelector.getSelectedAccessKey());
|
|
else
|
|
implSelectDatasource(m_aSelector.getSelected());
|
|
|
|
return 0L;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
IMPL_LINK(ODbAdminDialog, OnDatasourceModifed, SfxTabPage*, _pTabPage)
|
|
{
|
|
// check if the currently selected entry is already marked as modified
|
|
String sCurrentlySelected = m_aSelector.getSelected();
|
|
if (m_aDatasources[sCurrentlySelected].isModified())
|
|
// yes -> nothing to do
|
|
return 0L;
|
|
|
|
// no -> mark the item as modified
|
|
m_aSelector.modified(sCurrentlySelected);
|
|
m_aDatasources.update(sCurrentlySelected, *pExampleSet);
|
|
|
|
// enable the apply button
|
|
GetApplyButton()->Enable(sal_True);
|
|
|
|
return 0L;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
IMPL_LINK(ODbAdminDialog, OnNameModified, OGeneralPage*, _pTabPage)
|
|
{
|
|
if (!m_bResetting)
|
|
{
|
|
::rtl::OUString sNewStringSuggestion = _pTabPage->GetCurrentName();
|
|
|
|
// check if there's already a data source with the suggested name
|
|
ConstStringSetIterator aExistentPos = m_aValidDatasources.find(sNewStringSuggestion);
|
|
// !! m_aValidDatasources contains _all_ data source names _except_ the currently selected one !!
|
|
|
|
sal_Bool bValid = m_aValidDatasources.end() == aExistentPos;
|
|
|
|
// the user is not allowed to leave the current data source (or to commit the dialog) as long
|
|
// as the name is invalid
|
|
m_aSelector.Enable(bValid && m_aDatasources.isValid());
|
|
GetOKButton().Enable(bValid);
|
|
GetApplyButton()->Enable(bValid);
|
|
|
|
// if this is the first modification for this data source, we have to adjust the DS list accordingly
|
|
String sSelected = m_aSelector.getSelected();
|
|
if (!m_aDatasources[sSelected].isModified())
|
|
{ // (we could do it all the time here, but as this link is called every time a single character
|
|
// of the name changes, this maybe would be too expensive.)
|
|
m_aSelector.modified(sSelected);
|
|
m_aDatasources.update(sSelected, *pExampleSet);
|
|
}
|
|
|
|
// enable the apply button
|
|
GetApplyButton()->Enable(sal_True && bValid);
|
|
|
|
return bValid ? 1L : 0L;
|
|
}
|
|
return 1L;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
IMPL_LINK(ODbAdminDialog, OnTypeSelected, OGeneralPage*, _pTabPage)
|
|
{
|
|
// remove all current detail pages
|
|
while (m_aCurrentDetailPages.size())
|
|
{
|
|
RemoveTabPage(m_aCurrentDetailPages.top());
|
|
m_aCurrentDetailPages.pop();
|
|
}
|
|
|
|
// open our own resource block, as the page titles are strings local to this block
|
|
OLocalResourceAccess aDummy(DLG_DATABASE_ADMINISTRATION, RSC_TABDIALOG);
|
|
|
|
// doe have to reset the "password required" flag to false? (in case the datasource does not support passwords)
|
|
sal_Bool bResetPasswordRequired = sal_False;
|
|
|
|
// and insert the new ones
|
|
switch (_pTabPage->GetSelectedType())
|
|
{
|
|
case DST_DBASE:
|
|
AddTabPage(PAGE_DBASE, String(ResId(STR_PAGETITLE_DBASE)), ODbaseDetailsPage::Create, 0, sal_False, 1);
|
|
m_aCurrentDetailPages.push(PAGE_DBASE);
|
|
bResetPasswordRequired = sal_True;
|
|
break;
|
|
case DST_JDBC:
|
|
AddTabPage(PAGE_JDBC, String(ResId(STR_PAGETITLE_JDBC)), OJdbcDetailsPage::Create, 0, sal_False, 1);
|
|
m_aCurrentDetailPages.push(PAGE_JDBC);
|
|
break;
|
|
case DST_ADO:
|
|
AddTabPage(PAGE_ADO, String(ResId(STR_PAGETITLE_ADO)), OAdoDetailsPage::Create, 0, sal_False, 1);
|
|
m_aCurrentDetailPages.push(PAGE_ADO);
|
|
break;
|
|
case DST_TEXT:
|
|
AddTabPage(PAGE_TEXT, String(ResId(STR_PAGETITLE_TEXT)), OTextDetailsPage::Create, 0, sal_False, 1);
|
|
m_aCurrentDetailPages.push(PAGE_TEXT);
|
|
bResetPasswordRequired = sal_True;
|
|
break;
|
|
case DST_ODBC:
|
|
AddTabPage(PAGE_ODBC, String(ResId(STR_PAGETITLE_ODBC)), OOdbcDetailsPage::Create, 0, sal_False, 1);
|
|
m_aCurrentDetailPages.push(PAGE_ODBC);
|
|
break;
|
|
case DST_ADABAS:
|
|
AddTabPage(TAB_PAG_ADABAS_SETTINGS, String(ResId(STR_PAGETITLE_ADABAS_STATISTIC)), OAdabasAdminSettings::Create, 0, sal_False, 1);
|
|
AddTabPage(PAGE_ADABAS, String(ResId(STR_PAGETITLE_ADABAS)), OAdabasDetailsPage::Create, 0, sal_False, 1);
|
|
m_aCurrentDetailPages.push(TAB_PAG_ADABAS_SETTINGS);
|
|
m_aCurrentDetailPages.push(PAGE_ADABAS);
|
|
break;
|
|
}
|
|
|
|
if (bResetPasswordRequired)
|
|
{
|
|
GetInputSetImpl()->Put(SfxBoolItem(DSID_PASSWORDREQUIRED, sal_False));
|
|
if (pExampleSet)
|
|
pExampleSet->Put(SfxBoolItem(DSID_PASSWORDREQUIRED, sal_False));
|
|
}
|
|
|
|
return 0L;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
Reference< XPropertySet > ODbAdminDialog::getDatasource(const ::rtl::OUString& _rName)
|
|
{
|
|
DBG_ASSERT(m_aDatasources.isValid(), "ODbAdminDialog::getDatasource : have no database context!");
|
|
if (!m_aDatasources.exists(_rName))
|
|
return Reference< XPropertySet >();
|
|
|
|
return m_aDatasources[_rName]->getDatasource();
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODbAdminDialog::implSelectDeleted(sal_Int32 _nKey)
|
|
{
|
|
m_aSelector.select(_nKey);
|
|
|
|
// insert the previously selected data source into our "all valid datasources" set
|
|
if (m_sCurrentDatasource.getLength()) // previous selection was not on a deleted data source
|
|
m_aValidDatasources.insert(m_sCurrentDatasource);
|
|
m_sCurrentDatasource = ::rtl::OUString();
|
|
m_nCurrentDeletedDataSource = _nKey;
|
|
|
|
// reset the tag pages
|
|
resetPages(Reference< XPropertySet >(), sal_True);
|
|
|
|
// disallow reset for deleted pages
|
|
// GetResetButton().Enable(sal_False);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODbAdminDialog::implSelectDatasource(const ::rtl::OUString& _rRegisteredName)
|
|
{
|
|
m_aSelector.select(_rRegisteredName);
|
|
|
|
// insert the previously selected data source into our set
|
|
if (m_sCurrentDatasource.getLength()) // previous selection was not on a deleted data source
|
|
m_aValidDatasources.insert(m_sCurrentDatasource);
|
|
m_sCurrentDatasource = _rRegisteredName;
|
|
m_nCurrentDeletedDataSource = -1;
|
|
// remove the now selected data source from our set
|
|
m_aValidDatasources.erase(m_sCurrentDatasource);
|
|
|
|
// reset the tag pages
|
|
Reference< XPropertySet > xDatasource = getDatasource(_rRegisteredName);
|
|
resetPages(xDatasource, sal_False);
|
|
|
|
// allow reset for non-deleted pages
|
|
// GetResetButton().Enable(sal_True);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODbAdminDialog::resetPages(const Reference< XPropertySet >& _rxDatasource, sal_Bool _bDeleted)
|
|
{
|
|
// the selection is valid if and only if we have a datasource now
|
|
GetInputSetImpl()->Put(SfxBoolItem(DSID_INVALID_SELECTION, !_rxDatasource.is()));
|
|
// (sal_False tells the tab pages to disable and reset all their controls, which is different
|
|
// from "just set them to readonly")
|
|
|
|
// reset the pages
|
|
|
|
// prevent flicker
|
|
SetUpdateMode(sal_False);
|
|
|
|
// remove all tab pages (except the general one)
|
|
// remove all current detail pages
|
|
while (m_aCurrentDetailPages.size())
|
|
{
|
|
RemoveTabPage(m_aCurrentDetailPages.top());
|
|
m_aCurrentDetailPages.pop();
|
|
}
|
|
// remove the table/query tab pages
|
|
RemoveTabPage(PAGE_TABLESUBSCRIPTION);
|
|
RemoveTabPage(PAGE_QUERYADMINISTRATION);
|
|
|
|
// extract all relevant data from the property set of the data source
|
|
translateProperties(_rxDatasource, *GetInputSetImpl());
|
|
|
|
// reset some meta data items in the input set which are for tracking the state of the current ds
|
|
GetInputSetImpl()->Put(SfxBoolItem(DSID_NEWDATASOURCE, sal_False));
|
|
GetInputSetImpl()->Put(SfxBoolItem(DSID_DELETEDDATASOURCE, _bDeleted));
|
|
GetInputSetImpl()->Put(OPropertySetItem(DSID_DATASOURCE_UNO, _rxDatasource));
|
|
|
|
// fill in the remembered settings for the data source
|
|
if (m_sCurrentDatasource.getLength()) // the current datasource is not deleted
|
|
if (m_aDatasources[m_sCurrentDatasource]->isModified()) // the current data source was modified before
|
|
GetInputSetImpl()->Put(*m_aDatasources[m_sCurrentDatasource]->getModifications());
|
|
|
|
// propagate this set as our new input set and reset the example set
|
|
SetInputSet(GetInputSetImpl());
|
|
delete pExampleSet;
|
|
pExampleSet = new SfxItemSet(*GetInputSetImpl());
|
|
|
|
// and again, add the non-details tab pages
|
|
if (!_bDeleted)
|
|
{
|
|
OLocalResourceAccess aDummy(DLG_DATABASE_ADMINISTRATION, RSC_TABDIALOG);
|
|
AddTabPage(PAGE_TABLESUBSCRIPTION, String(ResId(STR_PAGETITLE_TABLESUBSCRIPTION)), OTableSubscriptionPage::Create, NULL);
|
|
AddTabPage(PAGE_QUERYADMINISTRATION, String(ResId(STR_PAGETITLE_QUERIES)), OQueryAdministrationPage::Create, NULL);
|
|
}
|
|
|
|
m_bResetting = sal_True;
|
|
ShowPage(PAGE_GENERAL);
|
|
SetUpdateMode(sal_True);
|
|
|
|
// propagate the new data to the general tab page the general tab page
|
|
SfxTabPage* pGeneralPage = GetTabPage(PAGE_GENERAL);
|
|
if (pGeneralPage)
|
|
pGeneralPage->Reset(*GetInputSetImpl());
|
|
// if this is NULL, the page has not been created yet, which means we're called before the
|
|
// dialog was displayed (probably from inside the ctor)
|
|
m_bResetting = sal_False;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
Any ODbAdminDialog::implTranslateProperty(const SfxPoolItem* _pItem)
|
|
{
|
|
// translate the SfxPoolItem
|
|
Any aValue;
|
|
if (_pItem->ISA(SfxStringItem))
|
|
aValue <<= ::rtl::OUString(PTR_CAST(SfxStringItem, _pItem)->GetValue().GetBuffer());
|
|
else if (_pItem->ISA(SfxBoolItem))
|
|
aValue = ::cppu::bool2any(PTR_CAST(SfxBoolItem, _pItem)->GetValue());
|
|
else if (_pItem->ISA(SfxInt32Item))
|
|
aValue <<= PTR_CAST(SfxInt32Item, _pItem)->GetValue();
|
|
else if (_pItem->ISA(OStringListItem))
|
|
aValue <<= PTR_CAST(OStringListItem, _pItem)->getList();
|
|
else
|
|
{
|
|
DBG_ERROR("ODbAdminDialog::implTranslateProperty: unsupported item type!");
|
|
return aValue;
|
|
}
|
|
|
|
return aValue;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODbAdminDialog::implTranslateProperty(const Reference< XPropertySet >& _rxSet, const ::rtl::OUString& _rName, const SfxPoolItem* _pItem)
|
|
{
|
|
Any aValue = implTranslateProperty(_pItem);
|
|
try
|
|
{
|
|
_rxSet->setPropertyValue(_rName, aValue);
|
|
}
|
|
catch(Exception&)
|
|
{
|
|
#ifdef DBG_UTIL
|
|
::rtl::OString sMessage("ODbAdminDialog::implTranslateProperty: could not set the property ");
|
|
sMessage += ::rtl::OString(_rName.getStr(), _rName.getLength(), RTL_TEXTENCODING_ASCII_US);
|
|
sMessage += ::rtl::OString("!");
|
|
DBG_ERROR(sMessage.getStr());
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODbAdminDialog::implTranslateProperty(SfxItemSet& _rSet, sal_Int32 _nId, const Any& _rValue)
|
|
{
|
|
switch (_rValue.getValueType().getTypeClass())
|
|
{
|
|
case TypeClass_STRING:
|
|
{
|
|
::rtl::OUString sValue;
|
|
_rValue >>= sValue;
|
|
_rSet.Put(SfxStringItem(_nId, sValue.getStr()));
|
|
}
|
|
break;
|
|
case TypeClass_BOOLEAN:
|
|
_rSet.Put(SfxBoolItem(_nId, ::cppu::any2bool(_rValue)));
|
|
break;
|
|
case TypeClass_LONG:
|
|
{
|
|
sal_Int32 nValue = 0;
|
|
_rValue >>= nValue;
|
|
_rSet.Put(SfxInt32Item(_nId, nValue));
|
|
}
|
|
break;
|
|
case TypeClass_SEQUENCE:
|
|
{
|
|
// determine the element type
|
|
TypeDescription aTD(_rValue.getValueType());
|
|
typelib_IndirectTypeDescription* pSequenceTD =
|
|
reinterpret_cast< typelib_IndirectTypeDescription* >(aTD.get());
|
|
DBG_ASSERT(pSequenceTD && pSequenceTD->pType, "ODbAdminDialog::implTranslateProperty: invalid sequence type!");
|
|
|
|
Type aElementType(pSequenceTD->pType);
|
|
switch (aElementType.getTypeClass())
|
|
{
|
|
case TypeClass_STRING:
|
|
{
|
|
Sequence< ::rtl::OUString > aStringList;
|
|
_rValue >>= aStringList;
|
|
_rSet.Put(OStringListItem(_nId, aStringList));
|
|
}
|
|
break;
|
|
default:
|
|
DBG_ERROR("ODbAdminDialog::implTranslateProperty: unsupported property value type!");
|
|
}
|
|
}
|
|
break;
|
|
case TypeClass_VOID:
|
|
_rSet.ClearItem(_nId);
|
|
break;
|
|
default:
|
|
DBG_ERROR("ODbAdminDialog::implTranslateProperty: unsupported property value type!");
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
struct PropertyValueLess
|
|
{
|
|
bool operator() (const PropertyValue& x, const PropertyValue& y) const
|
|
{ return x.Name < y.Name ? true : false; } // construct prevents a MSVC6 warning
|
|
};
|
|
DECLARE_STL_SET( PropertyValue, PropertyValueLess, PropertyValueSet);
|
|
|
|
//........................................................................
|
|
void ODbAdminDialog::translateProperties(const Reference< XPropertySet >& _rxSource, SfxItemSet& _rDest)
|
|
{
|
|
::rtl::OUString sNewConnectURL, sName, sUid, sPwd;
|
|
Sequence< ::rtl::OUString > aTableFitler;
|
|
sal_Bool bPasswordRequired = sal_False;
|
|
sal_Bool bReadOnly = sal_True;
|
|
|
|
if (_rxSource.is())
|
|
{
|
|
for ( ConstMapInt2StringIterator aDirect = m_aDirectPropTranslator.begin();
|
|
aDirect != m_aDirectPropTranslator.end();
|
|
++aDirect
|
|
)
|
|
{
|
|
// get the property value
|
|
Any aValue;
|
|
try
|
|
{
|
|
aValue = _rxSource->getPropertyValue(aDirect->second);
|
|
}
|
|
catch(Exception&)
|
|
{
|
|
#if DBG_UTIL
|
|
::rtl::OString aMessage("ODbAdminDialog::translateProperties: could not extract the property ");
|
|
aMessage += ::rtl::OString(aDirect->second.getStr(), aDirect->second.getLength(), RTL_TEXTENCODING_ASCII_US);
|
|
aMessage += ::rtl::OString("!");
|
|
DBG_ERROR(aMessage.getStr());
|
|
#endif
|
|
}
|
|
// transfer it into an item
|
|
implTranslateProperty(_rDest, aDirect->first, aValue);
|
|
}
|
|
|
|
// get the additional informations
|
|
Sequence< PropertyValue > aAdditionalInfo;
|
|
try
|
|
{
|
|
_rxSource->getPropertyValue(PROPERTY_INFO) >>= aAdditionalInfo;
|
|
}
|
|
catch(Exception&) { }
|
|
|
|
// collect the names of the additional settings
|
|
const PropertyValue* pAdditionalInfo = aAdditionalInfo.getConstArray();
|
|
PropertyValueSet aInfos;
|
|
for (sal_Int32 i=0; i<aAdditionalInfo.getLength(); ++i, ++pAdditionalInfo)
|
|
{
|
|
if (0 == pAdditionalInfo->Name.compareToAscii("JDBCDRV"))
|
|
{ // compatibility
|
|
PropertyValue aCompatibility(*pAdditionalInfo);
|
|
aCompatibility.Name = ::rtl::OUString::createFromAscii("JavaDriverClass");
|
|
aInfos.insert(aCompatibility);
|
|
}
|
|
else
|
|
aInfos.insert(*pAdditionalInfo);
|
|
}
|
|
|
|
// go through all known translations and check if we have such a setting
|
|
PropertyValue aSearchFor;
|
|
for ( ConstMapInt2StringIterator aIndirect = m_aIndirectPropTranslator.begin();
|
|
aIndirect != m_aIndirectPropTranslator.end();
|
|
++aIndirect
|
|
)
|
|
{
|
|
aSearchFor.Name = aIndirect->second;
|
|
ConstPropertyValueSetIterator aInfoPos = aInfos.find(aSearchFor);
|
|
if (aInfos.end() != aInfoPos)
|
|
// the property is contained in the info sequence
|
|
// -> transfer it into an item
|
|
implTranslateProperty(_rDest, aIndirect->first, aInfoPos->Value);
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODbAdminDialog::translateProperties(const SfxItemSet& _rSource, const Reference< XPropertySet >& _rxDest)
|
|
{
|
|
DBG_ASSERT(_rxDest.is(), "ODbAdminDialog::translateProperties: invalid property set!");
|
|
if (!_rxDest.is())
|
|
return;
|
|
|
|
// the property set info
|
|
Reference< XPropertySetInfo > xInfo;
|
|
try { xInfo = _rxDest->getPropertySetInfo(); }
|
|
catch(Exception&) { }
|
|
|
|
// -----------------------------
|
|
// transfer the direct propertis
|
|
for ( ConstMapInt2StringIterator aDirect = m_aDirectPropTranslator.begin();
|
|
aDirect != m_aDirectPropTranslator.end();
|
|
++aDirect
|
|
)
|
|
{
|
|
const SfxPoolItem* pCurrentItem = _rSource.GetItem(aDirect->first);
|
|
if (pCurrentItem)
|
|
{
|
|
sal_Int16 nAttributes = PropertyAttribute::READONLY;
|
|
if (xInfo.is())
|
|
{
|
|
try { nAttributes = xInfo->getPropertyByName(aDirect->second).Attributes; }
|
|
catch(Exception&) { }
|
|
}
|
|
if ((nAttributes & PropertyAttribute::READONLY) == 0)
|
|
implTranslateProperty(_rxDest, aDirect->second, pCurrentItem);
|
|
}
|
|
}
|
|
|
|
// -------------------------------
|
|
// now for the indirect properties
|
|
|
|
Sequence< PropertyValue > aInfo;
|
|
// the original properties
|
|
try
|
|
{
|
|
_rxDest->getPropertyValue(PROPERTY_INFO) >>= aInfo;
|
|
}
|
|
catch(Exception&) { }
|
|
|
|
// overwrite and extend them
|
|
fillDatasourceInfo(_rSource, aInfo);
|
|
|
|
// and propagate the (newly composed) sequence to the set
|
|
try
|
|
{
|
|
_rxDest->setPropertyValue(PROPERTY_INFO, makeAny(aInfo));
|
|
}
|
|
catch(Exception&)
|
|
{
|
|
DBG_ERROR("ODbAdminDialog::translateProperties: could not propagate the composed info sequence to the property set!");
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
DATASOURCE_TYPE ODbAdminDialog::getDatasourceType(const SfxItemSet& _rSet) const
|
|
{
|
|
SFX_ITEMSET_GET(_rSet, pConnectURL, SfxStringItem, DSID_CONNECTURL, sal_True);
|
|
SFX_ITEMSET_GET(_rSet, pTypeCollection, DbuTypeCollectionItem, DSID_TYPECOLLECTION, sal_True);
|
|
DBG_ASSERT(pConnectURL && pTypeCollection, "ODbAdminDialog::getDatasourceType: invalid items in the source set!");
|
|
String sConnectURL = pConnectURL->GetValue();
|
|
ODsnTypeCollection* pCollection = pTypeCollection->getCollection();
|
|
DBG_ASSERT(pCollection, "ODbAdminDialog::getDatasourceType: invalid type collection!");
|
|
return pCollection->getType(sConnectURL);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
sal_Bool ODbAdminDialog::hasAuthentication(const SfxItemSet& _rSet) const
|
|
{
|
|
DATASOURCE_TYPE eType = getDatasourceType(_rSet);
|
|
SFX_ITEMSET_GET(_rSet, pTypeCollection, DbuTypeCollectionItem, DSID_TYPECOLLECTION, sal_True);
|
|
return pTypeCollection->getCollection()->hasAuthentication(eType);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
const sal_Int32* ODbAdminDialog::getRelevantItems(const SfxItemSet& _rSet) const
|
|
{
|
|
DATASOURCE_TYPE eType = getDatasourceType(_rSet);
|
|
const sal_Int32* pRelevantItems = NULL;
|
|
switch (eType)
|
|
{
|
|
case DST_ADABAS:
|
|
{
|
|
static sal_Int32* pAdabasItems = NULL;
|
|
if(!pAdabasItems)
|
|
{
|
|
const sal_Int32* pFirstRelevantItems = OAdabasDetailsPage::getDetailIds();
|
|
const sal_Int32* pSecondRelevantItems = OAdabasAdminSettings::getDetailIds();
|
|
sal_Int32 nFLen = 0;
|
|
sal_Int32 nSLen = 0;
|
|
|
|
for(pRelevantItems = pFirstRelevantItems;pRelevantItems && *pRelevantItems;++pRelevantItems)
|
|
++nFLen;
|
|
|
|
for(pRelevantItems = pSecondRelevantItems;pRelevantItems && *pRelevantItems;++pRelevantItems)
|
|
++nSLen;
|
|
|
|
pAdabasItems = new sal_Int32[nFLen + nSLen];
|
|
nFLen = 0;
|
|
for(pRelevantItems = pFirstRelevantItems;pRelevantItems && *pRelevantItems;++pRelevantItems)
|
|
pAdabasItems[nFLen++] = *pRelevantItems;
|
|
|
|
for(pRelevantItems = pSecondRelevantItems;pRelevantItems && *pRelevantItems;++pRelevantItems)
|
|
pAdabasItems[nFLen++] = *pRelevantItems;
|
|
|
|
}
|
|
pRelevantItems = pAdabasItems;
|
|
}
|
|
break;
|
|
case DST_JDBC: pRelevantItems = OJdbcDetailsPage::getDetailIds(); break;
|
|
case DST_ADO: pRelevantItems = OAdoDetailsPage::getDetailIds(); break;
|
|
case DST_ODBC: pRelevantItems = OOdbcDetailsPage::getDetailIds(); break;
|
|
case DST_DBASE: pRelevantItems = ODbaseDetailsPage::getDetailIds(); break;
|
|
case DST_TEXT: pRelevantItems = OTextDetailsPage::getDetailIds(); break;
|
|
case DST_CALC:
|
|
{
|
|
// spreadsheet currently has no options page
|
|
static sal_Int32 nRelevantIds[] = { 0 };
|
|
pRelevantItems = nRelevantIds;
|
|
}
|
|
break;
|
|
}
|
|
return pRelevantItems;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODbAdminDialog::fillDatasourceInfo(const SfxItemSet& _rSource, ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _rInfo)
|
|
{
|
|
// within the current "Info" sequence, replace the ones we can examine from the item set
|
|
// (we don't just fill a completely new sequence with our own items, but we preserve any properties unknown to
|
|
// us)
|
|
|
|
// first determine which of all the items are relevant for the data source (depends on the connection url)
|
|
const sal_Int32* pRelevantItems = getRelevantItems(_rSource);
|
|
DBG_ASSERT(pRelevantItems, "ODbAdminDialog::translateProperties: invalid item ids got from the page!");
|
|
|
|
// collect the translated property values for the relevant items
|
|
PropertyValueSet aRelevantSettings;
|
|
ConstMapInt2StringIterator aTranslation;
|
|
while (pRelevantItems && *pRelevantItems)
|
|
{
|
|
const SfxPoolItem* pCurrent = _rSource.GetItem(*pRelevantItems);
|
|
aTranslation = m_aIndirectPropTranslator.find(*pRelevantItems);
|
|
if (pCurrent && (m_aIndirectPropTranslator.end() != aTranslation))
|
|
aRelevantSettings.insert(PropertyValue(aTranslation->second, 0, implTranslateProperty(pCurrent), PropertyState_DIRECT_VALUE));
|
|
|
|
++pRelevantItems;
|
|
}
|
|
|
|
// now aRelevantSettings contains all the property values relevant for the current data source type,
|
|
// check the original sequence if it already contains any of these values (which have to be overwritten, then)
|
|
PropertyValue* pInfo = _rInfo.getArray();
|
|
PropertyValue aSearchFor;
|
|
sal_Int32 nObsoleteSetting = -1;
|
|
for (sal_Int32 i=0; i<_rInfo.getLength(); ++i, ++pInfo)
|
|
{
|
|
aSearchFor.Name = pInfo->Name;
|
|
PropertyValueSetIterator aOverwrittenSetting = aRelevantSettings.find(aSearchFor);
|
|
if (aRelevantSettings.end() != aOverwrittenSetting)
|
|
{ // the setting was present in the original sequence, and it is to be overwritten -> replace it
|
|
*pInfo = *aOverwrittenSetting;
|
|
aRelevantSettings.erase(aOverwrittenSetting);
|
|
}
|
|
|
|
if (0 == pInfo->Name.compareToAscii("JDBCDRV"))
|
|
{ // this is a compatibility setting, remove it from the sequence (it's replaced by JavaDriverClass)
|
|
nObsoleteSetting = i;
|
|
}
|
|
}
|
|
if (-1 != nObsoleteSetting)
|
|
::comphelper::removeElementAt(_rInfo, nObsoleteSetting);
|
|
|
|
// check which values are still left ('cause they were not present in the original sequence, but are to be set)
|
|
sal_Int32 nOldLength = _rInfo.getLength();
|
|
_rInfo.realloc(nOldLength + aRelevantSettings.size());
|
|
PropertyValue* pAppendValues = _rInfo.getArray() + nOldLength;
|
|
for ( ConstPropertyValueSetIterator aLoop = aRelevantSettings.begin();
|
|
aLoop != aRelevantSettings.end();
|
|
++aLoop, ++pAppendValues
|
|
)
|
|
{
|
|
*pAppendValues = *aLoop;
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
::rtl::OUString ODbAdminDialog::getUniqueName() const
|
|
{
|
|
::rtl::OUString sBase = String(ModuleRes(STR_DATASOURCE_DEFAULTNAME)).GetBuffer();
|
|
sBase += ::rtl::OUString(" ", 1, RTL_TEXTENCODING_ASCII_US);
|
|
for (sal_Int32 i=1; i<65635; ++i)
|
|
{
|
|
::rtl::OUString sCheck(sBase);
|
|
sCheck += ::rtl::OUString::valueOf(i);
|
|
|
|
// check if "all but the current" datasources aleady contain the to-be-checked name
|
|
if (m_aValidDatasources.end() != m_aValidDatasources.find(sCheck))
|
|
continue;
|
|
// check if the currently selected data source allows the new name
|
|
if (m_sCurrentDatasource.equals(sCheck))
|
|
continue;
|
|
|
|
// have a valid new name
|
|
return sCheck;
|
|
}
|
|
|
|
DBG_ERROR("ODbAdminDialog::getUniqueName: no free names!");
|
|
return ::rtl::OUString();
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
IMPL_LINK(ODbAdminDialog, OnNewDatasource, Window*, _pWindow)
|
|
{
|
|
::rtl::OUString sNewName = getUniqueName();
|
|
if (0 == sNewName.getLength())
|
|
return 1L; // no free names
|
|
|
|
// create a new datasource (not belonging to a context, yet)
|
|
Reference< XPropertySet > xFloatingDatasource = m_aDatasources.createNew(sNewName, GetInputSetImpl()->GetPool(), GetInputSetImpl()->GetRanges());
|
|
if (!xFloatingDatasource.is())
|
|
{
|
|
ShowServiceNotAvailableError(this, String(SERVICE_SDB_DATASOURCE), sal_True);
|
|
return 1L;
|
|
}
|
|
|
|
GetInputSetImpl()->ClearItem();
|
|
|
|
// insert a new entry for the new DS
|
|
m_aSelector.insertNew(sNewName);
|
|
// update our "all-but the selected ds" structure
|
|
m_aValidDatasources.insert(sNewName);
|
|
|
|
// and select this new entry
|
|
m_aSelector.select(sNewName);
|
|
implSelectDatasource(sNewName);
|
|
|
|
// enable the apply button
|
|
GetApplyButton()->Enable(sal_True);
|
|
|
|
SfxTabPage* pGeneralPage = GetTabPage(PAGE_GENERAL);
|
|
if (pGeneralPage)
|
|
pGeneralPage->GrabFocus();
|
|
|
|
return 0L;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
IMPL_LINK(ODbAdminDialog, OnDeleteDatasource, Window*, _pWindow)
|
|
{
|
|
::rtl::OUString sDeleteWhich = m_aSelector.getSelected();
|
|
|
|
if (NEW == m_aSelector.getSelectedState())
|
|
{
|
|
// insert the previously selected data source into our "all valid datasources" set
|
|
if (m_sCurrentDatasource.getLength()) // previous selection was not on a deleted data source
|
|
m_aValidDatasources.insert(m_sCurrentDatasource);
|
|
m_sCurrentDatasource = ::rtl::OUString();
|
|
|
|
m_aDatasources.deleted(sDeleteWhich);
|
|
m_aSelector.deleted(sDeleteWhich);
|
|
}
|
|
else
|
|
{
|
|
sal_Int32 nAccessKey = m_aDatasources.markDeleted(sDeleteWhich);
|
|
if (-1 == nAccessKey)
|
|
return 0L;
|
|
|
|
// mark it as deleted
|
|
m_aSelector.markDeleted(sDeleteWhich, nAccessKey);
|
|
// re-select it (to reset the pages so they reflect the new state)
|
|
implSelectDeleted(nAccessKey);
|
|
}
|
|
|
|
// mark the name as "available"
|
|
m_aValidDatasources.erase(sDeleteWhich);
|
|
|
|
// enable the apply button
|
|
GetApplyButton()->Enable(sal_True);
|
|
|
|
return 1L;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
IMPL_LINK(ODbAdminDialog, OnRestoreDatasource, Window*, _pWindow)
|
|
{
|
|
sal_Int32 nAccessKey = m_aSelector.getSelectedAccessKey();
|
|
::rtl::OUString sName;
|
|
if (m_aDatasources.restoreDeleted(nAccessKey, sName))
|
|
{ // successfully restore the item in the map
|
|
// -> restore it in the view, too
|
|
ODatasourceMap::ODatasourceInfo aInfo(m_aDatasources[sName]);
|
|
m_aSelector.restoreDeleted(nAccessKey, aInfo.isModified() ? MODIFIED : aInfo.isNew() ? NEW : CLEAN);
|
|
|
|
implSelectDatasource(sName);
|
|
}
|
|
else
|
|
{
|
|
ErrorBox aError(this, ModuleRes(ERR_COULDNOTRESTOREDS));
|
|
aError.Execute();
|
|
}
|
|
|
|
// enable the apply button
|
|
GetApplyButton()->Enable(sal_True);
|
|
|
|
return 0L;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
ODbAdminDialog::ApplyResult ODbAdminDialog::implApplyChanges(const sal_Bool _bActivateOnSuccess)
|
|
{
|
|
if (!PrepareLeaveCurrentPage())
|
|
{ // the page did not allow us to leave
|
|
return AR_KEEP;
|
|
}
|
|
|
|
ApplyResult eResult = AR_LEAVE_UNCHANGED;
|
|
|
|
// save the settings for the currently selected data source
|
|
if (m_aSelector.count() && (DELETED != m_aSelector.getSelectedState()))
|
|
{
|
|
::rtl::OUString sCurrentlySelected = m_aSelector.getSelected();
|
|
if (m_aDatasources[sCurrentlySelected]->isModified())
|
|
{
|
|
m_aDatasources.update(sCurrentlySelected, *pExampleSet);
|
|
String sNewName = m_aDatasources.adjustRealName(sCurrentlySelected);
|
|
String sOldName = sCurrentlySelected;
|
|
// the data source has not only been modified, but renamed, too
|
|
// -> adjust the selector and m_sCurrentDatasource
|
|
// (we are allowed to do this here, this is no part of the committment of the changes, it just
|
|
// leaves our structures in a consistent state for the real commitment)
|
|
if (!sNewName.Equals(sOldName))
|
|
{
|
|
// tell our selector window that the name has changed
|
|
m_aSelector.renamed(sOldName, sNewName);
|
|
// update our "current database"
|
|
m_sCurrentDatasource = sNewName;
|
|
|
|
// adjust the selection
|
|
implSelectDatasource(m_sCurrentDatasource);
|
|
}
|
|
}
|
|
}
|
|
|
|
// We allowed the user to freely rename/create/delete datasources, without committing anything ('til now).
|
|
// This could lead to conflicts: if datasource "A" was renamed to "B", and a new ds "A" created, then we
|
|
// would have to do the renaming before the creation. This would require us to analyze the changes in
|
|
// m_aDatasources for any such dependencies, which could be difficult (okay, I'm not willing to do it :)
|
|
// Instead we use another approach: If we encounter a conflict (a DS which can't be renamed or inserted),
|
|
// we save this entry and continue with the next one. This way, the ds causing the conflict should be handled
|
|
// first. After that, we do a new round, assuming that now the conflict is resolved.
|
|
// A disadvantage is that this may require O(n^2) rounds, but this is not really expensive ....
|
|
|
|
// first delete all datasources which were scheduled for deletion
|
|
for ( ODatasourceMap::Iterator aLoopDeleted = m_aDatasources.beginDeleted();
|
|
aLoopDeleted != m_aDatasources.endDeleted();
|
|
++aLoopDeleted
|
|
)
|
|
{
|
|
::rtl::OUString sDeleteWhich = aLoopDeleted->getOriginalName();
|
|
sal_Bool bOperationSuccess = sal_False;
|
|
try
|
|
{
|
|
m_xDynamicContext->revokeObject(sDeleteWhich);
|
|
bOperationSuccess = sal_True;
|
|
}
|
|
catch(Exception&) { }
|
|
if (bOperationSuccess)
|
|
{
|
|
eResult = AR_LEAVE_MODIFIED;
|
|
m_aSelector.deleted(aLoopDeleted->getAccessKey());
|
|
}
|
|
else
|
|
{
|
|
DBG_ERROR("ODbAdminDialog::implApplyChanges: could not delete a data source!");
|
|
// TODO: an error message
|
|
}
|
|
}
|
|
m_aDatasources.clearDeleted();
|
|
|
|
sal_Int32 nDelayed = 0;
|
|
sal_Int32 nLastRoundDelayed = -1;
|
|
// to ensure that we're not looping 'til death: If this doesn't change within one round, the DatabaseContext
|
|
// is not in the state as this dialog started anymore. This means somebody else did some renamings
|
|
// or insertings, causing us conflicts now.
|
|
|
|
do
|
|
{
|
|
if (nLastRoundDelayed == nDelayed)
|
|
{
|
|
DBG_ERROR("ODbAdminDialog::implApplyChanges: somebody tampered with the context!");
|
|
// TODO: error handling
|
|
break;
|
|
}
|
|
|
|
// reset the counter
|
|
nLastRoundDelayed = nDelayed;
|
|
nDelayed = 0;
|
|
|
|
// propagate all the settings made to the appropriate data source, and add/drop/rename data sources
|
|
for ( ODatasourceMap::Iterator aLoop = m_aDatasources.begin();
|
|
aLoop != m_aDatasources.end();
|
|
++aLoop
|
|
)
|
|
{
|
|
// nothing to do if no modifications were done
|
|
if (aLoop->isModified())
|
|
{
|
|
Reference< XPropertySet > xDatasource = aLoop->getDatasource();
|
|
if (xDatasource.is())
|
|
{
|
|
eResult = AR_LEAVE_MODIFIED;
|
|
// we changes something
|
|
|
|
// put the remembered settings into the property set
|
|
translateProperties(*aLoop->getModifications(), xDatasource);
|
|
|
|
::rtl::OUString sName = aLoop->getName();
|
|
DBG_ASSERT(sName.equals(aLoop->getRealName()), "ODbAdminDialog::implApplyChanges: invalid name/realname combination!");
|
|
// these both names shouldn't be diefferent here anymore
|
|
::rtl::OUString sOriginalName = aLoop->getOriginalName();
|
|
|
|
// if we need a new name, check for conflicts
|
|
if (aLoop->isRenamed() || aLoop->isNew())
|
|
{
|
|
sal_Bool bAlreadyHaveNewName = sal_True;
|
|
try
|
|
{
|
|
bAlreadyHaveNewName = m_xDatabaseContext->hasByName(sName);
|
|
}
|
|
catch(RuntimeException&) { }
|
|
if (bAlreadyHaveNewName)
|
|
{
|
|
++nDelayed;
|
|
continue;
|
|
// | <---------------- continue with the next data source
|
|
}
|
|
|
|
if (aLoop->isRenamed())
|
|
{
|
|
// remove the object
|
|
sal_Bool bOperationSuccess = sal_False;
|
|
try
|
|
{
|
|
m_xDynamicContext->revokeObject(sOriginalName);
|
|
bOperationSuccess = sal_True;
|
|
}
|
|
catch(Exception&) { }
|
|
if (!bOperationSuccess)
|
|
{
|
|
DBG_ERROR("ODbAdminDialog::implApplyChanges: data source was renamed, but could not remove it (to insert it under a new name)!");
|
|
// TODO: an error message
|
|
}
|
|
}
|
|
|
|
// (re)insert the object under the new name
|
|
sal_Bool bOperationSuccess = sal_False;
|
|
try
|
|
{
|
|
m_xDynamicContext->registerObject(sName, xDatasource.get());
|
|
bOperationSuccess = sal_True;
|
|
}
|
|
catch(Exception&) { }
|
|
if (bOperationSuccess)
|
|
{
|
|
// everything's ok ...
|
|
// no need to flush the object anymore, this is done automatically upon insertion
|
|
}
|
|
else if (aLoop->isRenamed())
|
|
{
|
|
// oops ... we removed the ds, but could not re-insert it
|
|
// try to prevent data loss
|
|
DBG_ERROR("ODbAdminDialog::implApplyChanges: removed the entry, but could not re-insert it!");
|
|
// we're going to re-insert the object under it's old name
|
|
bOperationSuccess = sal_False;
|
|
try
|
|
{
|
|
m_xDynamicContext->registerObject(sOriginalName, xDatasource.get());
|
|
bOperationSuccess = sal_True;
|
|
}
|
|
catch(Exception&) { }
|
|
DBG_ASSERT(bOperationSuccess, "ODbAdminDialog::implApplyChanges: could not insert it under the old name, too ... no we have a data loss!");
|
|
}
|
|
|
|
// reset the item, so in case we need an extra round (because of delayed items) it
|
|
// won't be included anymore
|
|
m_aDatasources.clearModifiedFlag(sName);
|
|
// and tell the selector the new state
|
|
m_aSelector.flushed(sName);
|
|
|
|
continue;
|
|
// | <------------ continue with the next data source
|
|
}
|
|
|
|
// We're here if the data source was not renamed, not deleted and is not new. Just flush it.
|
|
Reference< XFlushable > xFlushDatasource(xDatasource, UNO_QUERY);
|
|
if (!xFlushDatasource.is())
|
|
{
|
|
DBG_ERROR("ODbAdminDialog::implApplyChanges: the datasource should be flushable!");
|
|
continue;
|
|
}
|
|
|
|
try
|
|
{
|
|
xFlushDatasource->flush();
|
|
}
|
|
catch(RuntimeException&)
|
|
{
|
|
DBG_ERROR("ODbAdminDialog::implApplyChanges: caught an exception whild flushing the data source's data!");
|
|
}
|
|
// reset the item, so in case we need an extra round (because of delayed items) it
|
|
// won't be included anymore
|
|
m_aDatasources.clearModifiedFlag(sName);
|
|
// and tell the selector the new state
|
|
m_aSelector.flushed(sName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
while (nDelayed);
|
|
|
|
// reset some meta-data-items in the the example set
|
|
// 00/11/10 - 80185 - FS
|
|
pExampleSet->Put(SfxBoolItem(DSID_NEWDATASOURCE, sal_False));
|
|
pExampleSet->Put(SfxBoolItem(DSID_DELETEDDATASOURCE, sal_False));
|
|
|
|
// disable the apply button
|
|
GetApplyButton()->Enable(sal_False);
|
|
|
|
|
|
if (_bActivateOnSuccess)
|
|
ShowPage(GetCurPageId());
|
|
// This does the usual ActivatePage, so the pages can save their current status.
|
|
// This way, next time they're asked what has changed since now and here, they really
|
|
// can compare with the status they have _now_ (not the one they had before this apply call).
|
|
|
|
return eResult;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
IMPL_LINK(ODbAdminDialog, OnAsyncApplyChanges, void*, EMPTYARG)
|
|
{
|
|
SfxTabDialog::Ok();
|
|
if (AR_KEEP != implApplyChanges())
|
|
{
|
|
ShowPage(PAGE_QUERYADMINISTRATION);
|
|
return 1L;
|
|
}
|
|
return 0L;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
IMPL_LINK(ODbAdminDialog, OnApplyChanges, PushButton*, EMPTYARG)
|
|
{
|
|
implApplyChanges();
|
|
return 0L;
|
|
}
|
|
|
|
//=========================================================================
|
|
//= ODatasourceSelector
|
|
//=========================================================================
|
|
//-------------------------------------------------------------------------
|
|
ODatasourceSelector::ODatasourceSelector(Window* _pParent, const ResId& _rResId)
|
|
:Window(_pParent, _rResId)
|
|
,m_aDatasourceList (this, ResId(LB_DATASOURCES))
|
|
,m_aNewDatasource (this, ResId(PB_NEW_DATASOURCE))
|
|
{
|
|
FreeResource();
|
|
|
|
m_aDatasourceList.EnableClipSiblings(sal_True);
|
|
m_aNewDatasource.SetClickHdl(LINK(this, ODatasourceSelector, OnButtonPressed));
|
|
|
|
SetStyle((GetStyle() | WB_TABSTOP | WB_DIALOGCONTROL) & ~WB_NODIALOGCONTROL);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
ODatasourceSelector::~ODatasourceSelector()
|
|
{
|
|
for (sal_Int32 i=0; i<m_aDatasourceList.GetEntryCount(); ++i)
|
|
delete reinterpret_cast<EntryData*>(m_aDatasourceList.GetEntryData(i));
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
sal_Int32 ODatasourceSelector::getImageId(DatasourceState _eState)
|
|
{
|
|
switch (_eState)
|
|
{
|
|
case CLEAN: return IMG_DATABASE;
|
|
case MODIFIED: return IMG_DATABASE_MODIFIED;
|
|
case NEW: return IMG_DATABASE_NEW;
|
|
case DELETED: return IMG_DATABASE_DELETED;
|
|
}
|
|
DBG_ERROR("ODatasourceSelector::getImage: invalid state");
|
|
return 0;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
DatasourceState ODatasourceSelector::getEntryState(sal_Int32 _nPos) const
|
|
{
|
|
EntryData* pData = static_cast<EntryData*>(m_aDatasourceList.GetEntryData(_nPos));
|
|
if (!pData)
|
|
return CLEAN;
|
|
return pData->eState;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceSelector::setEntryState(sal_Int32 _nPos, DatasourceState _eState)
|
|
{
|
|
EntryData* pData = static_cast<EntryData*>(m_aDatasourceList.GetEntryData(_nPos));
|
|
if (pData ? _eState == pData->eState : CLEAN == _eState)
|
|
// nothing changed
|
|
return;
|
|
|
|
// to restore the selection afterwards ...
|
|
sal_Bool bWasSelected = m_aDatasourceList.GetSelectEntryPos() == _nPos;
|
|
|
|
String sName = m_aDatasourceList.GetEntry(_nPos);
|
|
m_aDatasourceList.RemoveEntry(_nPos);
|
|
_nPos = m_aDatasourceList.InsertEntry(sName, Image(ModuleRes(getImageId(_eState))), _nPos);
|
|
|
|
if (!pData)
|
|
pData = new EntryData;
|
|
pData->eState = _eState;
|
|
m_aDatasourceList.SetEntryData(_nPos, static_cast<void*>(pData));
|
|
|
|
if (bWasSelected)
|
|
m_aDatasourceList.SelectEntryPos(_nPos, sal_True);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
sal_Int32 ODatasourceSelector::getAccessKey(sal_Int32 _nPos) const
|
|
{
|
|
EntryData* pData = static_cast<EntryData*>(m_aDatasourceList.GetEntryData(_nPos));
|
|
if (!pData)
|
|
return 0; // entry is in default state
|
|
return pData->nAccessKey;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceSelector::setAccessKey(sal_Int32 _nPos, sal_Int32 _nAccessKey)
|
|
{
|
|
EntryData* pData = static_cast<EntryData*>(m_aDatasourceList.GetEntryData(_nPos));
|
|
DBG_ASSERT(pData, "ODatasourceSelector::setAccessKey: to be called for entry in DELETED state only!");
|
|
if (!pData)
|
|
{
|
|
pData = new EntryData(DELETED);
|
|
m_aDatasourceList.SetEntryData(_nPos, static_cast<void*>(pData));
|
|
}
|
|
pData->nAccessKey = _nAccessKey;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceSelector::implDeleted(sal_Int32 _nPos)
|
|
{
|
|
// remove the entry
|
|
m_aDatasourceList.RemoveEntry(_nPos);
|
|
|
|
// select the one below (or above, if it was the last one)
|
|
if (_nPos >= m_aDatasourceList.GetEntryCount())
|
|
_nPos = m_aDatasourceList.GetEntryCount() - 1;
|
|
m_aDatasourceList.SelectEntryPos(_nPos);
|
|
// call the select handler to propagate the new selection
|
|
m_aDatasourceList.GetSelectHdl().Call(&m_aDatasourceList);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceSelector::deleted(sal_Int32 _nAccessKey)
|
|
{
|
|
sal_Int32 nPos = getDeletedEntryPos(_nAccessKey);
|
|
if (-1 != nPos)
|
|
implDeleted(nPos);
|
|
else
|
|
DBG_ERROR("ODatasourceSelector::deleted: no deleted entry wiht that name!");
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceSelector::deleted(const String& _rName)
|
|
{
|
|
sal_Int32 nPos = getValidEntryPos(_rName);
|
|
if (-1 != nPos)
|
|
implDeleted(nPos);
|
|
else
|
|
DBG_ERROR("ODatasourceSelector::deleted: no non-deleted entry wiht that name!");
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceSelector::restoreDeleted(sal_Int32 _nAccessKey, DatasourceState _eState)
|
|
{
|
|
DBG_ASSERT(DELETED != _eState, "ODatasourceSelector::restoreDeleted: invalid datasource state!");
|
|
sal_Int32 nPos = getDeletedEntryPos(_nAccessKey);
|
|
if (-1 == nPos)
|
|
{
|
|
DBG_ERROR("ODatasourceSelector::restoreDeleted: invalid access key!");
|
|
return;
|
|
}
|
|
DBG_ASSERT(-1 == getValidEntryPos(m_aDatasourceList.GetEntry(nPos)),
|
|
"ODatasourceSelector::restoreDeleted: already have a not-deleted entry with that name!");
|
|
|
|
setEntryState(nPos, _eState);
|
|
setAccessKey(nPos, 0);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceSelector::markDeleted(const String& _rName, sal_Int32 _nAccessKey)
|
|
{
|
|
sal_Int32 nPos = getValidEntryPos(_rName);
|
|
DBG_ASSERT(-1 != nPos, "ODatasourceSelector::markDeleted: no non-deleted entry wiht that name!");
|
|
setEntryState(nPos, DELETED);
|
|
DBG_ASSERT(_nAccessKey, "ODatasourceSelector::markDeleted: invalid access key!");
|
|
DBG_ASSERT(-1 == getDeletedEntryPos(_nAccessKey), "ODatasourceSelector::modified: already have a deleted entry with this access key!");
|
|
setAccessKey(nPos, _nAccessKey);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceSelector::modified(const String& _sName)
|
|
{
|
|
sal_Int32 nPos = getValidEntryPos(_sName);
|
|
DBG_ASSERT(-1 != nPos, "ODatasourceSelector::modified: invalid name!");
|
|
setEntryState(nPos, MODIFIED);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
sal_Int32 ODatasourceSelector::getDeletedEntryPos(sal_Int32 _nAccessKey)
|
|
{
|
|
for (sal_Int32 i=0; i<m_aDatasourceList.GetEntryCount(); ++i)
|
|
if ((DELETED == getEntryState(i)) && (_nAccessKey == getAccessKey(i)))
|
|
return i;
|
|
|
|
return -1;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
sal_Int32 ODatasourceSelector::getValidEntryPos(const String& _rName)
|
|
{
|
|
// first guess
|
|
sal_Int32 nPos = m_aDatasourceList.GetEntryPos(_rName);
|
|
while (DELETED == getEntryState(nPos))
|
|
{
|
|
// unfortunally we no such thing as "GetEntryPos(<name>, <startindex>) ... -> search manually
|
|
while ((++nPos<m_aDatasourceList.GetEntryCount()))
|
|
if (m_aDatasourceList.GetEntry(nPos).Equals(_rName))
|
|
// have a candidate
|
|
break;
|
|
if (nPos>=m_aDatasourceList.GetEntryCount())
|
|
// did not find another candidate
|
|
return -1;
|
|
}
|
|
return nPos;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceSelector::renamed(const String& _rOldName, const String& _rNewName)
|
|
{
|
|
sal_Int32 nPos = getValidEntryPos(_rOldName);
|
|
DBG_ASSERT(-1 != nPos, "ODatasourceSelector::renamed: invalid old name!");
|
|
|
|
// save the info about the entry
|
|
DatasourceState eState = getEntryState(nPos);
|
|
EntryData* pData = static_cast<EntryData*>(m_aDatasourceList.GetEntryData(nPos));
|
|
|
|
m_aDatasourceList.RemoveEntry(nPos);
|
|
nPos = m_aDatasourceList.InsertEntry(_rNewName, Image(ModuleRes(getImageId(eState))), nPos);
|
|
|
|
// restore the info about the entry
|
|
m_aDatasourceList.SetEntryData(nPos, static_cast<void*>(pData));
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
sal_Int32 ODatasourceSelector::insert(const String& _rName)
|
|
{
|
|
sal_Int16 nPos = m_aDatasourceList.InsertEntry(_rName, Image(ModuleRes(getImageId(CLEAN))));
|
|
m_aDatasourceList.SetEntryData(nPos, static_cast<void*>(NULL));
|
|
return nPos;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceSelector::flushed(const String& _rName)
|
|
{
|
|
sal_Int32 nPos = getValidEntryPos(_rName);
|
|
DBG_ASSERT(-1 != nPos, "ODatasourceSelector::flushed: invalid data source name!");
|
|
|
|
setEntryState(nPos, CLEAN);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceSelector::insertNew(const String& _rName)
|
|
{
|
|
// insert the new entry with the appropriate image
|
|
sal_Int16 nPos = m_aDatasourceList.InsertEntry(_rName, Image(ModuleRes(getImageId(NEW))));
|
|
m_aDatasourceList.SetEntryData(nPos, static_cast<void*>(new EntryData(NEW)));
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceSelector::select(const String& _rName)
|
|
{
|
|
sal_Int32 nPos = getValidEntryPos(_rName);
|
|
DBG_ASSERT(-1 != nPos, "ODatasourceSelector::select: invalid data source name (maybe deleted or not existent)!");
|
|
|
|
m_aDatasourceList.SelectEntryPos(nPos);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceSelector::select(sal_Int32 _nAccessKey)
|
|
{
|
|
sal_Int32 nPos = getDeletedEntryPos(_nAccessKey);
|
|
DBG_ASSERT(-1 != nPos, "ODatasourceSelector::select: invalid access key (have no such entry)!");
|
|
|
|
m_aDatasourceList.SelectEntryPos(nPos);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
long ODatasourceSelector::Notify(NotifyEvent& _rNEvt)
|
|
{
|
|
sal_Bool bHandled = sal_False;
|
|
|
|
switch (_rNEvt.GetType())
|
|
{
|
|
case EVENT_COMMAND:
|
|
{
|
|
const CommandEvent* pCommand = _rNEvt.GetCommandEvent();
|
|
if (COMMAND_CONTEXTMENU == pCommand->GetCommand())
|
|
{
|
|
// check if the context menu request occured in the listbox
|
|
if (m_aDatasourceList.IsChild(_rNEvt.GetWindow()))
|
|
{
|
|
// calc the pos where to open the menu
|
|
Point aWhere;
|
|
if (pCommand->IsMouseEvent())
|
|
{
|
|
aWhere = pCommand->GetMousePosPixel();
|
|
}
|
|
else
|
|
{ // context menu via keyboard -> assume the center of the currently selected data source
|
|
// TODO: use another class instead of the listbox (e.g. a SvTreeListBox). We have no change
|
|
// to get an item rect or the item height or something like that from a listbox ...
|
|
aWhere = Point(0, 0);
|
|
}
|
|
PopupMenu aMenu(ModuleRes(MENU_DATASOURCELIST_POPUP));
|
|
aMenu.SetMenuFlags(aMenu.GetMenuFlags() | MENU_FLAG_HIDEDISABLEDENTRIES);
|
|
|
|
// we don't really know if adding datasources is allowed currently. But an other instance does
|
|
// (the dialog), and this instance en- or disables our "new datasource" button
|
|
aMenu.EnableItem(MID_NEW_DATASOURCE, m_aNewDatasource.IsEnabled());
|
|
|
|
USHORT nSelectionPos = m_aDatasourceList.GetSelectEntryPos();
|
|
DatasourceState eState = getEntryState(nSelectionPos);
|
|
aMenu.EnableItem(MID_DELETE_DATASOURCE, (DELETED != eState && nSelectionPos != LISTBOX_ENTRY_NOTFOUND));
|
|
aMenu.EnableItem(MID_RESTORE_DATASOURCE, DELETED == eState);
|
|
|
|
switch (aMenu.Execute(_rNEvt.GetWindow(), aWhere))
|
|
{
|
|
case MID_NEW_DATASOURCE:
|
|
m_aNewHandler.Call(this);
|
|
break;
|
|
case MID_DELETE_DATASOURCE:
|
|
m_aDeleteHandler.Call(this);
|
|
break;
|
|
case MID_RESTORE_DATASOURCE:
|
|
m_aRestoreHandler.Call(this);
|
|
break;
|
|
}
|
|
bHandled = sal_True;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case EVENT_KEYINPUT:
|
|
{
|
|
const KeyEvent* pKeyEvent = _rNEvt.GetKeyEvent();
|
|
const KeyCode& rKeyCode = pKeyEvent->GetKeyCode();
|
|
if ((0 == rKeyCode.GetAllModifier()) && ((sal_Int32)-1 != m_aDatasourceList.GetSelectEntryPos()))
|
|
switch (rKeyCode.GetCode())
|
|
{
|
|
case KEY_DELETE:
|
|
if (getAccessKey(m_aDatasourceList.GetSelectEntryPos()) <= 0)
|
|
// for a non-deleted data source, call the delete handler
|
|
m_aDeleteHandler.Call(this);
|
|
bHandled = sal_True;
|
|
break;
|
|
case KEY_INSERT:
|
|
m_aNewHandler.Call(this);
|
|
bHandled = sal_True;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return bHandled ? 1 : Window::Notify(_rNEvt);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void ODatasourceSelector::Resize()
|
|
{
|
|
Window::Resize();
|
|
Size aSize = GetSizePixel();
|
|
|
|
// adjust the width of the button
|
|
sal_Int32 nButtonHeight = m_aNewDatasource.GetSizePixel().Height();
|
|
m_aNewDatasource.SetSizePixel(Size(aSize.Width(), nButtonHeight));
|
|
|
|
// adjust width/height of the listbox
|
|
m_aDatasourceList.SetPosPixel(Point(0, nButtonHeight));
|
|
m_aDatasourceList.SetSizePixel(Size(aSize.Width(), aSize.Height() - nButtonHeight));
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
IMPL_LINK(ODatasourceSelector, OnButtonPressed, Button*, EMPTYARG)
|
|
{
|
|
return m_aNewHandler.Call(this);
|
|
}
|
|
|
|
//.........................................................................
|
|
} // namespace dbaui
|
|
//.........................................................................
|
|
|
|
/*************************************************************************
|
|
* history:
|
|
* $Log: not supported by cvs2svn $
|
|
* Revision 1.39 2001/03/15 08:23:00 fs
|
|
* cppuhelper/extract -> comphelper/extract
|
|
*
|
|
* Revision 1.38 2001/03/13 10:21:34 fs
|
|
* #84827# #84908# allow changes to be applied without re-initializing the page (which could lead to opening a connection)
|
|
*
|
|
* Revision 1.37 2001/03/05 15:32:14 fs
|
|
* #84620# remove the reset button
|
|
*
|
|
* Revision 1.36 2001/02/20 13:18:26 fs
|
|
* #84151# when entering the queries page for a new data source, apply the changes asynchronously
|
|
*
|
|
* Revision 1.35 2001/02/07 10:05:43 fs
|
|
* introduce the connection option 'SystemDriverSettings'
|
|
*
|
|
* Revision 1.34 2001/02/07 09:32:15 fs
|
|
* renamed JDBCDRV to JavaDriverClass
|
|
*
|
|
* Revision 1.33 2001/02/05 14:00:08 fs
|
|
* #83430# applyChanges / isApplyable
|
|
*
|
|
* Revision 1.32 2001/01/29 16:16:08 nn
|
|
* added DST_CALC
|
|
*
|
|
* Revision 1.31 2001/01/26 16:13:26 fs
|
|
* added the query administration page
|
|
*
|
|
* Revision 1.30 2001/01/26 06:59:12 fs
|
|
* some basics for the query administration page - not enabled yet
|
|
*
|
|
* Revision 1.29 2001/01/17 09:17:27 fs
|
|
* #82627# implApplyChanges: do an ShowPage after applying the changes
|
|
*
|
|
* Revision 1.28 2001/01/04 11:23:01 fs
|
|
* #81485# +ADO page
|
|
*
|
|
* Revision 1.27 2000/12/20 13:28:06 fs
|
|
* #81761# dis-/enable the apply button the same way as the ok button
|
|
*
|
|
* Revision 1.26 2000/12/14 08:23:14 fs
|
|
* #81938# make the ThousandsSeparator persistent
|
|
*
|
|
* Revision 1.25 2000/12/07 14:16:41 fs
|
|
* #80186# reset the 'password required' flag when changing the data source type to one without passwords
|
|
*
|
|
* Revision 1.24 2000/12/03 10:29:23 fs
|
|
* #79820# SetSavePassword on the login dialog
|
|
*
|
|
* Revision 1.23 2000/11/30 08:32:30 fs
|
|
* #80003# changed some sal_uInt16 to sal_Int32 (need some -1's)
|
|
*
|
|
* Revision 1.22 2000/11/28 13:47:59 fs
|
|
* #80152# implApplyChanges: check the entry count of the listbox
|
|
*
|
|
* Revision 1.21 2000/11/28 11:41:42 oj
|
|
* #80827# check dbroot if dbconfig failed
|
|
*
|
|
* Revision 1.0 20.09.00 10:55:58 fs
|
|
************************************************************************/
|
|
|