summaryrefslogtreecommitdiffstats
path: root/dbaccess/source/ui/misc
diff options
context:
space:
mode:
Diffstat (limited to 'dbaccess/source/ui/misc')
-rw-r--r--dbaccess/source/ui/misc/DExport.cxx839
-rw-r--r--dbaccess/source/ui/misc/HtmlReader.cxx481
-rw-r--r--dbaccess/source/ui/misc/RowSetDrop.cxx247
-rw-r--r--dbaccess/source/ui/misc/RtfReader.cxx309
-rw-r--r--dbaccess/source/ui/misc/TableCopyHelper.cxx306
-rw-r--r--dbaccess/source/ui/misc/TokenWriter.cxx967
-rw-r--r--dbaccess/source/ui/misc/UITools.cxx1371
-rw-r--r--dbaccess/source/ui/misc/UpdateHelperImpl.hxx74
-rw-r--r--dbaccess/source/ui/misc/WCPage.cxx325
-rw-r--r--dbaccess/source/ui/misc/WColumnSelect.cxx403
-rw-r--r--dbaccess/source/ui/misc/WCopyTable.cxx1553
-rw-r--r--dbaccess/source/ui/misc/WExtendPages.cxx62
-rw-r--r--dbaccess/source/ui/misc/WNameMatch.cxx330
-rw-r--r--dbaccess/source/ui/misc/WTypeSelect.cxx416
-rw-r--r--dbaccess/source/ui/misc/asyncmodaldialog.cxx91
-rw-r--r--dbaccess/source/ui/misc/charsets.cxx131
-rw-r--r--dbaccess/source/ui/misc/controllerframe.cxx389
-rw-r--r--dbaccess/source/ui/misc/databaseobjectview.cxx281
-rw-r--r--dbaccess/source/ui/misc/datasourceconnector.cxx199
-rw-r--r--dbaccess/source/ui/misc/dbaundomanager.cxx324
-rw-r--r--dbaccess/source/ui/misc/dbsubcomponentcontroller.cxx605
-rw-r--r--dbaccess/source/ui/misc/defaultobjectnamecheck.cxx140
-rw-r--r--dbaccess/source/ui/misc/dsmeta.cxx165
-rw-r--r--dbaccess/source/ui/misc/imageprovider.cxx192
-rw-r--r--dbaccess/source/ui/misc/indexcollection.cxx328
-rw-r--r--dbaccess/source/ui/misc/linkeddocuments.cxx350
-rw-r--r--dbaccess/source/ui/misc/propertystorage.cxx106
-rw-r--r--dbaccess/source/ui/misc/singledoccontroller.cxx172
-rw-r--r--dbaccess/source/ui/misc/stringlistitem.cxx62
29 files changed, 11218 insertions, 0 deletions
diff --git a/dbaccess/source/ui/misc/DExport.cxx b/dbaccess/source/ui/misc/DExport.cxx
new file mode 100644
index 0000000000..a1e02b8745
--- /dev/null
+++ b/dbaccess/source/ui/misc/DExport.cxx
@@ -0,0 +1,839 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <DExport.hxx>
+#include <core_resource.hxx>
+
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/util/NumberFormat.hpp>
+#include <com/sun/star/util/XNumberFormatTypes.hpp>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <connectivity/dbconversion.hxx>
+#include <sal/log.hxx>
+#include <sfx2/sfxhtml.hxx>
+#include <svl/numuno.hxx>
+#include <connectivity/dbtools.hxx>
+#include <TypeInfo.hxx>
+#include <FieldDescriptions.hxx>
+#include <UITools.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <WCopyTable.hxx>
+#include <unotools/syslocale.hxx>
+#include <svl/numformat.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/FValue.hxx>
+#include <com/sun/star/sdb/application/CopyTableOperation.hpp>
+#include <sqlmessage.hxx>
+#include "UpdateHelperImpl.hxx"
+#include <cppuhelper/exc_hlp.hxx>
+
+using namespace dbaui;
+using namespace utl;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::awt;
+
+namespace CopyTableOperation = ::com::sun::star::sdb::application::CopyTableOperation;
+
+// ODatabaseExport
+ODatabaseExport::ODatabaseExport(sal_Int32 nRows,
+ TPositions&&_rColumnPositions,
+ const Reference< XNumberFormatter >& _rxNumberF,
+ const Reference< css::uno::XComponentContext >& _rxContext,
+ const TColumnVector* pList,
+ const OTypeInfoMap* _pInfoMap,
+ bool _bAutoIncrementEnabled,
+ SvStream& _rInputStream)
+ :m_vColumnPositions(std::move(_rColumnPositions))
+ ,m_aDestColumns(true)
+ ,m_xFormatter(_rxNumberF)
+ ,m_xContext(_rxContext)
+ ,m_pFormatter(nullptr)
+ ,m_rInputStream( _rInputStream )
+ ,m_pColumnList(pList)
+ ,m_pInfoMap(_pInfoMap)
+ ,m_nColumnPos(0)
+ ,m_nRows(1)
+ ,m_nRowCount(0)
+ ,m_bError(false)
+ ,m_bInTbl(false)
+ ,m_bHead(true)
+ ,m_bDontAskAgain(false)
+ ,m_bIsAutoIncrement(_bAutoIncrementEnabled)
+ ,m_bFoundTable(false)
+ ,m_bCheckOnly(false)
+ ,m_bAppendFirstLine(false)
+{
+ m_nRows += nRows;
+ sal_Int32 nCount = 0;
+ for(const std::pair<sal_Int32,sal_Int32> & rPair : m_vColumnPositions)
+ if ( rPair.first != COLUMN_POSITION_NOT_FOUND )
+ ++nCount;
+
+ m_vColumnSize.resize(nCount);
+ m_vNumberFormat.resize(nCount);
+ for(sal_Int32 i=0;i<nCount;++i)
+ {
+ m_vColumnSize[i] = 0;
+ m_vNumberFormat[i] = 0;
+ }
+
+ try
+ {
+ SvtSysLocale aSysLocale;
+ m_aLocale = aSysLocale.GetLanguageTag().getLocale();
+ }
+ catch(Exception&)
+ {
+ }
+
+ SetColumnTypes(pList,_pInfoMap);
+}
+
+ODatabaseExport::ODatabaseExport(const SharedConnection& _rxConnection,
+ const Reference< XNumberFormatter >& _rxNumberF,
+ const Reference< css::uno::XComponentContext >& _rxContext,
+ SvStream& _rInputStream)
+ :m_aDestColumns(_rxConnection->getMetaData().is() && _rxConnection->getMetaData()->supportsMixedCaseQuotedIdentifiers())
+ ,m_xConnection(_rxConnection)
+ ,m_xFormatter(_rxNumberF)
+ ,m_xContext(_rxContext)
+ ,m_pFormatter(nullptr)
+ ,m_rInputStream( _rInputStream )
+ ,m_pColumnList(nullptr)
+ ,m_pInfoMap(nullptr)
+ ,m_nColumnPos(0)
+ ,m_nRows(1)
+ ,m_nRowCount(0)
+ ,m_bError(false)
+ ,m_bInTbl(false)
+ ,m_bHead(true)
+ ,m_bDontAskAgain(false)
+ ,m_bIsAutoIncrement(false)
+ ,m_bFoundTable(false)
+ ,m_bCheckOnly(false)
+ ,m_bAppendFirstLine(false)
+{
+ try
+ {
+ SvtSysLocale aSysLocale;
+ m_aLocale = aSysLocale.GetLanguageTag().getLocale();
+ }
+ catch(Exception&)
+ {
+ }
+
+ Reference<XTablesSupplier> xTablesSup(m_xConnection,UNO_QUERY);
+ if(xTablesSup.is())
+ m_xTables = xTablesSup->getTables();
+
+ Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData();
+ Reference<XResultSet> xSet = xMeta.is() ? xMeta->getTypeInfo() : Reference<XResultSet>();
+ if(xSet.is())
+ {
+ ::connectivity::ORowSetValue aValue;
+ std::vector<sal_Int32> aTypes;
+ std::vector<bool> aNullable;
+ Reference<XResultSetMetaData> xResultSetMetaData = Reference<XResultSetMetaDataSupplier>(xSet,UNO_QUERY_THROW)->getMetaData();
+ Reference<XRow> xRow(xSet,UNO_QUERY_THROW);
+ while(xSet->next())
+ {
+ if ( aTypes.empty() )
+ {
+ sal_Int32 nCount = xResultSetMetaData->getColumnCount();
+ if ( nCount < 1 )
+ nCount = 18;
+ aTypes.reserve(nCount+1);
+ aNullable.reserve(nCount+1);
+ aTypes.push_back(-1);
+ aNullable.push_back(false);
+ for (sal_Int32 j = 1; j <= nCount ; ++j)
+ {
+ aNullable.push_back(xResultSetMetaData->isNullable(j) != ColumnValue::NO_NULLS );
+ aTypes.push_back(xResultSetMetaData->getColumnType(j));
+ }
+ }
+
+ sal_Int32 nPos = 1;
+ OSL_ENSURE((nPos) < static_cast<sal_Int32>(aTypes.size()),"aTypes: Illegal index for vector");
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ OUString sTypeName = aValue.getString();
+ ++nPos;
+ OSL_ENSURE((nPos) < static_cast<sal_Int32>(aTypes.size()),"aTypes: Illegal index for vector");
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ sal_Int32 nType = aValue.getInt32();
+ ++nPos;
+
+ if( nType == DataType::VARCHAR )
+ {
+ m_pTypeInfo = std::make_shared<OTypeInfo>();
+
+ m_pTypeInfo->aTypeName = sTypeName;
+ m_pTypeInfo->nType = nType;
+
+ OSL_ENSURE((nPos) < static_cast<sal_Int32>(aTypes.size()),"aTypes: Illegal index for vector");
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->nPrecision = aValue.getInt32();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); //LiteralPrefix
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); //LiteralSuffix
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->aCreateParams = aValue.getString();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->bNullable = aValue.getInt32() == ColumnValue::NULLABLE;
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ // bCaseSensitive
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->nSearchType = aValue.getInt16();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ // bUnsigned
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->bCurrency = aValue.getBool();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->bAutoIncrement = aValue.getBool();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->aLocalTypeName = aValue.getString();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->nMinimumScale = aValue.getInt16();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ m_pTypeInfo->nMaximumScale = aValue.getInt16();
+ nPos = 18;
+ aValue.fill(nPos,aTypes[nPos],xRow);
+ m_pTypeInfo->nNumPrecRadix = aValue.getInt32();
+
+ // check if values are less than zero like it happens in a oracle jdbc driver
+ if( m_pTypeInfo->nPrecision < 0)
+ m_pTypeInfo->nPrecision = 0;
+ if( m_pTypeInfo->nMinimumScale < 0)
+ m_pTypeInfo->nMinimumScale = 0;
+ if( m_pTypeInfo->nMaximumScale < 0)
+ m_pTypeInfo->nMaximumScale = 0;
+ if( m_pTypeInfo->nNumPrecRadix <= 1)
+ m_pTypeInfo->nNumPrecRadix = 10;
+ break;
+ }
+ }
+ }
+ if ( !m_pTypeInfo )
+ m_pTypeInfo = std::make_shared<OTypeInfo>();
+}
+
+ODatabaseExport::~ODatabaseExport()
+{
+ m_pFormatter = nullptr;
+ for (auto const& destColumn : m_aDestColumns)
+ delete destColumn.second;
+ m_vDestVector.clear();
+ m_aDestColumns.clear();
+}
+
+void ODatabaseExport::insertValueIntoColumn()
+{
+ if(m_nColumnPos >= sal_Int32(m_vDestVector.size()))
+ return;
+
+ OFieldDescription* pField = m_vDestVector[m_nColumnPos]->second;
+ if(!pField)
+ return;
+
+ sal_Int32 nNewPos = m_bIsAutoIncrement ? m_nColumnPos+1 : m_nColumnPos;
+ OSL_ENSURE(nNewPos < static_cast<sal_Int32>(m_vColumnPositions.size()),"m_vColumnPositions: Illegal index for vector");
+
+ if ( nNewPos < static_cast<sal_Int32>(m_vColumnPositions.size() ) )
+ {
+ sal_Int32 nPos = m_vColumnPositions[nNewPos].first;
+ if ( nPos != COLUMN_POSITION_NOT_FOUND )
+ {
+ if ( m_sTextToken.isEmpty() && pField->IsNullable() )
+ m_pUpdateHelper->updateNull(nPos,pField->GetType());
+ else
+ {
+ OSL_ENSURE((nNewPos) < static_cast<sal_Int32>(m_vColumnTypes.size()),"Illegal index for vector");
+ if (m_vColumnTypes[nNewPos] != DataType::VARCHAR && m_vColumnTypes[nNewPos] != DataType::CHAR && m_vColumnTypes[nNewPos] != DataType::LONGVARCHAR )
+ {
+ SAL_INFO("dbaccess.ui", "ODatabaseExport::insertValueIntoColumn != DataType::VARCHAR" );
+ ensureFormatter();
+ sal_Int32 nNumberFormat = 0;
+ double fOutNumber = 0.0;
+ bool bNumberFormatError = false;
+ if ( m_pFormatter && !m_sNumToken.isEmpty() )
+ {
+ LanguageType eNumLang = LANGUAGE_NONE;
+ sal_uInt32 nNumberFormat2( nNumberFormat );
+ fOutNumber = SfxHTMLParser::GetTableDataOptionsValNum(nNumberFormat2,eNumLang,m_sTextToken,m_sNumToken,*m_pFormatter);
+ if ( eNumLang != LANGUAGE_NONE )
+ {
+ nNumberFormat2 = m_pFormatter->GetFormatForLanguageIfBuiltIn( nNumberFormat2, eNumLang );
+ (void)m_pFormatter->IsNumberFormat( m_sTextToken, nNumberFormat2, fOutNumber );
+ }
+ nNumberFormat = static_cast<sal_Int32>(nNumberFormat2);
+ }
+ else
+ {
+ Reference< XNumberFormatsSupplier > xSupplier = m_xFormatter->getNumberFormatsSupplier();
+ Reference<XNumberFormatTypes> xNumType(xSupplier->getNumberFormats(),UNO_QUERY);
+ const sal_Int16 nFormats[] = {
+ NumberFormat::DATETIME
+ ,NumberFormat::DATE
+ ,NumberFormat::TIME
+ ,NumberFormat::CURRENCY
+ ,NumberFormat::NUMBER
+ ,NumberFormat::LOGICAL
+ };
+ for (short nFormat : nFormats)
+ {
+ try
+ {
+ nNumberFormat = m_xFormatter->detectNumberFormat(xNumType->getStandardFormat(nFormat,m_aLocale),m_sTextToken);
+ break;
+ }
+ catch(Exception&)
+ {
+ }
+ }
+ try
+ {
+ fOutNumber = m_xFormatter->convertStringToNumber(nNumberFormat,m_sTextToken);
+ }
+ catch(Exception&)
+ {
+ bNumberFormatError = true;
+ m_pUpdateHelper->updateString(nPos,m_sTextToken);
+ }
+ }
+ if ( !bNumberFormatError )
+ {
+ try
+ {
+ Reference< XNumberFormatsSupplier > xSupplier = m_xFormatter->getNumberFormatsSupplier();
+ Reference< XNumberFormats > xFormats = xSupplier->getNumberFormats();
+ Reference<XPropertySet> xProp = xFormats->getByKey(nNumberFormat);
+ sal_Int16 nType = 0;
+ xProp->getPropertyValue(PROPERTY_TYPE) >>= nType;
+ switch(nType)
+ {
+ case NumberFormat::DATE:
+ m_pUpdateHelper->updateDate(nPos,::dbtools::DBTypeConversion::toDate(fOutNumber,m_aNullDate));
+ break;
+ case NumberFormat::DATETIME:
+ m_pUpdateHelper->updateTimestamp(nPos,::dbtools::DBTypeConversion::toDateTime(fOutNumber,m_aNullDate));
+ break;
+ case NumberFormat::TIME:
+ m_pUpdateHelper->updateTime(nPos,::dbtools::DBTypeConversion::toTime(fOutNumber));
+ break;
+ default:
+ m_pUpdateHelper->updateDouble(nPos,fOutNumber);
+ }
+ }
+ catch(Exception&)
+ {
+ m_pUpdateHelper->updateString(nPos,m_sTextToken);
+ }
+ }
+
+ }
+ else
+ m_pUpdateHelper->updateString(nPos,m_sTextToken);
+ }
+ }
+ }
+ eraseTokens();
+}
+
+sal_Int16 ODatabaseExport::CheckString(const OUString& aCheckToken, sal_Int16 _nOldNumberFormat)
+{
+ sal_Int16 nNumberFormat = 0;
+
+ try
+ {
+ Reference< XNumberFormatsSupplier > xSupplier = m_xFormatter->getNumberFormatsSupplier();
+ Reference< XNumberFormats > xFormats = xSupplier->getNumberFormats();
+
+ ensureFormatter();
+ if ( m_pFormatter && !m_sNumToken.isEmpty() )
+ {
+ LanguageType eNumLang;
+ sal_uInt32 nFormatKey(0);
+ double fOutNumber = SfxHTMLParser::GetTableDataOptionsValNum(nFormatKey,eNumLang,m_sTextToken,m_sNumToken,*m_pFormatter);
+ if ( eNumLang != LANGUAGE_NONE )
+ {
+ nFormatKey = m_pFormatter->GetFormatForLanguageIfBuiltIn( nFormatKey, eNumLang );
+ if ( !m_pFormatter->IsNumberFormat( m_sTextToken, nFormatKey, fOutNumber ) )
+ return NumberFormat::TEXT;
+ }
+ Reference<XPropertySet> xProp = xFormats->getByKey(nFormatKey);
+ xProp->getPropertyValue(PROPERTY_TYPE) >>= nNumberFormat;
+ }
+ else
+ {
+ Reference<XNumberFormatTypes> xNumType(xFormats,UNO_QUERY);
+ sal_Int32 nFormatKey = m_xFormatter->detectNumberFormat(xNumType->getStandardFormat(NumberFormat::ALL,m_aLocale),aCheckToken);
+ m_xFormatter->convertStringToNumber(nFormatKey,aCheckToken);
+
+ Reference<XPropertySet> xProp = xFormats->getByKey(nFormatKey);
+ sal_Int16 nType = 0;
+ xProp->getPropertyValue(PROPERTY_TYPE) >>= nType;
+
+ switch(nType)
+ {
+ case NumberFormat::ALL:
+ nNumberFormat = NumberFormat::ALL;
+ break;
+ case NumberFormat::DEFINED:
+ nNumberFormat = NumberFormat::TEXT;
+ break;
+ case NumberFormat::DATE:
+ switch(_nOldNumberFormat)
+ {
+ case NumberFormat::DATETIME:
+ case NumberFormat::TEXT:
+ case NumberFormat::DATE:
+ nNumberFormat = _nOldNumberFormat;
+ break;
+ case NumberFormat::ALL:
+ nNumberFormat = NumberFormat::DATE;
+ break;
+ default:
+ nNumberFormat = NumberFormat::TEXT;
+
+ }
+ break;
+ case NumberFormat::TIME:
+ switch(_nOldNumberFormat)
+ {
+ case NumberFormat::DATETIME:
+ case NumberFormat::TEXT:
+ case NumberFormat::TIME:
+ nNumberFormat = _nOldNumberFormat;
+ break;
+ case NumberFormat::ALL:
+ nNumberFormat = NumberFormat::TIME;
+ break;
+ default:
+ nNumberFormat = NumberFormat::TEXT;
+ break;
+ }
+ break;
+ case NumberFormat::CURRENCY:
+ switch(_nOldNumberFormat)
+ {
+ case NumberFormat::NUMBER:
+ nNumberFormat = NumberFormat::CURRENCY;
+ break;
+ case NumberFormat::CURRENCY:
+ nNumberFormat = _nOldNumberFormat;
+ break;
+ case NumberFormat::ALL:
+ nNumberFormat = NumberFormat::CURRENCY;
+ break;
+ default:
+ nNumberFormat = NumberFormat::TEXT;
+ break;
+ }
+ break;
+ case NumberFormat::NUMBER:
+ case NumberFormat::SCIENTIFIC:
+ case NumberFormat::FRACTION:
+ case NumberFormat::PERCENT:
+ switch(_nOldNumberFormat)
+ {
+ case NumberFormat::NUMBER:
+ nNumberFormat = _nOldNumberFormat;
+ break;
+ case NumberFormat::CURRENCY:
+ nNumberFormat = NumberFormat::CURRENCY;
+ break;
+ case NumberFormat::ALL:
+ nNumberFormat = nType;
+ break;
+ default:
+ nNumberFormat = NumberFormat::TEXT;
+ break;
+ }
+ break;
+ case NumberFormat::TEXT:
+ case NumberFormat::UNDEFINED:
+ case NumberFormat::LOGICAL:
+ nNumberFormat = NumberFormat::TEXT; // Text overwrites everything
+ break;
+ case NumberFormat::DATETIME:
+ switch(_nOldNumberFormat)
+ {
+ case NumberFormat::DATETIME:
+ case NumberFormat::TEXT:
+ case NumberFormat::TIME:
+ nNumberFormat = _nOldNumberFormat;
+ break;
+ case NumberFormat::ALL:
+ nNumberFormat = NumberFormat::DATETIME;
+ break;
+ default:
+ nNumberFormat = NumberFormat::TEXT;
+ break;
+ }
+ break;
+ default:
+ SAL_WARN("dbaccess.ui", "ODatabaseExport: Unknown NumberFormat");
+ }
+ }
+ }
+ catch(Exception&)
+ {
+ nNumberFormat = NumberFormat::TEXT; // Text overwrites everything
+ }
+
+ return nNumberFormat;
+}
+
+void ODatabaseExport::SetColumnTypes(const TColumnVector* _pList,const OTypeInfoMap* _pInfoMap)
+{
+ if(!(_pList && _pInfoMap))
+ return;
+
+ OSL_ENSURE(m_vNumberFormat.size() == m_vColumnSize.size() && m_vColumnSize.size() == _pList->size(),"Illegal columns in list");
+ Reference< XNumberFormatsSupplier > xSupplier = m_xFormatter->getNumberFormatsSupplier();
+ Reference< XNumberFormats > xFormats = xSupplier->getNumberFormats();
+ sal_Int32 minBothSize = std::min<sal_Int32>(m_vNumberFormat.size(), m_vColumnSize.size());
+ sal_Int32 i = 0;
+ for (auto const& elem : *_pList)
+ {
+ if (i >= minBothSize)
+ break;
+
+ sal_Int32 nDataType;
+ sal_Int32 nLength(0),nScale(0);
+ sal_Int16 nType = m_vNumberFormat[i] & ~NumberFormat::DEFINED;
+
+ switch ( nType )
+ {
+ case NumberFormat::ALL:
+ nDataType = DataType::DOUBLE;
+ break;
+ case NumberFormat::DEFINED:
+ nDataType = DataType::VARCHAR;
+ nLength = ((m_vColumnSize[i] % 10 ) ? m_vColumnSize[i]/ 10 + 1: m_vColumnSize[i]/ 10) * 10;
+ break;
+ case NumberFormat::DATE:
+ nDataType = DataType::DATE;
+ break;
+ case NumberFormat::TIME:
+ nDataType = DataType::TIME;
+ break;
+ case NumberFormat::DATETIME:
+ nDataType = DataType::TIMESTAMP;
+ break;
+ case NumberFormat::CURRENCY:
+ nDataType = DataType::NUMERIC;
+ nScale = 4;
+ nLength = 19;
+ break;
+ case NumberFormat::NUMBER:
+ case NumberFormat::SCIENTIFIC:
+ case NumberFormat::FRACTION:
+ case NumberFormat::PERCENT:
+ nDataType = DataType::DOUBLE;
+ break;
+ case NumberFormat::TEXT:
+ case NumberFormat::UNDEFINED:
+ case NumberFormat::LOGICAL:
+ default:
+ nDataType = DataType::VARCHAR;
+ nLength = ((m_vColumnSize[i] % 10 ) ? m_vColumnSize[i]/ 10 + 1: m_vColumnSize[i]/ 10) * 10;
+ break;
+ }
+ OTypeInfoMap::const_iterator aFind = _pInfoMap->find(nDataType);
+ if(aFind != _pInfoMap->end())
+ {
+ elem->second->SetType(aFind->second);
+ elem->second->SetPrecision(std::min<sal_Int32>(aFind->second->nPrecision,nLength));
+ elem->second->SetScale(std::min<sal_Int32>(aFind->second->nMaximumScale,nScale));
+
+ sal_Int32 nFormatKey = ::dbtools::getDefaultNumberFormat( nDataType,
+ elem->second->GetScale(),
+ elem->second->IsCurrency(),
+ Reference< XNumberFormatTypes>(xFormats,UNO_QUERY),
+ m_aLocale);
+
+ elem->second->SetFormatKey(nFormatKey);
+ }
+ ++i;
+ }
+}
+
+void ODatabaseExport::CreateDefaultColumn(const OUString& _rColumnName)
+{
+ Reference< XDatabaseMetaData> xDestMetaData(m_xConnection->getMetaData());
+ sal_Int32 nMaxNameLen(xDestMetaData->getMaxColumnNameLength());
+ OUString aAlias = _rColumnName;
+ if ( isSQL92CheckEnabled(m_xConnection) )
+ aAlias = ::dbtools::convertName2SQLName(_rColumnName,xDestMetaData->getExtraNameCharacters());
+
+ if(nMaxNameLen && aAlias.getLength() > nMaxNameLen)
+ aAlias = aAlias.copy(0, std::min<sal_Int32>( nMaxNameLen-1, aAlias.getLength() ) );
+
+ OUString sName(aAlias);
+ if(m_aDestColumns.find(sName) != m_aDestColumns.end())
+ {
+ sal_Int32 nPos = 0;
+ sal_Int32 nCount = 2;
+ while(m_aDestColumns.find(sName) != m_aDestColumns.end())
+ {
+ sName = aAlias
+ + OUString::number(++nPos);
+ if(nMaxNameLen && sName.getLength() > nMaxNameLen)
+ {
+ aAlias = aAlias.copy(0,std::min<sal_Int32>( nMaxNameLen-nCount, aAlias.getLength() ));
+ sName = aAlias
+ + OUString::number(nPos);
+ ++nCount;
+ }
+ }
+ }
+ aAlias = sName;
+ // now create a column
+ OFieldDescription* pField = new OFieldDescription();
+ pField->SetType(m_pTypeInfo);
+ pField->SetName(aAlias);
+ pField->SetPrecision(std::min<sal_Int32>(sal_Int32(255),m_pTypeInfo->nPrecision));
+ pField->SetScale(0);
+ pField->SetIsNullable(ColumnValue::NULLABLE);
+ pField->SetAutoIncrement(false);
+ pField->SetPrimaryKey(false);
+ pField->SetCurrency(false);
+
+ TColumns::const_iterator aFind = m_aDestColumns.find( aAlias );
+ if ( aFind != m_aDestColumns.end() )
+ {
+ delete aFind->second;
+ m_aDestColumns.erase(aFind);
+ }
+
+ m_vDestVector.emplace_back(m_aDestColumns.emplace(aAlias,pField).first);
+}
+
+void ODatabaseExport::createRowSet()
+{
+ m_pUpdateHelper = std::make_shared<OParameterUpdateHelper>(createPreparedStatement(m_xConnection->getMetaData(),m_xTable,m_vColumnPositions));
+}
+
+bool ODatabaseExport::executeWizard(const OUString& _rTableName, const Any& _aTextColor, const FontDescriptor& _rFont)
+{
+ bool bHaveDefaultTable = !m_sDefaultTableName.isEmpty();
+ const OUString& rTableName(bHaveDefaultTable ? m_sDefaultTableName : _rTableName);
+ OCopyTableWizard aWizard(
+ nullptr,
+ rTableName,
+ bHaveDefaultTable ? CopyTableOperation::AppendData : CopyTableOperation::CopyDefinitionAndData,
+ ODatabaseExport::TColumns(m_aDestColumns),
+ m_vDestVector,
+ m_xConnection,
+ m_xFormatter,
+ getTypeSelectionPageFactory(),
+ m_rInputStream,
+ m_xContext
+ );
+
+ bool bError = false;
+ try
+ {
+ if (aWizard.run())
+ {
+ switch(aWizard.getOperation())
+ {
+ case CopyTableOperation::CopyDefinitionAndData:
+ case CopyTableOperation::AppendData:
+ {
+ m_xTable = aWizard.returnTable();
+ bError = !m_xTable.is();
+ if(m_xTable.is())
+ {
+ m_xTable->setPropertyValue(PROPERTY_FONT,Any(_rFont));
+ if(_aTextColor.hasValue())
+ m_xTable->setPropertyValue(PROPERTY_TEXTCOLOR,_aTextColor);
+ }
+ m_bIsAutoIncrement = aWizard.shouldCreatePrimaryKey();
+ m_vColumnPositions = aWizard.GetColumnPositions();
+ m_vColumnTypes = aWizard.GetColumnTypes();
+ m_bAppendFirstLine = !aWizard.UseHeaderLine();
+ }
+ break;
+ default:
+ bError = true; // there is no error but I have nothing more to do
+ }
+ }
+ else
+ bError = true;
+
+ if(!bError)
+ createRowSet();
+ }
+ catch( const SQLException&)
+ {
+ ::dbtools::showError( ::dbtools::SQLExceptionInfo( ::cppu::getCaughtException() ), aWizard.getDialog()->GetXWindow(), m_xContext );
+ bError = true;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return bError;
+}
+
+void ODatabaseExport::showErrorDialog(const css::sdbc::SQLException& e)
+{
+ if(!m_bDontAskAgain)
+ {
+ OUString aMsg = e.Message
+ + "\n"
+ + DBA_RES( STR_QRY_CONTINUE );
+ OSQLWarningBox aBox(nullptr, aMsg, MessBoxStyle::YesNo | MessBoxStyle::DefaultNo);
+
+ if (aBox.run() == RET_YES)
+ m_bDontAskAgain = true;
+ else
+ m_bError = true;
+ }
+}
+
+void ODatabaseExport::adjustFormat()
+{
+ if ( m_sTextToken.isEmpty() )
+ return;
+
+ sal_Int32 nNewPos = m_bIsAutoIncrement ? m_nColumnPos+1 : m_nColumnPos;
+ OSL_ENSURE(nNewPos < static_cast<sal_Int32>(m_vColumnPositions.size()),"Illegal index for vector");
+ if ( nNewPos < static_cast<sal_Int32>(m_vColumnPositions.size()) )
+ {
+ sal_Int32 nColPos = m_vColumnPositions[nNewPos].first;
+ if( nColPos != COLUMN_POSITION_NOT_FOUND)
+ {
+ --nColPos;
+ OSL_ENSURE((nColPos) < static_cast<sal_Int32>(m_vNumberFormat.size()),"m_vFormatKey: Illegal index for vector");
+ OSL_ENSURE((nColPos) < static_cast<sal_Int32>(m_vColumnSize.size()),"m_vColumnSize: Illegal index for vector");
+ m_vNumberFormat[nColPos] = CheckString(m_sTextToken,m_vNumberFormat[nColPos]);
+ m_vColumnSize[nColPos] = std::max<sal_Int32>(static_cast<sal_Int32>(m_vColumnSize[nColPos]), m_sTextToken.getLength());
+ }
+ }
+ eraseTokens();
+}
+
+void ODatabaseExport::eraseTokens()
+{
+ m_sTextToken.clear();
+ m_sNumToken.clear();
+}
+
+void ODatabaseExport::ensureFormatter()
+{
+ if ( !m_pFormatter )
+ {
+ Reference< XNumberFormatsSupplier > xSupplier = m_xFormatter->getNumberFormatsSupplier();
+ auto pSupplierImpl = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(xSupplier);
+ m_pFormatter = pSupplierImpl ? pSupplierImpl->GetNumberFormatter() : nullptr;
+ Reference<XPropertySet> xNumberFormatSettings = xSupplier->getNumberFormatSettings();
+ xNumberFormatSettings->getPropertyValue("NullDate") >>= m_aNullDate;
+ }
+}
+
+Reference< XPreparedStatement > ODatabaseExport::createPreparedStatement( const Reference<XDatabaseMetaData>& _xMetaData
+ ,const Reference<XPropertySet>& _xDestTable
+ ,const TPositions& _rvColumns)
+{
+ OUString sComposedTableName = ::dbtools::composeTableName( _xMetaData, _xDestTable, ::dbtools::EComposeRule::InDataManipulation, true );
+
+ OUStringBuffer aSql = "INSERT INTO "
+ + sComposedTableName
+ + " ( ";
+
+ // set values and column names
+ OUStringBuffer aValues(" VALUES ( ");
+
+ OUString aQuote;
+ if ( _xMetaData.is() )
+ aQuote = _xMetaData->getIdentifierQuoteString();
+
+ Reference<XColumnsSupplier> xDestColsSup(_xDestTable,UNO_QUERY_THROW);
+
+ // create sql string and set column types
+ Sequence< OUString> aDestColumnNames = xDestColsSup->getColumns()->getElementNames();
+ if ( !aDestColumnNames.hasElements() )
+ {
+ return Reference< XPreparedStatement > ();
+ }
+ const OUString* pIter = aDestColumnNames.getConstArray();
+ std::vector< OUString> aInsertList;
+ aInsertList.resize(aDestColumnNames.getLength()+1);
+ for(size_t j=0; j < aInsertList.size(); ++j)
+ {
+ ODatabaseExport::TPositions::const_iterator aFind = std::find_if(_rvColumns.begin(),_rvColumns.end(),
+ [j] (const ODatabaseExport::TPositions::value_type& tPos)
+ { return tPos.second == static_cast<sal_Int32>(j+1); });
+ if ( _rvColumns.end() != aFind && aFind->second != COLUMN_POSITION_NOT_FOUND && aFind->first != COLUMN_POSITION_NOT_FOUND )
+ {
+ OSL_ENSURE((aFind->first) < static_cast<sal_Int32>(aInsertList.size()),"aInsertList: Illegal index for vector");
+ aInsertList[aFind->first] = ::dbtools::quoteName( aQuote,*(pIter+j));
+ }
+ }
+
+ // create the sql string
+ for (auto const& elem : aInsertList)
+ {
+ if ( !elem.isEmpty() )
+ {
+ aSql.append(elem + ",");
+ aValues.append("?,");
+ }
+ }
+
+ aSql[aSql.getLength()-1] = ')';
+ aValues[aValues.getLength()-1] = ')';
+
+ aSql.append(aValues);
+ // now create,fill and execute the prepared statement
+ return _xMetaData->getConnection()->prepareStatement(aSql.makeStringAndClear());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/HtmlReader.cxx b/dbaccess/source/ui/misc/HtmlReader.cxx
new file mode 100644
index 0000000000..c2917a6300
--- /dev/null
+++ b/dbaccess/source/ui/misc/HtmlReader.cxx
@@ -0,0 +1,481 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <HtmlReader.hxx>
+#include <connectivity/dbtools.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/stream.hxx>
+#include <tools/tenccvt.hxx>
+#include <comphelper/string.hxx>
+#include <strings.hrc>
+#include <osl/diagnose.h>
+#include <core_resource.hxx>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <com/sun/star/awt/FontStrikeout.hpp>
+#include <com/sun/star/awt/FontSlant.hpp>
+#include <com/sun/star/awt/FontUnderline.hpp>
+#include <svtools/htmltokn.h>
+#include <svtools/htmlkywd.hxx>
+#include <tools/color.hxx>
+#include <WExtendPages.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+using namespace dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::awt;
+
+#define DBAUI_HTML_FONTSIZES 8 // like export, HTML-Options
+
+// OHTMLReader
+OHTMLReader::OHTMLReader(SvStream& rIn,const SharedConnection& _rxConnection,
+ const Reference< css::util::XNumberFormatter >& _rxNumberF,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext)
+ : HTMLParser(rIn)
+ , ODatabaseExport( _rxConnection, _rxNumberF, _rxContext, rIn )
+ , m_nTableCount(0)
+ , m_nColumnWidth(87)
+{
+ SetSrcEncoding( GetExtendedCompatibilityTextEncoding( RTL_TEXTENCODING_ISO_8859_1 ) );
+ // If the file starts with a BOM, switch to UCS2.
+ SetSwitchToUCS2( true );
+}
+
+OHTMLReader::OHTMLReader(SvStream& rIn,
+ sal_Int32 nRows,
+ TPositions&& _rColumnPositions,
+ const Reference< css::util::XNumberFormatter >& _rxNumberF,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ const TColumnVector* pList,
+ const OTypeInfoMap* _pInfoMap,
+ bool _bAutoIncrementEnabled)
+ : HTMLParser(rIn)
+ , ODatabaseExport( nRows, std::move(_rColumnPositions), _rxNumberF, _rxContext, pList, _pInfoMap, _bAutoIncrementEnabled, rIn )
+ , m_nTableCount(0)
+ , m_nColumnWidth(87)
+{
+ SetSrcEncoding( GetExtendedCompatibilityTextEncoding( RTL_TEXTENCODING_ISO_8859_1 ) );
+ // If the file starts with a BOM, switch to UCS2.
+ SetSwitchToUCS2( true );
+}
+
+OHTMLReader::~OHTMLReader()
+{
+}
+
+SvParserState OHTMLReader::CallParser()
+{
+ rInput.Seek(STREAM_SEEK_TO_BEGIN);
+ rInput.ResetError();
+ SvParserState eParseState = HTMLParser::CallParser();
+ SetColumnTypes(m_pColumnList,m_pInfoMap);
+ return m_bFoundTable ? eParseState : SvParserState::Error;
+}
+
+#if defined _MSC_VER
+#pragma warning(disable: 4702) // unreachable code, bug in MSVC2015
+#endif
+void OHTMLReader::NextToken( HtmlTokenId nToken )
+{
+ if(m_bError || !m_nRows) // if there is an error or no more rows to check, return immediately
+ return;
+ if ( nToken == HtmlTokenId::META )
+ setTextEncoding();
+
+ if(m_xConnection.is()) // names, which CTOR was called and hence, if a table should be created
+ {
+ switch(nToken)
+ {
+ case HtmlTokenId::TABLE_ON:
+ ++m_nTableCount;
+ { // can also be TD or TH, if there was no TABLE before
+ const HTMLOptions& rHtmlOptions = GetOptions();
+ for (const auto & rOption : rHtmlOptions)
+ {
+ if( rOption.GetToken() == HtmlOptionId::WIDTH )
+ { // percentage: of document width respectively outer cell
+ m_nColumnWidth = GetWidthPixel( rOption );
+ }
+ }
+ }
+ [[fallthrough]];
+ case HtmlTokenId::THEAD_ON:
+ case HtmlTokenId::TBODY_ON:
+ {
+ sal_uInt64 const nTell = rInput.Tell(); // perhaps alters position of the stream
+ if ( !m_xTable.is() )
+ {// use first line as header
+ m_bError = !CreateTable(nToken);
+ if ( m_bAppendFirstLine )
+ rInput.Seek(nTell);
+ }
+ }
+ break;
+ case HtmlTokenId::TABLE_OFF:
+ if(!--m_nTableCount)
+ {
+ m_xTable = nullptr;
+ }
+ break;
+ case HtmlTokenId::TABLEROW_ON:
+ if ( !m_pUpdateHelper )
+ m_bError = true;
+ break;
+ case HtmlTokenId::TEXTTOKEN:
+ case HtmlTokenId::SINGLECHAR:
+ if ( m_bInTbl ) //&& !m_bSDNum ) // important, as otherwise we also get the names of the fonts
+ m_sTextToken += aToken;
+ break;
+ case HtmlTokenId::PARABREAK_OFF:
+ m_sCurrent += m_sTextToken;
+ break;
+ case HtmlTokenId::PARABREAK_ON:
+ m_sTextToken.clear();
+ break;
+ case HtmlTokenId::TABLEDATA_ON:
+ fetchOptions();
+ break;
+ case HtmlTokenId::TABLEDATA_OFF:
+ {
+ if ( !m_sCurrent.isEmpty() )
+ m_sTextToken = m_sCurrent;
+ try
+ {
+ insertValueIntoColumn();
+ }
+ catch(SQLException& e)
+ // handling update failure
+ {
+ showErrorDialog(e);
+ }
+ m_sCurrent.clear();
+ m_nColumnPos++;
+ eraseTokens();
+ m_bInTbl = false;
+ }
+ break;
+ case HtmlTokenId::TABLEROW_OFF:
+ if ( !m_pUpdateHelper )
+ {
+ m_bError = true;
+ break;
+ }
+ try
+ {
+ m_nRowCount++;
+ if (m_bIsAutoIncrement) // if bSetAutoIncrement then I have to set the autoincrement
+ m_pUpdateHelper->updateInt(1,m_nRowCount);
+ m_pUpdateHelper->insertRow();
+ }
+ catch(SQLException& e)
+ // handling update failure
+ {
+ showErrorDialog(e);
+ }
+ m_nColumnPos = 0;
+ break;
+ default: break;
+ }
+ }
+ else // branch only valid for type checking
+ {
+ switch(nToken)
+ {
+ case HtmlTokenId::THEAD_ON:
+ case HtmlTokenId::TBODY_ON:
+ // The head of the column is not included
+ if(m_bHead)
+ {
+ do
+ {}
+ while(GetNextToken() != HtmlTokenId::TABLEROW_OFF);
+ m_bHead = false;
+ }
+ break;
+ case HtmlTokenId::TABLEDATA_ON:
+ case HtmlTokenId::TABLEHEADER_ON:
+ fetchOptions();
+ break;
+ case HtmlTokenId::TEXTTOKEN:
+ case HtmlTokenId::SINGLECHAR:
+ if ( m_bInTbl ) // && !m_bSDNum ) // important, as otherwise we also get the names of the fonts
+ m_sTextToken += aToken;
+ break;
+ case HtmlTokenId::PARABREAK_OFF:
+ m_sCurrent += m_sTextToken;
+ break;
+ case HtmlTokenId::PARABREAK_ON:
+ m_sTextToken.clear();
+ break;
+ case HtmlTokenId::TABLEDATA_OFF:
+ if ( !m_sCurrent.isEmpty() )
+ m_sTextToken = m_sCurrent;
+ adjustFormat();
+ m_nColumnPos++;
+ m_bInTbl = false;
+ m_sCurrent.clear();
+ break;
+ case HtmlTokenId::TABLEROW_OFF:
+ if ( !m_sCurrent.isEmpty() )
+ m_sTextToken = m_sCurrent;
+ adjustFormat();
+ m_nColumnPos = 0;
+ m_nRows--;
+ m_sCurrent.clear();
+ break;
+ default: break;
+ }
+ }
+}
+
+void OHTMLReader::fetchOptions()
+{
+ m_bInTbl = true;
+ const HTMLOptions& options = GetOptions();
+ for (const auto & rOption : options)
+ {
+ switch( rOption.GetToken() )
+ {
+ case HtmlOptionId::SDNUM:
+ m_sNumToken = rOption.GetString();
+ break;
+ default: break;
+ }
+ }
+}
+
+void OHTMLReader::TableDataOn(SvxCellHorJustify& eVal)
+{
+ const HTMLOptions& rHtmlOptions = GetOptions();
+ for (const auto & rOption : rHtmlOptions)
+ {
+ switch( rOption.GetToken() )
+ {
+ case HtmlOptionId::ALIGN:
+ {
+ const OUString& rOptVal = rOption.GetString();
+ if (rOptVal.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_AL_right ))
+ eVal = SvxCellHorJustify::Right;
+ else if (rOptVal.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_AL_center ))
+ eVal = SvxCellHorJustify::Center;
+ else if (rOptVal.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_AL_left ))
+ eVal = SvxCellHorJustify::Left;
+ else
+ eVal = SvxCellHorJustify::Standard;
+ }
+ break;
+ default: break;
+ }
+ }
+}
+
+void OHTMLReader::TableFontOn(FontDescriptor& _rFont, Color &_rTextColor)
+{
+ const HTMLOptions& rHtmlOptions = GetOptions();
+ for (const auto & rOption : rHtmlOptions)
+ {
+ switch( rOption.GetToken() )
+ {
+ case HtmlOptionId::COLOR:
+ {
+ Color aColor;
+ rOption.GetColor( aColor );
+ _rTextColor = aColor.GetRGBColor();
+ }
+ break;
+ case HtmlOptionId::FACE :
+ {
+ const OUString& rFace = rOption.GetString();
+ OUStringBuffer aFontName;
+ sal_Int32 nPos = 0;
+ while( nPos != -1 )
+ {
+ // list of fonts, VCL: semicolon as separator, HTML: comma
+ std::u16string_view aFName = o3tl::getToken(rFace, 0, ',', nPos );
+ aFName = comphelper::string::strip(aFName, ' ');
+ if( !aFontName.isEmpty() )
+ aFontName.append(";");
+ aFontName.append(aFName);
+ }
+ if ( !aFontName.isEmpty() )
+ _rFont.Name = aFontName.makeStringAndClear();
+ }
+ break;
+ case HtmlOptionId::SIZE :
+ {
+ sal_Int16 nSize = static_cast<sal_Int16>(rOption.GetNumber());
+ if ( nSize == 0 )
+ nSize = 1;
+ else if ( nSize < DBAUI_HTML_FONTSIZES )
+ nSize = DBAUI_HTML_FONTSIZES;
+
+ _rFont.Height = nSize;
+ }
+ break;
+ default: break;
+ }
+ }
+}
+
+sal_Int16 OHTMLReader::GetWidthPixel( const HTMLOption& rOption )
+{
+ const OUString& rOptVal = rOption.GetString();
+ if ( rOptVal.indexOf('%') != -1 )
+ { // percentage
+ OSL_ENSURE( m_nColumnWidth, "WIDTH Option: m_nColumnWidth==0 and Width%" );
+ return static_cast<sal_Int16>((rOption.GetNumber() * m_nColumnWidth) / 100);
+ }
+ else
+ {
+ if ( rOptVal.indexOf('*') != -1 )
+ { // relative to what?!?
+//TODO: collect ColArray of all relevant values and then MakeCol
+ return 0;
+ }
+ else
+ return static_cast<sal_Int16>(rOption.GetNumber()); // pixel
+ }
+}
+
+bool OHTMLReader::CreateTable(HtmlTokenId nToken)
+{
+ OUString aTempName(DBA_RES(STR_TBL_TITLE));
+ aTempName = aTempName.getToken(0,' ');
+ aTempName = ::dbtools::createUniqueName(m_xTables, aTempName);
+
+ bool bCaption = false;
+ bool bTableHeader = false;
+ OUString aColumnName;
+ SvxCellHorJustify eVal;
+
+ OUString aTableName;
+ FontDescriptor aFont = VCLUnoHelper::CreateFontDescriptor(Application::GetSettings().GetStyleSettings().GetAppFont());
+ Color nTextColor;
+ do
+ {
+ switch (nToken)
+ {
+ case HtmlTokenId::TEXTTOKEN:
+ case HtmlTokenId::SINGLECHAR:
+ if(bTableHeader)
+ aColumnName += aToken;
+ if(bCaption)
+ aTableName += aToken;
+ break;
+ case HtmlTokenId::PARABREAK_OFF:
+ m_sCurrent += aColumnName;
+ break;
+ case HtmlTokenId::PARABREAK_ON:
+ m_sTextToken.clear();
+ break;
+ case HtmlTokenId::TABLEDATA_ON:
+ case HtmlTokenId::TABLEHEADER_ON:
+ TableDataOn(eVal);
+ bTableHeader = true;
+ break;
+ case HtmlTokenId::TABLEDATA_OFF:
+ case HtmlTokenId::TABLEHEADER_OFF:
+ {
+ aColumnName = comphelper::string::strip(aColumnName, ' ' );
+ if (aColumnName.isEmpty() || m_bAppendFirstLine )
+ aColumnName = DBA_RES(STR_COLUMN_NAME);
+ else if ( !m_sCurrent.isEmpty() )
+ aColumnName = m_sCurrent;
+
+ aColumnName = comphelper::string::strip(aColumnName, ' ');
+ CreateDefaultColumn(aColumnName);
+ aColumnName.clear();
+ m_sCurrent.clear();
+
+ eVal = SvxCellHorJustify::Standard;
+ bTableHeader = false;
+ }
+ break;
+
+ case HtmlTokenId::TITLE_ON:
+ case HtmlTokenId::CAPTION_ON:
+ bCaption = true;
+ break;
+ case HtmlTokenId::TITLE_OFF:
+ case HtmlTokenId::CAPTION_OFF:
+ aTableName = comphelper::string::strip(aTableName, ' ');
+ if(aTableName.isEmpty())
+ aTableName = ::dbtools::createUniqueName(m_xTables, aTableName);
+ else
+ aTableName = aTempName;
+ bCaption = false;
+ break;
+ case HtmlTokenId::FONT_ON:
+ TableFontOn(aFont,nTextColor);
+ break;
+ case HtmlTokenId::BOLD_ON:
+ aFont.Weight = css::awt::FontWeight::BOLD;
+ break;
+ case HtmlTokenId::ITALIC_ON:
+ aFont.Slant = css::awt::FontSlant_ITALIC;
+ break;
+ case HtmlTokenId::UNDERLINE_ON:
+ aFont.Underline = css::awt::FontUnderline::SINGLE;
+ break;
+ case HtmlTokenId::STRIKE_ON:
+ aFont.Strikeout = css::awt::FontStrikeout::SINGLE;
+ break;
+ default: break;
+ }
+ nToken = GetNextToken();
+ }
+ while (nToken != HtmlTokenId::TABLEROW_OFF);
+
+ if ( !m_sCurrent.isEmpty() )
+ aColumnName = m_sCurrent;
+ aColumnName = comphelper::string::strip(aColumnName, ' ');
+ if(!aColumnName.isEmpty())
+ CreateDefaultColumn(aColumnName);
+
+ if ( m_vDestVector.empty() )
+ return false;
+
+ if(aTableName.isEmpty())
+ aTableName = aTempName;
+
+ m_bInTbl = false;
+ m_bFoundTable = true;
+
+ if ( isCheckEnabled() )
+ return true;
+
+ return !executeWizard(aTableName,Any(nTextColor),aFont) && m_xTable.is();
+}
+
+void OHTMLReader::setTextEncoding()
+{
+ ParseMetaOptions(nullptr, nullptr);
+}
+
+TypeSelectionPageFactory OHTMLReader::getTypeSelectionPageFactory()
+{
+ return &OWizHTMLExtend::Create;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/RowSetDrop.cxx b/dbaccess/source/ui/misc/RowSetDrop.cxx
new file mode 100644
index 0000000000..065fee9ce9
--- /dev/null
+++ b/dbaccess/source/ui/misc/RowSetDrop.cxx
@@ -0,0 +1,247 @@
+
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <DExport.hxx>
+#include <TokenWriter.hxx>
+#include <com/sun/star/sdbc/XColumnLocate.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <sqlmessage.hxx>
+#include <com/sun/star/sdbc/XRowUpdate.hpp>
+
+using namespace dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::lang;
+
+// export data
+ORowSetImportExport::ORowSetImportExport(weld::Window* pParent,
+ const Reference< XResultSetUpdate >& xResultSetUpdate,
+ const svx::ODataAccessDescriptor& aDataDescriptor,
+ const Reference< XComponentContext >& rM)
+ : ODatabaseImportExport(aDataDescriptor,rM,nullptr)
+ ,m_xTargetResultSetUpdate(xResultSetUpdate)
+ ,m_xTargetRowUpdate(xResultSetUpdate,UNO_QUERY)
+ ,m_pParent(pParent)
+ ,m_bAlreadyAsked(false)
+{
+ OSL_ENSURE(pParent,"Window can't be null!");
+}
+
+void ORowSetImportExport::initialize()
+{
+ ODatabaseImportExport::initialize();
+ // do namemapping
+ Reference<XColumnLocate> xColumnLocate(m_xResultSet,UNO_QUERY);
+ OSL_ENSURE(xColumnLocate.is(),"The rowset normally should support this");
+
+ m_xTargetResultSetMetaData = Reference<XResultSetMetaDataSupplier>(m_xTargetResultSetUpdate,UNO_QUERY_THROW)->getMetaData();
+ if(!m_xTargetResultSetMetaData.is() || !xColumnLocate.is() || !m_xResultSetMetaData.is() )
+ throw SQLException(DBA_RES(STR_UNEXPECTED_ERROR),*this,"S1000",0,Any());
+
+ sal_Int32 nCount = m_xTargetResultSetMetaData->getColumnCount();
+ m_aColumnMapping.reserve(nCount);
+ m_aColumnTypes.reserve(nCount);
+ for (sal_Int32 i = 1;i <= nCount; ++i)
+ {
+ sal_Int32 nPos = COLUMN_POSITION_NOT_FOUND; // means column is autoincrement or doesn't exist
+ if(!m_xTargetResultSetMetaData->isAutoIncrement(i))
+ {
+ try
+ {
+ OUString sColumnName = m_xTargetResultSetMetaData->getColumnName(i);
+ nPos = xColumnLocate->findColumn(sColumnName);
+ }
+ catch(const SQLException&)
+ {
+ if(m_xTargetResultSetMetaData->isNullable(i))
+ nPos = 0; // column doesn't exist but we could set it to null
+ }
+ }
+
+ m_aColumnMapping.push_back(nPos);
+ if(nPos > 0)
+ m_aColumnTypes.push_back(m_xResultSetMetaData->getColumnType(nPos));
+ else
+ m_aColumnTypes.push_back(DataType::OTHER);
+ }
+}
+
+bool ORowSetImportExport::Write()
+{
+ return true;
+}
+
+bool ORowSetImportExport::Read()
+{
+ // check if there is any column to copy
+ if(std::none_of(m_aColumnMapping.begin(),m_aColumnMapping.end(),
+ [](sal_Int32 n) { return n > 0; }))
+ return false;
+ bool bContinue = true;
+ if(m_aSelection.hasElements())
+ {
+ const Any* pBegin = m_aSelection.getConstArray();
+ const Any* pEnd = pBegin + m_aSelection.getLength();
+ for(;pBegin != pEnd && bContinue;++pBegin)
+ {
+ sal_Int32 nPos = -1;
+ *pBegin >>= nPos;
+ OSL_ENSURE(nPos != -1,"Invalid position!");
+ bContinue = (m_xResultSet.is() && m_xResultSet->absolute(nPos) && insertNewRow());
+ }
+ }
+ else
+ {
+ Reference<XPropertySet> xProp(m_xResultSet,UNO_QUERY);
+ sal_Int32 nRowCount = 0;
+ if ( xProp.is() && xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_ISROWCOUNTFINAL) )
+ {
+ bool bFinal = false;
+ xProp->getPropertyValue(PROPERTY_ISROWCOUNTFINAL) >>= bFinal;
+ if ( !bFinal )
+ m_xResultSet->afterLast();
+ xProp->getPropertyValue(PROPERTY_ROWCOUNT) >>= nRowCount;
+ }
+ if ( !nRowCount )
+ {
+ m_xResultSet->afterLast();
+ nRowCount = m_xResultSet->getRow();
+ }
+ OSL_ENSURE(nRowCount,"RowCount is 0!");
+ m_xResultSet->beforeFirst();
+ while(m_xResultSet.is() && m_xResultSet->next() && bContinue && nRowCount )
+ {
+ --nRowCount;
+ bContinue = insertNewRow();
+ }
+ }
+ return true;
+}
+
+bool ORowSetImportExport::insertNewRow()
+{
+ try
+ {
+ m_xTargetResultSetUpdate->moveToInsertRow();
+ sal_Int32 i = 1;
+ for (auto const& column : m_aColumnMapping)
+ {
+ if(column > 0)
+ {
+ Any aValue;
+ switch(m_aColumnTypes[i-1])
+ {
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ aValue <<= m_xRow->getString(column);
+ break;
+ case DataType::DECIMAL:
+ case DataType::NUMERIC:
+ aValue <<= m_xRow->getDouble(column);
+ break;
+ case DataType::BIGINT:
+ aValue <<= m_xRow->getLong(column);
+ break;
+ case DataType::FLOAT:
+ aValue <<= m_xRow->getFloat(column);
+ break;
+ case DataType::DOUBLE:
+ aValue <<= m_xRow->getDouble(column);
+ break;
+ case DataType::LONGVARCHAR:
+ aValue <<= m_xRow->getString(column);
+ break;
+ case DataType::LONGVARBINARY:
+ aValue <<= m_xRow->getBytes(column);
+ break;
+ case DataType::DATE:
+ aValue <<= m_xRow->getDate(column);
+ break;
+ case DataType::TIME:
+ aValue <<= m_xRow->getTime(column);
+ break;
+ case DataType::TIMESTAMP:
+ aValue <<= m_xRow->getTimestamp(column);
+ break;
+ case DataType::BIT:
+ case DataType::BOOLEAN:
+ aValue <<= m_xRow->getBoolean(column);
+ break;
+ case DataType::TINYINT:
+ aValue <<= m_xRow->getByte(column);
+ break;
+ case DataType::SMALLINT:
+ aValue <<= m_xRow->getShort(column);
+ break;
+ case DataType::INTEGER:
+ aValue <<= m_xRow->getInt(column);
+ break;
+ case DataType::REAL:
+ aValue <<= m_xRow->getDouble(column);
+ break;
+ case DataType::BINARY:
+ case DataType::VARBINARY:
+ aValue <<= m_xRow->getBytes(column);
+ break;
+ case DataType::BLOB:
+ aValue <<= m_xRow->getBlob(column);
+ break;
+ case DataType::CLOB:
+ aValue <<= m_xRow->getClob(column);
+ break;
+ default:
+ SAL_WARN("dbaccess.ui", "Unknown type");
+ }
+ if(m_xRow->wasNull())
+ m_xTargetRowUpdate->updateNull(i);
+ else
+ m_xTargetRowUpdate->updateObject(i,aValue);
+ }
+ else if(column == 0)//now we have know that we to set this column to null
+ m_xTargetRowUpdate->updateNull(i);
+ ++i;
+ }
+ m_xTargetResultSetUpdate->insertRow();
+ }
+ catch(const SQLException&)
+ {
+ if(!m_bAlreadyAsked)
+ {
+ OUString sAskIfContinue = DBA_RES(STR_ERROR_OCCURRED_WHILE_COPYING);
+ OSQLWarningBox aDlg(m_pParent, sAskIfContinue, MessBoxStyle::YesNo | MessBoxStyle::DefaultYes);
+ if (aDlg.run() == RET_YES)
+ m_bAlreadyAsked = true;
+ else
+ return false;
+ }
+ }
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/RtfReader.cxx b/dbaccess/source/ui/misc/RtfReader.cxx
new file mode 100644
index 0000000000..8895d494f8
--- /dev/null
+++ b/dbaccess/source/ui/misc/RtfReader.cxx
@@ -0,0 +1,309 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <RtfReader.hxx>
+#include <tools/stream.hxx>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <com/sun/star/awt/FontStrikeout.hpp>
+#include <com/sun/star/awt/FontSlant.hpp>
+#include <com/sun/star/awt/FontUnderline.hpp>
+#include <core_resource.hxx>
+#include <svtools/rtftoken.h>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <strings.hrc>
+#include <connectivity/dbtools.hxx>
+#include <comphelper/string.hxx>
+#include <tools/color.hxx>
+#include <WExtendPages.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+using namespace dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::awt;
+
+// ORTFReader
+ORTFReader::ORTFReader( SvStream& rIn,
+ const SharedConnection& _rxConnection,
+ const Reference< css::util::XNumberFormatter >& _rxNumberF,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext)
+ :SvRTFParser(rIn)
+ ,ODatabaseExport( _rxConnection, _rxNumberF, _rxContext, rIn )
+{
+ m_bAppendFirstLine = false;
+}
+
+ORTFReader::ORTFReader(SvStream& rIn,
+ sal_Int32 nRows,
+ TPositions&& _rColumnPositions,
+ const Reference< css::util::XNumberFormatter >& _rxNumberF,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ const TColumnVector* pList,
+ const OTypeInfoMap* _pInfoMap,
+ bool _bAutoIncrementEnabled)
+ :SvRTFParser(rIn)
+ ,ODatabaseExport( nRows, std::move(_rColumnPositions), _rxNumberF, _rxContext, pList, _pInfoMap, _bAutoIncrementEnabled, rIn )
+{
+ m_bAppendFirstLine = false;
+}
+
+ORTFReader::~ORTFReader()
+{
+}
+
+SvParserState ORTFReader::CallParser()
+{
+ rInput.Seek(STREAM_SEEK_TO_BEGIN);
+ rInput.ResetError();
+ SvParserState eParseState = SvRTFParser::CallParser();
+ SetColumnTypes(m_pColumnList,m_pInfoMap);
+ return m_bFoundTable ? eParseState : SvParserState::Error;
+}
+
+#if defined _MSC_VER
+#pragma warning(disable: 4702) // unreachable code, bug in MSVC2015
+#endif
+
+void ORTFReader::NextToken( int nToken )
+{
+ if(m_bError || !m_nRows) // if there is an error or no more rows to check, return immediately
+ return;
+
+ if(m_xConnection.is()) // names, which CTOR was called and hence, if a table should be created
+ {
+ switch(nToken)
+ {
+ case RTF_COLORTBL:
+ {
+
+ int nTmpToken2 = GetNextToken();
+ do
+ {
+ Color aColor;
+ do
+ {
+ switch(nTmpToken2)
+ {
+ case RTF_RED: aColor.SetRed(static_cast<sal_uInt8>(nTokenValue)); break;
+ case RTF_BLUE: aColor.SetBlue(static_cast<sal_uInt8>(nTokenValue)); break;
+ case RTF_GREEN: aColor.SetGreen(static_cast<sal_uInt8>(nTokenValue)); break;
+ default: break;
+ }
+ nTmpToken2 = GetNextToken();
+ }
+ while(aToken[0] != ';' && eState != SvParserState::Error && eState != SvParserState::Accepted);
+ m_vecColor.push_back(aColor.GetRGBColor());
+ nTmpToken2 = GetNextToken();
+ }
+ while(nTmpToken2 == RTF_RED && eState != SvParserState::Error && eState != SvParserState::Accepted);
+ SkipToken();
+ }
+ break;
+
+ case RTF_TROWD:
+ {
+ if ( !m_xTable.is() ) // use first line as header
+ {
+ sal_uInt64 const nTell = rInput.Tell(); // perhaps alters position of the stream
+
+ m_bError = !CreateTable(nToken);
+ if ( m_bAppendFirstLine )
+ {
+ rInput.Seek(nTell);
+ rInput.ResetError();
+ }
+ }
+ }
+ break;
+ case RTF_INTBL:
+ if(m_bInTbl)
+ {
+ eraseTokens();
+ }
+
+ m_bInTbl = true; // Now we are in a table description
+ break;
+ case RTF_TEXTTOKEN:
+ case RTF_SINGLECHAR:
+ if(m_bInTbl) // important, as otherwise we also get the names of the fonts
+ m_sTextToken += aToken;
+ break;
+ case RTF_CELL:
+ {
+ try
+ {
+ insertValueIntoColumn();
+ }
+ catch(SQLException& e)
+ // handling update failure
+ {
+ showErrorDialog(e);
+ }
+ m_nColumnPos++;
+ eraseTokens();
+ }
+ break;
+ case RTF_ROW:
+ // it can happen that the last cell is not concluded with \cell
+ try
+ {
+ insertValueIntoColumn();
+ m_nRowCount++;
+ if(m_bIsAutoIncrement) // if bSetAutoIncrement then I have to set the autoincrement
+ m_pUpdateHelper->updateInt(1,m_nRowCount);
+ m_pUpdateHelper->insertRow();
+ }
+ catch(SQLException& e)
+ // handling update failure
+ {
+ showErrorDialog(e);
+ }
+ m_nColumnPos = 0;
+ break;
+ }
+ }
+ else // branch only valid for type checking
+ {
+ switch(nToken)
+ {
+ case RTF_TROWD:
+ // The head of the column is not included
+ if(m_bHead)
+ {
+ do
+ {}
+ while(GetNextToken() != RTF_ROW && eState != SvParserState::Error && eState != SvParserState::Accepted);
+ m_bHead = false;
+ }
+ break;
+ case RTF_INTBL:
+ m_bInTbl = true;
+ break;
+ case RTF_TEXTTOKEN:
+ case RTF_SINGLECHAR:
+ if(m_bInTbl)
+ m_sTextToken += aToken;
+ break;
+ case RTF_CELL:
+ adjustFormat();
+ m_nColumnPos++;
+ break;
+ case RTF_ROW:
+ adjustFormat();
+ m_nColumnPos = 0;
+ m_nRows--;
+ break;
+ }
+ }
+}
+
+bool ORTFReader::CreateTable(int nToken)
+{
+ OUString aTableName(DBA_RES(STR_TBL_TITLE));
+ aTableName = aTableName.getToken(0,' ');
+ aTableName = ::dbtools::createUniqueName(m_xTables, aTableName);
+
+ OUString aColumnName;
+
+ FontDescriptor aFont = VCLUnoHelper::CreateFontDescriptor(Application::GetSettings().GetStyleSettings().GetAppFont());
+ do
+ {
+ switch (nToken)
+ {
+ case RTF_UNKNOWNCONTROL:
+ case RTF_UNKNOWNDATA:
+ m_bInTbl = false;
+ aColumnName.clear();
+ break;
+ case RTF_INTBL:
+ if(m_bInTbl)
+ aColumnName.clear();
+
+ m_bInTbl = true;
+ break;
+ case RTF_TEXTTOKEN:
+ case RTF_SINGLECHAR:
+ if(m_bInTbl)
+ aColumnName += aToken;
+ break;
+ case RTF_CELL:
+ {
+ aColumnName = comphelper::string::strip(aColumnName, ' ');
+ if (aColumnName.isEmpty() || m_bAppendFirstLine )
+ aColumnName = DBA_RES(STR_COLUMN_NAME);
+
+ CreateDefaultColumn(aColumnName);
+ aColumnName.clear();
+ }
+ break;
+ case RTF_CF:
+ break;
+ case RTF_B:
+ aFont.Weight = css::awt::FontWeight::BOLD;
+ break;
+ case RTF_I:
+ aFont.Slant = css::awt::FontSlant_ITALIC;
+ break;
+ case RTF_UL:
+ aFont.Underline = css::awt::FontUnderline::SINGLE;
+ break;
+ case RTF_STRIKE:
+ aFont.Strikeout = css::awt::FontStrikeout::SINGLE;
+ break;
+ }
+ nToken = GetNextToken();
+ }
+ while(nToken != RTF_TROWD && eState != SvParserState::Error && eState != SvParserState::Accepted);
+
+ bool bOk = !m_vDestVector.empty();
+ if(bOk)
+ {
+ if ( !aColumnName.isEmpty() )
+ {
+ if ( m_bAppendFirstLine )
+ aColumnName = DBA_RES(STR_COLUMN_NAME);
+ CreateDefaultColumn(aColumnName);
+ }
+
+ m_bInTbl = false;
+ m_bFoundTable = true;
+
+ if ( isCheckEnabled() )
+ return true;
+ Any aTextColor;
+ if(!m_vecColor.empty())
+ aTextColor <<= m_vecColor[0];
+
+ bOk = !executeWizard(aTableName,aTextColor,aFont) && m_xTable.is();
+ }
+ return bOk;
+}
+
+TypeSelectionPageFactory ORTFReader::getTypeSelectionPageFactory()
+{
+ return &OWizRTFExtend::Create;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/TableCopyHelper.cxx b/dbaccess/source/ui/misc/TableCopyHelper.cxx
new file mode 100644
index 0000000000..c69c046997
--- /dev/null
+++ b/dbaccess/source/ui/misc/TableCopyHelper.cxx
@@ -0,0 +1,306 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TableCopyHelper.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <dbaccess/genericcontroller.hxx>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <com/sun/star/sdb/application/CopyTableOperation.hpp>
+#include <com/sun/star/sdb/application/CopyTableWizard.hpp>
+#include <com/sun/star/sdb/DataAccessDescriptorFactory.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+
+#include <TokenWriter.hxx>
+#include <UITools.hxx>
+#include <dbaccess/dataview.hxx>
+#include <svx/dbaexchange.hxx>
+#include <unotools/ucbhelper.hxx>
+#include <tools/urlobj.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <sal/log.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <unotools/tempfile.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+namespace dbaui
+{
+using namespace ::dbtools;
+using namespace ::svx;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdb::application;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::ucb;
+
+OTableCopyHelper::OTableCopyHelper(OGenericUnoController* _pController)
+ :m_pController(_pController)
+{
+}
+
+void OTableCopyHelper::insertTable( std::u16string_view i_rSourceDataSource, const Reference<XConnection>& i_rSourceConnection,
+ const OUString& i_rCommand, const sal_Int32 i_nCommandType,
+ const Reference< XResultSet >& i_rSourceRows, const Sequence< Any >& i_rSelection, const bool i_bBookmarkSelection,
+ std::u16string_view i_rDestDataSource, const Reference<XConnection>& i_rDestConnection)
+{
+ if ( CommandType::QUERY != i_nCommandType && CommandType::TABLE != i_nCommandType )
+ {
+ SAL_WARN("dbaccess.ui", "OTableCopyHelper::insertTable: invalid call (no supported format found)!" );
+ return;
+ }
+
+ try
+ {
+ Reference<XConnection> xSrcConnection( i_rSourceConnection );
+ if ( i_rSourceDataSource == i_rDestDataSource )
+ xSrcConnection = i_rDestConnection;
+
+ if ( !xSrcConnection.is() || !i_rDestConnection.is() )
+ {
+ SAL_WARN("dbaccess.ui", "OTableCopyHelper::insertTable: no connection/s!" );
+ return;
+ }
+
+ Reference<XComponentContext> aContext( m_pController->getORB() );
+
+ Reference< XDataAccessDescriptorFactory > xFactory( DataAccessDescriptorFactory::get( aContext ) );
+
+ Reference< XPropertySet > xSource( xFactory->createDataAccessDescriptor(), UNO_SET_THROW );
+ xSource->setPropertyValue( PROPERTY_COMMAND_TYPE, Any( i_nCommandType ) );
+ xSource->setPropertyValue( PROPERTY_COMMAND, Any( i_rCommand ) );
+ xSource->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, Any( xSrcConnection ) );
+ xSource->setPropertyValue( PROPERTY_RESULT_SET, Any( i_rSourceRows ) );
+ xSource->setPropertyValue( PROPERTY_SELECTION, Any( i_rSelection ) );
+ xSource->setPropertyValue( PROPERTY_BOOKMARK_SELECTION, Any( i_bBookmarkSelection ) );
+
+ Reference< XPropertySet > xDest( xFactory->createDataAccessDescriptor(), UNO_SET_THROW );
+ xDest->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, Any( i_rDestConnection ) );
+
+ auto xInteractionHandler = InteractionHandler::createWithParent(aContext, VCLUnoHelper::GetInterface(m_pController->getView()));
+
+ Reference<XCopyTableWizard> xWizard(CopyTableWizard::createWithInteractionHandler(aContext, xSource, xDest, xInteractionHandler), UNO_SET_THROW);
+
+ OUString sTableNameForAppend( GetTableNameForAppend() );
+ xWizard->setDestinationTableName( GetTableNameForAppend() );
+
+ bool bAppendToExisting = !sTableNameForAppend.isEmpty();
+ xWizard->setOperation( bAppendToExisting ? CopyTableOperation::AppendData : CopyTableOperation::CopyDefinitionAndData );
+
+ xWizard->execute();
+ }
+ catch( const SQLException& )
+ {
+ m_pController->showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+void OTableCopyHelper::pasteTable( const svx::ODataAccessDescriptor& _rPasteData, std::u16string_view i_rDestDataSourceName,
+ const SharedConnection& i_rDestConnection )
+{
+ OUString sSrcDataSourceName = _rPasteData.getDataSource();
+
+ OUString sCommand;
+ _rPasteData[ DataAccessDescriptorProperty::Command ] >>= sCommand;
+
+ Reference<XConnection> xSrcConnection;
+ if ( _rPasteData.has(DataAccessDescriptorProperty::Connection) )
+ {
+ OSL_VERIFY( _rPasteData[DataAccessDescriptorProperty::Connection] >>= xSrcConnection );
+ }
+
+ Reference< XResultSet > xResultSet;
+ if ( _rPasteData.has(DataAccessDescriptorProperty::Cursor) )
+ {
+ OSL_VERIFY( _rPasteData[ DataAccessDescriptorProperty::Cursor ] >>= xResultSet );
+ }
+
+ Sequence< Any > aSelection;
+ if ( _rPasteData.has( DataAccessDescriptorProperty::Selection ) )
+ {
+ OSL_VERIFY( _rPasteData[ DataAccessDescriptorProperty::Selection ] >>= aSelection );
+ OSL_ENSURE( _rPasteData.has( DataAccessDescriptorProperty::BookmarkSelection ), "OTableCopyHelper::pasteTable: you should specify BookmarkSelection, too, to be on the safe side!" );
+ }
+
+ bool bBookmarkSelection( true );
+ if ( _rPasteData.has( DataAccessDescriptorProperty::BookmarkSelection ) )
+ {
+ OSL_VERIFY( _rPasteData[ DataAccessDescriptorProperty::BookmarkSelection ] >>= bBookmarkSelection );
+ }
+ OSL_ENSURE( bBookmarkSelection, "OTableCopyHelper::pasteTable: working with selection-indices (instead of bookmarks) is error-prone, and thus deprecated!" );
+
+ sal_Int32 nCommandType = CommandType::COMMAND;
+ if ( _rPasteData.has(DataAccessDescriptorProperty::CommandType) )
+ _rPasteData[DataAccessDescriptorProperty::CommandType] >>= nCommandType;
+
+ insertTable( sSrcDataSourceName, xSrcConnection, sCommand, nCommandType,
+ xResultSet, aSelection, bBookmarkSelection,
+ i_rDestDataSourceName, i_rDestConnection );
+}
+
+void OTableCopyHelper::pasteTable( SotClipboardFormatId _nFormatId
+ ,const TransferableDataHelper& _rTransData
+ ,std::u16string_view i_rDestDataSource
+ ,const SharedConnection& _xConnection)
+{
+ if ( _nFormatId == SotClipboardFormatId::DBACCESS_TABLE || _nFormatId == SotClipboardFormatId::DBACCESS_QUERY )
+ {
+ if ( ODataAccessObjectTransferable::canExtractObjectDescriptor(_rTransData.GetDataFlavorExVector()) )
+ {
+ svx::ODataAccessDescriptor aPasteData = ODataAccessObjectTransferable::extractObjectDescriptor(_rTransData);
+ pasteTable( aPasteData,i_rDestDataSource,_xConnection);
+ }
+ }
+ else if ( _rTransData.HasFormat(_nFormatId) )
+ {
+ try
+ {
+ DropDescriptor aTrans;
+ bool bOk;
+ if ( _nFormatId != SotClipboardFormatId::RTF )
+ bOk = _rTransData.GetSotStorageStream(SotClipboardFormatId::HTML ,aTrans.aHtmlRtfStorage);
+ else
+ bOk = _rTransData.GetSotStorageStream(SotClipboardFormatId::RTF,aTrans.aHtmlRtfStorage);
+
+ aTrans.nType = E_TABLE;
+ aTrans.bHtml = SotClipboardFormatId::HTML == _nFormatId;
+ aTrans.sDefaultTableName = GetTableNameForAppend();
+ if ( !bOk || !copyTagTable(aTrans,false,_xConnection) )
+ m_pController->showError(SQLException(DBA_RES(STR_NO_TABLE_FORMAT_INSIDE), *m_pController, "S1000", 0, Any()));
+ }
+ catch(const SQLException&)
+ {
+ m_pController->showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ else
+ m_pController->showError(SQLException(DBA_RES(STR_NO_TABLE_FORMAT_INSIDE), *m_pController, "S1000", 0, Any()));
+}
+
+void OTableCopyHelper::pasteTable( const TransferableDataHelper& _rTransData
+ ,std::u16string_view i_rDestDataSource
+ ,const SharedConnection& _xConnection)
+{
+ if ( _rTransData.HasFormat(SotClipboardFormatId::DBACCESS_TABLE) || _rTransData.HasFormat(SotClipboardFormatId::DBACCESS_QUERY) )
+ pasteTable( SotClipboardFormatId::DBACCESS_TABLE,_rTransData,i_rDestDataSource,_xConnection);
+ else if ( _rTransData.HasFormat(SotClipboardFormatId::HTML) )
+ pasteTable( SotClipboardFormatId::HTML,_rTransData,i_rDestDataSource,_xConnection);
+ else if ( _rTransData.HasFormat(SotClipboardFormatId::RTF) )
+ pasteTable( SotClipboardFormatId::RTF,_rTransData,i_rDestDataSource,_xConnection);
+}
+
+bool OTableCopyHelper::copyTagTable(OTableCopyHelper::DropDescriptor const & _rDesc, bool _bCheck, const SharedConnection& _xConnection)
+{
+ rtl::Reference<ODatabaseImportExport> pImport;
+ if ( _rDesc.bHtml )
+ pImport = new OHTMLImportExport(_xConnection,getNumberFormatter(_xConnection, m_pController->getORB()),m_pController->getORB());
+ else
+ pImport = new ORTFImportExport(_xConnection,getNumberFormatter(_xConnection, m_pController->getORB()),m_pController->getORB());
+
+ SvStream* pStream = _rDesc.aHtmlRtfStorage.get();
+ if ( _bCheck )
+ pImport->enableCheckOnly();
+
+ //set the selected tablename
+ pImport->setSTableName(_rDesc.sDefaultTableName);
+
+ pImport->setStream(pStream);
+ return pImport->Read();
+}
+
+bool OTableCopyHelper::isTableFormat(const TransferableDataHelper& _rClipboard)
+{
+ bool bTableFormat = _rClipboard.HasFormat(SotClipboardFormatId::DBACCESS_TABLE)
+ || _rClipboard.HasFormat(SotClipboardFormatId::DBACCESS_QUERY)
+ || _rClipboard.HasFormat(SotClipboardFormatId::RTF)
+ || _rClipboard.HasFormat(SotClipboardFormatId::HTML);
+
+ return bTableFormat;
+}
+
+bool OTableCopyHelper::copyTagTable(const TransferableDataHelper& _aDroppedData
+ ,DropDescriptor& _rAsyncDrop
+ ,const SharedConnection& _xConnection)
+{
+ bool bRet = false;
+ bool bHtml = _aDroppedData.HasFormat(SotClipboardFormatId::HTML);
+ if ( bHtml || _aDroppedData.HasFormat(SotClipboardFormatId::RTF) )
+ {
+ bool bOk;
+ if ( bHtml )
+ bOk = _aDroppedData.GetSotStorageStream(SotClipboardFormatId::HTML ,_rAsyncDrop.aHtmlRtfStorage);
+ else
+ bOk = _aDroppedData.GetSotStorageStream(SotClipboardFormatId::RTF,_rAsyncDrop.aHtmlRtfStorage);
+
+ _rAsyncDrop.bHtml = bHtml;
+ _rAsyncDrop.bError = !copyTagTable(_rAsyncDrop,true,_xConnection);
+
+ bRet = ( !_rAsyncDrop.bError && bOk && _rAsyncDrop.aHtmlRtfStorage.is() );
+ if ( bRet )
+ {
+ // now we need to copy the stream
+ ::utl::TempFileNamed aTmp;
+ _rAsyncDrop.aUrl = aTmp.GetURL();
+ ::tools::SvRef<SotTempStream> aNew = new SotTempStream( aTmp.GetFileName() );
+ _rAsyncDrop.aHtmlRtfStorage->Seek(STREAM_SEEK_TO_BEGIN);
+ _rAsyncDrop.aHtmlRtfStorage->CopyTo( aNew.get() );
+ _rAsyncDrop.aHtmlRtfStorage = aNew;
+ }
+ else
+ _rAsyncDrop.aHtmlRtfStorage = nullptr;
+ }
+ return bRet;
+}
+
+void OTableCopyHelper::asyncCopyTagTable( DropDescriptor& _rDesc
+ ,std::u16string_view i_rDestDataSource
+ ,const SharedConnection& _xConnection)
+{
+ if ( _rDesc.aHtmlRtfStorage.is() )
+ {
+ copyTagTable(_rDesc,false,_xConnection);
+ _rDesc.aHtmlRtfStorage = nullptr;
+ // we now have to delete the temp file created in executeDrop
+ INetURLObject aURL;
+ aURL.SetURL(_rDesc.aUrl);
+ ::utl::UCBContentHelper::Kill(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE));
+ }
+ else if ( !_rDesc.bError )
+ pasteTable(_rDesc.aDroppedData,i_rDestDataSource,_xConnection);
+ else
+ m_pController->showError(SQLException(DBA_RES(STR_NO_TABLE_FORMAT_INSIDE), *m_pController, "S1000", 0, Any()));
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/TokenWriter.cxx b/dbaccess/source/ui/misc/TokenWriter.cxx
new file mode 100644
index 0000000000..fd2f098db4
--- /dev/null
+++ b/dbaccess/source/ui/misc/TokenWriter.cxx
@@ -0,0 +1,967 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TokenWriter.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <tools/stream.hxx>
+#include <osl/diagnose.h>
+#include <rtl/tencinfo.h>
+#include <sal/log.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <RtfReader.hxx>
+#include <HtmlReader.hxx>
+#include <strings.hxx>
+#include <comphelper/types.hxx>
+#include <connectivity/dbtools.hxx>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XRowSet.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <com/sun/star/awt/FontStrikeout.hpp>
+#include <com/sun/star/awt/FontSlant.hpp>
+#include <com/sun/star/awt/FontUnderline.hpp>
+#include <com/sun/star/document/DocumentProperties.hpp>
+#include <svtools/htmlkywd.hxx>
+#include <svtools/rtfkeywd.hxx>
+#include <tools/color.hxx>
+#include <svtools/htmlout.hxx>
+#include <sfx2/frmhtmlw.hxx>
+#include <svl/numuno.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <UITools.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/settings.hxx>
+#include <svtools/rtfout.hxx>
+#include <svtools/htmlcfg.hxx>
+#include <o3tl/string_view.hxx>
+#include <connectivity/formattedcolumnvalue.hxx>
+#include <memory>
+
+using namespace dbaui;
+using namespace dbtools;
+using namespace svx;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::util;
+
+#define CELL_X 1437
+
+ODatabaseImportExport::ODatabaseImportExport(const svx::ODataAccessDescriptor& _aDataDescriptor,
+ const Reference< XComponentContext >& _rM,
+ const Reference< css::util::XNumberFormatter >& _rxNumberF)
+ :m_bBookmarkSelection( false )
+ ,m_pStream(nullptr)
+ ,m_xFormatter(_rxNumberF)
+ ,m_xContext(_rM)
+ ,m_nCommandType(CommandType::TABLE)
+ ,m_bNeedToReInitialize(false)
+ ,m_bInInitialize(false)
+ ,m_bCheckOnly(false)
+{
+ m_eDestEnc = osl_getThreadTextEncoding();
+
+ osl_atomic_increment( &m_refCount );
+ impl_initFromDescriptor( _aDataDescriptor, false );
+ osl_atomic_decrement( &m_refCount );
+}
+
+// import data
+ODatabaseImportExport::ODatabaseImportExport( ::dbtools::SharedConnection _xConnection,
+ const Reference< XNumberFormatter >& _rxNumberF, const Reference< XComponentContext >& _rM )
+ :m_bBookmarkSelection( false )
+ ,m_pStream(nullptr)
+ ,m_xConnection(std::move(_xConnection))
+ ,m_xFormatter(_rxNumberF)
+ ,m_xContext(_rM)
+ ,m_nCommandType(css::sdb::CommandType::TABLE)
+ ,m_bNeedToReInitialize(false)
+ ,m_bInInitialize(false)
+ ,m_bCheckOnly(false)
+{
+ m_eDestEnc = osl_getThreadTextEncoding();
+}
+
+ODatabaseImportExport::~ODatabaseImportExport()
+{
+ acquire();
+ dispose();
+}
+
+void ODatabaseImportExport::dispose()
+{
+ // remove me as listener
+ Reference< XComponent > xComponent(m_xConnection, UNO_QUERY);
+ if (xComponent.is())
+ {
+ Reference< XEventListener> xEvt(this);
+ xComponent->removeEventListener(xEvt);
+ }
+ m_xConnection.clear();
+
+ ::comphelper::disposeComponent(m_xRow);
+
+ m_xObject.clear();
+ m_xResultSetMetaData.clear();
+ m_xResultSet.clear();
+ m_xRow.clear();
+ m_xRowLocate.clear();
+ m_xFormatter.clear();
+ m_xRowSetColumns.clear();
+}
+
+void SAL_CALL ODatabaseImportExport::disposing( const EventObject& Source )
+{
+ Reference<XConnection> xCon(Source.Source,UNO_QUERY);
+ if(m_xConnection.is() && m_xConnection == xCon)
+ {
+ m_xConnection.clear();
+ dispose();
+ m_bNeedToReInitialize = true;
+ }
+}
+
+void ODatabaseImportExport::initialize( const ODataAccessDescriptor& _aDataDescriptor )
+{
+ impl_initFromDescriptor( _aDataDescriptor, true );
+}
+
+void ODatabaseImportExport::impl_initFromDescriptor( const ODataAccessDescriptor& _aDataDescriptor, bool _bPlusDefaultInit)
+{
+ if ( !_bPlusDefaultInit )
+ {
+ m_sDataSourceName = _aDataDescriptor.getDataSource();
+ _aDataDescriptor[DataAccessDescriptorProperty::CommandType] >>= m_nCommandType;
+ _aDataDescriptor[DataAccessDescriptorProperty::Command] >>= m_sName;
+ // some additional information
+ if(_aDataDescriptor.has(DataAccessDescriptorProperty::Connection))
+ {
+ Reference< XConnection > xPureConn( _aDataDescriptor[DataAccessDescriptorProperty::Connection], UNO_QUERY );
+ m_xConnection.reset( xPureConn, SharedConnection::NoTakeOwnership );
+ Reference< XEventListener> xEvt(this);
+ Reference< XComponent > xComponent(m_xConnection, UNO_QUERY);
+ if (xComponent.is() && xEvt.is())
+ xComponent->addEventListener(xEvt);
+ }
+
+ if ( _aDataDescriptor.has( DataAccessDescriptorProperty::Selection ) )
+ _aDataDescriptor[ DataAccessDescriptorProperty::Selection ] >>= m_aSelection;
+
+ if ( _aDataDescriptor.has( DataAccessDescriptorProperty::BookmarkSelection ) )
+ _aDataDescriptor[ DataAccessDescriptorProperty::BookmarkSelection ] >>= m_bBookmarkSelection;
+
+ if ( _aDataDescriptor.has( DataAccessDescriptorProperty::Cursor ) )
+ {
+ _aDataDescriptor[ DataAccessDescriptorProperty::Cursor ] >>= m_xResultSet;
+ m_xRowLocate.set( m_xResultSet, UNO_QUERY );
+ }
+
+ if ( m_aSelection.hasElements() )
+ {
+ if ( !m_xResultSet.is() )
+ {
+ SAL_WARN("dbaccess.ui", "ODatabaseImportExport::impl_initFromDescriptor: selection without result set is nonsense!" );
+ m_aSelection.realloc( 0 );
+ }
+ }
+
+ if ( m_aSelection.hasElements() )
+ {
+ if ( m_bBookmarkSelection && !m_xRowLocate.is() )
+ {
+ SAL_WARN("dbaccess.ui", "ODatabaseImportExport::impl_initFromDescriptor: no XRowLocate -> no bookmarks!" );
+ m_aSelection.realloc( 0 );
+ }
+ }
+ }
+ else
+ initialize();
+}
+
+void ODatabaseImportExport::initialize()
+{
+ m_bInInitialize = true;
+ m_bNeedToReInitialize = false;
+
+ if ( !m_xConnection.is() )
+ { // we need a connection
+ OSL_ENSURE(!m_sDataSourceName.isEmpty(),"There must be a datsource name!");
+ Reference<XNameAccess> xDatabaseContext( DatabaseContext::create(m_xContext), UNO_QUERY_THROW);
+ Reference< XEventListener> xEvt(this);
+
+ Reference< XConnection > xConnection;
+ SQLExceptionInfo aInfo = ::dbaui::createConnection( m_sDataSourceName, xDatabaseContext, m_xContext, xEvt, xConnection );
+ m_xConnection.reset( xConnection );
+
+ if(aInfo.isValid() && aInfo.getType() == SQLExceptionInfo::TYPE::SQLException)
+ throw *static_cast<const SQLException*>(aInfo);
+ }
+
+ Reference<XNameAccess> xNameAccess;
+ switch(m_nCommandType)
+ {
+ case CommandType::TABLE:
+ {
+ // only for tables
+ Reference<XTablesSupplier> xSup(m_xConnection,UNO_QUERY);
+ if(xSup.is())
+ xNameAccess = xSup->getTables();
+ }
+ break;
+ case CommandType::QUERY:
+ {
+ Reference<XQueriesSupplier> xSup(m_xConnection,UNO_QUERY);
+ if(xSup.is())
+ xNameAccess = xSup->getQueries();
+ }
+ break;
+ }
+ if(xNameAccess.is() && xNameAccess->hasByName(m_sName))
+ {
+ xNameAccess->getByName(m_sName) >>= m_xObject;
+ }
+
+ if(m_xObject.is())
+ {
+ try
+ {
+ if(m_xObject->getPropertySetInfo()->hasPropertyByName(PROPERTY_FONT))
+ m_xObject->getPropertyValue(PROPERTY_FONT) >>= m_aFont;
+
+ // the result set may be already set with the datadescriptor
+ if ( !m_xResultSet.is() )
+ {
+ m_xResultSet.set( m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.sdb.RowSet", m_xContext), UNO_QUERY );
+ Reference< XPropertySet > xProp( m_xResultSet, UNO_QUERY_THROW );
+ xProp->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, Any( m_xConnection.getTyped() ) );
+ xProp->setPropertyValue( PROPERTY_COMMAND_TYPE, Any( m_nCommandType ) );
+ xProp->setPropertyValue( PROPERTY_COMMAND, Any( m_sName ) );
+ Reference< XRowSet > xRowSet( xProp, UNO_QUERY );
+ xRowSet->execute();
+ }
+ if ( !m_xRow.is() && m_xResultSet.is() )
+ {
+ m_xRow.set( m_xResultSet, UNO_QUERY );
+ m_xRowLocate.set( m_xResultSet, UNO_QUERY );
+ m_xResultSetMetaData = Reference<XResultSetMetaDataSupplier>(m_xRow,UNO_QUERY_THROW)->getMetaData();
+ Reference<XColumnsSupplier> xSup(m_xResultSet,UNO_QUERY_THROW);
+ m_xRowSetColumns.set(xSup->getColumns(),UNO_QUERY_THROW);
+ }
+ }
+ catch(Exception& )
+ {
+ m_xRow = nullptr;
+ m_xResultSetMetaData = nullptr;
+ ::comphelper::disposeComponent(m_xResultSet);
+ throw;
+ }
+ }
+ if ( m_aFont.Name.isEmpty() )
+ {
+ vcl::Font aApplicationFont = OutputDevice::GetDefaultFont(
+ DefaultFontType::SANS_UNICODE,
+ Application::GetSettings().GetUILanguageTag().getLanguageType(),
+ GetDefaultFontFlags::OnlyOne
+ );
+ m_aFont = VCLUnoHelper::CreateFontDescriptor( aApplicationFont );
+ }
+
+ m_bInInitialize = false;
+}
+
+bool ODatabaseImportExport::Write()
+{
+ if ( m_bNeedToReInitialize )
+ {
+ if ( !m_bInInitialize )
+ initialize();
+ }
+ return true;
+}
+
+bool ODatabaseImportExport::Read()
+{
+ if ( m_bNeedToReInitialize )
+ {
+ if ( !m_bInInitialize )
+ initialize();
+ }
+ return true;
+}
+
+bool ORTFImportExport::Write()
+{
+ ODatabaseImportExport::Write();
+ m_pStream->WriteChar( '{' ).WriteOString( OOO_STRING_SVTOOLS_RTF_RTF );
+ m_pStream->WriteOString(OOO_STRING_SVTOOLS_RTF_ANSI);
+ if (sal_uInt32 nCpg = rtl_getWindowsCodePageFromTextEncoding(m_eDestEnc); nCpg && nCpg != 65001)
+ {
+ m_pStream->WriteOString(OOO_STRING_SVTOOLS_RTF_ANSICPG).WriteNumberAsString(nCpg);
+ }
+ m_pStream->WriteOString(SAL_NEWLINE_STRING);
+
+ bool bBold = ( css::awt::FontWeight::BOLD == m_aFont.Weight );
+ bool bItalic = ( css::awt::FontSlant_ITALIC == m_aFont.Slant );
+ bool bUnderline = ( css::awt::FontUnderline::NONE != m_aFont.Underline );
+ bool bStrikeout = ( css::awt::FontStrikeout::NONE != m_aFont.Strikeout );
+
+ ::Color aColor;
+ if(m_xObject.is())
+ m_xObject->getPropertyValue(PROPERTY_TEXTCOLOR) >>= aColor;
+
+ OString aFonts(OUStringToOString(m_aFont.Name, RTL_TEXTENCODING_MS_1252));
+ if (aFonts.isEmpty())
+ {
+ OUString aName = Application::GetSettings().GetStyleSettings().GetAppFont().GetFamilyName();
+ aFonts = OUStringToOString(aName, RTL_TEXTENCODING_MS_1252);
+ }
+
+ m_pStream->WriteOString( "{\\fonttbl" );
+ if (!aFonts.isEmpty())
+ {
+ sal_Int32 nIdx{0};
+ sal_Int32 nTok{-1}; // to compensate pre-increment
+ do {
+ m_pStream->WriteOString( "\\f" );
+ m_pStream->WriteNumberAsString(++nTok);
+ m_pStream->WriteOString( "\\fcharset0\\fnil " );
+ m_pStream->WriteOString( o3tl::getToken(aFonts, 0, ';', nIdx) );
+ m_pStream->WriteChar( ';' );
+ } while (nIdx>=0);
+ }
+ m_pStream->WriteChar( '}' ) ;
+ m_pStream->WriteOString( SAL_NEWLINE_STRING );
+ // write the rtf color table
+ m_pStream->WriteChar( '{' ).WriteOString( OOO_STRING_SVTOOLS_RTF_COLORTBL ).WriteOString( OOO_STRING_SVTOOLS_RTF_RED );
+ m_pStream->WriteNumberAsString(aColor.GetRed());
+ m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_GREEN );
+ m_pStream->WriteNumberAsString(aColor.GetGreen());
+ m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_BLUE );
+ m_pStream->WriteNumberAsString(aColor.GetBlue());
+
+ m_pStream->WriteOString( ";\\red255\\green255\\blue255;\\red192\\green192\\blue192;}" )
+ .WriteOString( SAL_NEWLINE_STRING );
+
+ static char const aCell1[] = "\\clbrdrl\\brdrs\\brdrcf0\\clbrdrt\\brdrs\\brdrcf0\\clbrdrb\\brdrs\\brdrcf0\\clbrdrr\\brdrs\\brdrcf0\\clshdng10000\\clcfpat2\\cellx";
+
+ m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_TROWD ).WriteOString( OOO_STRING_SVTOOLS_RTF_TRGAPH );
+ m_pStream->WriteOString("40");
+ m_pStream->WriteOString( SAL_NEWLINE_STRING );
+
+ if(m_xObject.is())
+ {
+ Reference<XColumnsSupplier> xColSup(m_xObject,UNO_QUERY);
+ Reference<XNameAccess> xColumns = xColSup->getColumns();
+ Sequence< OUString> aNames(xColumns->getElementNames());
+ const OUString* pIter = aNames.getConstArray();
+
+ sal_Int32 nCount = aNames.getLength();
+ bool bUseResultMetaData = false;
+ if ( !nCount )
+ {
+ nCount = m_xResultSetMetaData->getColumnCount();
+ bUseResultMetaData = true;
+ }
+
+ for( sal_Int32 i=1; i<=nCount; ++i )
+ {
+ m_pStream->WriteOString( aCell1 );
+ m_pStream->WriteNumberAsString(i*CELL_X);
+ m_pStream->WriteOString( SAL_NEWLINE_STRING );
+ }
+
+ // column description
+ m_pStream->WriteChar( '{' ).WriteOString( SAL_NEWLINE_STRING );
+ m_pStream->WriteOString( "\\trrh-270\\pard\\intbl" );
+
+ std::unique_ptr<OString[]> pHorzChar(new OString[nCount]);
+
+ for ( sal_Int32 i=1; i <= nCount; ++i )
+ {
+ sal_Int32 nAlign = 0;
+ OUString sColumnName;
+ if ( bUseResultMetaData )
+ sColumnName = m_xResultSetMetaData->getColumnName(i);
+ else
+ {
+ sColumnName = *pIter;
+ Reference<XPropertySet> xColumn;
+ xColumns->getByName(sColumnName) >>= xColumn;
+ xColumn->getPropertyValue(PROPERTY_ALIGN) >>= nAlign;
+ ++pIter;
+ }
+
+ const char* pChar;
+ switch( nAlign )
+ {
+ case 1: pChar = OOO_STRING_SVTOOLS_RTF_QC; break;
+ case 2: pChar = OOO_STRING_SVTOOLS_RTF_QR; break;
+ case 0:
+ default:pChar = OOO_STRING_SVTOOLS_RTF_QL; break;
+ }
+
+ pHorzChar[i-1] = pChar; // to avoid to always rummage in the ITEMSET later on
+
+ m_pStream->WriteOString( SAL_NEWLINE_STRING );
+ m_pStream->WriteChar( '{' );
+ m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_QC ); // column header always centered
+
+ if ( bBold ) m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_B );
+ if ( bItalic ) m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_I );
+ if ( bUnderline ) m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_UL );
+ if ( bStrikeout ) m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_STRIKE );
+
+ m_pStream->WriteOString( "\\fs20\\f0\\cf0\\cb2" );
+ m_pStream->WriteChar( ' ' );
+ RTFOutFuncs::Out_String(*m_pStream, sColumnName, m_eDestEnc);
+
+ m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_CELL );
+ m_pStream->WriteChar( '}' );
+ m_pStream->WriteOString( SAL_NEWLINE_STRING );
+ m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_PARD ).WriteOString( OOO_STRING_SVTOOLS_RTF_INTBL );
+ }
+
+ m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_ROW );
+ m_pStream->WriteOString( SAL_NEWLINE_STRING ).WriteChar( '}' );
+ m_pStream->WriteOString( SAL_NEWLINE_STRING );
+
+ sal_Int32 k=1;
+ sal_Int32 kk=0;
+ if ( m_aSelection.hasElements() )
+ {
+ const Any* pSelIter = m_aSelection.getConstArray();
+ const Any* pEnd = pSelIter + m_aSelection.getLength();
+
+ bool bContinue = true;
+ for( ; pSelIter != pEnd && bContinue; ++pSelIter )
+ {
+ if ( m_bBookmarkSelection )
+ {
+ bContinue = m_xRowLocate->moveToBookmark( *pSelIter );
+ }
+ else
+ {
+ sal_Int32 nPos = -1;
+ OSL_VERIFY( *pSelIter >>= nPos );
+ bContinue = ( m_xResultSet->absolute( nPos ) );
+ }
+
+ if ( bContinue )
+ appendRow( pHorzChar.get(), nCount, k, kk );
+ }
+ }
+ else
+ {
+ m_xResultSet->beforeFirst(); // set back before the first row
+ while(m_xResultSet->next())
+ {
+ appendRow(pHorzChar.get(),nCount,k,kk);
+ }
+ }
+ }
+
+ m_pStream->WriteChar( '}' ).WriteOString( SAL_NEWLINE_STRING );
+ m_pStream->WriteUChar( 0 );
+ return ((*m_pStream).GetError() == ERRCODE_NONE);
+}
+
+void ORTFImportExport::appendRow(OString const * pHorzChar,sal_Int32 _nColumnCount,sal_Int32& k,sal_Int32& kk)
+{
+ ++kk;
+ m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_TROWD ).WriteOString( OOO_STRING_SVTOOLS_RTF_TRGAPH );
+ m_pStream->WriteOString("40");
+ m_pStream->WriteOString( SAL_NEWLINE_STRING );
+
+ static char const aCell2[] = "\\clbrdrl\\brdrs\\brdrcf2\\clbrdrt\\brdrs\\brdrcf2\\clbrdrb\\brdrs\\brdrcf2\\clbrdrr\\brdrs\\brdrcf2\\clshdng10000\\clcfpat1\\cellx";
+
+ for ( sal_Int32 i=1; i<=_nColumnCount; ++i )
+ {
+ m_pStream->WriteOString( aCell2 );
+ m_pStream->WriteNumberAsString(i*CELL_X);
+ m_pStream->WriteOString( SAL_NEWLINE_STRING );
+ }
+
+ const bool bBold = ( css::awt::FontWeight::BOLD == m_aFont.Weight );
+ const bool bItalic = ( css::awt::FontSlant_ITALIC == m_aFont.Slant );
+ const bool bUnderline = ( css::awt::FontUnderline::NONE != m_aFont.Underline );
+ const bool bStrikeout = ( css::awt::FontStrikeout::NONE != m_aFont.Strikeout );
+ Reference< XRowSet > xRowSet(m_xRow,UNO_QUERY);
+
+ m_pStream->WriteChar( '{' );
+ m_pStream->WriteOString( "\\trrh-270\\pard\\intbl" );
+ for ( sal_Int32 i=1; i <= _nColumnCount; ++i )
+ {
+ m_pStream->WriteOString( SAL_NEWLINE_STRING );
+ m_pStream->WriteChar( '{' );
+ m_pStream->WriteOString( pHorzChar[i-1] );
+
+ if ( bBold ) m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_B );
+ if ( bItalic ) m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_I );
+ if ( bUnderline ) m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_UL );
+ if ( bStrikeout ) m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_STRIKE );
+
+ m_pStream->WriteOString( "\\fs20\\f1\\cf0\\cb1 " );
+
+ try
+ {
+ Reference<XPropertySet> xColumn(m_xRowSetColumns->getByIndex(i-1),UNO_QUERY_THROW);
+ dbtools::FormattedColumnValue aFormatedValue(m_xContext,xRowSet,xColumn);
+ OUString sValue = aFormatedValue.getFormattedValue();
+ if ( !sValue.isEmpty() )
+ RTFOutFuncs::Out_String(*m_pStream,sValue,m_eDestEnc);
+ }
+ catch (Exception&)
+ {
+ SAL_WARN("dbaccess.ui","RTF WRITE!");
+ }
+
+ m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_CELL );
+ m_pStream->WriteChar( '}' );
+ m_pStream->WriteOString( SAL_NEWLINE_STRING );
+ m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_PARD ).WriteOString( OOO_STRING_SVTOOLS_RTF_INTBL );
+ }
+ m_pStream->WriteOString( OOO_STRING_SVTOOLS_RTF_ROW ).WriteOString( SAL_NEWLINE_STRING );
+ m_pStream->WriteChar( '}' );
+ ++k;
+}
+
+bool ORTFImportExport::Read()
+{
+ ODatabaseImportExport::Read();
+ SvParserState eState = SvParserState::Error;
+ if ( m_pStream )
+ {
+ tools::SvRef<ORTFReader> xReader(new ORTFReader((*m_pStream),m_xConnection,m_xFormatter,m_xContext));
+ if ( isCheckEnabled() )
+ xReader->enableCheckOnly();
+ eState = xReader->CallParser();
+ }
+
+ return eState != SvParserState::Error;
+}
+
+const sal_Int16 OHTMLImportExport::nCellSpacing = 0;
+const char OHTMLImportExport::sIndentSource[nIndentMax+1] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
+
+OHTMLImportExport::OHTMLImportExport(const svx::ODataAccessDescriptor& _aDataDescriptor,
+ const Reference< XComponentContext >& _rM,
+ const Reference< css::util::XNumberFormatter >& _rxNumberF)
+ : ODatabaseImportExport(_aDataDescriptor,_rM,_rxNumberF)
+ ,m_nIndent(0)
+#if OSL_DEBUG_LEVEL > 0
+ ,m_bCheckFont(false)
+#endif
+{
+ // set HTML configuration
+ m_eDestEnc = RTL_TEXTENCODING_UTF8;
+ strncpy( sIndent, sIndentSource ,std::min(sizeof(sIndent),sizeof(sIndentSource)));
+ sIndent[0] = 0;
+}
+
+bool OHTMLImportExport::Write()
+{
+ ODatabaseImportExport::Write();
+ if(m_xObject.is())
+ {
+ m_pStream->WriteChar( '<' ).WriteOString( OOO_STRING_SVTOOLS_HTML_doctype ).WriteChar( ' ' ).WriteOString( OOO_STRING_SVTOOLS_HTML_doctype5 ).WriteChar( '>' ).WriteOString( SAL_NEWLINE_STRING ).WriteOString( SAL_NEWLINE_STRING );
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_html).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+ WriteHeader();
+ m_pStream->WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+ WriteBody();
+ m_pStream->WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_html, false).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+
+ return ((*m_pStream).GetError() == ERRCODE_NONE);
+ }
+ return false;
+}
+
+bool OHTMLImportExport::Read()
+{
+ ODatabaseImportExport::Read();
+ SvParserState eState = SvParserState::Error;
+ if ( m_pStream )
+ {
+ tools::SvRef<OHTMLReader> xReader(new OHTMLReader((*m_pStream),m_xConnection,m_xFormatter,m_xContext));
+ if ( isCheckEnabled() )
+ xReader->enableCheckOnly();
+ xReader->SetTableName(m_sDefaultTableName);
+ eState = xReader->CallParser();
+ }
+
+ return eState != SvParserState::Error;
+}
+
+void OHTMLImportExport::WriteHeader()
+{
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ document::DocumentProperties::create( m_xContext ) );
+ if (xDocProps.is()) {
+ xDocProps->setTitle(m_sName);
+ }
+
+ IncIndent(1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_head).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+
+ SfxFrameHTMLWriter::Out_DocInfo( (*m_pStream), OUString(),
+ xDocProps, sIndent );
+ m_pStream->WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+ IncIndent(-1);
+ m_pStream->WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_head, false).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+}
+
+void OHTMLImportExport::WriteBody()
+{
+ IncIndent(1);
+ m_pStream->WriteOString( "<" ).WriteOString( OOO_STRING_SVTOOLS_HTML_style ).WriteOString( " " ).WriteOString( OOO_STRING_SVTOOLS_HTML_O_type ).WriteOString( "=\"text/css\">" );
+
+ m_pStream->WriteOString( "<!-- " );
+ m_pStream->WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+ m_pStream->WriteOString( OOO_STRING_SVTOOLS_HTML_body ).WriteOString( " { " ).WriteOString( "font-family: " ).WriteChar( '"' ).WriteOString( OUStringToOString(m_aFont.Name, osl_getThreadTextEncoding()) ).WriteChar( '\"' );
+ // TODO : think about the encoding of the font name
+ m_pStream->WriteOString( "; " ).WriteOString( "font-size: " );
+ m_pStream->WriteNumberAsString(m_aFont.Height);
+ m_pStream->WriteChar( '}' );
+
+ m_pStream->WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+ m_pStream->WriteOString( " -->" );
+ IncIndent(-1);
+ m_pStream->WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_style, false).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+ m_pStream->WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+
+ // default Textcolour black
+ m_pStream->WriteChar( '<' ).WriteOString( OOO_STRING_SVTOOLS_HTML_body ).WriteChar( ' ' ).WriteOString( OOO_STRING_SVTOOLS_HTML_O_text ).WriteChar( '=' );
+ ::Color aColor;
+ if(m_xObject.is())
+ m_xObject->getPropertyValue(PROPERTY_TEXTCOLOR) >>= aColor;
+ HTMLOutFuncs::Out_Color( (*m_pStream), aColor );
+
+ m_pStream->WriteOString( " " OOO_STRING_SVTOOLS_HTML_O_bgcolor "=" );
+ HTMLOutFuncs::Out_Color( (*m_pStream), aColor );
+
+ m_pStream->WriteChar( '>' );
+ m_pStream->WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+
+ WriteTables();
+
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_body, false).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+}
+
+void OHTMLImportExport::WriteTables()
+{
+ OString aStrOut = OOO_STRING_SVTOOLS_HTML_table
+ " "
+ OOO_STRING_SVTOOLS_HTML_frame
+ "="
+ OOO_STRING_SVTOOLS_HTML_TF_void ""_ostr;
+
+ Sequence< OUString> aNames;
+ Reference<XNameAccess> xColumns;
+ bool bUseResultMetaData = false;
+ if(m_xObject.is())
+ {
+ Reference<XColumnsSupplier> xColSup(m_xObject,UNO_QUERY);
+ xColumns = xColSup->getColumns();
+ aNames = xColumns->getElementNames();
+ if ( !aNames.hasElements() )
+ {
+ sal_Int32 nCount = m_xResultSetMetaData->getColumnCount();
+ aNames.realloc(nCount);
+ auto aNamesRange = asNonConstRange(aNames);
+ for (sal_Int32 i= 0; i < nCount; ++i)
+ aNamesRange[i] = m_xResultSetMetaData->getColumnName(i+1);
+ bUseResultMetaData = true;
+ }
+ }
+
+ aStrOut += " "
+ OOO_STRING_SVTOOLS_HTML_O_align
+ "="
+ OOO_STRING_SVTOOLS_HTML_AL_left
+ " "
+ OOO_STRING_SVTOOLS_HTML_O_cellspacing
+ "=" +
+ OString::number(nCellSpacing) +
+ " "
+ OOO_STRING_SVTOOLS_HTML_O_cols
+ "=" +
+ OString::number(aNames.getLength()) +
+ " "
+ OOO_STRING_SVTOOLS_HTML_O_border
+ "=1";
+
+ IncIndent(1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, aStrOut);
+
+ FontOn();
+
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_caption);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_bold);
+
+ m_pStream->WriteOString( OUStringToOString(m_sName, osl_getThreadTextEncoding()) );
+ // TODO : think about the encoding of the name
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_bold, false);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_caption, false);
+
+ FontOff();
+ m_pStream->WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+ // </FONT>
+
+ IncIndent(1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_thead).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+
+ IncIndent(1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_tablerow).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+
+ if(m_xObject.is())
+ {
+ std::unique_ptr<sal_Int32[]> pFormat(new sal_Int32[aNames.getLength()]);
+
+ std::unique_ptr<const char *[]> pHorJustify(new const char*[aNames.getLength()]);
+ std::unique_ptr<sal_Int32[]> pColWidth(new sal_Int32[aNames.getLength()]);
+
+ sal_Int32 nHeight = 0;
+ m_xObject->getPropertyValue(PROPERTY_ROW_HEIGHT) >>= nHeight;
+
+ // 1. writing the column description
+ const OUString* pIter = aNames.getConstArray();
+ const OUString* pEnd = pIter + aNames.getLength();
+
+ for( sal_Int32 i=0;pIter != pEnd; ++pIter,++i )
+ {
+ sal_Int32 nAlign = 0;
+ pFormat[i] = 0;
+ pColWidth[i] = 100;
+ if ( !bUseResultMetaData )
+ {
+ Reference<XPropertySet> xColumn;
+ xColumns->getByName(*pIter) >>= xColumn;
+ xColumn->getPropertyValue(PROPERTY_ALIGN) >>= nAlign;
+ pFormat[i] = ::comphelper::getINT32(xColumn->getPropertyValue(PROPERTY_FORMATKEY));
+ pColWidth[i] = ::comphelper::getINT32(xColumn->getPropertyValue(PROPERTY_WIDTH));
+ }
+
+ switch( nAlign )
+ {
+ case 1: pHorJustify[i] = OOO_STRING_SVTOOLS_HTML_AL_center; break;
+ case 2: pHorJustify[i] = OOO_STRING_SVTOOLS_HTML_AL_right; break;
+ default: pHorJustify[i] = OOO_STRING_SVTOOLS_HTML_AL_left; break;
+ }
+
+ if(i == aNames.getLength()-1)
+ IncIndent(-1);
+
+ WriteCell(pFormat[i],pColWidth[i],nHeight,pHorJustify[i],*pIter,OOO_STRING_SVTOOLS_HTML_tableheader);
+ }
+
+ IncIndent(-1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_tablerow, false).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_thead, false).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+
+ IncIndent(1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_tbody).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+
+ // 2. and now the data
+ Reference< XRowSet > xRowSet(m_xRow,UNO_QUERY);
+ m_xResultSet->beforeFirst(); // set back before the first row
+ while(m_xResultSet->next())
+ {
+ IncIndent(1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_tablerow).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+
+ for(sal_Int32 i=1;i<=aNames.getLength();++i)
+ {
+ if(i == aNames.getLength())
+ IncIndent(-1);
+
+ OUString aValue;
+ try
+ {
+ Reference<XPropertySet> xColumn(m_xRowSetColumns->getByIndex(i-1),UNO_QUERY_THROW);
+ dbtools::FormattedColumnValue aFormatedValue(m_xContext,xRowSet,xColumn);
+ OUString sValue = aFormatedValue.getFormattedValue();
+ if (!sValue.isEmpty())
+ {
+ aValue = sValue;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ WriteCell(pFormat[i-1],pColWidth[i-1],nHeight,pHorJustify[i-1],aValue,OOO_STRING_SVTOOLS_HTML_tabledata);
+ }
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_tablerow, false).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+ }
+ }
+ else
+ {
+ IncIndent(-1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_tablerow, false).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_thead, false).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+
+ IncIndent(1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_tbody).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+ }
+
+ IncIndent(-1);
+ m_pStream->WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_tbody, false).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+ IncIndent(-1);
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_table, false).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+}
+
+void OHTMLImportExport::WriteCell( sal_Int32 nFormat, sal_Int32 nWidthPixel, sal_Int32 nHeightPixel, const char* pChar,
+ const OUString& rValue, const char* pHtmlTag)
+{
+ OString aStrTD = pHtmlTag;
+
+ nWidthPixel = nWidthPixel ? nWidthPixel : 86;
+ nHeightPixel = nHeightPixel ? nHeightPixel : 17;
+
+ // despite the <TABLE COLS=n> and <COL WIDTH=x> designation necessary,
+ // as Netscape is not paying attention to them.
+ // column width
+ aStrTD += " "
+ OOO_STRING_SVTOOLS_HTML_O_width
+ "=" +
+ OString::number(nWidthPixel) +
+ // line height
+ " "
+ OOO_STRING_SVTOOLS_HTML_O_height
+ "=" +
+ OString::number(nHeightPixel) +
+ " "
+ OOO_STRING_SVTOOLS_HTML_O_align
+ "=" +
+ pChar;
+
+ SvNumberFormatsSupplierObj* pSupplierImpl = m_xFormatter.is() ? comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(m_xFormatter->getNumberFormatsSupplier()) : nullptr;
+ SvNumberFormatter* pFormatter = pSupplierImpl ? pSupplierImpl->GetNumberFormatter() : nullptr;
+ if(pFormatter)
+ {
+ double fVal = 0.0;
+
+ try
+ {
+ fVal = m_xFormatter->convertStringToNumber(nFormat,rValue);
+ HTMLOutFuncs::CreateTableDataOptionsValNum(false, fVal,nFormat, *pFormatter);
+ }
+ catch(const Exception&)
+ {
+ HTMLOutFuncs::CreateTableDataOptionsValNum(false, fVal,nFormat, *pFormatter);
+ }
+ }
+
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, aStrTD);
+
+ FontOn();
+
+ bool bBold = ( css::awt::FontWeight::BOLD == m_aFont.Weight );
+ bool bItalic = ( css::awt::FontSlant_ITALIC == m_aFont.Slant );
+ bool bUnderline = ( css::awt::FontUnderline::NONE != m_aFont.Underline );
+ bool bStrikeout = ( css::awt::FontStrikeout::NONE != m_aFont.Strikeout );
+
+ if ( bBold ) HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_bold);
+ if ( bItalic ) HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_italic);
+ if ( bUnderline ) HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_underline);
+ if ( bStrikeout ) HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_strike);
+
+ if ( rValue.isEmpty() )
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_linebreak); // no completely empty cell
+ else
+ HTMLOutFuncs::Out_String( (*m_pStream), rValue );
+
+ if ( bStrikeout ) HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_strike, false);
+ if ( bUnderline ) HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_underline, false);
+ if ( bItalic ) HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_italic, false);
+ if ( bBold ) HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_bold, false);
+
+ FontOff();
+
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, pHtmlTag, false).WriteOString(SAL_NEWLINE_STRING).WriteOString(GetIndentStr());
+}
+
+void OHTMLImportExport::FontOn()
+{
+#if OSL_DEBUG_LEVEL > 0
+ m_bCheckFont = true;
+#endif
+
+ // <FONT FACE="xxx">
+ OString aStrOut = "<"
+ OOO_STRING_SVTOOLS_HTML_font
+ " "
+ OOO_STRING_SVTOOLS_HTML_O_face
+ "="
+ "\"" +
+ OUStringToOString(m_aFont.Name,osl_getThreadTextEncoding()) +
+ // TODO : think about the encoding of the font name
+ "\""
+ " "
+ OOO_STRING_SVTOOLS_HTML_O_color
+ "=";
+ m_pStream->WriteOString( aStrOut );
+
+ ::Color aColor;
+ if(m_xObject.is())
+ m_xObject->getPropertyValue(PROPERTY_TEXTCOLOR) >>= aColor;
+
+ HTMLOutFuncs::Out_Color( (*m_pStream), aColor );
+ m_pStream->WriteOString( ">" );
+}
+
+inline void OHTMLImportExport::FontOff()
+{
+#if OSL_DEBUG_LEVEL > 0
+ OSL_ENSURE(m_bCheckFont,"No FontOn() called");
+#endif
+ HTMLOutFuncs::Out_AsciiTag(*m_pStream, OOO_STRING_SVTOOLS_HTML_font, false);
+#if OSL_DEBUG_LEVEL > 0
+ m_bCheckFont = false;
+#endif
+}
+
+void OHTMLImportExport::IncIndent( sal_Int16 nVal )
+{
+ sIndent[m_nIndent] = '\t';
+ m_nIndent = m_nIndent + nVal;
+ if ( m_nIndent < 0 )
+ m_nIndent = 0;
+ else if ( m_nIndent > nIndentMax )
+ m_nIndent = nIndentMax;
+ sIndent[m_nIndent] = 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/UITools.cxx b/dbaccess/source/ui/misc/UITools.cxx
new file mode 100644
index 0000000000..483afced10
--- /dev/null
+++ b/dbaccess/source/ui/misc/UITools.cxx
@@ -0,0 +1,1371 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <UITools.hxx>
+#include <sfx2/docfilt.hxx>
+#include <core_resource.hxx>
+#include <dlgsave.hxx>
+#include <defaultobjectnamecheck.hxx>
+#include <strings.hxx>
+#include <comphelper/extract.hxx>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/sdb/XSingleSelectQueryAnalyzer.hpp>
+#include <com/sun/star/sdb/XCompletedConnection.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/ucb/XContent.hpp>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/ucb/InteractiveIOException.hpp>
+#include <com/sun/star/sdb/XDocumentDataSource.hpp>
+#include <com/sun/star/ucb/IOErrorCode.hpp>
+#include <vcl/syswin.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XHierarchicalNameContainer.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/awt/TextAlign.hpp>
+#include <TypeInfo.hxx>
+#include <FieldDescriptions.hxx>
+#include <comphelper/stl_types.hxx>
+#include <comphelper/types.hxx>
+#include <comphelper/propertysequence.hxx>
+
+#include <svx/svxids.hrc>
+
+#include <sal/log.hxx>
+#include <svl/numformat.hxx>
+#include <svl/itempool.hxx>
+#include <helpids.h>
+#include <svl/itemset.hxx>
+#include <sbagrid.hrc>
+#include <svl/rngitem.hxx>
+#include <svl/intitem.hxx>
+#include <svx/numinf.hxx>
+#include <svl/zforlist.hxx>
+#include <dlgattr.hxx>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/util/NumberFormatter.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/util/XNumberFormatter.hpp>
+#include <strings.hrc>
+#include <sqlmessage.hxx>
+#include <dlgsize.hxx>
+#include <svtools/editbrowsebox.hxx>
+#include <tools/urlobj.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <svl/numuno.hxx>
+#include <svl/filenotation.hxx>
+#include <connectivity/FValue.hxx>
+
+#include <editeng/justifyitem.hxx>
+#include <memory>
+
+namespace dbaui
+{
+using namespace ::dbtools;
+using namespace ::comphelper;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::svt;
+using ::com::sun::star::ucb::InteractiveIOException;
+using ::com::sun::star::ucb::IOErrorCode_NO_FILE;
+using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING;
+
+SQLExceptionInfo createConnection( const OUString& _rsDataSourceName,
+ const Reference< css::container::XNameAccess >& _xDatabaseContext,
+ const Reference< css::uno::XComponentContext >& _rxContext,
+ Reference< css::lang::XEventListener> const & _rEvtLst,
+ Reference< css::sdbc::XConnection>& _rOUTConnection )
+{
+ Reference<XPropertySet> xProp;
+ try
+ {
+ xProp.set(_xDatabaseContext->getByName(_rsDataSourceName),UNO_QUERY);
+ }
+ catch(const Exception&)
+ {
+ }
+
+ return createConnection(xProp,_rxContext,_rEvtLst,_rOUTConnection);
+}
+
+SQLExceptionInfo createConnection( const Reference< css::beans::XPropertySet>& _xDataSource,
+ const Reference< css::uno::XComponentContext >& _rxContext,
+ Reference< css::lang::XEventListener> const & _rEvtLst,
+ Reference< css::sdbc::XConnection>& _rOUTConnection )
+{
+ SQLExceptionInfo aInfo;
+ if ( !_xDataSource.is() )
+ {
+ SAL_WARN("dbaccess.ui", "createConnection: could not retrieve the data source!");
+ return aInfo;
+ }
+
+ OUString sPwd, sUser;
+ bool bPwdReq = false;
+ try
+ {
+ _xDataSource->getPropertyValue(PROPERTY_PASSWORD) >>= sPwd;
+ bPwdReq = ::cppu::any2bool(_xDataSource->getPropertyValue(PROPERTY_ISPASSWORDREQUIRED));
+ _xDataSource->getPropertyValue(PROPERTY_USER) >>= sUser;
+ }
+ catch(const Exception&)
+ {
+ SAL_WARN("dbaccess.ui", "createConnection: error while retrieving data source properties!");
+ }
+
+ try
+ {
+ if(bPwdReq && sPwd.isEmpty())
+ { // password required, but empty -> connect using an interaction handler
+ Reference<XCompletedConnection> xConnectionCompletion(_xDataSource, UNO_QUERY);
+ if (!xConnectionCompletion.is())
+ {
+ SAL_WARN("dbaccess.ui", "createConnection: missing an interface ... need an error message here!");
+ }
+ else
+ { // instantiate the default SDB interaction handler
+ Reference< XInteractionHandler > xHandler = InteractionHandler::createWithParent(_rxContext, nullptr);
+ _rOUTConnection = xConnectionCompletion->connectWithCompletion(xHandler);
+ }
+ }
+ else
+ {
+ Reference<XDataSource> xDataSource(_xDataSource,UNO_QUERY);
+ _rOUTConnection = xDataSource->getConnection(sUser, sPwd);
+ }
+ // be notified when connection is in disposing
+ Reference< XComponent > xComponent(_rOUTConnection, UNO_QUERY);
+ if (xComponent.is() && _rEvtLst.is())
+ xComponent->addEventListener(_rEvtLst);
+ }
+ catch(const SQLContext& e) { aInfo = SQLExceptionInfo(e); }
+ catch(const SQLWarning& e) { aInfo = SQLExceptionInfo(e); }
+ catch(const SQLException& e) { aInfo = SQLExceptionInfo(e); }
+ catch(const Exception&) {
+ TOOLS_WARN_EXCEPTION("dbaccess.ui", "SbaTableQueryBrowser::OnExpandEntry: could not connect - unknown exception");
+ }
+
+ return aInfo;
+}
+
+Reference< XDataSource > getDataSourceByName( const OUString& _rDataSourceName,
+ weld::Window* _pErrorMessageParent, const Reference< XComponentContext >& _rxContext, ::dbtools::SQLExceptionInfo* _pErrorInfo )
+{
+ Reference< XDatabaseContext > xDatabaseContext = DatabaseContext::create(_rxContext);
+
+ Reference< XDataSource > xDatasource;
+ SQLExceptionInfo aSQLError;
+ try
+ {
+ xDatabaseContext->getByName( _rDataSourceName ) >>= xDatasource;
+ }
+ catch(const WrappedTargetException& e)
+ {
+ InteractiveIOException aIOException;
+ if ( ( e.TargetException >>= aIOException )
+ && ( ( aIOException.Code == IOErrorCode_NO_FILE )
+ || ( aIOException.Code == IOErrorCode_NOT_EXISTING )
+ )
+ )
+ {
+ OUString sErrorMessage( DBA_RES( STR_FILE_DOES_NOT_EXIST ) );
+ OFileNotation aTransformer( e.Message );
+ sErrorMessage = sErrorMessage.replaceFirst( "$file$", aTransformer.get( OFileNotation::N_SYSTEM ) );
+ aSQLError = SQLExceptionInfo( sErrorMessage ).get();
+ }
+ else
+ {
+ aSQLError = SQLExceptionInfo( e.TargetException );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ if ( xDatasource.is() )
+ return xDatasource;
+
+ if ( aSQLError.isValid() )
+ {
+ if ( _pErrorInfo )
+ {
+ *_pErrorInfo = aSQLError;
+ }
+ else
+ {
+ showError( aSQLError, _pErrorMessageParent ? _pErrorMessageParent->GetXWindow() : nullptr, _rxContext );
+ }
+ }
+
+ return Reference<XDataSource>();
+}
+
+Reference< XInterface > getDataSourceOrModel(const Reference< XInterface >& _xObject)
+{
+ Reference< XInterface > xRet;
+ Reference<XDocumentDataSource> xDocumentDataSource(_xObject,UNO_QUERY);
+ if ( xDocumentDataSource.is() )
+ xRet = xDocumentDataSource->getDatabaseDocument();
+
+ if ( !xRet.is() )
+ {
+ Reference<XOfficeDatabaseDocument> xOfficeDoc(_xObject,UNO_QUERY);
+ if ( xOfficeDoc.is() )
+ xRet = xOfficeDoc->getDataSource();
+ }
+
+ return xRet;
+}
+
+TOTypeInfoSP getTypeInfoFromType(const OTypeInfoMap& _rTypeInfo,
+ sal_Int32 _nType,
+ const OUString& _sTypeName,
+ const OUString& _sCreateParams,
+ sal_Int32 _nPrecision,
+ sal_Int32 _nScale,
+ bool _bAutoIncrement,
+ bool& _brForceToType)
+{
+ TOTypeInfoSP pTypeInfo;
+ _brForceToType = false;
+ // search for type
+ std::pair<OTypeInfoMap::const_iterator, OTypeInfoMap::const_iterator> aPair = _rTypeInfo.equal_range(_nType);
+ OTypeInfoMap::const_iterator aIter = aPair.first;
+ if(aIter != _rTypeInfo.end()) // compare with end is correct here
+ {
+ for(;aIter != aPair.second;++aIter)
+ {
+ // search the best matching type
+ #ifdef DBG_UTIL
+ OUString sDBTypeName = aIter->second->aTypeName; (void)sDBTypeName;
+ #endif
+ if ( (
+ _sTypeName.isEmpty()
+ || (aIter->second->aTypeName.equalsIgnoreAsciiCase(_sTypeName))
+ )
+ && (
+ (
+ !aIter->second->aCreateParams.getLength()
+ && _sCreateParams.isEmpty()
+ )
+ || (
+ (aIter->second->nPrecision >= _nPrecision)
+ && (aIter->second->nMaximumScale >= _nScale)
+ && ( (_bAutoIncrement && aIter->second->bAutoIncrement) || !_bAutoIncrement )
+ )
+ )
+ )
+ break;
+ }
+
+ if (aIter == aPair.second)
+ {
+ for(aIter = aPair.first; aIter != aPair.second; ++aIter)
+ {
+ sal_Int32 nPrec = aIter->second->nPrecision;
+ sal_Int32 nScale = aIter->second->nMaximumScale;
+ // search the best matching type (now comparing the local names)
+ if ( (aIter->second->aLocalTypeName.equalsIgnoreAsciiCase(_sTypeName))
+ && (nPrec >= _nPrecision)
+ && (nScale >= _nScale)
+ && ( (_bAutoIncrement && aIter->second->bAutoIncrement) || !_bAutoIncrement )
+ )
+ {
+ SAL_WARN("dbaccess.ui", "getTypeInfoFromType: assuming column type " <<
+ aIter->second->aTypeName << "\" (expected type name " <<
+ _sTypeName << " matches the type's local name).");
+ break;
+ }
+ }
+ }
+
+ if (aIter == aPair.second)
+ { // no match for the names, no match for the local names
+ // -> drop the precision and the scale restriction, accept any type with the property
+ // type id (nType)
+
+ for(aIter = aPair.first; aIter != aPair.second; ++aIter)
+ {
+ // search the best matching type (now comparing the local names)
+ sal_Int32 nPrec = aIter->second->nPrecision;
+ sal_Int32 nScale = aIter->second->nMaximumScale;
+ if ( (nPrec >= _nPrecision)
+ && (nScale >= _nScale)
+ && ( (_bAutoIncrement && aIter->second->bAutoIncrement) || !_bAutoIncrement )
+ )
+ break;
+ }
+ }
+ if (aIter == aPair.second)
+ {
+ if ( _bAutoIncrement )
+ {
+ for(aIter = aPair.first; aIter != aPair.second; ++aIter)
+ {
+ // search the best matching type (now comparing the local names)
+ sal_Int32 nScale = aIter->second->nMaximumScale;
+ if ( (nScale >= _nScale)
+ && (aIter->second->bAutoIncrement == _bAutoIncrement)
+ )
+ break;
+ }
+ if ( aIter == aPair.second )
+ {
+ // try it without the auto increment flag
+ pTypeInfo = getTypeInfoFromType(_rTypeInfo,
+ _nType,
+ _sTypeName,
+ _sCreateParams,
+ _nPrecision,
+ _nScale,
+ false,
+ _brForceToType);
+ }
+ else
+ pTypeInfo = aIter->second;
+ }
+ else
+ {
+ pTypeInfo = aPair.first->second;
+ _brForceToType = true;
+ }
+ }
+ else
+ pTypeInfo = aIter->second;
+ }
+ else
+ {
+ ::comphelper::UStringMixEqual aCase(false);
+ // search for typeinfo where the typename is equal _sTypeName
+ for (auto const& elem : _rTypeInfo)
+ {
+ if ( aCase( elem.second->getDBName() , _sTypeName ) )
+ {
+ pTypeInfo = elem.second;
+ break;
+ }
+ }
+ }
+
+ OSL_ENSURE(pTypeInfo, "getTypeInfoFromType: no type info found for this type!");
+ return pTypeInfo;
+}
+
+void fillTypeInfo( const Reference< css::sdbc::XConnection>& _rxConnection,
+ std::u16string_view _rsTypeNames,
+ OTypeInfoMap& _rTypeInfoMap,
+ std::vector<OTypeInfoMap::iterator>& _rTypeInfoIters)
+{
+ if(!_rxConnection.is())
+ return;
+ Reference< XResultSet> xRs = _rxConnection->getMetaData ()->getTypeInfo ();
+ Reference< XRow> xRow(xRs,UNO_QUERY);
+ // Information for a single SQL type
+ if(!xRs.is())
+ return;
+
+ Reference<XResultSetMetaData> xResultSetMetaData = Reference<XResultSetMetaDataSupplier>(xRs,UNO_QUERY_THROW)->getMetaData();
+ ::connectivity::ORowSetValue aValue;
+ std::vector<sal_Int32> aTypes;
+ std::vector<bool> aNullable;
+ // Loop on the result set until we reach end of file
+ while (xRs->next())
+ {
+ TOTypeInfoSP pInfo = std::make_shared<OTypeInfo>();
+ sal_Int32 nPos = 1;
+ if ( aTypes.empty() )
+ {
+ sal_Int32 nCount = xResultSetMetaData->getColumnCount();
+ if ( nCount < 1 )
+ nCount = 18;
+ aTypes.reserve(nCount+1);
+ aTypes.push_back(-1);
+ aNullable.push_back(false);
+ for (sal_Int32 j = 1; j <= nCount ; ++j)
+ {
+ aTypes.push_back(xResultSetMetaData->getColumnType(j));
+ aNullable.push_back(xResultSetMetaData->isNullable(j) != ColumnValue::NO_NULLS);
+ }
+ }
+
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->aTypeName = aValue.getString();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->nType = aValue.getInt32();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->nPrecision = aValue.getInt32();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); // LiteralPrefix
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow); //LiteralSuffix
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->aCreateParams = aValue.getString();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->bNullable = aValue.getInt32() == ColumnValue::NULLABLE;
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ // bCaseSensitive
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->nSearchType = aValue.getInt16();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ // bUnsigned
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->bCurrency = aValue.getBool();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->bAutoIncrement = aValue.getBool();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->aLocalTypeName = aValue.getString();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->nMinimumScale = aValue.getInt16();
+ ++nPos;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->nMaximumScale = aValue.getInt16();
+ assert(nPos == 15);
+ // 16 and 17 are unused
+ nPos = 18;
+ aValue.fill(nPos,aTypes[nPos],aNullable[nPos],xRow);
+ pInfo->nNumPrecRadix = aValue.getInt32();
+
+ // check if values are less than zero like it happens in a oracle jdbc driver
+ if( pInfo->nPrecision < 0)
+ pInfo->nPrecision = 0;
+ if( pInfo->nMinimumScale < 0)
+ pInfo->nMinimumScale = 0;
+ if( pInfo->nMaximumScale < 0)
+ pInfo->nMaximumScale = 0;
+ if( pInfo->nNumPrecRadix <= 1)
+ pInfo->nNumPrecRadix = 10;
+
+ std::u16string_view aName;
+ switch(pInfo->nType)
+ {
+ case DataType::CHAR:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_CHAR, ';');
+ break;
+ case DataType::VARCHAR:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_TEXT, ';');
+ break;
+ case DataType::DECIMAL:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_DECIMAL, ';');
+ break;
+ case DataType::NUMERIC:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_NUMERIC, ';');
+ break;
+ case DataType::BIGINT:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_BIGINT, ';');
+ break;
+ case DataType::FLOAT:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_FLOAT, ';');
+ break;
+ case DataType::DOUBLE:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_DOUBLE, ';');
+ break;
+ case DataType::LONGVARCHAR:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_MEMO, ';');
+ break;
+ case DataType::LONGVARBINARY:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_IMAGE, ';');
+ break;
+ case DataType::DATE:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_DATE, ';');
+ break;
+ case DataType::TIME:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_TIME, ';');
+ break;
+ case DataType::TIMESTAMP:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_DATETIME, ';');
+ break;
+ case DataType::BIT:
+ if ( !pInfo->aCreateParams.isEmpty() )
+ {
+ aName = o3tl::getToken(_rsTypeNames, TYPE_BIT, ';');
+ break;
+ }
+ [[fallthrough]];
+ case DataType::BOOLEAN:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_BOOL, ';');
+ break;
+ case DataType::TINYINT:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_TINYINT, ';');
+ break;
+ case DataType::SMALLINT:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_SMALLINT, ';');
+ break;
+ case DataType::INTEGER:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_INTEGER, ';');
+ break;
+ case DataType::REAL:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_REAL, ';');
+ break;
+ case DataType::BINARY:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_BINARY, ';');
+ break;
+ case DataType::VARBINARY:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_VARBINARY, ';');
+ break;
+ case DataType::SQLNULL:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_SQLNULL, ';');
+ break;
+ case DataType::OBJECT:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_OBJECT, ';');
+ break;
+ case DataType::DISTINCT:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_DISTINCT, ';');
+ break;
+ case DataType::STRUCT:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_STRUCT, ';');
+ break;
+ case DataType::ARRAY:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_ARRAY, ';');
+ break;
+ case DataType::BLOB:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_BLOB, ';');
+ break;
+ case DataType::CLOB:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_CLOB, ';');
+ break;
+ case DataType::REF:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_REF, ';');
+ break;
+ case DataType::OTHER:
+ aName = o3tl::getToken(_rsTypeNames, TYPE_OTHER, ';');
+ break;
+ }
+ if ( !aName.empty() )
+ {
+ pInfo->aUIName = aName;
+ pInfo->aUIName += " [ ";
+ }
+ pInfo->aUIName += pInfo->aTypeName;
+ if ( !aName.empty() )
+ pInfo->aUIName += " ]";
+ // Now that we have the type info, save it in the multimap
+ _rTypeInfoMap.emplace(pInfo->nType,pInfo);
+ }
+ // for a faster index access
+ _rTypeInfoIters.reserve(_rTypeInfoMap.size());
+
+ OTypeInfoMap::iterator aIter = _rTypeInfoMap.begin();
+ OTypeInfoMap::const_iterator aEnd = _rTypeInfoMap.end();
+ for(;aIter != aEnd;++aIter)
+ _rTypeInfoIters.push_back(aIter);
+
+ // Close the result set/statement.
+
+ ::comphelper::disposeComponent(xRs);
+}
+
+void setColumnProperties(const Reference<XPropertySet>& _rxColumn,const OFieldDescription* _pFieldDesc)
+{
+ _rxColumn->setPropertyValue(PROPERTY_NAME,Any(_pFieldDesc->GetName()));
+ _rxColumn->setPropertyValue(PROPERTY_TYPENAME,Any(_pFieldDesc->getTypeInfo()->aTypeName));
+ _rxColumn->setPropertyValue(PROPERTY_TYPE,Any(_pFieldDesc->GetType()));
+ _rxColumn->setPropertyValue(PROPERTY_PRECISION,Any(_pFieldDesc->GetPrecision()));
+ _rxColumn->setPropertyValue(PROPERTY_SCALE,Any(_pFieldDesc->GetScale()));
+ _rxColumn->setPropertyValue(PROPERTY_ISNULLABLE, Any(_pFieldDesc->GetIsNullable()));
+ _rxColumn->setPropertyValue(PROPERTY_ISAUTOINCREMENT, css::uno::Any(_pFieldDesc->IsAutoIncrement()));
+ _rxColumn->setPropertyValue(PROPERTY_DESCRIPTION,Any(_pFieldDesc->GetDescription()));
+ if ( _rxColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_ISCURRENCY) && _pFieldDesc->IsCurrency() )
+ _rxColumn->setPropertyValue(PROPERTY_ISCURRENCY, css::uno::Any(_pFieldDesc->IsCurrency()));
+ // set autoincrement value when available
+ // and only set when the entry is not empty, that lets the value in the column untouched
+ if ( _pFieldDesc->IsAutoIncrement() && !_pFieldDesc->GetAutoIncrementValue().isEmpty() && _rxColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_AUTOINCREMENTCREATION) )
+ _rxColumn->setPropertyValue(PROPERTY_AUTOINCREMENTCREATION,Any(_pFieldDesc->GetAutoIncrementValue()));
+}
+
+OUString createDefaultName(const Reference< XDatabaseMetaData>& _xMetaData,const Reference<XNameAccess>& _xTables,const OUString& _sName)
+{
+ OSL_ENSURE(_xMetaData.is(),"No MetaData!");
+ OUString sDefaultName = _sName;
+ try
+ {
+ OUString sCatalog,sSchema,sCompsedName;
+ if(_xMetaData->supportsCatalogsInTableDefinitions())
+ {
+ try
+ {
+ Reference< XConnection> xCon = _xMetaData->getConnection();
+ if ( xCon.is() )
+ sCatalog = xCon->getCatalog();
+ if ( sCatalog.isEmpty() )
+ {
+ Reference<XResultSet> xRes = _xMetaData->getCatalogs();
+ Reference<XRow> xRow(xRes,UNO_QUERY);
+ while(xRes.is() && xRes->next())
+ {
+ sCatalog = xRow->getString(1);
+ if(!xRow->wasNull())
+ break;
+ }
+ }
+ }
+ catch(const SQLException&)
+ {
+ }
+ }
+ if(_xMetaData->supportsSchemasInTableDefinitions())
+ {
+ sSchema = _xMetaData->getUserName();
+ }
+ sCompsedName = ::dbtools::composeTableName( _xMetaData, sCatalog, sSchema, _sName, false, ::dbtools::EComposeRule::InDataManipulation );
+ sDefaultName = ::dbtools::createUniqueName(_xTables,sCompsedName);
+ }
+ catch(const SQLException&)
+ {
+ }
+ return sDefaultName;
+}
+
+bool checkDataSourceAvailable(const OUString& _sDataSourceName,const Reference< css::uno::XComponentContext >& _xContext)
+{
+ Reference< XDatabaseContext > xDataBaseContext = DatabaseContext::create(_xContext);
+ bool bRet = xDataBaseContext->hasByName(_sDataSourceName);
+ if ( !bRet )
+ { // try if this one is a URL
+ try
+ {
+ bRet = xDataBaseContext->getByName(_sDataSourceName).hasValue();
+ }
+ catch(const Exception&)
+ {
+ }
+ }
+ return bRet;
+}
+
+sal_Int32 mapTextAlign(const SvxCellHorJustify& _eAlignment)
+{
+ sal_Int32 nAlignment = css::awt::TextAlign::LEFT;
+ switch (_eAlignment)
+ {
+ case SvxCellHorJustify::Standard:
+ case SvxCellHorJustify::Left: nAlignment = css::awt::TextAlign::LEFT; break;
+ case SvxCellHorJustify::Center: nAlignment = css::awt::TextAlign::CENTER; break;
+ case SvxCellHorJustify::Right: nAlignment = css::awt::TextAlign::RIGHT; break;
+ default:
+ SAL_WARN("dbaccess.ui", "Invalid TextAlign!");
+ }
+ return nAlignment;
+}
+
+SvxCellHorJustify mapTextJustify(sal_Int32 _nAlignment)
+{
+ SvxCellHorJustify eJustify = SvxCellHorJustify::Left;
+ switch (_nAlignment)
+ {
+ case css::awt::TextAlign::LEFT : eJustify = SvxCellHorJustify::Left; break;
+ case css::awt::TextAlign::CENTER : eJustify = SvxCellHorJustify::Center; break;
+ case css::awt::TextAlign::RIGHT : eJustify = SvxCellHorJustify::Right; break;
+ default:
+ SAL_WARN("dbaccess.ui", "Invalid TextAlign!");
+ }
+ return eJustify;
+}
+
+void callColumnFormatDialog(const Reference<XPropertySet>& xAffectedCol,
+ const Reference<XPropertySet>& xField,
+ SvNumberFormatter* _pFormatter,
+ weld::Widget* _pParent)
+{
+ if (!(xAffectedCol.is() && xField.is()))
+ return;
+
+ try
+ {
+ Reference< XPropertySetInfo > xInfo = xAffectedCol->getPropertySetInfo();
+ bool bHasFormat = xInfo->hasPropertyByName(PROPERTY_FORMATKEY);
+ sal_Int32 nDataType = ::comphelper::getINT32(xField->getPropertyValue(PROPERTY_TYPE));
+
+ SvxCellHorJustify eJustify(SvxCellHorJustify::Standard);
+ Any aAlignment = xAffectedCol->getPropertyValue(PROPERTY_ALIGN);
+ if (aAlignment.hasValue())
+ eJustify = dbaui::mapTextJustify(::comphelper::getINT16(aAlignment));
+ sal_Int32 nFormatKey = 0;
+ if ( bHasFormat )
+ nFormatKey = ::comphelper::getINT32(xAffectedCol->getPropertyValue(PROPERTY_FORMATKEY));
+
+ if(callColumnFormatDialog(_pParent,_pFormatter,nDataType,nFormatKey,eJustify,bHasFormat))
+ {
+ xAffectedCol->setPropertyValue(PROPERTY_ALIGN, Any(static_cast<sal_Int16>(dbaui::mapTextAlign(eJustify))));
+ if (bHasFormat)
+ xAffectedCol->setPropertyValue(PROPERTY_FORMATKEY, Any(nFormatKey));
+
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+bool callColumnFormatDialog(weld::Widget* _pParent,
+ SvNumberFormatter* _pFormatter,
+ sal_Int32 _nDataType,
+ sal_Int32& _nFormatKey,
+ SvxCellHorJustify& _eJustify,
+ bool _bHasFormat)
+{
+ bool bRet = false;
+
+ // UNO->ItemSet
+ static SfxItemInfo aItemInfos[] =
+ {
+ // _nSID, _bNeedsPoolRegistration, _bShareable
+ { 0, false, true }, // SBA_DEF_RANGEFORMAT
+ { SID_ATTR_NUMBERFORMAT_VALUE, false, true }, // SBA_DEF_FMTVALUE
+ { SID_ATTR_ALIGN_HOR_JUSTIFY, false, true }, // SBA_ATTR_ALIGN_HOR_JUSTIFY
+ { SID_ATTR_NUMBERFORMAT_INFO, false, true }, // SID_ATTR_NUMBERFORMAT_INFO
+ { SID_ATTR_NUMBERFORMAT_ONE_AREA, false, true } // SID_ATTR_NUMBERFORMAT_ONE_AREA
+ };
+ static const auto aAttrMap = svl::Items<
+ SBA_DEF_RANGEFORMAT, SBA_ATTR_ALIGN_HOR_JUSTIFY,
+ SID_ATTR_NUMBERFORMAT_INFO, SID_ATTR_NUMBERFORMAT_INFO,
+ SID_ATTR_NUMBERFORMAT_ONE_AREA, SID_ATTR_NUMBERFORMAT_ONE_AREA
+ >;
+
+ std::vector<SfxPoolItem*> pDefaults
+ {
+ new SfxRangeItem(SBA_DEF_RANGEFORMAT, SBA_DEF_FMTVALUE, SBA_ATTR_ALIGN_HOR_JUSTIFY),
+ new SfxUInt32Item(SBA_DEF_FMTVALUE),
+ new SvxHorJustifyItem(SvxCellHorJustify::Standard, SBA_ATTR_ALIGN_HOR_JUSTIFY),
+ new SvxNumberInfoItem(SID_ATTR_NUMBERFORMAT_INFO),
+ new SfxBoolItem(SID_ATTR_NUMBERFORMAT_ONE_AREA, false)
+ };
+
+ rtl::Reference<SfxItemPool> pPool(new SfxItemPool("GridBrowserProperties", SBA_DEF_RANGEFORMAT, SBA_ATTR_ALIGN_HOR_JUSTIFY, aItemInfos, &pDefaults));
+ pPool->SetDefaultMetric( MapUnit::MapTwip ); // ripped, don't understand why
+ pPool->FreezeIdRanges(); // the same
+
+ std::optional<SfxItemSet> pFormatDescriptor(SfxItemSet(*pPool, aAttrMap));
+ // fill it
+ pFormatDescriptor->Put(SvxHorJustifyItem(_eJustify, SBA_ATTR_ALIGN_HOR_JUSTIFY));
+ bool bText = false;
+ if (_bHasFormat)
+ {
+ // if the col is bound to a text field we have to disallow all non-text formats
+ if ((DataType::CHAR == _nDataType) || (DataType::VARCHAR == _nDataType) || (DataType::LONGVARCHAR == _nDataType) || (DataType::CLOB == _nDataType))
+ {
+ bText = true;
+ pFormatDescriptor->Put(SfxBoolItem(SID_ATTR_NUMBERFORMAT_ONE_AREA, true));
+ if (!_pFormatter->IsTextFormat(_nFormatKey))
+ // text fields can only have text formats
+ _nFormatKey = _pFormatter->GetStandardFormat(SvNumFormatType::TEXT, Application::GetSettings().GetLanguageTag().getLanguageType());
+ }
+
+ pFormatDescriptor->Put(SfxUInt32Item(SBA_DEF_FMTVALUE, _nFormatKey));
+ }
+
+ if (!bText)
+ {
+ SvxNumberInfoItem aFormatter(_pFormatter, 1234.56789, SID_ATTR_NUMBERFORMAT_INFO);
+ pFormatDescriptor->Put(aFormatter);
+ }
+
+ { // want the dialog to be destroyed before our set
+ SbaSbAttrDlg aDlg(_pParent, &*pFormatDescriptor, _pFormatter, _bHasFormat);
+ if (RET_OK == aDlg.run())
+ {
+ // ItemSet->UNO
+ // UNO-properties
+ const SfxItemSet* pSet = aDlg.GetExampleSet();
+ // (of course we could put the modified items directly into the column, but then the UNO-model
+ // won't reflect these changes, and why do we have a model, then ?)
+
+ // horizontal justify
+ const SvxHorJustifyItem* pHorJustify = pSet->GetItem<SvxHorJustifyItem>(SBA_ATTR_ALIGN_HOR_JUSTIFY);
+
+ _eJustify = pHorJustify->GetValue();
+
+ // format key
+ if (_bHasFormat)
+ {
+ const SfxUInt32Item* pFormat = pSet->GetItem<SfxUInt32Item>(SBA_DEF_FMTVALUE);
+ _nFormatKey = static_cast<sal_Int32>(pFormat->GetValue());
+ }
+ bRet = true;
+ }
+ // deleted formats
+ const SfxItemSet* pResult = aDlg.GetOutputItemSet();
+ if (pResult)
+ {
+ const SfxPoolItem* pItem = pResult->GetItem( SID_ATTR_NUMBERFORMAT_INFO );
+ const SvxNumberInfoItem* pInfoItem = static_cast<const SvxNumberInfoItem*>(pItem);
+ if (pInfoItem)
+ {
+ for (sal_uInt32 key : pInfoItem->GetDelFormats())
+ _pFormatter->DeleteEntry(key);
+ }
+ }
+ }
+
+ pFormatDescriptor.reset();
+ pPool.clear();
+ for (SfxPoolItem* pDefault : pDefaults)
+ delete pDefault;
+
+ return bRet;
+}
+
+std::shared_ptr<const SfxFilter> getStandardDatabaseFilter()
+{
+ std::shared_ptr<const SfxFilter> pFilter = SfxFilter::GetFilterByName("StarOffice XML (Base)");
+ OSL_ENSURE(pFilter,"Filter: StarOffice XML (Base) could not be found!");
+ return pFilter;
+}
+
+bool appendToFilter(const Reference<XConnection>& _xConnection,
+ const OUString& _sName,
+ const Reference< XComponentContext >& _rxContext,
+ weld::Window* pParent)
+{
+ bool bRet = false;
+ Reference< XChild> xChild(_xConnection,UNO_QUERY);
+ if(xChild.is())
+ {
+ Reference< XPropertySet> xProp(xChild->getParent(),UNO_QUERY);
+ if(xProp.is())
+ {
+ Sequence< OUString > aFilter;
+ xProp->getPropertyValue(PROPERTY_TABLEFILTER) >>= aFilter;
+ // first check if we have something like SCHEMA.%
+ bool bHasToInsert = true;
+ for (const OUString& rItem : std::as_const(aFilter))
+ {
+ if(rItem.indexOf('%') != -1)
+ {
+ sal_Int32 nLen = rItem.lastIndexOf('.');
+ if(nLen != -1 && !rItem.compareTo(_sName,nLen))
+ bHasToInsert = false;
+ else if(rItem.getLength() == 1)
+ bHasToInsert = false;
+ }
+ }
+
+ bRet = true;
+ if(bHasToInsert)
+ {
+ if(! ::dbaui::checkDataSourceAvailable(::comphelper::getString(xProp->getPropertyValue(PROPERTY_NAME)),_rxContext))
+ {
+ OUString aMessage(DBA_RES(STR_TABLEDESIGN_DATASOURCE_DELETED));
+ OSQLWarningBox aWarning(pParent, aMessage);
+ aWarning.run();
+ bRet = false;
+ }
+ else
+ {
+ aFilter.realloc(aFilter.getLength()+1);
+ aFilter.getArray()[aFilter.getLength()-1] = _sName;
+ xProp->setPropertyValue(PROPERTY_TABLEFILTER,Any(aFilter));
+ }
+ }
+ }
+ }
+ return bRet;
+}
+
+void notifySystemWindow(vcl::Window const * _pWindow, vcl::Window* _pToRegister, const ::comphelper::mem_fun1_t<TaskPaneList,vcl::Window*>& _rMemFunc)
+{
+ OSL_ENSURE(_pWindow,"Window can not be null!");
+ SystemWindow* pSystemWindow = _pWindow ? _pWindow->GetSystemWindow() : nullptr;
+ if ( pSystemWindow )
+ {
+ _rMemFunc( pSystemWindow->GetTaskPaneList(), _pToRegister );
+ }
+}
+
+void adjustBrowseBoxColumnWidth( ::svt::EditBrowseBox* _pBox, sal_uInt16 _nColId )
+{
+ sal_Int32 nColSize = -1;
+ ::tools::Long nDefaultWidth = _pBox->GetDefaultColumnWidth( _pBox->GetColumnTitle( _nColId ) );
+ if ( nDefaultWidth != _pBox->GetColumnWidth( _nColId ) )
+ {
+ Size aSizeMM = _pBox->PixelToLogic( Size( _pBox->GetColumnWidth( _nColId ), 0 ), MapMode( MapUnit::MapMM ) );
+ nColSize = aSizeMM.Width() * 10;
+ }
+
+ Size aDefaultMM = _pBox->PixelToLogic( Size( nDefaultWidth, 0 ), MapMode( MapUnit::MapMM ) );
+
+ DlgSize aColumnSizeDlg(_pBox->GetFrameWeld(), nColSize, false, aDefaultMM.Width() * 10);
+ if (aColumnSizeDlg.run() != RET_OK)
+ return;
+
+ sal_Int32 nValue = aColumnSizeDlg.GetValue();
+ if ( -1 == nValue )
+ { // default width
+ nValue = _pBox->GetDefaultColumnWidth( _pBox->GetColumnTitle( _nColId ) );
+ }
+ else
+ {
+ Size aSizeMM( nValue / 10, 0 );
+ nValue = _pBox->LogicToPixel( aSizeMM, MapMode( MapUnit::MapMM ) ).Width();
+ }
+ _pBox->SetColumnWidth( _nColId, nValue );
+}
+
+// check if SQL92 name checking is enabled
+bool isSQL92CheckEnabled(const Reference<XConnection>& _xConnection)
+{
+ return ::dbtools::getBooleanDataSourceSetting( _xConnection, PROPERTY_ENABLESQL92CHECK );
+}
+
+bool isAppendTableAliasEnabled(const Reference<XConnection>& _xConnection)
+{
+ return ::dbtools::getBooleanDataSourceSetting( _xConnection, INFO_APPEND_TABLE_ALIAS );
+}
+
+bool generateAsBeforeTableAlias(const Reference<XConnection>& _xConnection)
+{
+ return ::dbtools::getBooleanDataSourceSetting( _xConnection, INFO_AS_BEFORE_CORRELATION_NAME );
+}
+
+void fillAutoIncrementValue(const Reference<XPropertySet>& _xDatasource,
+ bool& _rAutoIncrementValueEnabled,
+ OUString& _rsAutoIncrementValue)
+{
+ if ( !_xDatasource.is() )
+ return;
+
+ OSL_ENSURE(_xDatasource->getPropertySetInfo()->hasPropertyByName(PROPERTY_INFO),"NO datasource supplied!");
+ Sequence<PropertyValue> aInfo;
+ _xDatasource->getPropertyValue(PROPERTY_INFO) >>= aInfo;
+
+ // search the right propertyvalue
+ const PropertyValue* pValue =std::find_if(std::cbegin(aInfo), std::cend(aInfo),
+ [](const PropertyValue& lhs)
+ {return lhs.Name == PROPERTY_AUTOINCREMENTCREATION;} );
+
+ if ( pValue != std::cend(aInfo) )
+ pValue->Value >>= _rsAutoIncrementValue;
+ pValue =std::find_if(std::cbegin(aInfo), std::cend(aInfo),
+ [](const PropertyValue& lhs)
+ {return lhs.Name == "IsAutoRetrievingEnabled";} );
+
+ if ( pValue != std::cend(aInfo) )
+ pValue->Value >>= _rAutoIncrementValueEnabled;
+}
+
+void fillAutoIncrementValue(const Reference<XConnection>& _xConnection,
+ bool& _rAutoIncrementValueEnabled,
+ OUString& _rsAutoIncrementValue)
+{
+ Reference< XChild> xChild(_xConnection,UNO_QUERY);
+ if(xChild.is())
+ {
+ Reference< XPropertySet> xProp(xChild->getParent(),UNO_QUERY);
+ fillAutoIncrementValue(xProp,_rAutoIncrementValueEnabled,_rsAutoIncrementValue);
+ }
+}
+
+OUString getStrippedDatabaseName(const Reference<XPropertySet>& _xDataSource,OUString& _rsDatabaseName)
+{
+ if ( _rsDatabaseName.isEmpty() && _xDataSource.is() )
+ {
+ try
+ {
+ _xDataSource->getPropertyValue(PROPERTY_NAME) >>= _rsDatabaseName;
+ }
+ catch(const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ OUString sName = _rsDatabaseName;
+ INetURLObject aURL(sName);
+ if ( aURL.GetProtocol() != INetProtocol::NotValid )
+ sName = aURL.getBase(INetURLObject::LAST_SEGMENT,true,INetURLObject::DecodeMechanism::Unambiguous);
+ return sName;
+}
+
+void setEvalDateFormatForFormatter(Reference< css::util::XNumberFormatter > const & _rxFormatter)
+{
+ OSL_ENSURE( _rxFormatter.is(),"setEvalDateFormatForFormatter: Formatter is NULL!");
+ if ( !_rxFormatter.is() )
+ return;
+
+ Reference< css::util::XNumberFormatsSupplier > xSupplier = _rxFormatter->getNumberFormatsSupplier();
+
+ auto pSupplierImpl = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(xSupplier);
+ OSL_ENSURE(pSupplierImpl,"No Supplier!");
+
+ if ( pSupplierImpl )
+ {
+ SvNumberFormatter* pFormatter = pSupplierImpl->GetNumberFormatter();
+ pFormatter->SetEvalDateFormat(NF_EVALDATEFORMAT_FORMAT);
+ }
+}
+
+TOTypeInfoSP queryPrimaryKeyType(const OTypeInfoMap& _rTypeInfo)
+{
+ TOTypeInfoSP pTypeInfo;
+ // first we search for a type which supports autoIncrement
+ for (auto const& elem : _rTypeInfo)
+ {
+ // OJ: we don't want to set an autoincrement column to be key
+ // because we don't have the possibility to know how to create
+ // such auto increment column later on
+ // so until we know how to do it, we create a column without autoincrement
+ // therefore we have searched
+ if ( elem.second->nType == DataType::INTEGER )
+ {
+ pTypeInfo = elem.second; // alternative
+ break;
+ }
+ else if ( !pTypeInfo && elem.second->nType == DataType::DOUBLE )
+ pTypeInfo = elem.second; // alternative
+ else if ( !pTypeInfo && elem.second->nType == DataType::REAL )
+ pTypeInfo = elem.second; // alternative
+ }
+ if ( !pTypeInfo ) // just a fallback
+ pTypeInfo = queryTypeInfoByType(DataType::VARCHAR,_rTypeInfo);
+
+ OSL_ENSURE(pTypeInfo,"checkColumns: can't find a type which is usable as a key!");
+ return pTypeInfo;
+}
+
+TOTypeInfoSP queryTypeInfoByType(sal_Int32 _nDataType,const OTypeInfoMap& _rTypeInfo)
+{
+ OTypeInfoMap::const_iterator aIter = _rTypeInfo.find(_nDataType);
+ if(aIter != _rTypeInfo.end())
+ return aIter->second;
+ // fall back if the type is unknown
+ TOTypeInfoSP pTypeInfo;
+ switch(_nDataType)
+ {
+ case DataType::TINYINT:
+ if( (pTypeInfo = queryTypeInfoByType(DataType::SMALLINT,_rTypeInfo) ) )
+ break;
+ [[fallthrough]];
+ case DataType::SMALLINT:
+ if( (pTypeInfo = queryTypeInfoByType(DataType::INTEGER,_rTypeInfo) ) )
+ break;
+ [[fallthrough]];
+ case DataType::INTEGER:
+ if( (pTypeInfo = queryTypeInfoByType(DataType::FLOAT,_rTypeInfo) ) )
+ break;
+ [[fallthrough]];
+ case DataType::FLOAT:
+ if( (pTypeInfo = queryTypeInfoByType(DataType::REAL,_rTypeInfo) ) )
+ break;
+ [[fallthrough]];
+ case DataType::DATE:
+ case DataType::TIME:
+ if( DataType::DATE == _nDataType || DataType::TIME == _nDataType )
+ {
+ if( (pTypeInfo = queryTypeInfoByType(DataType::TIMESTAMP,_rTypeInfo) ) )
+ break;
+ }
+ [[fallthrough]];
+ case DataType::TIMESTAMP:
+ case DataType::REAL:
+ case DataType::BIGINT:
+ if ( (pTypeInfo = queryTypeInfoByType(DataType::DOUBLE,_rTypeInfo) ) )
+ break;
+ [[fallthrough]];
+ case DataType::DOUBLE:
+ if ( (pTypeInfo = queryTypeInfoByType(DataType::NUMERIC,_rTypeInfo) ) )
+ break;
+ [[fallthrough]];
+ case DataType::NUMERIC:
+ pTypeInfo = queryTypeInfoByType(DataType::DECIMAL,_rTypeInfo);
+ break;
+ case DataType::DECIMAL:
+ if ( (pTypeInfo = queryTypeInfoByType(DataType::NUMERIC,_rTypeInfo) ) )
+ break;
+ if ( (pTypeInfo = queryTypeInfoByType(DataType::DOUBLE,_rTypeInfo) ) )
+ break;
+ break;
+ case DataType::VARCHAR:
+ if ( (pTypeInfo = queryTypeInfoByType(DataType::LONGVARCHAR,_rTypeInfo) ) )
+ break;
+ break;
+ case DataType::LONGVARCHAR:
+ if ( (pTypeInfo = queryTypeInfoByType(DataType::CLOB,_rTypeInfo) ) )
+ break;
+ break;
+ default:
+ ;
+ }
+ if ( !pTypeInfo )
+ {
+ bool bForce = true;
+ pTypeInfo = ::dbaui::getTypeInfoFromType(_rTypeInfo,DataType::VARCHAR,OUString(),"x",50,0,false,bForce);
+ }
+ OSL_ENSURE(pTypeInfo,"Wrong DataType supplied!");
+ return pTypeInfo;
+}
+
+sal_Int32 askForUserAction(weld::Window* pParent, TranslateId pTitle, TranslateId pText, bool _bAll, std::u16string_view _sName)
+{
+ SolarMutexGuard aGuard;
+ OUString aMsg = DBA_RES(pText);
+ aMsg = aMsg.replaceFirst("%1", _sName);
+ OSQLMessageBox aAsk(pParent, DBA_RES(pTitle), aMsg, MessBoxStyle::YesNo | MessBoxStyle::DefaultYes, MessageType::Query);
+ if ( _bAll )
+ {
+ aAsk.add_button(DBA_RES(STR_BUTTON_TEXT_ALL), RET_ALL, HID_CONFIRM_DROP_BUTTON_ALL);
+ }
+ return aAsk.run();
+}
+
+namespace
+{
+ OUString lcl_createSDBCLevelStatement( const OUString& _rStatement, const Reference< XConnection >& _rxConnection )
+ {
+ OUString sSDBCLevelStatement( _rStatement );
+ try
+ {
+ Reference< XMultiServiceFactory > xAnalyzerFactory( _rxConnection, UNO_QUERY_THROW );
+ Reference< XSingleSelectQueryAnalyzer > xAnalyzer( xAnalyzerFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW );
+ xAnalyzer->setQuery( _rStatement );
+ sSDBCLevelStatement = xAnalyzer->getQueryWithSubstitution();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return sSDBCLevelStatement;
+ }
+}
+
+Reference< XPropertySet > createView( const OUString& _rName, const Reference< XConnection >& _rxConnection,
+ const OUString& _rCommand )
+{
+ Reference<XViewsSupplier> xSup(_rxConnection,UNO_QUERY);
+ Reference< XNameAccess > xViews;
+ if(xSup.is())
+ xViews = xSup->getViews();
+ Reference<XDataDescriptorFactory> xFact(xViews,UNO_QUERY);
+ OSL_ENSURE(xFact.is(),"No XDataDescriptorFactory available!");
+ if(!xFact.is())
+ return nullptr;
+
+ Reference<XPropertySet> xView = xFact->createDataDescriptor();
+ if ( !xView.is() )
+ return nullptr;
+
+ OUString sCatalog,sSchema,sTable;
+ ::dbtools::qualifiedNameComponents(_rxConnection->getMetaData(),
+ _rName,
+ sCatalog,
+ sSchema,
+ sTable,
+ ::dbtools::EComposeRule::InDataManipulation);
+
+ xView->setPropertyValue(PROPERTY_CATALOGNAME,Any(sCatalog));
+ xView->setPropertyValue(PROPERTY_SCHEMANAME,Any(sSchema));
+ xView->setPropertyValue(PROPERTY_NAME,Any(sTable));
+
+ xView->setPropertyValue( PROPERTY_COMMAND, Any( _rCommand ) );
+
+ Reference<XAppend> xAppend(xViews,UNO_QUERY);
+ if(xAppend.is())
+ xAppend->appendByDescriptor(xView);
+
+ xView = nullptr;
+ // we need to reget the view because after appending it, it is no longer valid
+ // but this time it isn't a view object it is a table object with type "VIEW"
+ Reference<XTablesSupplier> xTabSup(_rxConnection,UNO_QUERY);
+ Reference< XNameAccess > xTables;
+ if ( xTabSup.is() )
+ {
+ xTables = xTabSup->getTables();
+ if ( xTables.is() && xTables->hasByName( _rName ) )
+ xTables->getByName( _rName ) >>= xView;
+ }
+
+ return xView;
+}
+
+Reference<XPropertySet> createView( const OUString& _rName, const Reference< XConnection >& _rxConnection
+ ,const Reference<XPropertySet>& _rxSourceObject)
+{
+ OUString sCommand;
+ Reference< XPropertySetInfo > xPSI( _rxSourceObject->getPropertySetInfo(), UNO_SET_THROW );
+ if ( xPSI->hasPropertyByName( PROPERTY_COMMAND ) )
+ {
+ _rxSourceObject->getPropertyValue( PROPERTY_COMMAND ) >>= sCommand;
+
+ bool bEscapeProcessing( false );
+ OSL_VERIFY( _rxSourceObject->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bEscapeProcessing );
+ if ( bEscapeProcessing )
+ sCommand = lcl_createSDBCLevelStatement( sCommand, _rxConnection );
+ }
+ else
+ {
+ sCommand = "SELECT * FROM " + composeTableNameForSelect( _rxConnection, _rxSourceObject );
+ }
+ return createView( _rName, _rxConnection, sCommand );
+}
+
+bool insertHierarchyElement(weld::Window* pParent, const Reference< XComponentContext >& _rxContext,
+ const Reference<XHierarchicalNameContainer>& _xNames,
+ const OUString& _sParentFolder,
+ bool _bForm,
+ bool _bCollection,
+ const Reference<XContent>& _xContent,
+ bool _bMove)
+{
+ OSL_ENSURE( _xNames.is(), "insertHierarchyElement: illegal name container!" );
+ if ( !_xNames.is() )
+ return false;
+
+ Reference<XNameAccess> xNameAccess( _xNames, UNO_QUERY );
+ if ( _xNames->hasByHierarchicalName(_sParentFolder) )
+ {
+ Reference<XChild> xChild(_xNames->getByHierarchicalName(_sParentFolder),UNO_QUERY);
+ xNameAccess.set(xChild,UNO_QUERY);
+ if ( !xNameAccess.is() && xChild.is() )
+ xNameAccess.set(xChild->getParent(),UNO_QUERY);
+ }
+
+ OSL_ENSURE( xNameAccess.is(), "insertHierarchyElement: could not find the proper name container!" );
+ if ( !xNameAccess.is() )
+ return false;
+
+ OUString sNewName;
+ Reference<XPropertySet> xProp(_xContent,UNO_QUERY);
+ if ( xProp.is() )
+ xProp->getPropertyValue(PROPERTY_NAME) >>= sNewName;
+
+ if ( !_bMove || sNewName.isEmpty() )
+ {
+ if ( sNewName.isEmpty() || xNameAccess->hasByName(sNewName) )
+ {
+ OUString sLabel, sTargetName;
+ if ( !sNewName.isEmpty() )
+ sTargetName = sNewName;
+ else
+ sTargetName = DBA_RES( _bCollection ? STR_NEW_FOLDER : ((_bForm) ? RID_STR_FORM : RID_STR_REPORT));
+ sLabel = DBA_RES( _bCollection ? STR_FOLDER_LABEL : ((_bForm) ? STR_FRM_LABEL : STR_RPT_LABEL));
+ sTargetName = ::dbtools::createUniqueName(xNameAccess,sTargetName);
+
+ // here we have everything needed to create a new query object ...
+ HierarchicalNameCheck aNameChecker( _xNames, _sParentFolder );
+ // ... ehm, except a new name
+ OSaveAsDlg aAskForName(pParent,
+ _rxContext,
+ sTargetName,
+ sLabel,
+ aNameChecker,
+ SADFlags::AdditionalDescription | SADFlags::TitlePasteAs);
+ if ( RET_OK != aAskForName.run() )
+ // cancelled by the user
+ return false;
+
+ sNewName = aAskForName.getName();
+ }
+ }
+ else if ( xNameAccess->hasByName(sNewName) )
+ {
+ OUString sError(DBA_RES(STR_NAME_ALREADY_EXISTS));
+ sError = sError.replaceFirst("#",sNewName);
+ throw SQLException(sError,nullptr,"S1000",0,Any());
+ }
+
+ try
+ {
+ Reference<XMultiServiceFactory> xORB( xNameAccess, UNO_QUERY_THROW );
+ uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
+ {
+ {"Name", uno::Any(sNewName)}, // set as folder
+ {"Parent", uno::Any(xNameAccess)},
+ {PROPERTY_EMBEDDEDOBJECT, uno::Any(_xContent)},
+ }));
+ OUString sServiceName(_bCollection ? (_bForm ? SERVICE_NAME_FORM_COLLECTION : SERVICE_NAME_REPORT_COLLECTION) : SERVICE_SDB_DOCUMENTDEFINITION);
+
+ Reference<XContent > xNew( xORB->createInstanceWithArguments( sServiceName, aArguments ), UNO_QUERY_THROW );
+ Reference< XNameContainer > xNameContainer( xNameAccess, UNO_QUERY_THROW );
+ xNameContainer->insertByName( sNewName, Any( xNew ) );
+ }
+ catch( const IllegalArgumentException& e )
+ {
+ ::dbtools::throwGenericSQLException( e.Message, e.Context );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ return false;
+ }
+
+ return true;
+}
+
+Reference< XNumberFormatter > getNumberFormatter(const Reference< XConnection >& _rxConnection, const Reference< css::uno::XComponentContext >& _rxContext )
+{
+ // create a formatter working with the connections format supplier
+ Reference< XNumberFormatter > xFormatter;
+
+ try
+ {
+ Reference< css::util::XNumberFormatsSupplier > xSupplier(::dbtools::getNumberFormats(_rxConnection, true, _rxContext));
+
+ if ( xSupplier.is() )
+ {
+ // create a new formatter
+ xFormatter.set(util::NumberFormatter::create( _rxContext ), UNO_QUERY_THROW);
+ xFormatter->attachNumberFormatsSupplier(xSupplier);
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return xFormatter;
+}
+
+} // dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/UpdateHelperImpl.hxx b/dbaccess/source/ui/misc/UpdateHelperImpl.hxx
new file mode 100644
index 0000000000..9f8d0d3998
--- /dev/null
+++ b/dbaccess/source/ui/misc/UpdateHelperImpl.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdbc/XPreparedStatement.hpp>
+#include <IUpdateHelper.hxx>
+
+namespace dbaui
+{
+ class OParameterUpdateHelper : public IUpdateHelper
+ {
+ css::uno::Reference< css::sdbc::XPreparedStatement > m_xPrepared;
+ css::uno::Reference< css::sdbc::XParameters > m_xParameters;
+
+ public:
+ explicit OParameterUpdateHelper(const css::uno::Reference< css::sdbc::XPreparedStatement >& _xPrepared)
+ :m_xPrepared(_xPrepared)
+ ,m_xParameters(_xPrepared,css::uno::UNO_QUERY)
+ {
+ }
+ virtual ~OParameterUpdateHelper() {}
+ virtual void updateString(sal_Int32 _nPos, const OUString& _sValue) override
+ {
+ m_xParameters->setString(_nPos, _sValue);
+ }
+ virtual void updateDouble(sal_Int32 _nPos,const double& _nValue) override
+ {
+ m_xParameters->setDouble(_nPos, _nValue);
+ }
+ virtual void updateDate(sal_Int32 _nPos,const css::util::Date& _nValue) override
+ {
+ m_xParameters->setDate(_nPos, _nValue);
+ }
+ virtual void updateTime(sal_Int32 _nPos,const css::util::Time& _nValue) override
+ {
+ m_xParameters->setTime(_nPos, _nValue);
+ }
+ virtual void updateTimestamp(sal_Int32 _nPos,const css::util::DateTime& _nValue) override
+ {
+ m_xParameters->setTimestamp(_nPos, _nValue);
+ }
+ virtual void updateInt(sal_Int32 _nPos, sal_Int32 _nValue) override
+ {
+ m_xParameters->setInt(_nPos, _nValue);
+ }
+ virtual void updateNull(sal_Int32 _nPos, ::sal_Int32 sqlType) override
+ {
+ m_xParameters->setNull(_nPos,sqlType);
+ }
+ virtual void insertRow() override
+ {
+ m_xPrepared->executeUpdate();
+ }
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/WCPage.cxx b/dbaccess/source/ui/misc/WCPage.cxx
new file mode 100644
index 0000000000..602edd2d6e
--- /dev/null
+++ b/dbaccess/source/ui/misc/WCPage.cxx
@@ -0,0 +1,325 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <WCPage.hxx>
+#include <WCopyTable.hxx>
+
+#include <defaultobjectnamecheck.hxx>
+#include <strings.hrc>
+#include <core_resource.hxx>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdb/application/CopyTableOperation.hpp>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbtools.hxx>
+
+using namespace ::dbaui;
+using namespace ::dbtools;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+
+namespace CopyTableOperation = css::sdb::application::CopyTableOperation;
+
+OCopyTable::OCopyTable(weld::Container* pPage, OCopyTableWizard* pWizard)
+ : OWizardPage(pPage, pWizard, "dbaccess/ui/copytablepage.ui", "CopyTablePage")
+ , m_bPKeyAllowed(false)
+ , m_bUseHeaderAllowed(true)
+ , m_nOldOperation(0)
+ , m_xEdTableName(m_xBuilder->weld_entry("name"))
+ , m_xRB_DefData(m_xBuilder->weld_radio_button("defdata"))
+ , m_xRB_Def(m_xBuilder->weld_radio_button("def"))
+ , m_xRB_View(m_xBuilder->weld_radio_button("view"))
+ , m_xRB_AppendData(m_xBuilder->weld_radio_button("data"))
+ , m_xCB_UseHeaderLine(m_xBuilder->weld_check_button("firstline"))
+ , m_xCB_PrimaryColumn(m_xBuilder->weld_check_button("primarykey"))
+ , m_xFT_KeyName(m_xBuilder->weld_label("keynamelabel"))
+ , m_xEdKeyName(m_xBuilder->weld_entry("keyname"))
+{
+ if ( m_pParent->m_xDestConnection.is() )
+ {
+ if (!m_pParent->supportsViews())
+ m_xRB_View->set_sensitive(false);
+
+ m_xCB_UseHeaderLine->set_active(true);
+ m_bPKeyAllowed = m_pParent->supportsPrimaryKey();
+
+ m_xCB_PrimaryColumn->set_sensitive(m_bPKeyAllowed);
+
+ m_xRB_AppendData->connect_toggled( LINK( this, OCopyTable, RadioChangeHdl ) );
+ m_xRB_DefData->connect_toggled( LINK( this, OCopyTable, RadioChangeHdl ) );
+ m_xRB_Def->connect_toggled( LINK( this, OCopyTable, RadioChangeHdl ) );
+ m_xRB_View->connect_toggled( LINK( this, OCopyTable, RadioChangeHdl ) );
+
+ m_xCB_PrimaryColumn->connect_toggled(LINK( this, OCopyTable, KeyClickHdl ) );
+
+ m_xFT_KeyName->set_sensitive(false);
+ m_xEdKeyName->set_sensitive(false);
+ m_xEdKeyName->set_text(m_pParent->createUniqueName("ID"));
+
+ const sal_Int32 nMaxLen = m_pParent->getMaxColumnNameLength();
+ m_xEdKeyName->set_max_length(nMaxLen);
+ }
+
+ SetPageTitle(DBA_RES(STR_COPYTABLE_TITLE_COPY));
+}
+
+OCopyTable::~OCopyTable()
+{
+}
+
+void OCopyTable::SetAppendDataRadio()
+{
+ m_pParent->EnableNextButton(true);
+ m_xFT_KeyName->set_sensitive(false);
+ m_xCB_PrimaryColumn->set_sensitive(false);
+ m_xEdKeyName->set_sensitive(false);
+ m_pParent->setOperation(CopyTableOperation::AppendData);
+}
+
+IMPL_LINK(OCopyTable, RadioChangeHdl, weld::Toggleable&, rButton, void)
+{
+ if (!rButton.get_active())
+ return;
+ if (m_xRB_AppendData->get_active())
+ {
+ SetAppendDataRadio();
+ return;
+ }
+ m_pParent->EnableNextButton(!m_xRB_View->get_active());
+ bool bKey = m_bPKeyAllowed && !m_xRB_View->get_active();
+ m_xFT_KeyName->set_sensitive(bKey && m_xCB_PrimaryColumn->get_active());
+ m_xEdKeyName->set_sensitive(bKey && m_xCB_PrimaryColumn->get_active());
+ m_xCB_PrimaryColumn->set_sensitive(bKey);
+ m_xCB_UseHeaderLine->set_sensitive(m_bUseHeaderAllowed && IsOptionDefData());
+
+ // set type what to do
+ if( IsOptionDefData() )
+ m_pParent->setOperation( CopyTableOperation::CopyDefinitionAndData );
+ else if( IsOptionDef() )
+ m_pParent->setOperation( CopyTableOperation::CopyDefinitionOnly );
+ else if( IsOptionView() )
+ m_pParent->setOperation( CopyTableOperation::CreateAsView );
+}
+
+IMPL_LINK_NOARG( OCopyTable, KeyClickHdl, weld::Toggleable&, void )
+{
+ m_xEdKeyName->set_sensitive(m_xCB_PrimaryColumn->get_active());
+ m_xFT_KeyName->set_sensitive(m_xCB_PrimaryColumn->get_active());
+}
+
+bool OCopyTable::LeavePage()
+{
+ m_pParent->m_bCreatePrimaryKeyColumn = m_bPKeyAllowed && m_xCB_PrimaryColumn->get_sensitive() && m_xCB_PrimaryColumn->get_active();
+ m_pParent->m_aKeyName = m_pParent->m_bCreatePrimaryKeyColumn ? m_xEdKeyName->get_text() : OUString();
+ m_pParent->setUseHeaderLine( m_xCB_UseHeaderLine->get_active() );
+
+ // first check if the table already exists in the database
+ if( m_pParent->getOperation() != CopyTableOperation::AppendData )
+ {
+ m_pParent->clearDestColumns();
+ DynamicTableOrQueryNameCheck aNameCheck( m_pParent->m_xDestConnection, CommandType::TABLE );
+ SQLExceptionInfo aErrorInfo;
+ if ( !aNameCheck.isNameValid( m_xEdTableName->get_text(), aErrorInfo ) )
+ {
+ aErrorInfo.append( SQLExceptionInfo::TYPE::SQLContext, DBA_RES( STR_SUGGEST_APPEND_TABLE_DATA ) );
+ m_pParent->showError(aErrorInfo.get());
+
+ return false;
+ }
+
+ // have to check the length of the table name
+ Reference< XDatabaseMetaData > xMeta = m_pParent->m_xDestConnection->getMetaData();
+ OUString sCatalog;
+ OUString sSchema;
+ OUString sTable;
+ ::dbtools::qualifiedNameComponents( xMeta,
+ m_xEdTableName->get_text(),
+ sCatalog,
+ sSchema,
+ sTable,
+ ::dbtools::EComposeRule::InDataManipulation);
+ sal_Int32 nMaxLength = xMeta->getMaxTableNameLength();
+ if ( nMaxLength && sTable.getLength() > nMaxLength )
+ {
+ m_pParent->showError(DBA_RES(STR_INVALID_TABLE_NAME_LENGTH));
+ return false;
+ }
+
+ // now we have to check if the name of the primary key already exists
+ if ( m_pParent->m_bCreatePrimaryKeyColumn
+ && m_pParent->m_aKeyName != m_pParent->createUniqueName(m_pParent->m_aKeyName) )
+ {
+ m_pParent->showError(DBA_RES(STR_WIZ_NAME_ALREADY_DEFINED) + " " + m_pParent->m_aKeyName);
+ return false;
+ }
+ }
+
+ if (m_xEdTableName->get_value_changed_from_saved())
+ { // table exists and name has changed
+ if ( m_pParent->getOperation() == CopyTableOperation::AppendData )
+ {
+ if(!checkAppendData())
+ return false;
+ }
+ else if ( m_nOldOperation == CopyTableOperation::AppendData )
+ {
+ m_xEdTableName->save_value();
+ return LeavePage();
+ }
+ }
+ else
+ { // table exist and is not new or doesn't exist and so on
+ if ( CopyTableOperation::AppendData == m_pParent->getOperation() )
+ {
+ if( !checkAppendData() )
+ return false;
+ }
+ }
+ m_pParent->m_sName = m_xEdTableName->get_text();
+ m_xEdTableName->save_value();
+
+ if(m_pParent->m_sName.isEmpty())
+ {
+ m_pParent->showError(DBA_RES(STR_INVALID_TABLE_NAME));
+ return false;
+ }
+
+ return true;
+}
+
+void OCopyTable::Activate()
+{
+ m_pParent->GetOKButton().set_sensitive(true);
+ m_nOldOperation = m_pParent->getOperation();
+ m_xEdTableName->grab_focus();
+ m_xCB_UseHeaderLine->set_active(m_pParent->UseHeaderLine());
+}
+
+OUString OCopyTable::GetTitle() const
+{
+ return DBA_RES(STR_WIZ_TABLE_COPY);
+}
+
+void OCopyTable::Reset()
+{
+ m_bFirstTime = false;
+
+ m_xEdTableName->set_text( m_pParent->m_sName );
+ m_xEdTableName->save_value();
+}
+
+bool OCopyTable::checkAppendData()
+{
+ m_pParent->clearDestColumns();
+ Reference< XPropertySet > xTable;
+ Reference< XTablesSupplier > xSup( m_pParent->m_xDestConnection, UNO_QUERY );
+ Reference<XNameAccess> xTables;
+ if (xSup.is())
+ xTables = xSup->getTables();
+ if (xTables.is() && xTables->hasByName(m_xEdTableName->get_text()))
+ {
+ const ODatabaseExport::TColumnVector& rSrcColumns = m_pParent->getSrcVector();
+ const sal_uInt32 nSrcSize = rSrcColumns.size();
+ m_pParent->m_vColumnPositions.resize( nSrcSize, ODatabaseExport::TPositions::value_type( COLUMN_POSITION_NOT_FOUND, COLUMN_POSITION_NOT_FOUND ) );
+ m_pParent->m_vColumnTypes.resize( nSrcSize , COLUMN_POSITION_NOT_FOUND );
+
+ // set new destination
+ xTables->getByName( m_xEdTableName->get_text() ) >>= xTable;
+ ObjectCopySource aTableCopySource( m_pParent->m_xDestConnection, xTable );
+ m_pParent->loadData( aTableCopySource, m_pParent->m_vDestColumns, m_pParent->m_aDestVec );
+ const ODatabaseExport::TColumnVector& rDestColumns = m_pParent->getDestVector();
+ const sal_uInt32 nMinSrcDestSize = std::min<sal_uInt32>(nSrcSize, rDestColumns.size());
+ sal_uInt32 i = 0;
+ for (auto const& column : rDestColumns)
+ {
+ if (i >= nMinSrcDestSize)
+ break;
+ bool bNotConvert = true;
+ m_pParent->m_vColumnPositions[i] = ODatabaseExport::TPositions::value_type(i+1,i+1);
+ TOTypeInfoSP pTypeInfo = m_pParent->convertType(column->second->getSpecialTypeInfo(),bNotConvert);
+ if ( !bNotConvert )
+ {
+ m_pParent->showColumnTypeNotSupported(column->first);
+ return false;
+ }
+
+ if ( pTypeInfo )
+ m_pParent->m_vColumnTypes[i] = pTypeInfo->nType;
+ else
+ m_pParent->m_vColumnTypes[i] = DataType::VARCHAR;
+ ++i;
+ }
+
+ }
+
+ if ( !xTable.is() )
+ {
+ m_pParent->showError(DBA_RES(STR_INVALID_TABLE_NAME));
+ return false;
+ }
+ return true;
+}
+
+void OCopyTable::setCreatePrimaryKey( bool _bDoCreate, const OUString& _rSuggestedName )
+{
+ bool bCreatePK = m_bPKeyAllowed && _bDoCreate;
+ m_xCB_PrimaryColumn->set_active( bCreatePK );
+ m_xEdKeyName->set_text( _rSuggestedName );
+
+ m_xFT_KeyName->set_sensitive( bCreatePK );
+ m_xEdKeyName->set_sensitive( bCreatePK );
+}
+
+void OCopyTable::setCreateStyleAction()
+{
+ // reselect the last action before
+ switch (m_pParent->getOperation())
+ {
+ case CopyTableOperation::CopyDefinitionAndData:
+ m_xRB_DefData->set_active(true);
+ RadioChangeHdl(*m_xRB_DefData);
+ break;
+ case CopyTableOperation::CopyDefinitionOnly:
+ m_xRB_Def->set_active(true);
+ RadioChangeHdl(*m_xRB_Def);
+ break;
+ case CopyTableOperation::AppendData:
+ m_xRB_AppendData->set_active(true);
+ SetAppendDataRadio();
+ break;
+ case CopyTableOperation::CreateAsView:
+ if (m_xRB_View->get_sensitive())
+ {
+ m_xRB_View->set_active(true);
+ RadioChangeHdl(*m_xRB_View);
+ }
+ else
+ {
+ m_xRB_DefData->set_active(true);
+ RadioChangeHdl(*m_xRB_DefData);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/WColumnSelect.cxx b/dbaccess/source/ui/misc/WColumnSelect.cxx
new file mode 100644
index 0000000000..3ad6d58a31
--- /dev/null
+++ b/dbaccess/source/ui/misc/WColumnSelect.cxx
@@ -0,0 +1,403 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <WColumnSelect.hxx>
+#include <strings.hrc>
+#include <osl/diagnose.h>
+#include <WCopyTable.hxx>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <core_resource.hxx>
+#include <com/sun/star/sdb/application/CopyTableOperation.hpp>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace dbaui;
+
+namespace CopyTableOperation = ::com::sun::star::sdb::application::CopyTableOperation;
+
+OUString OWizColumnSelect::GetTitle() const { return DBA_RES(STR_WIZ_COLUMN_SELECT_TITLE); }
+
+OWizardPage::OWizardPage(weld::Container* pPage, OCopyTableWizard* pWizard, const OUString& rUIXMLDescription, const OUString& rID)
+ : ::vcl::OWizardPage(pPage, pWizard, rUIXMLDescription, rID)
+ , m_pParent(pWizard)
+ , m_bFirstTime(true)
+{
+}
+
+OWizardPage::~OWizardPage()
+{
+}
+
+// OWizColumnSelect
+OWizColumnSelect::OWizColumnSelect(weld::Container* pPage, OCopyTableWizard* pWizard)
+ : OWizardPage(pPage, pWizard, "dbaccess/ui/applycolpage.ui", "ApplyColPage")
+ , m_xOrgColumnNames(m_xBuilder->weld_tree_view("from"))
+ , m_xColumn_RH(m_xBuilder->weld_button("colrh"))
+ , m_xColumns_RH(m_xBuilder->weld_button("colsrh"))
+ , m_xColumn_LH(m_xBuilder->weld_button("collh"))
+ , m_xColumns_LH(m_xBuilder->weld_button("colslh"))
+ , m_xNewColumnNames(m_xBuilder->weld_tree_view("to"))
+{
+ m_xColumn_RH->connect_clicked(LINK(this,OWizColumnSelect,ButtonClickHdl));
+ m_xColumn_LH->connect_clicked(LINK(this,OWizColumnSelect,ButtonClickHdl));
+ m_xColumns_RH->connect_clicked(LINK(this,OWizColumnSelect,ButtonClickHdl));
+ m_xColumns_LH->connect_clicked(LINK(this,OWizColumnSelect,ButtonClickHdl));
+
+ m_xOrgColumnNames->set_selection_mode(SelectionMode::Multiple);
+ m_xNewColumnNames->set_selection_mode(SelectionMode::Multiple);
+
+ m_xOrgColumnNames->connect_row_activated(LINK(this,OWizColumnSelect,ListDoubleClickHdl));
+ m_xNewColumnNames->connect_row_activated(LINK(this,OWizColumnSelect,ListDoubleClickHdl));
+}
+
+OWizColumnSelect::~OWizColumnSelect()
+{
+ while (m_xNewColumnNames->n_children())
+ {
+ delete weld::fromId<OFieldDescription*>(m_xNewColumnNames->get_id(0));
+ m_xNewColumnNames->remove(0);
+ }
+}
+
+void OWizColumnSelect::Reset()
+{
+ // restore original state
+ clearListBox(*m_xOrgColumnNames);
+ clearListBox(*m_xNewColumnNames);
+ m_pParent->m_mNameMapping.clear();
+
+ // insert the source columns in the left listbox
+ const ODatabaseExport::TColumnVector& rSrcColumns = m_pParent->getSrcVector();
+
+ for (auto const& column : rSrcColumns)
+ {
+ OUString sId(weld::toId(column->second));
+ m_xOrgColumnNames->append(sId, column->first);
+ }
+
+ if (m_xOrgColumnNames->n_children())
+ m_xOrgColumnNames->select(0);
+
+ m_bFirstTime = false;
+}
+
+void OWizColumnSelect::Activate( )
+{
+ // if there are no dest columns reset the left side with the original columns
+ if(m_pParent->getDestColumns().empty())
+ Reset();
+
+ clearListBox(*m_xNewColumnNames);
+
+ const ODatabaseExport::TColumnVector& rDestColumns = m_pParent->getDestVector();
+
+ // tdf#113923, the added columns must exist in the table
+ // in the case where:
+ // 1: we enabled the creation of a primary key
+ // 2: we come back here from the "Back" button of the next page,
+ // we want to avoid to list the new column generated in the next page
+ const ODatabaseExport::TColumns& rSrcColumns = m_pParent->getSourceColumns();
+
+ for (auto const& column : rDestColumns)
+ {
+ if (rSrcColumns.find(column->first) != rSrcColumns.end())
+ {
+ OUString sId(weld::toId(new OFieldDescription(*(column->second))));
+ m_xNewColumnNames->append(sId, column->first);
+ int nRemove = m_xOrgColumnNames->find_text(column->first);
+ if (nRemove != -1)
+ m_xOrgColumnNames->remove(nRemove);
+ }
+ }
+ m_pParent->GetOKButton().set_sensitive(m_xNewColumnNames->n_children() != 0);
+ m_pParent->EnableNextButton(m_xNewColumnNames->n_children() && m_pParent->getOperation() != CopyTableOperation::AppendData);
+ m_xColumns_RH->grab_focus();
+}
+
+bool OWizColumnSelect::LeavePage()
+{
+
+ m_pParent->clearDestColumns();
+
+ for(sal_Int32 i=0 ; i< m_xNewColumnNames->n_children();++i)
+ {
+ OFieldDescription* pField = weld::fromId<OFieldDescription*>(m_xNewColumnNames->get_id(i));
+ OSL_ENSURE(pField,"The field information can not be null!");
+ m_pParent->insertColumn(i,pField);
+ }
+
+ clearListBox(*m_xNewColumnNames);
+
+ if ( m_pParent->GetPressedButton() == OCopyTableWizard::WIZARD_NEXT
+ || m_pParent->GetPressedButton() == OCopyTableWizard::WIZARD_FINISH
+ )
+ return !m_pParent->getDestColumns().empty();
+ else
+ return true;
+}
+
+IMPL_LINK(OWizColumnSelect, ButtonClickHdl, weld::Button&, rButton, void)
+{
+ weld::TreeView *pLeft = nullptr;
+ weld::TreeView *pRight = nullptr;
+ bool bAll = false;
+
+ if (&rButton == m_xColumn_RH.get())
+ {
+ pLeft = m_xOrgColumnNames.get();
+ pRight = m_xNewColumnNames.get();
+ }
+ else if (&rButton == m_xColumn_LH.get())
+ {
+ pLeft = m_xNewColumnNames.get();
+ pRight = m_xOrgColumnNames.get();
+ }
+ else if (&rButton == m_xColumns_RH.get())
+ {
+ pLeft = m_xOrgColumnNames.get();
+ pRight = m_xNewColumnNames.get();
+ bAll = true;
+ }
+ else if (&rButton == m_xColumns_LH.get())
+ {
+ pLeft = m_xNewColumnNames.get();
+ pRight = m_xOrgColumnNames.get();
+ bAll = true;
+ }
+
+ if (!pLeft || !pRight)
+ return;
+
+ Reference< XDatabaseMetaData > xMetaData( m_pParent->m_xDestConnection->getMetaData() );
+ OUString sExtraChars = xMetaData->getExtraNameCharacters();
+ sal_Int32 nMaxNameLen = m_pParent->getMaxColumnNameLength();
+
+ ::comphelper::UStringMixEqual aCase(xMetaData->supportsMixedCaseQuotedIdentifiers());
+ std::vector< OUString> aRightColumns;
+ fillColumns(pRight,aRightColumns);
+
+ if(!bAll)
+ {
+ auto aRows = pLeft->get_selected_rows();
+ std::sort(aRows.begin(), aRows.end());
+
+ for (auto it = aRows.begin(); it != aRows.end(); ++it)
+ moveColumn(pRight,pLeft,aRightColumns,pLeft->get_text(*it),sExtraChars,nMaxNameLen,aCase);
+
+ for (auto it = aRows.rbegin(); it != aRows.rend(); ++it)
+ pLeft->remove(*it);
+ }
+ else
+ {
+ const sal_Int32 nEntries = pLeft->n_children();
+ for(sal_Int32 i=0; i < nEntries; ++i)
+ moveColumn(pRight,pLeft,aRightColumns,pLeft->get_text(i),sExtraChars,nMaxNameLen,aCase);
+ for(sal_Int32 j=pLeft->n_children(); j ; )
+ pLeft->remove(--j);
+ }
+
+ enableButtons();
+
+ if (m_xOrgColumnNames->n_children())
+ m_xOrgColumnNames->select(0);
+}
+
+IMPL_LINK( OWizColumnSelect, ListDoubleClickHdl, weld::TreeView&, rListBox, bool )
+{
+ weld::TreeView *pLeft,*pRight;
+ if (&rListBox == m_xOrgColumnNames.get())
+ {
+ pLeft = m_xOrgColumnNames.get();
+ pRight = m_xNewColumnNames.get();
+ }
+ else
+ {
+ pRight = m_xOrgColumnNames.get();
+ pLeft = m_xNewColumnNames.get();
+ }
+
+ // If database is able to process PrimaryKeys, set PrimaryKey
+ Reference< XDatabaseMetaData > xMetaData( m_pParent->m_xDestConnection->getMetaData() );
+ OUString sExtraChars = xMetaData->getExtraNameCharacters();
+ sal_Int32 nMaxNameLen = m_pParent->getMaxColumnNameLength();
+
+ ::comphelper::UStringMixEqual aCase(xMetaData->supportsMixedCaseQuotedIdentifiers());
+ std::vector< OUString> aRightColumns;
+ fillColumns(pRight,aRightColumns);
+
+ auto aRows = pLeft->get_selected_rows();
+ std::sort(aRows.begin(), aRows.end());
+
+ for (auto it = aRows.begin(); it != aRows.end(); ++it)
+ moveColumn(pRight,pLeft,aRightColumns,pLeft->get_text(*it),sExtraChars,nMaxNameLen,aCase);
+
+ for (auto it = aRows.rbegin(); it != aRows.rend(); ++it)
+ pLeft->remove(*it);
+
+ enableButtons();
+
+ return true;
+}
+
+void OWizColumnSelect::clearListBox(weld::TreeView& rListBox)
+{
+ rListBox.clear();
+}
+
+void OWizColumnSelect::fillColumns(weld::TreeView const * pRight,std::vector< OUString> &_rRightColumns)
+{
+ const sal_Int32 nCount = pRight->n_children();
+ _rRightColumns.reserve(nCount);
+ for (sal_Int32 i=0; i < nCount; ++i)
+ _rRightColumns.push_back(pRight->get_text(i));
+}
+
+void OWizColumnSelect::createNewColumn( weld::TreeView* _pListbox,
+ OFieldDescription const * _pSrcField,
+ std::vector< OUString>& _rRightColumns,
+ const OUString& _sColumnName,
+ std::u16string_view _sExtraChars,
+ sal_Int32 _nMaxNameLen,
+ const ::comphelper::UStringMixEqual& _aCase)
+{
+ OUString sConvertedName = m_pParent->convertColumnName(TMultiListBoxEntryFindFunctor(&_rRightColumns,_aCase),
+ _sColumnName,
+ _sExtraChars,
+ _nMaxNameLen);
+ OFieldDescription* pNewField = new OFieldDescription(*_pSrcField);
+ pNewField->SetName(sConvertedName);
+ bool bNotConvert = true;
+ pNewField->SetType(m_pParent->convertType(_pSrcField->getSpecialTypeInfo(),bNotConvert));
+ if ( !m_pParent->supportsPrimaryKey() )
+ pNewField->SetPrimaryKey(false);
+
+ _pListbox->append(weld::toId(pNewField), sConvertedName);
+ _rRightColumns.push_back(sConvertedName);
+
+ if ( !bNotConvert )
+ m_pParent->showColumnTypeNotSupported(sConvertedName);
+}
+
+void OWizColumnSelect::moveColumn( weld::TreeView* _pRight,
+ weld::TreeView const * _pLeft,
+ std::vector< OUString>& _rRightColumns,
+ const OUString& _sColumnName,
+ std::u16string_view _sExtraChars,
+ sal_Int32 _nMaxNameLen,
+ const ::comphelper::UStringMixEqual& _aCase)
+{
+ if(_pRight == m_xNewColumnNames.get())
+ {
+ // we copy the column into the new format for the dest
+ OFieldDescription* pSrcField = weld::fromId<OFieldDescription*>(_pLeft->get_id(_pLeft->find_text(_sColumnName)));
+ createNewColumn(_pRight,pSrcField,_rRightColumns,_sColumnName,_sExtraChars,_nMaxNameLen,_aCase);
+ }
+ else
+ {
+ // find the new column in the dest name mapping to obtain the old column
+ OCopyTableWizard::TNameMapping::const_iterator aIter = std::find_if(m_pParent->m_mNameMapping.begin(),m_pParent->m_mNameMapping.end(),
+ [&_aCase, &_sColumnName] (const OCopyTableWizard::TNameMapping::value_type& nameMap) {
+ return _aCase(nameMap.second, _sColumnName);
+ });
+
+ OSL_ENSURE(aIter != m_pParent->m_mNameMapping.end(),"Column must be defined");
+ if ( aIter == m_pParent->m_mNameMapping.end() )
+ return; // do nothing
+ const ODatabaseExport::TColumns& rSrcColumns = m_pParent->getSourceColumns();
+ ODatabaseExport::TColumns::const_iterator aSrcIter = rSrcColumns.find((*aIter).first);
+ if ( aSrcIter != rSrcColumns.end() )
+ {
+ // we need also the old position of this column to insert it back on that position again
+ const ODatabaseExport::TColumnVector& rSrcVector = m_pParent->getSrcVector();
+ ODatabaseExport::TColumnVector::const_iterator aPos = std::find(rSrcVector.begin(), rSrcVector.end(), aSrcIter);
+ OSL_ENSURE( aPos != rSrcVector.end(),"Invalid position for the iterator here!");
+ ODatabaseExport::TColumnVector::size_type nPos = (aPos - rSrcVector.begin()) - adjustColumnPosition(_pLeft, _sColumnName, (aPos - rSrcVector.begin()), _aCase);
+
+ OUString sId(weld::toId(aSrcIter->second));
+ const OUString& rStr = (*aIter).first;
+ _pRight->insert(nullptr, nPos, &rStr, &sId, nullptr, nullptr, false, nullptr);
+ _rRightColumns.push_back(rStr);
+ m_pParent->removeColumnNameFromNameMap(_sColumnName);
+ }
+ }
+}
+
+// Simply returning fields back to their original position is
+// not enough. We need to take into account what fields have
+// been removed earlier and adjust accordingly. Based on the
+// algorithm employed in moveColumn().
+sal_Int32 OWizColumnSelect::adjustColumnPosition(weld::TreeView const * _pLeft,
+ std::u16string_view _sColumnName,
+ ODatabaseExport::TColumnVector::size_type nCurrentPos,
+ const ::comphelper::UStringMixEqual& _aCase)
+{
+ sal_Int32 nAdjustedPos = 0;
+
+ // if returning all entries to their original position,
+ // then there is no need to adjust the positions.
+ if (m_xColumns_LH->has_focus())
+ return nAdjustedPos;
+
+ const sal_Int32 nCount = _pLeft->n_children();
+ OUString sColumnString;
+ for(sal_Int32 i=0; i < nCount; ++i)
+ {
+ sColumnString = _pLeft->get_text(i);
+ if(_sColumnName != sColumnString)
+ {
+ // find the new column in the dest name mapping to obtain the old column
+ OCopyTableWizard::TNameMapping::const_iterator aIter = std::find_if(m_pParent->m_mNameMapping.begin(),m_pParent->m_mNameMapping.end(),
+ [&_aCase, &sColumnString] (const OCopyTableWizard::TNameMapping::value_type& nameMap) {
+ return _aCase(nameMap.second, sColumnString);
+ });
+
+ OSL_ENSURE(aIter != m_pParent->m_mNameMapping.end(),"Column must be defined");
+ const ODatabaseExport::TColumns& rSrcColumns = m_pParent->getSourceColumns();
+ ODatabaseExport::TColumns::const_iterator aSrcIter = rSrcColumns.find((*aIter).first);
+ if ( aSrcIter != rSrcColumns.end() )
+ {
+ // we need also the old position of this column to insert it back on that position again
+ const ODatabaseExport::TColumnVector& rSrcVector = m_pParent->getSrcVector();
+ ODatabaseExport::TColumnVector::const_iterator aPos = std::find(rSrcVector.begin(), rSrcVector.end(), aSrcIter);
+ ODatabaseExport::TColumnVector::size_type nPos = aPos - rSrcVector.begin();
+ if( nPos < nCurrentPos)
+ {
+ nAdjustedPos++;
+ }
+ }
+ }
+ }
+
+ return nAdjustedPos;
+}
+
+void OWizColumnSelect::enableButtons()
+{
+ bool bEntries = m_xNewColumnNames->n_children() != 0;
+ if (!bEntries)
+ m_pParent->m_mNameMapping.clear();
+
+ m_pParent->GetOKButton().set_sensitive(bEntries);
+ m_pParent->EnableNextButton(bEntries && m_pParent->getOperation() != CopyTableOperation::AppendData);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/WCopyTable.cxx b/dbaccess/source/ui/misc/WCopyTable.cxx
new file mode 100644
index 0000000000..29be877474
--- /dev/null
+++ b/dbaccess/source/ui/misc/WCopyTable.cxx
@@ -0,0 +1,1553 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <strings.hrc>
+#include <strings.hxx>
+#include <core_resource.hxx>
+#include <sqlmessage.hxx>
+#include <UITools.hxx>
+#include <WColumnSelect.hxx>
+#include <WCopyTable.hxx>
+#include <WCPage.hxx>
+#include <WExtendPages.hxx>
+#include <WNameMatch.hxx>
+#include <WTypeSelect.hxx>
+
+#include <com/sun/star/sdb/application/CopyTableOperation.hpp>
+#include <com/sun/star/sdb/SQLContext.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XStatement.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbcx/KeyType.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/sdbcx/XKeysSupplier.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+
+#include <comphelper/interaction.hxx>
+#include <connectivity/dbtools.hxx>
+#include <connectivity/dbmetadata.hxx>
+#include <connectivity/dbexception.hxx>
+#include <o3tl/safeint.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <algorithm>
+#include <utility>
+
+using namespace ::dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::task;
+using namespace dbtools;
+
+namespace CopyTableOperation = ::com::sun::star::sdb::application::CopyTableOperation;
+
+#define MAX_PAGES 4 // max. number of pages, which are shown
+
+namespace
+{
+ void clearColumns(ODatabaseExport::TColumns& _rColumns, ODatabaseExport::TColumnVector& _rColumnsVec)
+ {
+ for (auto const& column : _rColumns)
+ delete column.second;
+
+ _rColumnsVec.clear();
+ _rColumns.clear();
+ }
+}
+
+// ICopyTableSourceObject
+ICopyTableSourceObject::~ICopyTableSourceObject()
+{
+}
+
+// ObjectCopySource
+ObjectCopySource::ObjectCopySource( const Reference< XConnection >& _rxConnection, const Reference< XPropertySet >& _rxObject )
+ :m_xConnection( _rxConnection, UNO_SET_THROW )
+ ,m_xMetaData( _rxConnection->getMetaData(), UNO_SET_THROW )
+ ,m_xObject( _rxObject, UNO_SET_THROW )
+ ,m_xObjectPSI( _rxObject->getPropertySetInfo(), UNO_SET_THROW )
+ ,m_xObjectColumns( Reference< XColumnsSupplier >( _rxObject, UNO_QUERY_THROW )->getColumns(), UNO_SET_THROW )
+{
+}
+
+OUString ObjectCopySource::getQualifiedObjectName() const
+{
+ OUString sName;
+
+ if ( !m_xObjectPSI->hasPropertyByName( PROPERTY_COMMAND ) )
+ sName = ::dbtools::composeTableName( m_xMetaData, m_xObject, ::dbtools::EComposeRule::InDataManipulation, false );
+ else
+ m_xObject->getPropertyValue( PROPERTY_NAME ) >>= sName;
+ return sName;
+}
+
+bool ObjectCopySource::isView() const
+{
+ bool bIsView = false;
+ try
+ {
+ if ( m_xObjectPSI->hasPropertyByName( PROPERTY_TYPE ) )
+ {
+ OUString sObjectType;
+ OSL_VERIFY( m_xObject->getPropertyValue( PROPERTY_TYPE ) >>= sObjectType );
+ bIsView = sObjectType == "VIEW";
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return bIsView;
+}
+
+void ObjectCopySource::copyUISettingsTo( const Reference< XPropertySet >& _rxObject ) const
+{
+ const OUString aCopyProperties[] = {
+ PROPERTY_FONT, PROPERTY_ROW_HEIGHT, PROPERTY_TEXTCOLOR,PROPERTY_TEXTLINECOLOR,PROPERTY_TEXTEMPHASIS,PROPERTY_TEXTRELIEF
+ };
+ for (const auto & aCopyProperty : aCopyProperties)
+ {
+ if ( m_xObjectPSI->hasPropertyByName( aCopyProperty ) )
+ _rxObject->setPropertyValue( aCopyProperty, m_xObject->getPropertyValue( aCopyProperty ) );
+ }
+}
+
+void ObjectCopySource::copyFilterAndSortingTo( const Reference< XConnection >& _xConnection,const Reference< XPropertySet >& _rxObject ) const
+{
+ std::pair< OUString, OUString > aProperties[] = {
+ std::pair< OUString, OUString >(PROPERTY_FILTER,OUString(" AND "))
+ ,std::pair< OUString, OUString >(PROPERTY_ORDER,OUString(" ORDER BY "))
+ };
+
+ try
+ {
+ const OUString sSourceName = ::dbtools::composeTableNameForSelect(m_xConnection,m_xObject) + ".";
+ const OUString sTargetName = ::dbtools::composeTableNameForSelect(_xConnection,_rxObject);
+ const OUString sTargetNameTemp = sTargetName + ".";
+
+ OUStringBuffer sStatement = "SELECT * FROM " + sTargetName + " WHERE 0=1";
+
+ for (const std::pair<OUString,OUString> & aProperty : aProperties)
+ {
+ if ( m_xObjectPSI->hasPropertyByName( aProperty.first ) )
+ {
+ OUString sFilter;
+ m_xObject->getPropertyValue( aProperty.first ) >>= sFilter;
+ if ( !sFilter.isEmpty() )
+ {
+ sStatement.append(aProperty.second);
+ sFilter = sFilter.replaceFirst(sSourceName,sTargetNameTemp);
+ _rxObject->setPropertyValue( aProperty.first, Any(sFilter) );
+ sStatement.append(sFilter);
+ }
+ }
+ }
+
+ _xConnection->createStatement()->executeQuery(sStatement.makeStringAndClear());
+
+ if ( m_xObjectPSI->hasPropertyByName( PROPERTY_APPLYFILTER ) )
+ _rxObject->setPropertyValue( PROPERTY_APPLYFILTER, m_xObject->getPropertyValue( PROPERTY_APPLYFILTER ) );
+ }
+ catch(Exception&)
+ {
+ }
+}
+
+Sequence< OUString > ObjectCopySource::getColumnNames() const
+{
+ return m_xObjectColumns->getElementNames();
+}
+
+Sequence< OUString > ObjectCopySource::getPrimaryKeyColumnNames() const
+{
+ const Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(m_xObject);
+ Sequence< OUString > aKeyColNames;
+ if ( xPrimaryKeyColumns.is() )
+ aKeyColNames = xPrimaryKeyColumns->getElementNames();
+ return aKeyColNames;
+}
+
+OFieldDescription* ObjectCopySource::createFieldDescription( const OUString& _rColumnName ) const
+{
+ Reference< XPropertySet > xColumn( m_xObjectColumns->getByName( _rColumnName ), UNO_QUERY_THROW );
+ return new OFieldDescription( xColumn );
+}
+
+OUString ObjectCopySource::getSelectStatement() const
+{
+ OUString sSelectStatement;
+ if ( m_xObjectPSI->hasPropertyByName( PROPERTY_COMMAND ) )
+ { // query
+ OSL_VERIFY( m_xObject->getPropertyValue( PROPERTY_COMMAND ) >>= sSelectStatement );
+ }
+ else
+ { // table
+ OUStringBuffer aSQL( "SELECT " );
+
+ // we need to create the sql stmt with column names
+ // otherwise it is possible that names don't match
+ const OUString sQuote = m_xMetaData->getIdentifierQuoteString();
+
+ Sequence< OUString > aColumnNames = getColumnNames();
+ const OUString* pColumnName = aColumnNames.getConstArray();
+ const OUString* pEnd = pColumnName + aColumnNames.getLength();
+ for ( ; pColumnName != pEnd; )
+ {
+ aSQL.append( ::dbtools::quoteName( sQuote, *pColumnName++ ) );
+
+ if ( pColumnName == pEnd )
+ aSQL.append( " " );
+ else
+ aSQL.append( ", " );
+ }
+
+ aSQL.append( "FROM " + ::dbtools::composeTableNameForSelect( m_xConnection, m_xObject ) );
+
+ sSelectStatement = aSQL.makeStringAndClear();
+ }
+
+ return sSelectStatement;
+}
+
+::utl::SharedUNOComponent< XPreparedStatement > ObjectCopySource::getPreparedSelectStatement() const
+{
+ ::utl::SharedUNOComponent< XPreparedStatement > xStatement(
+ m_xConnection->prepareStatement( getSelectStatement() ),
+ ::utl::SharedUNOComponent< XPreparedStatement >::TakeOwnership
+ );
+ return xStatement;
+}
+
+// NamedTableCopySource
+NamedTableCopySource::NamedTableCopySource( const Reference< XConnection >& _rxConnection, OUString _sTableName )
+ :m_xConnection( _rxConnection, UNO_SET_THROW )
+ ,m_xMetaData( _rxConnection->getMetaData(), UNO_SET_THROW )
+ ,m_sTableName(std::move( _sTableName ))
+{
+ ::dbtools::qualifiedNameComponents( m_xMetaData, m_sTableName, m_sTableCatalog, m_sTableSchema, m_sTableBareName, ::dbtools::EComposeRule::Complete );
+ impl_ensureColumnInfo_throw();
+}
+
+OUString NamedTableCopySource::getQualifiedObjectName() const
+{
+ return m_sTableName;
+}
+
+bool NamedTableCopySource::isView() const
+{
+ OUString sTableType;
+ try
+ {
+ Reference< XResultSet > xTableDesc( m_xMetaData->getTables( Any( m_sTableCatalog ), m_sTableSchema, m_sTableBareName,
+ Sequence< OUString >() ) );
+ Reference< XRow > xTableDescRow( xTableDesc, UNO_QUERY_THROW );
+ OSL_VERIFY( xTableDesc->next() );
+ sTableType = xTableDescRow->getString( 4 );
+ OSL_ENSURE( !xTableDescRow->wasNull(), "NamedTableCopySource::isView: invalid table type!" );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return sTableType == "VIEW";
+}
+
+void NamedTableCopySource::copyUISettingsTo( const Reference< XPropertySet >& /*_rxObject*/ ) const
+{
+ // not supported: we do not have UI settings to copy
+}
+
+void NamedTableCopySource::copyFilterAndSortingTo( const Reference< XConnection >& ,const Reference< XPropertySet >& /*_rxObject*/ ) const
+{
+}
+
+void NamedTableCopySource::impl_ensureColumnInfo_throw()
+{
+ if ( !m_aColumnInfo.empty() )
+ return;
+
+ Reference< XResultSetMetaDataSupplier > xStatementMetaSupp( impl_ensureStatement_throw().getTyped(), UNO_QUERY_THROW );
+ Reference< XResultSetMetaData > xStatementMeta( xStatementMetaSupp->getMetaData(), UNO_SET_THROW );
+
+ sal_Int32 nColCount( xStatementMeta->getColumnCount() );
+ for ( sal_Int32 i = 1; i <= nColCount; ++i )
+ {
+ OFieldDescription aDesc;
+
+ aDesc.SetName( xStatementMeta->getColumnName( i ) );
+ aDesc.SetHelpText( xStatementMeta->getColumnLabel( i ) );
+ aDesc.SetTypeValue( xStatementMeta->getColumnType( i ) );
+ aDesc.SetTypeName( xStatementMeta->getColumnTypeName( i ) );
+ aDesc.SetPrecision( xStatementMeta->getPrecision( i ) );
+ aDesc.SetScale( xStatementMeta->getScale( i ) );
+ aDesc.SetIsNullable( xStatementMeta->isNullable( i ) );
+ aDesc.SetCurrency( xStatementMeta->isCurrency( i ) );
+ aDesc.SetAutoIncrement( xStatementMeta->isAutoIncrement( i ) );
+
+ m_aColumnInfo.push_back( aDesc );
+ }
+}
+
+::utl::SharedUNOComponent< XPreparedStatement > const & NamedTableCopySource::impl_ensureStatement_throw()
+{
+ if ( !m_xStatement.is() )
+ m_xStatement.set( m_xConnection->prepareStatement( getSelectStatement() ), UNO_SET_THROW );
+ return m_xStatement;
+}
+
+Sequence< OUString > NamedTableCopySource::getColumnNames() const
+{
+ Sequence< OUString > aNames( m_aColumnInfo.size() );
+ std::transform(m_aColumnInfo.begin(), m_aColumnInfo.end(), aNames.getArray(),
+ [](const auto& elem) { return elem.GetName(); });
+
+ return aNames;
+}
+
+Sequence< OUString > NamedTableCopySource::getPrimaryKeyColumnNames() const
+{
+ Sequence< OUString > aPKColNames;
+
+ try
+ {
+ Reference< XResultSet > xPKDesc( m_xMetaData->getPrimaryKeys( Any( m_sTableCatalog ), m_sTableSchema, m_sTableBareName ) );
+ Reference< XRow > xPKDescRow( xPKDesc, UNO_QUERY_THROW );
+ while ( xPKDesc->next() )
+ {
+ sal_Int32 len( aPKColNames.getLength() );
+ aPKColNames.realloc( len + 1 );
+ aPKColNames.getArray()[ len ] = xPKDescRow->getString( 4 ); // COLUMN_NAME
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return aPKColNames;
+}
+
+OFieldDescription* NamedTableCopySource::createFieldDescription( const OUString& _rColumnName ) const
+{
+ for (auto const& elem : m_aColumnInfo)
+ if ( elem.GetName() == _rColumnName )
+ return new OFieldDescription(elem);
+
+ return nullptr;
+}
+
+OUString NamedTableCopySource::getSelectStatement() const
+{
+ return "SELECT * FROM " +
+ ::dbtools::composeTableNameForSelect( m_xConnection, m_sTableCatalog, m_sTableSchema, m_sTableBareName );
+}
+
+::utl::SharedUNOComponent< XPreparedStatement > NamedTableCopySource::getPreparedSelectStatement() const
+{
+ return const_cast< NamedTableCopySource* >( this )->impl_ensureStatement_throw();
+}
+
+namespace {
+
+// DummyCopySource
+class DummyCopySource : public ICopyTableSourceObject
+{
+public:
+ DummyCopySource() { }
+
+ static const DummyCopySource& Instance();
+
+ // ICopyTableSourceObject overridables
+ virtual OUString getQualifiedObjectName() const override;
+ virtual bool isView() const override;
+ virtual void copyUISettingsTo( const css::uno::Reference< css::beans::XPropertySet >& _rxObject ) const override;
+ virtual void copyFilterAndSortingTo(const css::uno::Reference< css::sdbc::XConnection >& _xConnection, const css::uno::Reference< css::beans::XPropertySet >& _rxObject ) const override;
+ virtual css::uno::Sequence< OUString >
+ getColumnNames() const override;
+ virtual css::uno::Sequence< OUString >
+ getPrimaryKeyColumnNames() const override;
+ virtual OFieldDescription* createFieldDescription( const OUString& _rColumnName ) const override;
+ virtual OUString getSelectStatement() const override;
+ virtual ::utl::SharedUNOComponent< XPreparedStatement >
+ getPreparedSelectStatement() const override;
+};
+
+}
+
+const DummyCopySource& DummyCopySource::Instance()
+{
+ static DummyCopySource s_aTheInstance;
+ return s_aTheInstance;
+}
+
+OUString DummyCopySource::getQualifiedObjectName() const
+{
+ SAL_WARN("dbaccess.ui", "DummyCopySource::getQualifiedObjectName: not to be called!" );
+ return OUString();
+}
+
+bool DummyCopySource::isView() const
+{
+ SAL_WARN("dbaccess.ui", "DummyCopySource::isView: not to be called!" );
+ return false;
+}
+
+void DummyCopySource::copyUISettingsTo( const Reference< XPropertySet >& /*_rxObject*/ ) const
+{
+ // no support
+}
+
+void DummyCopySource::copyFilterAndSortingTo( const Reference< XConnection >& ,const Reference< XPropertySet >& /*_rxObject*/ ) const
+{
+}
+
+Sequence< OUString > DummyCopySource::getColumnNames() const
+{
+ return Sequence< OUString >();
+}
+
+Sequence< OUString > DummyCopySource::getPrimaryKeyColumnNames() const
+{
+ SAL_WARN("dbaccess.ui", "DummyCopySource::getPrimaryKeyColumnNames: not to be called!" );
+ return Sequence< OUString >();
+}
+
+OFieldDescription* DummyCopySource::createFieldDescription( const OUString& /*_rColumnName*/ ) const
+{
+ SAL_WARN("dbaccess.ui", "DummyCopySource::createFieldDescription: not to be called!" );
+ return nullptr;
+}
+
+OUString DummyCopySource::getSelectStatement() const
+{
+ SAL_WARN("dbaccess.ui", "DummyCopySource::getSelectStatement: not to be called!" );
+ return OUString();
+}
+
+::utl::SharedUNOComponent< XPreparedStatement > DummyCopySource::getPreparedSelectStatement() const
+{
+ SAL_WARN("dbaccess.ui", "DummyCopySource::getPreparedSelectStatement: not to be called!" );
+ return ::utl::SharedUNOComponent< XPreparedStatement >();
+}
+
+namespace
+{
+ bool lcl_canCreateViewFor_nothrow( const Reference< XConnection >& _rxConnection )
+ {
+ Reference< XViewsSupplier > xSup( _rxConnection, UNO_QUERY );
+ Reference< XDataDescriptorFactory > xViewFac;
+ if ( xSup.is() )
+ xViewFac.set( xSup->getViews(), UNO_QUERY );
+ return xViewFac.is();
+ }
+
+ bool lcl_sameConnection_throw( const Reference< XConnection >& _rxLHS, const Reference< XConnection >& _rxRHS )
+ {
+ Reference< XDatabaseMetaData > xMetaLHS( _rxLHS->getMetaData(), UNO_SET_THROW );
+ Reference< XDatabaseMetaData > xMetaRHS( _rxRHS->getMetaData(), UNO_SET_THROW );
+ return xMetaLHS->getURL() == xMetaRHS->getURL();
+ }
+}
+
+// OCopyTableWizard
+OCopyTableWizard::OCopyTableWizard(weld::Window* pParent, const OUString& _rDefaultName, sal_Int16 _nOperation,
+ const ICopyTableSourceObject& _rSourceObject, const Reference< XConnection >& _xSourceConnection,
+ const Reference< XConnection >& _xConnection, const Reference< XComponentContext >& _rxContext,
+ const Reference< XInteractionHandler>& _xInteractionHandler)
+ : vcl::RoadmapWizardMachine(pParent)
+ , m_mNameMapping(_xConnection->getMetaData().is() && _xConnection->getMetaData()->supportsMixedCaseQuotedIdentifiers())
+ , m_xDestConnection( _xConnection )
+ , m_rSourceObject( _rSourceObject )
+ , m_xFormatter( getNumberFormatter( _xConnection, _rxContext ) )
+ , m_xContext(_rxContext)
+ , m_xInteractionHandler(_xInteractionHandler)
+ , m_sTypeNames(DBA_RES(STR_TABLEDESIGN_DBFIELDTYPES))
+ , m_nPageCount(0)
+ , m_bDeleteSourceColumns(true)
+ , m_bInterConnectionCopy( _xSourceConnection != _xConnection )
+ , m_sName( _rDefaultName )
+ , m_nOperation( _nOperation )
+ , m_ePressed( WIZARD_NONE )
+ , m_bCreatePrimaryKeyColumn(false)
+ , m_bUseHeaderLine(false)
+{
+ construct();
+
+ // extract table name
+ OUString sInitialTableName( _rDefaultName );
+ try
+ {
+ m_sSourceName = m_rSourceObject.getQualifiedObjectName();
+ OSL_ENSURE( !m_sSourceName.isEmpty(), "OCopyTableWizard::OCopyTableWizard: unable to retrieve the source object's name!" );
+
+ if ( sInitialTableName.isEmpty() )
+ sInitialTableName = m_sSourceName;
+
+ if ( m_sName.isEmpty() )
+ {
+ if ( _xSourceConnection == m_xDestConnection )
+ {
+ Reference< XTablesSupplier > xSup( m_xDestConnection, UNO_QUERY_THROW );
+ m_sName = ::dbtools::createUniqueName( xSup->getTables(), sInitialTableName, false );
+ }
+ else
+ m_sName = sInitialTableName;
+ }
+ }
+ catch ( const Exception& )
+ {
+ m_sName = sInitialTableName;
+ }
+
+ ::dbaui::fillTypeInfo( _xSourceConnection, m_sTypeNames, m_aTypeInfo, m_aTypeInfoIndex );
+ ::dbaui::fillTypeInfo( m_xDestConnection, m_sTypeNames, m_aDestTypeInfo, m_aDestTypeInfoIndex );
+ loadData( m_rSourceObject, m_vSourceColumns, m_vSourceVec );
+
+ bool bAllowViews = true;
+ // if the source is a, don't allow creating views
+ if ( m_rSourceObject.isView() )
+ bAllowViews = false;
+ // no views if the target connection does not support creating them
+ if ( !lcl_canCreateViewFor_nothrow( m_xDestConnection ) )
+ bAllowViews = false;
+ // no views if we're copying to a different database
+ if ( !lcl_sameConnection_throw( _xSourceConnection, m_xDestConnection ) )
+ bAllowViews = false;
+
+ if ( m_bInterConnectionCopy )
+ {
+ Reference< XDatabaseMetaData > xSrcMeta = _xSourceConnection->getMetaData();
+ OUString sCatalog;
+ OUString sSchema;
+ OUString sTable;
+ ::dbtools::qualifiedNameComponents( xSrcMeta,
+ m_sName,
+ sCatalog,
+ sSchema,
+ sTable,
+ ::dbtools::EComposeRule::InDataManipulation);
+
+ m_sName = ::dbtools::composeTableName(m_xDestConnection->getMetaData(),sCatalog,sSchema,sTable,false,::dbtools::EComposeRule::InTableDefinitions);
+ }
+
+ std::unique_ptr<OCopyTable> xPage1(new OCopyTable(CreatePageContainer(), this));
+ xPage1->disallowUseHeaderLine();
+ if ( !bAllowViews )
+ xPage1->disallowViews();
+ xPage1->setCreateStyleAction();
+ AddWizardPage(std::move(xPage1));
+
+ AddWizardPage( std::make_unique<OWizNameMatching>(CreatePageContainer(), this));
+ AddWizardPage( std::make_unique<OWizColumnSelect>(CreatePageContainer(), this));
+ AddWizardPage( std::make_unique<OWizNormalExtend>(CreatePageContainer(), this));
+ ActivatePage();
+
+ m_xAssistant->set_current_page(0);
+}
+
+weld::Container* OCopyTableWizard::CreatePageContainer()
+{
+ OUString sIdent(OUString::number(m_nPageCount));
+ weld::Container* pPageContainer = m_xAssistant->append_page(sIdent);
+ return pPageContainer;
+}
+
+OCopyTableWizard::OCopyTableWizard( weld::Window* pParent, OUString _sDefaultName, sal_Int16 _nOperation,
+ ODatabaseExport::TColumns&& _rSourceColumns, const ODatabaseExport::TColumnVector& _rSourceColVec,
+ const Reference< XConnection >& _xConnection, const Reference< XNumberFormatter >& _xFormatter,
+ TypeSelectionPageFactory _pTypeSelectionPageFactory, SvStream& _rTypeSelectionPageArg, const Reference< XComponentContext >& _rxContext )
+ : vcl::RoadmapWizardMachine(pParent)
+ , m_vSourceColumns(std::move(_rSourceColumns))
+ , m_mNameMapping(_xConnection->getMetaData().is() && _xConnection->getMetaData()->supportsMixedCaseQuotedIdentifiers())
+ , m_xDestConnection( _xConnection )
+ , m_rSourceObject( DummyCopySource::Instance() )
+ , m_xFormatter(_xFormatter)
+ , m_xContext(_rxContext)
+ , m_sTypeNames(DBA_RES(STR_TABLEDESIGN_DBFIELDTYPES))
+ , m_nPageCount(0)
+ , m_bDeleteSourceColumns(false)
+ , m_bInterConnectionCopy( false )
+ , m_sName(std::move(_sDefaultName))
+ , m_nOperation( _nOperation )
+ , m_ePressed( WIZARD_NONE )
+ , m_bCreatePrimaryKeyColumn(false)
+ , m_bUseHeaderLine(false)
+{
+ construct();
+ for (auto const& sourceCol : _rSourceColVec)
+ {
+ m_vSourceVec.emplace_back(m_vSourceColumns.find(sourceCol->first));
+ }
+
+ ::dbaui::fillTypeInfo( _xConnection, m_sTypeNames, m_aTypeInfo, m_aTypeInfoIndex );
+ ::dbaui::fillTypeInfo( _xConnection, m_sTypeNames, m_aDestTypeInfo, m_aDestTypeInfoIndex );
+
+ m_xInteractionHandler = InteractionHandler::createWithParent(m_xContext, nullptr);
+
+ std::unique_ptr<OCopyTable> xPage1(new OCopyTable(CreatePageContainer(), this));
+ xPage1->disallowViews();
+ xPage1->setCreateStyleAction();
+ AddWizardPage(std::move(xPage1));
+
+ AddWizardPage(std::make_unique<OWizNameMatching>(CreatePageContainer(), this));
+ AddWizardPage(std::make_unique<OWizColumnSelect>(CreatePageContainer(), this));
+ AddWizardPage((*_pTypeSelectionPageFactory)(CreatePageContainer(), this, _rTypeSelectionPageArg));
+
+ ActivatePage();
+
+ m_xAssistant->set_current_page(0);
+}
+
+void OCopyTableWizard::construct()
+{
+ m_xAssistant->set_size_request(700, 350);
+
+ m_xPrevPage->set_label(DBA_RES(STR_WIZ_PB_PREV));
+ m_xNextPage->set_label(DBA_RES(STR_WIZ_PB_NEXT));
+ m_xFinish->set_label(DBA_RES(STR_WIZ_PB_OK));
+
+ m_xHelp->show();
+ m_xCancel->show();
+ m_xPrevPage->show();
+ m_xNextPage->show();
+ m_xFinish->show();
+
+ m_xPrevPage->connect_clicked( LINK( this, OCopyTableWizard, ImplPrevHdl ) );
+ m_xNextPage->connect_clicked( LINK( this, OCopyTableWizard, ImplNextHdl ) );
+ m_xFinish->connect_clicked( LINK( this, OCopyTableWizard, ImplOKHdl ) );
+
+ m_xNextPage->grab_focus();
+
+ if (!m_vDestColumns.empty())
+ // source is a html or rtf table
+ m_xAssistant->change_default_widget(nullptr, m_xNextPage.get());
+ else
+ m_xAssistant->change_default_widget(nullptr, m_xFinish.get());
+
+ m_pTypeInfo = std::make_shared<OTypeInfo>();
+ m_pTypeInfo->aUIName = m_sTypeNames.getToken(TYPE_OTHER, ';');
+ m_bAddPKFirstTime = true;
+}
+
+OCopyTableWizard::~OCopyTableWizard()
+{
+ if ( m_bDeleteSourceColumns )
+ clearColumns(m_vSourceColumns,m_vSourceVec);
+
+ clearColumns(m_vDestColumns,m_aDestVec);
+
+ // clear the type information
+ m_aTypeInfoIndex.clear();
+ m_aTypeInfo.clear();
+ m_aDestTypeInfoIndex.clear();
+ m_aDestTypeInfo.clear();
+}
+
+IMPL_LINK_NOARG(OCopyTableWizard, ImplPrevHdl, weld::Button&, void)
+{
+ m_ePressed = WIZARD_PREV;
+ if ( GetCurLevel() )
+ {
+ if ( getOperation() != CopyTableOperation::AppendData )
+ {
+ if(GetCurLevel() == 2)
+ ShowPage(GetCurLevel()-2);
+ else
+ ShowPrevPage();
+ }
+ else
+ ShowPrevPage();
+ }
+}
+
+IMPL_LINK_NOARG(OCopyTableWizard, ImplNextHdl, weld::Button&, void)
+{
+ m_ePressed = WIZARD_NEXT;
+ if ( GetCurLevel() < MAX_PAGES )
+ {
+ if ( getOperation() != CopyTableOperation::AppendData )
+ {
+ if(GetCurLevel() == 0)
+ ShowPage(GetCurLevel()+2);
+ else
+ ShowNextPage();
+ }
+ else
+ ShowNextPage();
+ }
+}
+
+bool OCopyTableWizard::CheckColumns(sal_Int32& _rnBreakPos)
+{
+ bool bRet = true;
+ m_vColumnPositions.clear();
+ m_vColumnTypes.clear();
+
+ OSL_ENSURE( m_xDestConnection.is(), "OCopyTableWizard::CheckColumns: No connection!" );
+ // If database is able to process PrimaryKeys, set PrimaryKey
+ if ( m_xDestConnection.is() )
+ {
+ bool bPKeyAllowed = supportsPrimaryKey();
+
+ bool bContainsColumns = !m_vDestColumns.empty();
+
+ if ( bPKeyAllowed && shouldCreatePrimaryKey() )
+ {
+ // add extra column for the primary key
+ TOTypeInfoSP pTypeInfo = queryPrimaryKeyType(m_aDestTypeInfo);
+ if ( pTypeInfo )
+ {
+ if ( m_bAddPKFirstTime )
+ {
+ // tdf#114955: since we chose to create a primary key
+ // be sure all other columns won't be in primary key
+ for (auto const& elem : m_vDestColumns)
+ elem.second->SetPrimaryKey(false);
+ OFieldDescription* pField = new OFieldDescription();
+ pField->SetName(m_aKeyName);
+ pField->FillFromTypeInfo(pTypeInfo,true,true);
+ pField->SetPrimaryKey(true);
+ m_bAddPKFirstTime = false;
+ insertColumn(0,pField);
+ }
+ m_vColumnPositions.emplace_back(1,1);
+ m_vColumnTypes.push_back(pTypeInfo->nType);
+ }
+ }
+
+ if ( bContainsColumns )
+ { // we have dest columns so look for the matching column
+ for (auto const& elemSource : m_vSourceVec)
+ {
+ ODatabaseExport::TColumns::const_iterator aDestIter = m_vDestColumns.find(m_mNameMapping[elemSource->first]);
+
+ if ( aDestIter != m_vDestColumns.end() )
+ {
+ ODatabaseExport::TColumnVector::const_iterator aFind = std::find(m_aDestVec.begin(),m_aDestVec.end(),aDestIter);
+ assert(aFind != m_aDestVec.end());
+ sal_Int32 nPos = (aFind - m_aDestVec.begin())+1;
+ m_vColumnPositions.emplace_back(nPos,nPos);
+ m_vColumnTypes.push_back((*aFind)->second->GetType());
+ }
+ else
+ {
+ m_vColumnPositions.emplace_back( COLUMN_POSITION_NOT_FOUND, COLUMN_POSITION_NOT_FOUND );
+ m_vColumnTypes.push_back(0);
+ }
+ }
+ }
+ else
+ {
+ Reference< XDatabaseMetaData > xMetaData( m_xDestConnection->getMetaData() );
+ OUString sExtraChars = xMetaData->getExtraNameCharacters();
+ sal_Int32 nMaxNameLen = getMaxColumnNameLength();
+
+ _rnBreakPos=0;
+ for (auto const& elemSource : m_vSourceVec)
+ {
+ OFieldDescription* pField = new OFieldDescription(*elemSource->second);
+ pField->SetName(convertColumnName(TExportColumnFindFunctor(&m_vDestColumns),elemSource->first,sExtraChars,nMaxNameLen));
+ TOTypeInfoSP pType = convertType(elemSource->second->getSpecialTypeInfo(),bRet);
+ pField->SetType(pType);
+ if ( !bPKeyAllowed )
+ pField->SetPrimaryKey(false);
+
+ // now create a column
+ insertColumn(m_vDestColumns.size(),pField);
+ m_vColumnPositions.emplace_back(m_vDestColumns.size(),m_vDestColumns.size());
+ m_vColumnTypes.push_back(elemSource->second->GetType());
+ ++_rnBreakPos;
+ if (!bRet)
+ break;
+ }
+ }
+ }
+ return bRet;
+}
+
+IMPL_LINK_NOARG(OCopyTableWizard, ImplOKHdl, weld::Button&, void)
+{
+ m_ePressed = WIZARD_FINISH;
+ bool bFinish = DeactivatePage();
+
+ if(!bFinish)
+ return;
+
+ weld::WaitObject aWait(m_xAssistant.get());
+ switch(getOperation())
+ {
+ case CopyTableOperation::CopyDefinitionAndData:
+ case CopyTableOperation::CopyDefinitionOnly:
+ {
+ bool bOnFirstPage = GetCurLevel() == 0;
+ if ( bOnFirstPage )
+ {
+ // we came from the first page so we have to clear
+ // all column information already collected
+ clearDestColumns();
+ m_mNameMapping.clear();
+ }
+ sal_Int32 nBreakPos = 0;
+ bool bCheckOk = CheckColumns(nBreakPos);
+ if ( bOnFirstPage && !bCheckOk )
+ {
+ showColumnTypeNotSupported(m_vSourceVec[nBreakPos-1]->first);
+ OWizTypeSelect* pPage = static_cast<OWizTypeSelect*>(GetPage(3));
+ if ( pPage )
+ {
+ m_mNameMapping.clear();
+ pPage->setDisplayRow(nBreakPos);
+ ShowPage(3);
+ return;
+ }
+ }
+ if ( m_xDestConnection.is() )
+ {
+ if ( supportsPrimaryKey() )
+ {
+ bool noPrimaryKey = std::none_of(m_vDestColumns.begin(),m_vDestColumns.end(),
+ [] (const ODatabaseExport::TColumns::value_type& tCol) { return tCol.second->IsPrimaryKey(); });
+ if ( noPrimaryKey && m_xInteractionHandler.is() )
+ {
+
+ OUString sMsg(DBA_RES(STR_TABLEDESIGN_NO_PRIM_KEY));
+ SQLContext aError(sMsg, {}, {}, 0, {}, {});
+ ::rtl::Reference xRequest( new ::comphelper::OInteractionRequest( Any( aError ) ) );
+ ::rtl::Reference xYes = new ::comphelper::OInteractionApprove;
+ xRequest->addContinuation( xYes );
+ xRequest->addContinuation( new ::comphelper::OInteractionDisapprove );
+ ::rtl::Reference< ::comphelper::OInteractionAbort > xAbort = new ::comphelper::OInteractionAbort;
+ xRequest->addContinuation( xAbort );
+
+ m_xInteractionHandler->handle( xRequest );
+
+ if ( xYes->wasSelected() )
+ {
+ OCopyTable* pPage = static_cast<OCopyTable*>(GetPage(0));
+ m_bCreatePrimaryKeyColumn = true;
+ m_aKeyName = pPage->GetKeyName();
+ if ( m_aKeyName.isEmpty() )
+ m_aKeyName = "ID";
+ m_aKeyName = createUniqueName( m_aKeyName );
+ sal_Int32 nBreakPos2 = 0;
+ CheckColumns(nBreakPos2);
+ }
+ else if ( xAbort->wasSelected() )
+ {
+ ShowPage(3);
+ return;
+ }
+ }
+ }
+ }
+ break;
+ }
+ case CopyTableOperation::AppendData:
+ case CopyTableOperation::CreateAsView:
+ break;
+ default:
+ {
+ SAL_WARN("dbaccess.ui", "OCopyTableWizard::ImplOKHdl: invalid creation style!");
+ }
+ }
+
+ m_xAssistant->response(RET_OK);
+}
+
+void OCopyTableWizard::setCreatePrimaryKey( bool _bDoCreate, const OUString& _rSuggestedName )
+{
+ m_bCreatePrimaryKeyColumn = _bDoCreate;
+ if ( !_rSuggestedName.isEmpty() )
+ m_aKeyName = _rSuggestedName;
+
+ OCopyTable* pSettingsPage = dynamic_cast< OCopyTable* >( GetPage( 0 ) );
+ OSL_ENSURE( pSettingsPage, "OCopyTableWizard::setCreatePrimaryKey: page should have been added in the ctor!" );
+ if ( pSettingsPage )
+ pSettingsPage->setCreatePrimaryKey( _bDoCreate, _rSuggestedName );
+}
+
+void OCopyTableWizard::ActivatePage()
+{
+ OWizardPage* pCurrent = static_cast<OWizardPage*>(GetPage(GetCurLevel()));
+ if (pCurrent)
+ {
+ bool bFirstTime = pCurrent->IsFirstTime();
+ if(bFirstTime)
+ pCurrent->Reset();
+
+ CheckButtons();
+
+ m_xAssistant->set_title(pCurrent->GetTitle());
+ }
+}
+
+void OCopyTableWizard::CheckButtons()
+{
+ if(GetCurLevel() == 0) // the first page has no back button
+ {
+ if(m_nPageCount > 1)
+ m_xNextPage->set_sensitive(true);
+ else
+ m_xNextPage->set_sensitive(false);
+
+ m_xPrevPage->set_sensitive(false);
+ }
+ else if(GetCurLevel() == m_nPageCount-1) // the last page has no next button
+ {
+ m_xNextPage->set_sensitive(false);
+ m_xPrevPage->set_sensitive(true);
+ }
+ else
+ {
+ m_xPrevPage->set_sensitive(true);
+ // next already has its state
+ }
+}
+
+void OCopyTableWizard::EnableNextButton(bool bEnable)
+{
+ m_xNextPage->set_sensitive(bEnable);
+}
+
+bool OCopyTableWizard::DeactivatePage()
+{
+ OWizardPage* pPage = static_cast<OWizardPage*>(GetPage(GetCurLevel()));
+ return pPage && pPage->LeavePage();
+}
+
+void OCopyTableWizard::AddWizardPage(std::unique_ptr<OWizardPage> xPage)
+{
+ AddPage(std::move(xPage));
+ ++m_nPageCount;
+}
+
+void OCopyTableWizard::insertColumn(sal_Int32 _nPos,OFieldDescription* _pField)
+{
+ OSL_ENSURE(_pField,"FieldDescrioption is null!");
+ if ( !_pField )
+ return;
+
+ ODatabaseExport::TColumns::const_iterator aFind = m_vDestColumns.find(_pField->GetName());
+ if ( aFind != m_vDestColumns.end() )
+ {
+ delete aFind->second;
+ m_vDestColumns.erase(aFind);
+ }
+
+ m_aDestVec.insert(m_aDestVec.begin() + _nPos,
+ m_vDestColumns.emplace(_pField->GetName(),_pField).first);
+ m_mNameMapping[_pField->GetName()] = _pField->GetName();
+}
+
+void OCopyTableWizard::replaceColumn(sal_Int32 _nPos,OFieldDescription* _pField,const OUString& _sOldName)
+{
+ OSL_ENSURE(_pField,"FieldDescrioption is null!");
+ if ( _pField )
+ {
+ m_vDestColumns.erase(_sOldName);
+ OSL_ENSURE( m_vDestColumns.find(_pField->GetName()) == m_vDestColumns.end(),"Column with that name already exist!");
+
+ m_aDestVec[_nPos] = m_vDestColumns.emplace(_pField->GetName(),_pField).first;
+ }
+}
+
+void OCopyTableWizard::loadData( const ICopyTableSourceObject& _rSourceObject, ODatabaseExport::TColumns& _rColumns, ODatabaseExport::TColumnVector& _rColVector )
+{
+ for (auto const& column : _rColumns)
+ delete column.second;
+
+ _rColVector.clear();
+ _rColumns.clear();
+
+ OFieldDescription* pActFieldDescr = nullptr;
+ static constexpr OUStringLiteral sCreateParam(u"x");
+ // ReadOnly-Flag
+ // On drop no line must be editable.
+ // On add only empty lines must be editable.
+ // On Add and Drop all lines can be edited.
+ Sequence< OUString > aColumns( _rSourceObject.getColumnNames() );
+ const OUString* pColumn = aColumns.getConstArray();
+ const OUString* pColumnEnd = pColumn + aColumns.getLength();
+
+ for ( ; pColumn != pColumnEnd; ++pColumn )
+ {
+ // get the properties of the column
+ pActFieldDescr = _rSourceObject.createFieldDescription( *pColumn );
+ OSL_ENSURE( pActFieldDescr, "OCopyTableWizard::loadData: illegal field description!" );
+ if ( !pActFieldDescr )
+ continue;
+
+ sal_Int32 nType = pActFieldDescr->GetType();
+ sal_Int32 nScale = pActFieldDescr->GetScale();
+ sal_Int32 nPrecision = pActFieldDescr->GetPrecision();
+ bool bAutoIncrement = pActFieldDescr->IsAutoIncrement();
+ OUString sTypeName = pActFieldDescr->GetTypeName();
+
+ // search for type
+ bool bForce;
+ TOTypeInfoSP pTypeInfo = ::dbaui::getTypeInfoFromType(m_aTypeInfo,nType,sTypeName,sCreateParam,nPrecision,nScale,bAutoIncrement,bForce);
+ if ( !pTypeInfo )
+ pTypeInfo = m_pTypeInfo;
+
+ pActFieldDescr->FillFromTypeInfo(pTypeInfo,true,false);
+ _rColVector.emplace_back(_rColumns.emplace(pActFieldDescr->GetName(),pActFieldDescr).first);
+ }
+
+ // determine which columns belong to the primary key
+ Sequence< OUString > aPrimaryKeyColumns( _rSourceObject.getPrimaryKeyColumnNames() );
+ const OUString* pKeyColName = aPrimaryKeyColumns.getConstArray();
+ const OUString* pKeyColEnd = pKeyColName + aPrimaryKeyColumns.getLength();
+
+ for( ; pKeyColName != pKeyColEnd; ++pKeyColName )
+ {
+ ODatabaseExport::TColumns::const_iterator keyPos = _rColumns.find( *pKeyColName );
+ if ( keyPos != _rColumns.end() )
+ {
+ keyPos->second->SetPrimaryKey( true );
+ keyPos->second->SetIsNullable( ColumnValue::NO_NULLS );
+ }
+ }
+}
+
+void OCopyTableWizard::clearDestColumns()
+{
+ clearColumns(m_vDestColumns,m_aDestVec);
+ m_bAddPKFirstTime = true;
+ m_mNameMapping.clear();
+}
+
+void OCopyTableWizard::appendColumns( Reference<XColumnsSupplier> const & _rxColSup, const ODatabaseExport::TColumnVector* _pVec, bool _bKeyColumns)
+{
+ // now append the columns
+ OSL_ENSURE(_rxColSup.is(),"No columns supplier");
+ if(!_rxColSup.is())
+ return;
+ Reference<XNameAccess> xColumns = _rxColSup->getColumns();
+ OSL_ENSURE(xColumns.is(),"No columns");
+ Reference<XDataDescriptorFactory> xColumnFactory(xColumns,UNO_QUERY);
+
+ Reference<XAppend> xAppend(xColumns,UNO_QUERY);
+ OSL_ENSURE(xAppend.is(),"No XAppend Interface!");
+
+ for (auto const& elem : *_pVec)
+ {
+ OFieldDescription* pField = elem->second;
+ if(!pField)
+ continue;
+
+ Reference<XPropertySet> xColumn;
+ if(pField->IsPrimaryKey() || !_bKeyColumns)
+ xColumn = xColumnFactory->createDataDescriptor();
+ if(xColumn.is())
+ {
+ if(!_bKeyColumns)
+ dbaui::setColumnProperties(xColumn,pField);
+ else
+ xColumn->setPropertyValue(PROPERTY_NAME,Any(pField->GetName()));
+
+ xAppend->appendByDescriptor(xColumn);
+ xColumn = nullptr;
+ // now only the settings are missing
+ if(xColumns->hasByName(pField->GetName()))
+ {
+ xColumn.set(xColumns->getByName(pField->GetName()),UNO_QUERY);
+ OSL_ENSURE(xColumn.is(),"OCopyTableWizard::appendColumns: Column is NULL!");
+ if ( xColumn.is() )
+ pField->copyColumnSettingsTo(xColumn);
+ }
+ else
+ {
+ SAL_WARN("dbaccess.ui", "OCopyTableWizard::appendColumns: invalid field name!");
+ }
+
+ }
+ }
+}
+
+void OCopyTableWizard::appendKey( Reference<XKeysSupplier> const & _rxSup, const ODatabaseExport::TColumnVector* _pVec)
+{
+ if(!_rxSup.is())
+ return; // the database doesn't support keys
+ OSL_ENSURE(_rxSup.is(),"No XKeysSupplier!");
+ Reference<XDataDescriptorFactory> xKeyFactory(_rxSup->getKeys(),UNO_QUERY);
+ OSL_ENSURE(xKeyFactory.is(),"No XDataDescriptorFactory Interface!");
+ if ( !xKeyFactory.is() )
+ return;
+ Reference<XAppend> xAppend(xKeyFactory,UNO_QUERY);
+ OSL_ENSURE(xAppend.is(),"No XAppend Interface!");
+
+ Reference<XPropertySet> xKey = xKeyFactory->createDataDescriptor();
+ OSL_ENSURE(xKey.is(),"Key is null!");
+ xKey->setPropertyValue(PROPERTY_TYPE,Any(KeyType::PRIMARY));
+
+ Reference<XColumnsSupplier> xColSup(xKey,UNO_QUERY);
+ if(xColSup.is())
+ {
+ appendColumns(xColSup,_pVec,true);
+ Reference<XNameAccess> xColumns = xColSup->getColumns();
+ if(xColumns.is() && xColumns->getElementNames().hasElements())
+ xAppend->appendByDescriptor(xKey);
+ }
+
+}
+
+Reference< XPropertySet > OCopyTableWizard::createView() const
+{
+ OUString sCommand( m_rSourceObject.getSelectStatement() );
+ OSL_ENSURE( !sCommand.isEmpty(), "OCopyTableWizard::createView: no statement in the source object!" );
+ // there are legitimate cases in which getSelectStatement does not provide a statement,
+ // but in all those cases, this method here should never be called.
+ return ::dbaui::createView( m_sName, m_xDestConnection, sCommand );
+}
+
+Reference< XPropertySet > OCopyTableWizard::returnTable()
+{
+ if ( getOperation() == CopyTableOperation::AppendData )
+ return getTable();
+ else
+ return createTable();
+}
+
+Reference< XPropertySet > OCopyTableWizard::getTable() const
+{
+ Reference< XPropertySet > xTable;
+
+ Reference<XTablesSupplier> xSup( m_xDestConnection, UNO_QUERY );
+ Reference< XNameAccess > xTables;
+ if(xSup.is())
+ xTables = xSup->getTables();
+ if(xTables.is() && xTables->hasByName(m_sName))
+ xTables->getByName(m_sName) >>= xTable;
+
+ return xTable;
+}
+
+Reference< XPropertySet > OCopyTableWizard::createTable()
+{
+ Reference< XPropertySet > xTable;
+
+ Reference<XTablesSupplier> xSup( m_xDestConnection, UNO_QUERY );
+ Reference< XNameAccess > xTables;
+ if(xSup.is())
+ xTables = xSup->getTables();
+ Reference<XDataDescriptorFactory> xFact(xTables,UNO_QUERY);
+ OSL_ENSURE(xFact.is(),"No XDataDescriptorFactory available!");
+ if(!xFact.is())
+ return nullptr;
+
+ xTable = xFact->createDataDescriptor();
+ OSL_ENSURE(xTable.is(),"Could not create a new object!");
+ if(!xTable.is())
+ return nullptr;
+
+ OUString sCatalog,sSchema,sTable;
+ Reference< XDatabaseMetaData> xMetaData = m_xDestConnection->getMetaData();
+ ::dbtools::qualifiedNameComponents(xMetaData,
+ m_sName,
+ sCatalog,
+ sSchema,
+ sTable,
+ ::dbtools::EComposeRule::InDataManipulation);
+
+ if ( sCatalog.isEmpty() && xMetaData->supportsCatalogsInTableDefinitions() )
+ {
+ sCatalog = m_xDestConnection->getCatalog();
+ }
+
+ if ( sSchema.isEmpty() && xMetaData->supportsSchemasInTableDefinitions() )
+ {
+ // query of current schema is quite inconsistent. In case of some
+ // DBMS's each user has their own schema.
+ sSchema = xMetaData->getUserName();
+ // In case of mysql it is not that simple
+ if(xMetaData->getDatabaseProductName() == "MySQL")
+ {
+ Reference< XStatement > xSelect = m_xDestConnection->createStatement();
+ Reference< XResultSet > xRs = xSelect->executeQuery("select database()");
+ (void)xRs->next(); // first and only result
+ Reference< XRow > xRow( xRs, UNO_QUERY_THROW );
+ sSchema = xRow->getString(1);
+ }
+ }
+
+ xTable->setPropertyValue(PROPERTY_CATALOGNAME,Any(sCatalog));
+ xTable->setPropertyValue(PROPERTY_SCHEMANAME,Any(sSchema));
+ xTable->setPropertyValue(PROPERTY_NAME,Any(sTable));
+
+ Reference< XColumnsSupplier > xSuppDestinationColumns( xTable, UNO_QUERY );
+ // now append the columns
+ const ODatabaseExport::TColumnVector& rVec = getDestVector();
+ appendColumns( xSuppDestinationColumns, &rVec );
+ // now append the primary key
+ Reference<XKeysSupplier> xKeySup(xTable,UNO_QUERY);
+ appendKey(xKeySup, &rVec);
+
+ Reference<XAppend> xAppend(xTables,UNO_QUERY);
+ if(xAppend.is())
+ xAppend->appendByDescriptor(xTable);
+
+ // xTable = NULL;
+ // we need to reget the table because after appending it, it is no longer valid
+ if(xTables->hasByName(m_sName))
+ xTables->getByName(m_sName) >>= xTable;
+ else
+ {
+ OUString sComposedName(
+ ::dbtools::composeTableName( m_xDestConnection->getMetaData(), xTable, ::dbtools::EComposeRule::InDataManipulation, false ) );
+ if(xTables->hasByName(sComposedName))
+ {
+ xTables->getByName(sComposedName) >>= xTable;
+ m_sName = sComposedName;
+ }
+ else
+ xTable = nullptr;
+ }
+
+ if(xTable.is())
+ {
+ xSuppDestinationColumns.set( xTable, UNO_QUERY_THROW );
+ // insert new table name into table filter
+ ::dbaui::appendToFilter(m_xDestConnection, m_sName, GetComponentContext(), m_xAssistant.get());
+
+ // copy ui settings
+ m_rSourceObject.copyUISettingsTo( xTable );
+ //copy filter and sorting
+ m_rSourceObject.copyFilterAndSortingTo(m_xDestConnection,xTable);
+ // set column mappings
+ Reference<XNameAccess> xNameAccess = xSuppDestinationColumns->getColumns();
+ Sequence< OUString> aSeq = xNameAccess->getElementNames();
+ const OUString* pIter = aSeq.getConstArray();
+ const OUString* pEnd = pIter + aSeq.getLength();
+
+ for(sal_Int32 nNewPos=1;pIter != pEnd;++pIter,++nNewPos)
+ {
+ ODatabaseExport::TColumns::const_iterator aDestIter = m_vDestColumns.find(*pIter);
+
+ if ( aDestIter != m_vDestColumns.end() )
+ {
+ ODatabaseExport::TColumnVector::const_iterator aFind = std::find(m_aDestVec.begin(),m_aDestVec.end(),aDestIter);
+ sal_Int32 nPos = (aFind - m_aDestVec.begin())+1;
+
+ ODatabaseExport::TPositions::iterator aPosFind = std::find_if(
+ m_vColumnPositions.begin(),
+ m_vColumnPositions.end(),
+ [nPos] (const ODatabaseExport::TPositions::value_type& tPos) {
+ return tPos.first == nPos;
+ }
+ );
+
+ if ( m_vColumnPositions.end() != aPosFind )
+ {
+ aPosFind->second = nNewPos;
+ OSL_ENSURE( m_vColumnTypes.size() > o3tl::make_unsigned( aPosFind - m_vColumnPositions.begin() ),
+ "Invalid index for vector!" );
+ m_vColumnTypes[ aPosFind - m_vColumnPositions.begin() ] = (*aFind)->second->GetType();
+ }
+ }
+ }
+ }
+
+ return xTable;
+}
+
+bool OCopyTableWizard::supportsPrimaryKey( const Reference< XConnection >& _rxConnection )
+{
+ OSL_PRECOND( _rxConnection.is(), "OCopyTableWizard::supportsPrimaryKey: invalid connection!" );
+ if ( !_rxConnection.is() )
+ return false;
+
+ ::dbtools::DatabaseMetaData aMetaData( _rxConnection );
+ return aMetaData.supportsPrimaryKeys();
+}
+
+bool OCopyTableWizard::supportsViews( const Reference< XConnection >& _rxConnection )
+{
+ OSL_PRECOND( _rxConnection.is(), "OCopyTableWizard::supportsViews: invalid connection!" );
+ if ( !_rxConnection.is() )
+ return false;
+
+ bool bSupportsViews( false );
+ try
+ {
+ Reference< XDatabaseMetaData > xMetaData( _rxConnection->getMetaData(), UNO_SET_THROW );
+ Reference< XViewsSupplier > xViewSups( _rxConnection, UNO_QUERY );
+ bSupportsViews = xViewSups.is();
+ if ( !bSupportsViews )
+ {
+ try
+ {
+ Reference< XResultSet > xRs( xMetaData->getTableTypes(), UNO_SET_THROW );
+ Reference< XRow > xRow( xRs, UNO_QUERY_THROW );
+ while ( xRs->next() )
+ {
+ OUString sValue = xRow->getString( 1 );
+ if ( !xRow->wasNull() && sValue.equalsIgnoreAsciiCase("View") )
+ {
+ bSupportsViews = true;
+ break;
+ }
+ }
+ }
+ catch( const SQLException& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return bSupportsViews;
+}
+
+sal_Int32 OCopyTableWizard::getMaxColumnNameLength() const
+{
+ sal_Int32 nLen = 0;
+ if ( m_xDestConnection.is() )
+ {
+ try
+ {
+ Reference< XDatabaseMetaData > xMetaData( m_xDestConnection->getMetaData(), UNO_SET_THROW );
+ nLen = xMetaData->getMaxColumnNameLength();
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ return nLen;
+}
+
+void OCopyTableWizard::setOperation( const sal_Int16 _nOperation )
+{
+ m_nOperation = _nOperation;
+}
+
+
+OUString OCopyTableWizard::convertColumnName(const TColumnFindFunctor& _rCmpFunctor,
+ const OUString& _sColumnName,
+ std::u16string_view _sExtraChars,
+ sal_Int32 _nMaxNameLen)
+{
+ OUString sAlias = _sColumnName;
+ if ( isSQL92CheckEnabled( m_xDestConnection ) )
+ sAlias = ::dbtools::convertName2SQLName(_sColumnName,_sExtraChars);
+ if((_nMaxNameLen && sAlias.getLength() > _nMaxNameLen) || _rCmpFunctor(sAlias))
+ {
+ sal_Int32 nDiff = 1;
+ do
+ {
+ ++nDiff;
+ if(_nMaxNameLen && sAlias.getLength() >= _nMaxNameLen)
+ sAlias = sAlias.copy(0,sAlias.getLength() - (sAlias.getLength()-_nMaxNameLen+nDiff));
+
+ OUString sName(sAlias);
+ sal_Int32 nPos = 1;
+ sName += OUString::number(nPos);
+
+ while(_rCmpFunctor(sName))
+ {
+ sName = sAlias + OUString::number(++nPos);
+ }
+ sAlias = sName;
+ // we have to check again, it could happen that the name is already too long
+ }
+ while(_nMaxNameLen && sAlias.getLength() > _nMaxNameLen);
+ }
+ OSL_ENSURE(m_mNameMapping.find(_sColumnName) == m_mNameMapping.end(),"name doubled!");
+ m_mNameMapping[_sColumnName] = sAlias;
+ return sAlias;
+}
+
+void OCopyTableWizard::removeColumnNameFromNameMap(const OUString& _sName)
+{
+ m_mNameMapping.erase(_sName);
+}
+
+bool OCopyTableWizard::supportsType(sal_Int32 _nDataType, sal_Int32& _rNewDataType)
+{
+ bool bRet = m_aDestTypeInfo.find(_nDataType) != m_aDestTypeInfo.end();
+ if ( bRet )
+ _rNewDataType = _nDataType;
+ return bRet;
+}
+
+TOTypeInfoSP OCopyTableWizard::convertType(const TOTypeInfoSP& _pType, bool& _bNotConvert)
+{
+ if ( !m_bInterConnectionCopy )
+ // no need to convert if the source and destination connection are the same
+ return _pType;
+
+ bool bForce;
+ TOTypeInfoSP pType = ::dbaui::getTypeInfoFromType(m_aDestTypeInfo,_pType->nType,_pType->aTypeName,_pType->aCreateParams,_pType->nPrecision,_pType->nMaximumScale,_pType->bAutoIncrement,bForce);
+ if ( !pType || bForce )
+ { // no type found so we have to find the correct one ourself
+ sal_Int32 nDefaultType = DataType::VARCHAR;
+ switch(_pType->nType)
+ {
+ case DataType::TINYINT:
+ if(supportsType(DataType::SMALLINT,nDefaultType))
+ break;
+ [[fallthrough]];
+ case DataType::SMALLINT:
+ if(supportsType(DataType::INTEGER,nDefaultType))
+ break;
+ [[fallthrough]];
+ case DataType::INTEGER:
+ if(supportsType(DataType::FLOAT,nDefaultType))
+ break;
+ [[fallthrough]];
+ case DataType::FLOAT:
+ if(supportsType(DataType::REAL,nDefaultType))
+ break;
+ [[fallthrough]];
+ case DataType::DATE:
+ case DataType::TIME:
+ if( DataType::DATE == _pType->nType || DataType::TIME == _pType->nType )
+ {
+ if(supportsType(DataType::TIMESTAMP,nDefaultType))
+ break;
+ }
+ [[fallthrough]];
+ case DataType::TIMESTAMP:
+ case DataType::REAL:
+ case DataType::BIGINT:
+ if ( supportsType(DataType::DOUBLE,nDefaultType) )
+ break;
+ [[fallthrough]];
+ case DataType::DOUBLE:
+ if ( supportsType(DataType::NUMERIC,nDefaultType) )
+ break;
+ [[fallthrough]];
+ case DataType::NUMERIC:
+ supportsType(DataType::DECIMAL,nDefaultType);
+ break;
+ case DataType::DECIMAL:
+ if ( supportsType(DataType::NUMERIC,nDefaultType) )
+ break;
+ if ( supportsType(DataType::DOUBLE,nDefaultType) )
+ break;
+ break;
+ case DataType::VARCHAR:
+ if ( supportsType(DataType::LONGVARCHAR,nDefaultType) )
+ break;
+ break;
+ case DataType::LONGVARCHAR:
+ if ( supportsType(DataType::CLOB,nDefaultType) )
+ break;
+ break;
+ case DataType::BINARY:
+ if ( supportsType(DataType::VARBINARY,nDefaultType) )
+ break;
+ break;
+ case DataType::VARBINARY:
+ if ( supportsType(DataType::LONGVARBINARY,nDefaultType) )
+ break;
+ break;
+ case DataType::LONGVARBINARY:
+ if ( supportsType(DataType::BLOB,nDefaultType) )
+ break;
+ if ( supportsType(DataType::LONGVARCHAR,nDefaultType) )
+ break;
+ if ( supportsType(DataType::CLOB,nDefaultType) )
+ break;
+ break;
+ default:
+ nDefaultType = DataType::VARCHAR;
+ }
+ pType = ::dbaui::getTypeInfoFromType(m_aDestTypeInfo,nDefaultType,_pType->aTypeName,_pType->aCreateParams,_pType->nPrecision,_pType->nMaximumScale,_pType->bAutoIncrement,bForce);
+ if ( !pType )
+ {
+ _bNotConvert = false;
+ pType = ::dbaui::getTypeInfoFromType(m_aDestTypeInfo,DataType::VARCHAR,_pType->aTypeName,"x",50,0,false,bForce);
+ if ( !pType )
+ pType = m_pTypeInfo;
+ }
+ else if ( bForce )
+ _bNotConvert = false;
+ }
+ return pType;
+}
+
+OUString OCopyTableWizard::createUniqueName(const OUString& _sName)
+{
+ OUString sName = _sName;
+ Sequence< OUString > aColumnNames( m_rSourceObject.getColumnNames() );
+ if ( aColumnNames.hasElements() )
+ sName = ::dbtools::createUniqueName( aColumnNames, sName, false );
+ else
+ {
+ if ( m_vSourceColumns.find(sName) != m_vSourceColumns.end())
+ {
+ sal_Int32 nPos = 0;
+ while(m_vSourceColumns.find(sName) != m_vSourceColumns.end())
+ {
+ sName = _sName + OUString::number(++nPos);
+ }
+ }
+ }
+ return sName;
+}
+
+void OCopyTableWizard::showColumnTypeNotSupported(std::u16string_view _rColumnName)
+{
+ OUString sMessage( DBA_RES( STR_UNKNOWN_TYPE_FOUND ) );
+ sMessage = sMessage.replaceFirst("#1",_rColumnName);
+ showError(sMessage);
+}
+
+void OCopyTableWizard::showError(const OUString& _sErrorMessage)
+{
+ SQLExceptionInfo aInfo(_sErrorMessage);
+ showError(aInfo.get());
+}
+
+void OCopyTableWizard::showError(const Any& _aError)
+{
+ if ( _aError.hasValue() && m_xInteractionHandler.is() )
+ {
+ try
+ {
+ ::rtl::Reference< ::comphelper::OInteractionRequest > xRequest( new ::comphelper::OInteractionRequest( _aError ) );
+ m_xInteractionHandler->handle( xRequest );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/WExtendPages.cxx b/dbaccess/source/ui/misc/WExtendPages.cxx
new file mode 100644
index 0000000000..c7eac9181e
--- /dev/null
+++ b/dbaccess/source/ui/misc/WExtendPages.cxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <WExtendPages.hxx>
+#include <RtfReader.hxx>
+#include <HtmlReader.hxx>
+#include <WCopyTable.hxx>
+
+using namespace com::sun::star;
+
+namespace dbaui
+{
+
+void OWizHTMLExtend::createReaderAndCallParser(sal_Int32 _nRows)
+{
+ tools::SvRef<OHTMLReader> xParser = new OHTMLReader(*m_pParserStream,
+ _nRows,
+ std::vector(m_pParent->GetColumnPositions()),
+ m_pParent->GetFormatter(),
+ m_pParent->GetComponentContext(),
+ &m_pParent->getDestVector(),
+ &m_pParent->getTypeInfo(),
+ m_pParent->shouldCreatePrimaryKey());
+ xParser->CallParser();
+}
+
+void OWizRTFExtend::createReaderAndCallParser(sal_Int32 _nRows)
+{
+ tools::SvRef<ORTFReader> xParser = new ORTFReader(*m_pParserStream,
+ _nRows,
+ std::vector(m_pParent->GetColumnPositions()),
+ m_pParent->GetFormatter(),
+ m_pParent->GetComponentContext(),
+ &m_pParent->getDestVector(),
+ &m_pParent->getTypeInfo(),
+ m_pParent->shouldCreatePrimaryKey());
+ xParser->CallParser();
+}
+
+void OWizNormalExtend::createReaderAndCallParser(sal_Int32 /*_nRows*/)
+{
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/WNameMatch.cxx b/dbaccess/source/ui/misc/WNameMatch.cxx
new file mode 100644
index 0000000000..a6bb59da8e
--- /dev/null
+++ b/dbaccess/source/ui/misc/WNameMatch.cxx
@@ -0,0 +1,330 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <WNameMatch.hxx>
+#include <osl/diagnose.h>
+#include <FieldDescriptions.hxx>
+#include <WCopyTable.hxx>
+#include <core_resource.hxx>
+#include <strings.hrc>
+#include <bitmaps.hlst>
+#include <com/sun/star/sdbc/DataType.hpp>
+
+using namespace ::dbaui;
+
+// OWizColumnSelect
+OWizNameMatching::OWizNameMatching(weld::Container* pPage, OCopyTableWizard* pWizard)
+ : OWizardPage(pPage, pWizard, "dbaccess/ui/namematchingpage.ui", "NameMatching")
+ , m_xTABLE_LEFT(m_xBuilder->weld_label("leftlabel"))
+ , m_xTABLE_RIGHT(m_xBuilder->weld_label("rightlabel"))
+ , m_xCTRL_LEFT(m_xBuilder->weld_tree_view("left"))
+ , m_xCTRL_RIGHT(m_xBuilder->weld_tree_view("right"))
+ , m_xColumn_up(m_xBuilder->weld_button("up"))
+ , m_xColumn_down(m_xBuilder->weld_button("down"))
+ , m_xColumn_up_right(m_xBuilder->weld_button("up_right"))
+ , m_xColumn_down_right(m_xBuilder->weld_button("down_right"))
+ , m_xAll(m_xBuilder->weld_button("all"))
+ , m_xNone(m_xBuilder->weld_button("none"))
+{
+ OUString aImgUp(BMP_UP);
+ OUString aImgDown(BMP_DOWN);
+ m_xColumn_up->set_from_icon_name(aImgUp);
+ m_xColumn_down->set_from_icon_name(aImgDown);
+ m_xColumn_up_right->set_from_icon_name(aImgUp);
+ m_xColumn_down_right->set_from_icon_name(aImgDown);
+
+ m_xColumn_up->connect_clicked(LINK(this,OWizNameMatching,ButtonClickHdl));
+ m_xColumn_down->connect_clicked(LINK(this,OWizNameMatching,ButtonClickHdl));
+
+ m_xColumn_up_right->connect_clicked(LINK(this,OWizNameMatching,RightButtonClickHdl));
+ m_xColumn_down_right->connect_clicked(LINK(this,OWizNameMatching,RightButtonClickHdl));
+
+ m_xAll->connect_clicked(LINK(this,OWizNameMatching,AllNoneClickHdl));
+ m_xNone->connect_clicked(LINK(this,OWizNameMatching,AllNoneClickHdl));
+
+ m_xCTRL_LEFT->enable_toggle_buttons(weld::ColumnToggleType::Check);
+
+ m_xCTRL_LEFT->connect_changed(LINK(this,OWizNameMatching,TableListClickHdl));
+ m_xCTRL_RIGHT->connect_changed(LINK(this,OWizNameMatching,TableListRightSelectHdl));
+
+ m_sSourceText = m_xTABLE_LEFT->get_label() + "\n";
+ m_sDestText = m_xTABLE_RIGHT->get_label() + "\n";
+}
+
+OWizNameMatching::~OWizNameMatching()
+{
+}
+
+void OWizNameMatching::Reset()
+{
+ m_bFirstTime = false;
+}
+
+void OWizNameMatching::Activate( )
+{
+ // set source table name
+ OUString aName = m_sSourceText + m_pParent->m_sSourceName;
+
+ m_xTABLE_LEFT->set_label(aName);
+
+ // set dest table name
+ aName = m_sDestText + m_pParent->m_sName;
+ m_xTABLE_RIGHT->set_label(aName);
+
+ FillListBox(*m_xCTRL_LEFT, m_pParent->getSrcVector(), true);
+ FillListBox(*m_xCTRL_RIGHT, m_pParent->getDestVector(), false);
+
+ m_xColumn_up->set_sensitive( m_xCTRL_LEFT->n_children() > 1 );
+ m_xColumn_down->set_sensitive( m_xCTRL_LEFT->n_children() > 1 );
+
+ m_xColumn_up_right->set_sensitive( m_xCTRL_RIGHT->n_children() > 1 );
+ m_xColumn_down_right->set_sensitive( m_xCTRL_RIGHT->n_children() > 1 );
+
+ m_pParent->EnableNextButton(false);
+ m_xCTRL_LEFT->grab_focus();
+ TableListClickHdl(*m_xCTRL_LEFT);
+}
+
+bool OWizNameMatching::LeavePage()
+{
+
+ const ODatabaseExport::TColumnVector& rSrcColumns = m_pParent->getSrcVector();
+
+ m_pParent->m_vColumnPositions.clear();
+ m_pParent->m_vColumnTypes.clear();
+ m_pParent->m_vColumnPositions.resize( rSrcColumns.size(), ODatabaseExport::TPositions::value_type( COLUMN_POSITION_NOT_FOUND, COLUMN_POSITION_NOT_FOUND ) );
+ m_pParent->m_vColumnTypes.resize( rSrcColumns.size(), COLUMN_POSITION_NOT_FOUND );
+
+ std::unique_ptr<weld::TreeIter> xLeftEntry = m_xCTRL_LEFT->make_iterator();
+ std::unique_ptr<weld::TreeIter> xRightEntry = m_xCTRL_RIGHT->make_iterator();
+
+ sal_Int32 nParamPos = 0;
+ bool bLeftEntry = m_xCTRL_LEFT->get_iter_first(*xLeftEntry);
+ bool bRightEntry = m_xCTRL_RIGHT->get_iter_first(*xRightEntry);
+ while (bLeftEntry && bRightEntry)
+ {
+ OFieldDescription* pSrcField = weld::fromId<OFieldDescription*>(m_xCTRL_LEFT->get_id(*xLeftEntry));
+ OSL_ENSURE(pSrcField,"OWizNameMatching: OColumn can not be null!");
+
+ sal_Int32 nPos = 0;
+ for (auto const& column : rSrcColumns)
+ {
+ if (column->second == pSrcField)
+ break;
+ ++nPos;
+ }
+
+ if (m_xCTRL_LEFT->get_toggle(*xLeftEntry) == TRISTATE_TRUE)
+ {
+ OFieldDescription* pDestField = weld::fromId<OFieldDescription*>(m_xCTRL_RIGHT->get_id(*xRightEntry));
+ OSL_ENSURE(pDestField,"OWizNameMatching: OColumn can not be null!");
+ const ODatabaseExport::TColumnVector& rDestColumns = m_pParent->getDestVector();
+ sal_Int32 nPosDest = 1;
+ bool bDestColumnFound = false;
+ TOTypeInfoSP typeInfoSPFound;
+ for (auto const& column : rDestColumns)
+ {
+ if (column->second == pDestField)
+ {
+ bDestColumnFound = true;
+ typeInfoSPFound = column->second->getSpecialTypeInfo();
+ break;
+ }
+ ++nPosDest;
+ }
+
+ OSL_ENSURE((nPos) < static_cast<sal_Int32>(m_pParent->m_vColumnPositions.size()),"m_pParent->m_vColumnPositions: Illegal index for vector");
+ m_pParent->m_vColumnPositions[nPos].first = ++nParamPos;
+ m_pParent->m_vColumnPositions[nPos].second = nPosDest;
+
+ TOTypeInfoSP pTypeInfo;
+
+ assert(bDestColumnFound);
+ if (bDestColumnFound)
+ {
+ bool bNotConvert = true;
+ pTypeInfo = m_pParent->convertType(typeInfoSPFound, bNotConvert);
+ }
+
+ sal_Int32 nType = css::sdbc::DataType::VARCHAR;
+ if ( pTypeInfo )
+ nType = pTypeInfo->nType;
+ m_pParent->m_vColumnTypes[nPos] = nType;
+ }
+ else
+ {
+ m_pParent->m_vColumnPositions[nPos].first = COLUMN_POSITION_NOT_FOUND;
+ m_pParent->m_vColumnPositions[nPos].second = COLUMN_POSITION_NOT_FOUND;
+ }
+
+ bLeftEntry = m_xCTRL_LEFT->iter_next(*xLeftEntry);
+ bRightEntry = m_xCTRL_RIGHT->iter_next(*xRightEntry);
+ }
+
+ return true;
+}
+
+OUString OWizNameMatching::GetTitle() const { return DBA_RES(STR_WIZ_NAME_MATCHING_TITLE); }
+
+IMPL_LINK(OWizNameMatching, ButtonClickHdl, weld::Button&, rButton, void)
+{
+ int nPos = m_xCTRL_LEFT->get_selected_index();
+ if (nPos == -1)
+ return;
+
+ int nOrigPos = nPos;
+ if (&rButton == m_xColumn_up.get() && nPos)
+ --nPos;
+ else if (&rButton == m_xColumn_down.get() && nPos < m_xCTRL_LEFT->n_children() - 1)
+ ++nPos;
+
+ m_xCTRL_LEFT->swap(nOrigPos, nPos);
+
+ m_xCTRL_LEFT->scroll_to_row(nPos);
+
+ TableListClickHdl(*m_xCTRL_LEFT);
+}
+
+IMPL_LINK( OWizNameMatching, RightButtonClickHdl, weld::Button&, rButton, void )
+{
+ int nPos = m_xCTRL_RIGHT->get_selected_index();
+ if (nPos == -1)
+ return;
+
+ int nOrigPos = nPos;
+ if (&rButton == m_xColumn_up_right.get() && nPos)
+ --nPos;
+ else if (&rButton == m_xColumn_down_right.get() && nPos < m_xCTRL_RIGHT->n_children() - 1)
+ ++nPos;
+
+ m_xCTRL_RIGHT->swap(nOrigPos, nPos);
+
+ m_xCTRL_RIGHT->scroll_to_row(nPos);
+
+ TableListRightSelectHdl(*m_xCTRL_RIGHT);
+}
+
+namespace
+{
+ int GetFirstEntryInView(weld::TreeView& rTreeView)
+ {
+ int nFirstEntryInView = -1;
+
+ rTreeView.visible_foreach([&nFirstEntryInView, &rTreeView](weld::TreeIter& rEntry){
+ nFirstEntryInView = rTreeView.get_iter_index_in_parent(rEntry);
+ // stop after first entry
+ return true;
+ });
+
+ return nFirstEntryInView;
+ }
+}
+
+IMPL_LINK_NOARG(OWizNameMatching, TableListClickHdl, weld::TreeView&, void)
+{
+ int nPos = m_xCTRL_LEFT->get_selected_index();
+ if (nPos == -1)
+ return;
+
+ int nOldEntry = m_xCTRL_RIGHT->get_selected_index();
+ if (nOldEntry != -1 && nPos != nOldEntry)
+ {
+ m_xCTRL_RIGHT->unselect(nOldEntry);
+ if (nPos < m_xCTRL_RIGHT->n_children())
+ {
+ int nNewPos = GetFirstEntryInView(*m_xCTRL_LEFT);
+ if ( nNewPos - nPos == 1 )
+ --nNewPos;
+ m_xCTRL_RIGHT->scroll_to_row(nNewPos);
+ m_xCTRL_RIGHT->select(nPos);
+ }
+ }
+ else if (nOldEntry == -1)
+ {
+ if (nPos < m_xCTRL_RIGHT->n_children())
+ m_xCTRL_RIGHT->select(nPos);
+ }
+}
+
+IMPL_LINK_NOARG( OWizNameMatching, TableListRightSelectHdl, weld::TreeView&, void )
+{
+ int nPos = m_xCTRL_RIGHT->get_selected_index();
+ if (nPos == -1)
+ return;
+
+ OFieldDescription* pColumn = weld::fromId<OFieldDescription*>(m_xCTRL_RIGHT->get_id(nPos));
+ if (pColumn->IsAutoIncrement())
+ {
+ m_xCTRL_RIGHT->unselect(nPos);
+ return;
+ }
+
+ int nOldEntry = m_xCTRL_LEFT->get_selected_index();
+ if (nOldEntry != -1 && nPos != nOldEntry)
+ {
+ m_xCTRL_LEFT->unselect(nOldEntry);
+ if (nPos < m_xCTRL_LEFT->n_children())
+ {
+ int nNewPos = GetFirstEntryInView(*m_xCTRL_RIGHT);
+ if ( nNewPos - nPos == 1 )
+ nNewPos--;
+ m_xCTRL_LEFT->scroll_to_row(nNewPos);
+ m_xCTRL_LEFT->select(nPos);
+ }
+ }
+ else if (nOldEntry == -1)
+ {
+ if (nPos < m_xCTRL_LEFT->n_children())
+ m_xCTRL_LEFT->select(nPos);
+ }
+}
+
+IMPL_LINK(OWizNameMatching, AllNoneClickHdl, weld::Button&, rButton, void)
+{
+ bool bAll = &rButton == m_xAll.get();
+ m_xCTRL_LEFT->all_foreach([this, bAll](weld::TreeIter& rEntry){
+ m_xCTRL_LEFT->set_toggle(rEntry, bAll ? TRISTATE_TRUE : TRISTATE_FALSE);
+ return false;
+ });
+}
+
+void OWizNameMatching::FillListBox(weld::TreeView& rTreeView, const ODatabaseExport::TColumnVector& rList, bool bCheckButtons)
+{
+ rTreeView.clear();
+
+ int nRow(0);
+
+ for (auto const& elem : rList)
+ {
+ rTreeView.append();
+ if (bCheckButtons)
+ {
+ bool bChecked = !elem->second->IsAutoIncrement();
+ rTreeView.set_toggle(nRow, bChecked ? TRISTATE_TRUE : TRISTATE_FALSE);
+ }
+ rTreeView.set_text(nRow, elem->first, 0);
+ rTreeView.set_id(nRow, weld::toId(elem->second));
+ ++nRow;
+ }
+
+ if (rTreeView.n_children())
+ rTreeView.select(0);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/WTypeSelect.cxx b/dbaccess/source/ui/misc/WTypeSelect.cxx
new file mode 100644
index 0000000000..f5b4ee4baa
--- /dev/null
+++ b/dbaccess/source/ui/misc/WTypeSelect.cxx
@@ -0,0 +1,416 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <WTypeSelect.hxx>
+#include <bitmaps.hlst>
+#include <comphelper/diagnose_ex.hxx>
+#include <osl/diagnose.h>
+#include <FieldDescriptions.hxx>
+#include <WCopyTable.hxx>
+#include <strings.hrc>
+#include <tools/stream.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/svapp.hxx>
+#include <UITools.hxx>
+#include <core_resource.hxx>
+#include <FieldControls.hxx>
+
+using namespace ::dbaui;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::sdbc;
+
+// OWizTypeSelectControl
+OWizTypeSelectControl::OWizTypeSelectControl(weld::Container* pPage, OWizTypeSelect* pParentTabPage)
+ : OFieldDescControl(pPage, nullptr)
+ , m_pParentTabPage(pParentTabPage)
+{
+}
+
+OWizTypeSelectControl::~OWizTypeSelectControl()
+{
+}
+
+void OWizTypeSelectControl::ActivateAggregate( EControlType eType )
+{
+ switch(eType )
+ {
+ case tpFormat:
+ case tpDefault:
+ case tpAutoIncrement:
+ case tpAutoIncrementValue:
+ break;
+ default:
+ OFieldDescControl::ActivateAggregate( eType );
+ }
+}
+
+void OWizTypeSelectControl::DeactivateAggregate( EControlType eType )
+{
+ switch(eType )
+ {
+ case tpFormat:
+ case tpDefault:
+ case tpAutoIncrement:
+ case tpAutoIncrementValue:
+ break;
+ default:
+ OFieldDescControl::DeactivateAggregate( eType );
+ }
+}
+
+void OWizTypeSelectControl::CellModified(sal_Int32 nRow, sal_uInt16 nColId )
+{
+ OSL_ENSURE(nRow == -1,"nRow must be -1!");
+
+ weld::TreeView* pListBox = m_pParentTabPage->m_xColumnNames->GetWidget();
+
+ OFieldDescription* pCurFieldDescr = getCurrentFieldDescData();
+
+ const sal_Int32 nPos = pListBox->find_text(pCurFieldDescr->GetName());
+ pCurFieldDescr = weld::fromId<OFieldDescription*>(pListBox->get_id(nPos));
+ OSL_ENSURE( pCurFieldDescr, "OWizTypeSelectControl::CellModified: Columnname/type not found in the listbox!" );
+ if ( !pCurFieldDescr )
+ return;
+ setCurrentFieldDescData( pCurFieldDescr );
+
+ OUString sName = pCurFieldDescr->GetName();
+ OUString sNewName;
+ const OPropColumnEditCtrl* pColumnName = getColumnCtrl();
+ if ( pColumnName )
+ sNewName = pColumnName->get_text();
+
+ switch(nColId)
+ {
+ case FIELD_PROPERTY_COLUMNNAME:
+ {
+ OCopyTableWizard* pWiz = m_pParentTabPage->m_pParent;
+ // first we have to check if this name already exists
+ bool bDoubleName = false;
+ bool bCase = true;
+ if ( getMetaData().is() && !getMetaData()->supportsMixedCaseQuotedIdentifiers() )
+ {
+ bCase = false;
+ const sal_Int32 nCount = pListBox->n_children();
+ for (sal_Int32 i=0 ; !bDoubleName && i < nCount ; ++i)
+ {
+ OUString sEntry(pListBox->get_text(i));
+ bDoubleName = sNewName.equalsIgnoreAsciiCase(sEntry);
+ }
+ if ( !bDoubleName && pWiz->shouldCreatePrimaryKey() )
+ bDoubleName = sNewName.equalsIgnoreAsciiCase(pWiz->getPrimaryKeyName());
+
+ }
+ else
+ bDoubleName = ((pListBox->find_text(sNewName) != -1)
+ || ( pWiz->shouldCreatePrimaryKey()
+ && pWiz->getPrimaryKeyName() == sNewName) );
+
+ if ( bDoubleName )
+ {
+ OUString strMessage = DBA_RES(STR_TABLEDESIGN_DUPLICATE_NAME);
+ strMessage = strMessage.replaceFirst("$column$", sNewName);
+ pWiz->showError(strMessage);
+ pCurFieldDescr->SetName(sName);
+ DisplayData(pCurFieldDescr);
+ m_pParentTabPage->setDuplicateName(true);
+ return;
+ }
+
+ OUString sOldName = pCurFieldDescr->GetName();
+ pCurFieldDescr->SetName(sNewName);
+ m_pParentTabPage->setDuplicateName(false);
+
+ // now we change the name
+
+ ::comphelper::UStringMixEqual aCase(bCase);
+ for (auto & elem : pWiz->m_mNameMapping)
+ {
+ if ( aCase(elem.second,sName) )
+ {
+ elem.second = sNewName;
+ break;
+ }
+ }
+
+ pListBox->remove(nPos);
+ pListBox->insert_text(nPos, pCurFieldDescr->GetName());
+ pListBox->set_id(nPos, weld::toId(pCurFieldDescr));
+
+ pWiz->replaceColumn(nPos,pCurFieldDescr,sOldName);
+ }
+ break;
+ }
+ saveCurrentFieldDescData();
+}
+
+css::lang::Locale OWizTypeSelectControl::GetLocale() const
+{
+ return m_pParentTabPage->m_pParent->GetLocale();
+}
+
+Reference< XNumberFormatter > OWizTypeSelectControl::GetFormatter() const
+{
+ return m_pParentTabPage->m_pParent->GetFormatter();
+}
+
+TOTypeInfoSP OWizTypeSelectControl::getTypeInfo(sal_Int32 _nPos)
+{
+ return m_pParentTabPage->m_pParent->getDestTypeInfo(_nPos);
+}
+
+const OTypeInfoMap* OWizTypeSelectControl::getTypeInfo() const
+{
+ return &m_pParentTabPage->m_pParent->getDestTypeInfo();
+}
+
+css::uno::Reference< css::sdbc::XDatabaseMetaData> OWizTypeSelectControl::getMetaData()
+{
+ return m_pParentTabPage->m_pParent->m_xDestConnection->getMetaData();
+}
+
+css::uno::Reference< css::sdbc::XConnection> OWizTypeSelectControl::getConnection()
+{
+ return m_pParentTabPage->m_pParent->m_xDestConnection;
+}
+
+bool OWizTypeSelectControl::isAutoIncrementValueEnabled() const
+{
+ return m_pParentTabPage->m_bAutoIncrementEnabled;
+}
+
+OUString OWizTypeSelectControl::getAutoIncrementValue() const
+{
+ return m_pParentTabPage->m_sAutoIncrementValue;
+}
+
+OWizTypeSelect::OWizTypeSelect(weld::Container* pPage, OCopyTableWizard* pWizard, SvStream* pStream)
+ : OWizardPage(pPage, pWizard, "dbaccess/ui/typeselectpage.ui", "TypeSelect")
+ , m_xColumnNames(new OWizTypeSelectList(m_xBuilder->weld_tree_view("columnnames")))
+ , m_xControlContainer(m_xBuilder->weld_container("control_container"))
+ , m_xTypeControl(new OWizTypeSelectControl(m_xControlContainer.get(), this))
+ , m_xAutoType(m_xBuilder->weld_label("autotype"))
+ , m_xAutoFt(m_xBuilder->weld_label("autolabel"))
+ , m_xAutoEt(m_xBuilder->weld_spin_button("auto"))
+ , m_xAutoPb(m_xBuilder->weld_button("autobutton"))
+ , m_pParserStream(pStream)
+ , m_nDisplayRow(0)
+ , m_bAutoIncrementEnabled(false)
+ , m_bDuplicateName(false)
+{
+ m_xColumnNames->connect_changed(LINK(this,OWizTypeSelect,ColumnSelectHdl));
+
+ m_xTypeControl->Init();
+
+ m_xAutoEt->set_text("10");
+ m_xAutoEt->set_digits(0);
+ m_xAutoPb->connect_clicked(LINK(this,OWizTypeSelect,ButtonClickHdl));
+ m_xColumnNames->set_selection_mode(SelectionMode::Multiple);
+
+ try
+ {
+ m_xColumnNames->SetPKey( m_pParent->supportsPrimaryKey() );
+ ::dbaui::fillAutoIncrementValue( m_pParent->m_xDestConnection, m_bAutoIncrementEnabled, m_sAutoIncrementValue );
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+}
+
+OWizTypeSelect::~OWizTypeSelect()
+{
+}
+
+OUString OWizTypeSelect::GetTitle() const
+{
+ return DBA_RES(STR_WIZ_TYPE_SELECT_TITLE);
+}
+
+IMPL_LINK_NOARG(OWizTypeSelect, ColumnSelectHdl, weld::TreeView&, void)
+{
+ OFieldDescription* pField = weld::fromId<OFieldDescription*>(m_xColumnNames->get_selected_id());
+ if (pField)
+ m_xTypeControl->DisplayData(pField);
+
+ m_xTypeControl->Enable(m_xColumnNames->count_selected_rows() == 1);
+}
+
+void OWizTypeSelect::Reset()
+{
+ // restore original state
+ m_xColumnNames->clear();
+ sal_Int32 nCount(0), nBreakPos;
+ m_pParent->CheckColumns(nBreakPos);
+
+ const ODatabaseExport::TColumnVector& rDestColumns = m_pParent->getDestVector();
+ for (auto const& column : rDestColumns)
+ {
+ OUString sId(weld::toId(column->second));
+ m_xColumnNames->append(sId, column->first);
+ if (column->second->IsPrimaryKey())
+ m_xColumnNames->set_image(nCount, BMP_PRIMARY_KEY);
+ ++nCount;
+ }
+ m_bFirstTime = false;
+}
+
+void OWizTypeSelect::Activate( )
+{
+ bool bOldFirstTime = m_bFirstTime;
+ Reset();
+ m_bFirstTime = bOldFirstTime;
+
+ m_xColumnNames->select(m_nDisplayRow);
+ m_nDisplayRow = 0;
+ ColumnSelectHdl(*m_xColumnNames->GetWidget());
+}
+
+bool OWizTypeSelect::LeavePage()
+{
+ bool bDuplicateName = false;
+ OFieldDescription* pField = weld::fromId<OFieldDescription*>(m_xColumnNames->get_selected_id());
+ if ( pField )
+ {
+ m_xTypeControl->SaveData(pField);
+ bDuplicateName = m_bDuplicateName;
+ }
+ return !bDuplicateName;
+}
+
+void OWizTypeSelect::EnableAuto(bool bEnable)
+{
+ m_xAutoFt->set_visible(bEnable);
+ m_xAutoEt->set_visible(bEnable);
+ m_xAutoPb->set_visible(bEnable);
+ m_xAutoType->set_visible(bEnable);
+}
+
+IMPL_LINK_NOARG(OWizTypeSelect, ButtonClickHdl, weld::Button&, void)
+{
+ sal_Int32 nBreakPos;
+ m_pParent->CheckColumns(nBreakPos);
+
+ // fill column list
+ sal_uInt32 nRows = m_xAutoEt->get_text().toInt32();
+ if(m_pParserStream)
+ {
+ sal_uInt64 const nTell = m_pParserStream->Tell(); // might change seek position of stream
+
+ createReaderAndCallParser(nRows);
+ m_pParserStream->Seek(nTell);
+ }
+
+ Activate();
+}
+
+OWizTypeSelectList::OWizTypeSelectList(std::unique_ptr<weld::TreeView> xControl)
+ : m_xControl(std::move(xControl))
+ , m_bPKey(false)
+{
+ m_xControl->connect_popup_menu(LINK(this, OWizTypeSelectList, CommandHdl));
+}
+
+bool OWizTypeSelectList::IsPrimaryKeyAllowed() const
+{
+ auto aRows = m_xControl->get_selected_rows();
+ std::sort(aRows.begin(), aRows.end());
+
+ const sal_Int32 nCount = aRows.size();
+
+ for( sal_Int32 j = 0; m_bPKey && j < nCount; ++j )
+ {
+ OFieldDescription* pField = weld::fromId<OFieldDescription*>(m_xControl->get_id(aRows[j]));
+ if(!pField || pField->getTypeInfo()->nSearchType == ColumnSearch::NONE)
+ return false;
+ }
+ return true;
+}
+
+void OWizTypeSelectList::setPrimaryKey(OFieldDescription* _pFieldDescr, sal_uInt16 _nPos, bool _bSet)
+{
+ _pFieldDescr->SetPrimaryKey(_bSet);
+ if( _bSet )
+ {
+ m_xControl->set_image(_nPos, BMP_PRIMARY_KEY);
+ }
+ else if( _pFieldDescr->getTypeInfo()->bNullable )
+ {
+ _pFieldDescr->SetControlDefault(Any());
+ m_xControl->set_image(_nPos, OUString());
+ }
+}
+
+IMPL_LINK(OWizTypeSelectList, CommandHdl, const CommandEvent&, rCEvt, bool)
+{
+ if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
+ return false;
+ if (!IsPrimaryKeyAllowed())
+ return false;
+
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xControl.get(), "dbaccess/ui/keymenu.ui"));
+ auto xContextMenu = xBuilder->weld_menu("menu");
+ // Should primary key checkbox be checked?
+ const sal_Int32 nCount = m_xControl->n_children();
+ bool bCheckOk = false;
+ for(sal_Int32 j = 0 ; j < nCount ; ++j)
+ {
+ OFieldDescription* pFieldDescr = weld::fromId<OFieldDescription*>(m_xControl->get_id(j));
+ // if at least one of the fields is selected but not in the primary key,
+ // or is in the primary key but not selected, then don't check the
+ // primary key checkbox.
+ if( pFieldDescr && pFieldDescr->IsPrimaryKey() != m_xControl->is_selected(j) )
+ {
+ bCheckOk = false;
+ break;
+ }
+ if (!bCheckOk && m_xControl->is_selected(j))
+ bCheckOk = true;
+ }
+
+ if (bCheckOk)
+ xContextMenu->set_active("primarykey", true);
+
+ OUString sCommand(xContextMenu->popup_at_rect(m_xControl.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1))));
+ if (sCommand != "primarykey")
+ return true;
+
+ for (sal_Int32 j = 0 ; j < nCount; ++j)
+ {
+ OFieldDescription* pFieldDescr = weld::fromId<OFieldDescription*>(m_xControl->get_id(j));
+ if (pFieldDescr)
+ {
+ if(!bCheckOk && m_xControl->is_selected(j))
+ {
+ setPrimaryKey(pFieldDescr,j,true);
+ }
+ else
+ {
+ setPrimaryKey(pFieldDescr,j);
+ }
+ }
+ }
+ m_aChangeHdl.Call(*m_xControl);
+
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/asyncmodaldialog.cxx b/dbaccess/source/ui/misc/asyncmodaldialog.cxx
new file mode 100644
index 0000000000..8323d47dba
--- /dev/null
+++ b/dbaccess/source/ui/misc/asyncmodaldialog.cxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <asyncmodaldialog.hxx>
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+#include <vcl/svapp.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::ui::dialogs::XExecutableDialog;
+ using ::com::sun::star::lang::IllegalArgumentException;
+ using ::com::sun::star::uno::Exception;
+
+ namespace {
+
+ // AsyncDialogExecutor
+ class DialogExecutor_Impl
+ {
+ Reference< XExecutableDialog > m_xDialog;
+
+ public:
+ explicit DialogExecutor_Impl( const Reference< XExecutableDialog >& _rxDialog )
+ :m_xDialog( _rxDialog )
+ {
+ }
+
+ void execute()
+ {
+ Application::PostUserEvent( LINK( this, DialogExecutor_Impl, onExecute ) );
+ }
+
+ protected:
+ ~DialogExecutor_Impl()
+ {
+ }
+
+ private:
+ DECL_LINK( onExecute, void*, void );
+ };
+
+ }
+
+ IMPL_LINK_NOARG( DialogExecutor_Impl, onExecute, void*, void )
+ {
+ try
+ {
+ m_xDialog->execute();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ delete this;
+ }
+
+ // AsyncDialogExecutor
+ void AsyncDialogExecutor::executeModalDialogAsync( const Reference< XExecutableDialog >& _rxDialog )
+ {
+ if ( !_rxDialog.is() )
+ throw IllegalArgumentException();
+
+ DialogExecutor_Impl* pExecutor = new DialogExecutor_Impl( _rxDialog );
+ pExecutor->execute();
+ // will delete itself
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/charsets.cxx b/dbaccess/source/ui/misc/charsets.cxx
new file mode 100644
index 0000000000..5224e65d3c
--- /dev/null
+++ b/dbaccess/source/ui/misc/charsets.cxx
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <charsets.hxx>
+#include <core_resource.hxx>
+#include <osl/diagnose.h>
+#include <strings.hrc>
+#include <rtl/tencinfo.h>
+#include <svx/txenctab.hxx>
+#include <utility>
+
+namespace dbaui
+{
+ using namespace ::dbtools;
+
+ // OCharsetDisplay
+ OCharsetDisplay::OCharsetDisplay()
+ : m_aSystemDisplayName(DBA_RES( STR_RSC_CHARSETS ))
+ {
+ }
+
+ bool OCharsetDisplay::approveEncoding( const rtl_TextEncoding _eEncoding, const rtl_TextEncodingInfo& _rInfo ) const
+ {
+ if ( !OCharsetMap::approveEncoding( _eEncoding, _rInfo ) )
+ return false;
+
+ if ( RTL_TEXTENCODING_DONTKNOW == _eEncoding )
+ return true;
+
+ return !SvxTextEncodingTable::GetTextString(_eEncoding).isEmpty();
+ }
+
+ OCharsetDisplay::const_iterator OCharsetDisplay::begin() const
+ {
+ return const_iterator( this, OCharsetMap::begin() );
+ }
+
+ OCharsetDisplay::const_iterator OCharsetDisplay::end() const
+ {
+ return const_iterator( this, OCharsetMap::end() );
+ }
+
+ OCharsetDisplay::const_iterator OCharsetDisplay::findEncoding(const rtl_TextEncoding _eEncoding) const
+ {
+ OCharsetMap::const_iterator aBaseIter = OCharsetMap::find(_eEncoding);
+ return const_iterator( this, aBaseIter );
+ }
+
+ OCharsetDisplay::const_iterator OCharsetDisplay::findIanaName(std::u16string_view _rIanaName) const
+ {
+ OCharsetMap::const_iterator aBaseIter = OCharsetMap::findIanaName(_rIanaName);
+ return const_iterator( this, aBaseIter );
+ }
+
+ OCharsetDisplay::const_iterator OCharsetDisplay::findDisplayName(const OUString& _rDisplayName) const
+ {
+ rtl_TextEncoding eEncoding = RTL_TEXTENCODING_DONTKNOW;
+ if ( _rDisplayName != m_aSystemDisplayName )
+ {
+ eEncoding = SvxTextEncodingTable::GetTextEncoding(_rDisplayName);
+ OSL_ENSURE( RTL_TEXTENCODING_DONTKNOW != eEncoding,
+ "OCharsetDisplay::find: non-empty display name, but DONTKNOW!" );
+ }
+ return const_iterator( this, OCharsetMap::find( eEncoding ) );
+ }
+
+ // CharsetDisplayDerefHelper
+ CharsetDisplayDerefHelper::CharsetDisplayDerefHelper(const CharsetDisplayDerefHelper& _rSource)
+ :CharsetDisplayDerefHelper_Base(_rSource)
+ ,m_sDisplayName(_rSource.m_sDisplayName)
+ {
+ }
+
+ CharsetDisplayDerefHelper::CharsetDisplayDerefHelper(const ::dbtools::CharsetIteratorDerefHelper& _rBase, OUString _sDisplayName)
+ :CharsetDisplayDerefHelper_Base(_rBase)
+ ,m_sDisplayName(std::move(_sDisplayName))
+ {
+ OSL_ENSURE( !m_sDisplayName.isEmpty(), "CharsetDisplayDerefHelper::CharsetDisplayDerefHelper: invalid display name!" );
+ }
+
+ // OCharsetDisplay::ExtendedCharsetIterator
+ OCharsetDisplay::ExtendedCharsetIterator::ExtendedCharsetIterator( const OCharsetDisplay* _pContainer, base_iterator _aPosition )
+ :m_pContainer(_pContainer)
+ ,m_aPosition(std::move(_aPosition))
+ {
+ OSL_ENSURE(m_pContainer, "OCharsetDisplay::ExtendedCharsetIterator::ExtendedCharsetIterator : invalid container!");
+ }
+
+ CharsetDisplayDerefHelper OCharsetDisplay::ExtendedCharsetIterator::operator*() const
+ {
+ OSL_ENSURE( m_aPosition != m_pContainer->OCharsetDisplay_Base::end(), "OCharsetDisplay::ExtendedCharsetIterator::operator* : invalid position!");
+
+ rtl_TextEncoding eEncoding = (*m_aPosition).getEncoding();
+ return CharsetDisplayDerefHelper(
+ *m_aPosition,
+ RTL_TEXTENCODING_DONTKNOW == eEncoding ? m_pContainer->m_aSystemDisplayName : SvxTextEncodingTable::GetTextString(eEncoding)
+ );
+ }
+
+ const OCharsetDisplay::ExtendedCharsetIterator& OCharsetDisplay::ExtendedCharsetIterator::operator++()
+ {
+ OSL_ENSURE( m_aPosition != m_pContainer->OCharsetDisplay_Base::end(), "OCharsetDisplay::ExtendedCharsetIterator::operator++ : invalid position!");
+ if ( m_aPosition != m_pContainer->OCharsetDisplay_Base::end() )
+ ++m_aPosition;
+ return *this;
+ }
+
+ bool operator==(const OCharsetDisplay::ExtendedCharsetIterator& lhs, const OCharsetDisplay::ExtendedCharsetIterator& rhs)
+ {
+ return (lhs.m_pContainer == rhs.m_pContainer) && (lhs.m_aPosition == rhs.m_aPosition);
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/controllerframe.cxx b/dbaccess/source/ui/misc/controllerframe.cxx
new file mode 100644
index 0000000000..365e144390
--- /dev/null
+++ b/dbaccess/source/ui/misc/controllerframe.cxx
@@ -0,0 +1,389 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dbaccess/controllerframe.hxx>
+#include <dbaccess/IController.hxx>
+
+#include <com/sun/star/awt/XTopWindow.hpp>
+#include <com/sun/star/awt/XWindow2.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
+#include <com/sun/star/frame/XController2.hpp>
+
+#include <cppuhelper/implbase.hxx>
+#include <rtl/ref.hxx>
+#include <sfx2/objsh.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/window.hxx>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::frame::XFrame;
+ using ::com::sun::star::frame::FrameAction;
+ using ::com::sun::star::frame::FrameAction_FRAME_ACTIVATED;
+ using ::com::sun::star::frame::FrameAction_FRAME_UI_ACTIVATED;
+ using ::com::sun::star::frame::FrameAction_FRAME_DEACTIVATING;
+ using ::com::sun::star::frame::FrameAction_FRAME_UI_DEACTIVATING;
+ using ::com::sun::star::frame::XModel;
+ using ::com::sun::star::frame::XController;
+ using ::com::sun::star::frame::XController2;
+ using ::com::sun::star::awt::XTopWindow;
+ using ::com::sun::star::awt::XTopWindowListener;
+ using ::com::sun::star::awt::XWindow2;
+ using ::com::sun::star::lang::DisposedException;
+ using ::com::sun::star::lang::EventObject;
+ using ::com::sun::star::document::XDocumentEventBroadcaster;
+ using ::com::sun::star::awt::XWindow;
+
+ // FrameWindowActivationListener
+ typedef ::cppu::WeakImplHelper< XTopWindowListener
+ > FrameWindowActivationListener_Base;
+
+ namespace {
+
+ class FrameWindowActivationListener : public FrameWindowActivationListener_Base
+ {
+ public:
+ explicit FrameWindowActivationListener( ControllerFrame_Data& _rData );
+
+ void dispose();
+
+ protected:
+ virtual ~FrameWindowActivationListener() override;
+
+ // XTopWindowListener
+ virtual void SAL_CALL windowOpened( const css::lang::EventObject& e ) override;
+ virtual void SAL_CALL windowClosing( const css::lang::EventObject& e ) override;
+ virtual void SAL_CALL windowClosed( const css::lang::EventObject& e ) override;
+ virtual void SAL_CALL windowMinimized( const css::lang::EventObject& e ) override;
+ virtual void SAL_CALL windowNormalized( const css::lang::EventObject& e ) override;
+ virtual void SAL_CALL windowActivated( const css::lang::EventObject& e ) override;
+ virtual void SAL_CALL windowDeactivated( const css::lang::EventObject& e ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ private:
+ void impl_checkDisposed_throw() const;
+ void impl_registerOnFrameContainerWindow_nothrow( bool _bRegister );
+
+ private:
+ ControllerFrame_Data* m_pData;
+ };
+
+ }
+
+ // ControllerFrame_Data
+ struct ControllerFrame_Data
+ {
+ explicit ControllerFrame_Data( IController& _rController )
+ :m_rController( _rController )
+ ,m_bActive( false )
+ ,m_bIsTopLevelDocumentWindow( false )
+ {
+ }
+
+ IController& m_rController;
+ Reference< XFrame > m_xFrame;
+ Reference< XDocumentEventBroadcaster > m_xDocEventBroadcaster;
+ ::rtl::Reference< FrameWindowActivationListener > m_pListener;
+ bool m_bActive;
+ bool m_bIsTopLevelDocumentWindow;
+ };
+
+ // helper
+ static void lcl_setFrame_nothrow( ControllerFrame_Data& _rData, const Reference< XFrame >& _rxFrame )
+ {
+ // release old listener
+ if (_rData.m_pListener)
+ {
+ _rData.m_pListener->dispose();
+ _rData.m_pListener = nullptr;
+ }
+
+ // remember new frame
+ _rData.m_xFrame = _rxFrame;
+
+ // create new listener
+ if ( _rData.m_xFrame.is() )
+ _rData.m_pListener = new FrameWindowActivationListener( _rData );
+
+ // at this point in time, we can assume the controller also has a model set, if it supports models
+ try
+ {
+ Reference< XController > xController( _rData.m_rController.getXController(), UNO_SET_THROW );
+ Reference< XModel > xModel( xController->getModel() );
+ if ( xModel.is() )
+ _rData.m_xDocEventBroadcaster.set( xModel, UNO_QUERY );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ static bool lcl_isActive_nothrow( const Reference< XFrame >& _rxFrame )
+ {
+ bool bIsActive = false;
+ try
+ {
+ if ( _rxFrame.is() )
+ {
+ Reference< XWindow2 > xWindow( _rxFrame->getContainerWindow(), UNO_QUERY_THROW );
+ bIsActive = xWindow->isActive();
+ }
+
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return bIsActive;
+ }
+
+ /** updates various global and local states with a new active component
+
+ In particular, the following are updated
+ * the global working document (aka Basic's ThisComponent in the application
+ Basic), with our controller's model, or the controller itself if there is no such
+ model.
+ */
+ static void lcl_updateActiveComponents_nothrow( const ControllerFrame_Data& _rData )
+ {
+ try
+ {
+ Reference< XController > xCompController( _rData.m_rController.getXController() );
+ OSL_ENSURE( xCompController.is(), "lcl_updateActiveComponents_nothrow: can't do anything without a controller!" );
+ if ( !xCompController.is() )
+ return;
+
+ if ( _rData.m_bActive && _rData.m_bIsTopLevelDocumentWindow )
+ {
+ // set the "current component" at the SfxObjectShell
+ Reference< XModel > xModel( xCompController->getModel() );
+ Reference< XInterface > xCurrentComponent;
+ if ( xModel.is() )
+ xCurrentComponent = xModel;
+ else
+ xCurrentComponent = xCompController;
+ SfxObjectShell::SetCurrentComponent( xCurrentComponent );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ /** broadcasts the OnFocus resp. OnUnfocus event
+ */
+ static void lcl_notifyFocusChange_nothrow( ControllerFrame_Data& _rData, bool _bActive )
+ {
+ try
+ {
+ if ( _rData.m_xDocEventBroadcaster.is() )
+ {
+ OUString sEventName = _bActive ? OUString("OnFocus") : OUString("OnUnfocus");
+ Reference< XController2 > xController( _rData.m_rController.getXController(), UNO_QUERY_THROW );
+ _rData.m_xDocEventBroadcaster->notifyDocumentEvent( sEventName, xController, Any() );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ static void lcl_updateActive_nothrow( ControllerFrame_Data& _rData, bool _bActive )
+ {
+ if ( _rData.m_bActive == _bActive )
+ return;
+ _rData.m_bActive = _bActive;
+
+ lcl_updateActiveComponents_nothrow( _rData );
+ lcl_notifyFocusChange_nothrow( _rData, _bActive );
+ }
+
+ FrameWindowActivationListener::FrameWindowActivationListener( ControllerFrame_Data& _rData )
+ :m_pData( &_rData )
+ {
+ impl_registerOnFrameContainerWindow_nothrow( true );
+ }
+
+ FrameWindowActivationListener::~FrameWindowActivationListener()
+ {
+ }
+
+ void FrameWindowActivationListener::dispose()
+ {
+ impl_registerOnFrameContainerWindow_nothrow( false );
+ m_pData = nullptr;
+ }
+
+ void FrameWindowActivationListener::impl_registerOnFrameContainerWindow_nothrow( bool _bRegister )
+ {
+ OSL_ENSURE( m_pData && m_pData->m_xFrame.is(), "FrameWindowActivationListener::impl_registerOnFrameContainerWindow_nothrow: no frame!" );
+ if ( !m_pData || !m_pData->m_xFrame.is() )
+ return;
+
+ try
+ {
+ void ( SAL_CALL XTopWindow::*pListenerAction )( const Reference< XTopWindowListener >& ) =
+ _bRegister ? &XTopWindow::addTopWindowListener : &XTopWindow::removeTopWindowListener;
+
+ const Reference< XWindow > xContainerWindow( m_pData->m_xFrame->getContainerWindow(), UNO_SET_THROW );
+ if ( _bRegister )
+ {
+ const vcl::Window* pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
+ ENSURE_OR_THROW( pContainerWindow, "no Window implementation for the frame's container window!" );
+
+ m_pData->m_bIsTopLevelDocumentWindow = bool( pContainerWindow->GetExtendedStyle() & WindowExtendedStyle::Document );
+ }
+
+ const Reference< XTopWindow > xFrameContainer( xContainerWindow, UNO_QUERY );
+ if ( xFrameContainer.is() )
+ (xFrameContainer.get()->*pListenerAction)( this );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ void FrameWindowActivationListener::impl_checkDisposed_throw() const
+ {
+ if ( !m_pData )
+ throw DisposedException( OUString(), *const_cast< FrameWindowActivationListener* >( this ) );
+ }
+
+ void SAL_CALL FrameWindowActivationListener::windowOpened( const EventObject& /*_rEvent*/ )
+ {
+ // not interested in
+ }
+
+ void SAL_CALL FrameWindowActivationListener::windowClosing( const EventObject& /*_rEvent*/ )
+ {
+ // not interested in
+ }
+
+ void SAL_CALL FrameWindowActivationListener::windowClosed( const EventObject& /*_rEvent*/ )
+ {
+ // not interested in
+ }
+
+ void SAL_CALL FrameWindowActivationListener::windowMinimized( const EventObject& /*_rEvent*/ )
+ {
+ // not interested in
+ }
+
+ void SAL_CALL FrameWindowActivationListener::windowNormalized( const EventObject& /*_rEvent*/ )
+ {
+ // not interested in
+ }
+
+ void SAL_CALL FrameWindowActivationListener::windowActivated( const EventObject& /*_rEvent*/ )
+ {
+ impl_checkDisposed_throw();
+ lcl_updateActive_nothrow( *m_pData, true );
+ }
+
+ void SAL_CALL FrameWindowActivationListener::windowDeactivated( const EventObject& /*_rEvent*/ )
+ {
+ impl_checkDisposed_throw();
+ lcl_updateActive_nothrow( *m_pData, false );
+ }
+
+ void SAL_CALL FrameWindowActivationListener::disposing( const EventObject& /*_rEvent*/ )
+ {
+ dispose();
+ }
+
+ // ControllerFrame
+ ControllerFrame::ControllerFrame( IController& _rController )
+ :m_pData( new ControllerFrame_Data( _rController ) )
+ {
+ }
+
+ ControllerFrame::~ControllerFrame()
+ {
+ }
+
+ const Reference< XFrame >& ControllerFrame::attachFrame( const Reference< XFrame >& _rxFrame )
+ {
+ // set new frame, including listener handling
+ lcl_setFrame_nothrow( *m_pData, _rxFrame );
+
+ // determine whether we're active
+ m_pData->m_bActive = lcl_isActive_nothrow( m_pData->m_xFrame );
+
+ // update active component
+ if ( m_pData->m_bActive )
+ {
+ lcl_updateActiveComponents_nothrow( *m_pData );
+ lcl_notifyFocusChange_nothrow( *m_pData, true );
+ }
+
+ return m_pData->m_xFrame;
+ }
+
+ const Reference< XFrame >& ControllerFrame::getFrame() const
+ {
+ return m_pData->m_xFrame;
+ }
+
+ bool ControllerFrame::isActive() const
+ {
+ return m_pData->m_bActive;
+ }
+
+ void ControllerFrame::frameAction( FrameAction _eAction )
+ {
+ bool bActive = m_pData->m_bActive;
+
+ switch ( _eAction )
+ {
+ case FrameAction_FRAME_ACTIVATED:
+ case FrameAction_FRAME_UI_ACTIVATED:
+ bActive = true;
+ break;
+
+ case FrameAction_FRAME_DEACTIVATING:
+ case FrameAction_FRAME_UI_DEACTIVATING:
+ bActive = false;
+ break;
+
+ default:
+ break;
+ }
+
+ lcl_updateActive_nothrow( *m_pData, bActive );
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/databaseobjectview.cxx b/dbaccess/source/ui/misc/databaseobjectview.cxx
new file mode 100644
index 0000000000..47c3932ca2
--- /dev/null
+++ b/dbaccess/source/ui/misc/databaseobjectview.cxx
@@ -0,0 +1,281 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <databaseobjectview.hxx>
+#include <strings.hxx>
+#include <asyncmodaldialog.hxx>
+
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/frame/TaskCreator.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/application/XTableUIProvider.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+
+#include <connectivity/dbtools.hxx>
+#include <osl/diagnose.h>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <utility>
+#include <vcl/window.hxx>
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::sdb;
+ using namespace ::com::sun::star::sdb::application;
+ using namespace ::com::sun::star::ui::dialogs;
+ using namespace ::com::sun::star::frame;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::awt;
+
+ // DatabaseObjectView
+ DatabaseObjectView::DatabaseObjectView( const Reference< XComponentContext >& _rxORB,
+ const Reference< XDatabaseDocumentUI >& _rxApplication,
+ const Reference< XFrame >& _rxParentFrame,
+ OUString _sComponentURL )
+ :m_xORB ( _rxORB )
+ ,m_xParentFrame ( _rxParentFrame )
+ ,m_xApplication ( _rxApplication )
+ ,m_sComponentURL (std::move( _sComponentURL ))
+ {
+ OSL_ENSURE( m_xORB.is(), "DatabaseObjectView::DatabaseObjectView: invalid service factory!" );
+ OSL_ENSURE( m_xApplication.is(), "DatabaseObjectView::DatabaseObjectView: invalid connection!" );
+ }
+
+ Reference< XConnection > DatabaseObjectView::getConnection() const
+ {
+ Reference< XConnection > xConnection;
+ if ( m_xApplication.is() )
+ xConnection = m_xApplication->getActiveConnection();
+ return xConnection;
+ }
+
+ Reference< XComponent > DatabaseObjectView::createNew( const Reference< XDataSource >& _xDataSource, const ::comphelper::NamedValueCollection& i_rDispatchArgs )
+ {
+ return doCreateView( Any( _xDataSource ), OUString(), i_rDispatchArgs );
+ }
+
+ Reference< XComponent > DatabaseObjectView::openExisting( const Any& _rDataSource, const OUString& _rName,
+ const ::comphelper::NamedValueCollection& i_rDispatchArgs )
+ {
+ return doCreateView( _rDataSource, _rName, i_rDispatchArgs );
+ }
+
+ Reference< XComponent > DatabaseObjectView::doCreateView( const Any& _rDataSource, const OUString& _rObjectName,
+ const ::comphelper::NamedValueCollection& i_rCreationArgs )
+ {
+ ::comphelper::NamedValueCollection aDispatchArgs;
+
+ aDispatchArgs.merge( i_rCreationArgs, false ); // false => do not overwrite
+ fillDispatchArgs( aDispatchArgs, _rDataSource, _rObjectName );
+ aDispatchArgs.merge( i_rCreationArgs, true ); // true => do overwrite
+
+ return doDispatch( aDispatchArgs );
+ }
+
+ Reference< XComponent > DatabaseObjectView::doDispatch( const ::comphelper::NamedValueCollection& i_rDispatchArgs )
+ {
+ Reference< XComponent > xReturn;
+ if ( m_xORB.is() )
+ {
+ try
+ {
+ // if we have no externally provided frame, create one
+ if ( !m_xFrameLoader.is() )
+ {
+ Reference< XSingleServiceFactory > xFact = TaskCreator::create(m_xORB);
+ Sequence< Any > lArgs{ Any(NamedValue("ParentFrame", Any(m_xParentFrame))),
+ Any(NamedValue("TopWindow", Any(true))),
+ Any(NamedValue("SupportPersistentWindowState",
+ Any(true))) };
+
+ m_xFrameLoader.set(xFact->createInstanceWithArguments(lArgs), UNO_QUERY_THROW);
+
+ // everything we load can be considered a "top level document", so set the respective bit at the window.
+ // This, amongst other things, triggers that the component in this task participates in the
+ // "ThisComponent"-game for the global application Basic.
+ const Reference< XFrame > xFrame( m_xFrameLoader, UNO_QUERY_THROW );
+ const Reference< XWindow > xFrameWindow( xFrame->getContainerWindow(), UNO_SET_THROW );
+ VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( xFrameWindow );
+ ENSURE_OR_THROW( pContainerWindow, "no implementation access to the frame's container window!" );
+ pContainerWindow->SetExtendedStyle( pContainerWindow->GetExtendedStyle() | WindowExtendedStyle::Document );
+ }
+
+ Reference< XComponentLoader > xFrameLoader( m_xFrameLoader, UNO_SET_THROW );
+ xReturn = xFrameLoader->loadComponentFromURL(
+ m_sComponentURL,
+ "_self",
+ 0,
+ i_rDispatchArgs.getPropertyValues()
+ );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ return xReturn;
+ }
+
+ void DatabaseObjectView::fillDispatchArgs(
+ ::comphelper::NamedValueCollection& i_rDispatchArgs,
+ const Any& _aDataSource,
+ const OUString& /* _rName */
+ )
+ {
+ OUString sDataSource;
+ Reference<XDataSource> xDataSource;
+ if ( _aDataSource >>= sDataSource )
+ {
+ i_rDispatchArgs.put( PROPERTY_DATASOURCENAME, sDataSource );
+ }
+ else if ( _aDataSource >>= xDataSource )
+ {
+ i_rDispatchArgs.put( PROPERTY_DATASOURCE, xDataSource );
+ }
+
+ i_rDispatchArgs.put( PROPERTY_ACTIVE_CONNECTION, getConnection() );
+ }
+
+ // QueryDesigner
+ QueryDesigner::QueryDesigner( const Reference< XComponentContext >& _rxORB, const Reference< XDatabaseDocumentUI >& _rxApplication,
+ const Reference< XFrame >& _rxParentFrame, bool _bCreateView )
+ :DatabaseObjectView( _rxORB, _rxApplication, _rxParentFrame, _bCreateView ? URL_COMPONENT_VIEWDESIGN : URL_COMPONENT_QUERYDESIGN )
+ ,m_nCommandType( _bCreateView ? CommandType::TABLE : CommandType::QUERY )
+ {
+ }
+
+ void QueryDesigner::fillDispatchArgs( ::comphelper::NamedValueCollection& i_rDispatchArgs, const Any& _aDataSource,
+ const OUString& _rObjectName )
+ {
+ DatabaseObjectView::fillDispatchArgs( i_rDispatchArgs, _aDataSource, _rObjectName );
+
+ const bool bIncludeQueryName = !_rObjectName.isEmpty();
+ const bool bGraphicalDesign = i_rDispatchArgs.getOrDefault( PROPERTY_GRAPHICAL_DESIGN, true );
+ const bool bEditViewAsSQLCommand = ( m_nCommandType == CommandType::TABLE ) && !bGraphicalDesign;
+
+ i_rDispatchArgs.put( PROPERTY_COMMAND_TYPE, m_nCommandType );
+
+ if ( bIncludeQueryName )
+ {
+ i_rDispatchArgs.put( PROPERTY_COMMAND, _rObjectName );
+ }
+
+ if ( bEditViewAsSQLCommand )
+ {
+ i_rDispatchArgs.put( PROPERTY_ESCAPE_PROCESSING, false );
+ }
+ }
+
+ // TableDesigner
+ TableDesigner::TableDesigner( const Reference< XComponentContext >& _rxORB, const Reference< XDatabaseDocumentUI >& _rxApplication, const Reference< XFrame >& _rxParentFrame )
+ :DatabaseObjectView( _rxORB, _rxApplication, _rxParentFrame, URL_COMPONENT_TABLEDESIGN )
+ {
+ }
+
+ void TableDesigner::fillDispatchArgs( ::comphelper::NamedValueCollection& i_rDispatchArgs, const Any& _aDataSource,
+ const OUString& _rObjectName )
+ {
+ DatabaseObjectView::fillDispatchArgs( i_rDispatchArgs, _aDataSource, _rObjectName );
+
+ if ( !_rObjectName.isEmpty() )
+ {
+ i_rDispatchArgs.put( PROPERTY_CURRENTTABLE, _rObjectName );
+ }
+ }
+
+ Reference< XComponent > TableDesigner::doCreateView( const Any& _rDataSource, const OUString& _rObjectName,
+ const ::comphelper::NamedValueCollection& i_rCreationArgs )
+ {
+ bool bIsNewDesign = _rObjectName.isEmpty();
+
+ // let's see whether the connection can provide a dedicated table designer
+ Reference< XInterface > xDesigner;
+ if ( !bIsNewDesign )
+ xDesigner = impl_getConnectionProvidedDesigner_nothrow( _rObjectName );
+
+ if ( !xDesigner.is() )
+ return DatabaseObjectView::doCreateView( _rDataSource, _rObjectName, i_rCreationArgs );
+
+ // try whether the designer is a dialog
+ Reference< XExecutableDialog > xDialog( xDesigner, UNO_QUERY_THROW );
+ try { AsyncDialogExecutor::executeModalDialogAsync( xDialog ); }
+ catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("dbaccess"); }
+ return nullptr;
+ }
+
+ Reference< XInterface > TableDesigner::impl_getConnectionProvidedDesigner_nothrow( const OUString& _rTableName )
+ {
+ Reference< XInterface > xDesigner;
+ try
+ {
+ Reference< XTableUIProvider > xTableUIProv( getConnection(), UNO_QUERY );
+ if ( xTableUIProv.is() )
+ xDesigner = xTableUIProv->getTableEditor( getApplicationUI(), _rTableName );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return xDesigner;
+ }
+
+ // ResultSetBrowser
+ ResultSetBrowser::ResultSetBrowser( const Reference< XComponentContext >& _rxORB, const Reference< XDatabaseDocumentUI >& _rxApplication, const Reference< XFrame >& _rxParentFrame,
+ bool _bTable )
+ :DatabaseObjectView( _rxORB, _rxApplication, _rxParentFrame, URL_COMPONENT_DATASOURCEBROWSER )
+ ,m_bTable(_bTable)
+ {
+ }
+
+ void ResultSetBrowser::fillDispatchArgs( ::comphelper::NamedValueCollection& i_rDispatchArgs, const Any& _aDataSource,
+ const OUString& _rQualifiedName)
+ {
+ DatabaseObjectView::fillDispatchArgs( i_rDispatchArgs, _aDataSource, _rQualifiedName );
+ OSL_ENSURE( !_rQualifiedName.isEmpty(),"A Table name must be set");
+ i_rDispatchArgs.put( PROPERTY_COMMAND, _rQualifiedName );
+ i_rDispatchArgs.put( PROPERTY_ENABLE_BROWSER, false );
+
+ if ( m_bTable )
+ {
+ OUString sCatalog;
+ OUString sSchema;
+ OUString sTable;
+ ::dbtools::qualifiedNameComponents( getConnection()->getMetaData(), _rQualifiedName, sCatalog, sSchema, sTable, ::dbtools::EComposeRule::InDataManipulation );
+ i_rDispatchArgs.put( PROPERTY_UPDATE_CATALOGNAME, sCatalog );
+ i_rDispatchArgs.put( PROPERTY_UPDATE_SCHEMANAME, sSchema );
+ i_rDispatchArgs.put( PROPERTY_UPDATE_TABLENAME, sTable );
+ i_rDispatchArgs.put( PROPERTY_COMMAND_TYPE, CommandType::TABLE );
+ }
+ else
+ i_rDispatchArgs.put( PROPERTY_COMMAND_TYPE, CommandType::QUERY );
+ }
+
+ // RelationDesigner
+ RelationDesigner::RelationDesigner( const Reference< XComponentContext >& _rxORB, const Reference< XDatabaseDocumentUI >& _rxApplication, const Reference< XFrame >& _rxParentFrame )
+ :DatabaseObjectView( _rxORB, _rxApplication, _rxParentFrame, URL_COMPONENT_RELATIONDESIGN )
+ {
+ }
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/datasourceconnector.cxx b/dbaccess/source/ui/misc/datasourceconnector.cxx
new file mode 100644
index 0000000000..a170d02963
--- /dev/null
+++ b/dbaccess/source/ui/misc/datasourceconnector.cxx
@@ -0,0 +1,199 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include <datasourceconnector.hxx>
+#include <osl/diagnose.h>
+#include <com/sun/star/sdbc/XWarningsSupplier.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdb/XCompletedConnection.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/sdbc/SQLWarning.hpp>
+#include <comphelper/namedvaluecollection.hxx>
+#include <connectivity/dbexception.hxx>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <UITools.hxx>
+#include <utility>
+#include <vcl/mnemonic.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/stdtext.hxx>
+#include <vcl/weld.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::sdb;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::task;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::frame;
+ using namespace ::dbtools;
+
+ // ODatasourceConnector
+ ODatasourceConnector::ODatasourceConnector(const Reference< XComponentContext >& _rxContext, weld::Window* _pMessageParent)
+ :m_pErrorMessageParent(_pMessageParent)
+ ,m_xContext(_rxContext)
+ {
+ }
+
+ ODatasourceConnector::ODatasourceConnector( const Reference< XComponentContext >& _rxContext, weld::Window* _pMessageParent,
+ OUString _sContextInformation )
+ :m_pErrorMessageParent(_pMessageParent)
+ ,m_xContext(_rxContext)
+ ,m_sContextInformation(std::move( _sContextInformation ))
+ {
+ }
+
+ Reference< XConnection > ODatasourceConnector::connect( const OUString& _rDataSourceName,
+ ::dbtools::SQLExceptionInfo* _pErrorInfo ) const
+ {
+ Reference< XConnection > xConnection;
+
+ OSL_ENSURE(isValid(), "ODatasourceConnector::connect: invalid object!");
+ if (!isValid())
+ return xConnection;
+
+ // get the data source
+ Reference< XDataSource > xDatasource =
+ getDataSourceByName( _rDataSourceName, m_pErrorMessageParent, m_xContext, _pErrorInfo );
+
+ if ( xDatasource.is() )
+ xConnection = connect( xDatasource, _pErrorInfo );
+ return xConnection;
+ }
+
+ Reference< XConnection > ODatasourceConnector::connect(const Reference< XDataSource>& _xDataSource,
+ ::dbtools::SQLExceptionInfo* _pErrorInfo ) const
+ {
+ Reference< XConnection > xConnection;
+
+ OSL_ENSURE( isValid() && _xDataSource.is(), "ODatasourceConnector::connect: invalid object or argument!" );
+ if ( !isValid() || !_xDataSource.is() )
+ return xConnection;
+
+ // get user/password
+ OUString sPassword, sUser;
+ bool bPwdRequired = false;
+ Reference<XPropertySet> xProp(_xDataSource,UNO_QUERY);
+ try
+ {
+ xProp->getPropertyValue(PROPERTY_PASSWORD) >>= sPassword;
+ xProp->getPropertyValue(PROPERTY_ISPASSWORDREQUIRED) >>= bPwdRequired;
+ xProp->getPropertyValue(PROPERTY_USER) >>= sUser;
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ // try to connect
+ SQLExceptionInfo aInfo;
+ try
+ {
+ if (bPwdRequired && sPassword.isEmpty())
+ { // password required, but empty -> connect using an interaction handler
+ Reference< XCompletedConnection > xConnectionCompletion( _xDataSource, UNO_QUERY_THROW );
+
+ Reference< XModel > xModel( getDataSourceOrModel( _xDataSource ), UNO_QUERY_THROW );
+ ::comphelper::NamedValueCollection aArgs( xModel->getArgs() );
+ Reference< XInteractionHandler > xHandler( aArgs.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ) );
+
+ if ( !xHandler.is() )
+ {
+ // instantiate the default SDB interaction handler
+ xHandler = InteractionHandler::createWithParent(m_xContext, m_pErrorMessageParent ? m_pErrorMessageParent->GetXWindow() : nullptr);
+ }
+
+ xConnection = xConnectionCompletion->connectWithCompletion(xHandler);
+ }
+ else
+ {
+ xConnection = _xDataSource->getConnection(sUser, sPassword);
+ }
+ }
+ catch( const SQLException& )
+ {
+ aInfo = ::cppu::getCaughtException();
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ if ( !aInfo.isValid() )
+ {
+ // there was no error during connecting, but perhaps a warning?
+ Reference< XWarningsSupplier > xConnectionWarnings( xConnection, UNO_QUERY );
+ if ( xConnectionWarnings.is() )
+ {
+ try
+ {
+ Any aWarnings( xConnectionWarnings->getWarnings() );
+ if ( aWarnings.hasValue() )
+ {
+ OUString sMessage( DBA_RES( STR_WARNINGS_DURING_CONNECT ) );
+ sMessage = sMessage.replaceFirst( "$buttontext$", GetStandardText( StandardButtonType::More ) );
+ sMessage = removeMnemonicFromString( sMessage );
+
+ SQLWarning aContext(sMessage, {}, {}, 0, aWarnings);
+ aInfo = aContext;
+ }
+ xConnectionWarnings->clearWarnings();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+ else
+ {
+ if ( !m_sContextInformation.isEmpty() )
+ {
+ SQLException aError(m_sContextInformation, {}, {}, 0, aInfo.get());
+ aInfo = aError;
+ }
+ }
+
+ // was there an error?
+ if ( aInfo.isValid() )
+ {
+ if ( _pErrorInfo )
+ {
+ *_pErrorInfo = aInfo;
+ }
+ else
+ {
+ showError(aInfo, m_pErrorMessageParent ? m_pErrorMessageParent->GetXWindow() : nullptr, m_xContext);
+ }
+ }
+ return xConnection;
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/dbaundomanager.cxx b/dbaccess/source/ui/misc/dbaundomanager.cxx
new file mode 100644
index 0000000000..9ed72bbdf4
--- /dev/null
+++ b/dbaccess/source/ui/misc/dbaundomanager.cxx
@@ -0,0 +1,324 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dbaccess/dbaundomanager.hxx>
+
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+
+#include <svl/undo.hxx>
+#include <vcl/svapp.hxx>
+#include <framework/undomanagerhelper.hxx>
+#include <framework/imutex.hxx>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::document::XUndoManager;
+ using ::com::sun::star::lang::DisposedException;
+ using ::com::sun::star::document::XUndoAction;
+ using ::com::sun::star::document::XUndoManagerListener;
+ using ::com::sun::star::lang::NoSupportException;
+
+ // UndoManager_Impl
+ struct UndoManager_Impl : public ::framework::IUndoManagerImplementation
+ {
+ UndoManager_Impl( UndoManager& i_antiImpl, ::cppu::OWeakObject& i_parent, ::osl::Mutex& i_mutex )
+ :rAntiImpl( i_antiImpl )
+ ,rParent( i_parent )
+ ,rMutex( i_mutex )
+ ,bDisposed( false )
+ ,aUndoHelper( *this )
+ {
+ }
+
+ virtual ~UndoManager_Impl()
+ {
+ }
+
+ UndoManager& rAntiImpl;
+ ::cppu::OWeakObject& rParent;
+ ::osl::Mutex& rMutex;
+ bool bDisposed;
+ SfxUndoManager aUndoManager;
+ ::framework::UndoManagerHelper aUndoHelper;
+
+ // IUndoManagerImplementation
+ virtual SfxUndoManager& getImplUndoManager() override;
+ virtual Reference< XUndoManager > getThis() override;
+ };
+
+ SfxUndoManager& UndoManager_Impl::getImplUndoManager()
+ {
+ return aUndoManager;
+ }
+
+ Reference< XUndoManager > UndoManager_Impl::getThis()
+ {
+ return static_cast< XUndoManager* >( &rAntiImpl );
+ }
+
+ namespace {
+
+ // OslMutexFacade
+ class OslMutexFacade : public ::framework::IMutex
+ {
+ public:
+ explicit OslMutexFacade( ::osl::Mutex& i_mutex )
+ :m_rMutex( i_mutex )
+ {
+ }
+
+ virtual ~OslMutexFacade() {}
+
+ virtual void acquire() override;
+ virtual void release() override;
+
+ private:
+ ::osl::Mutex& m_rMutex;
+ };
+
+ }
+
+ void OslMutexFacade::acquire()
+ {
+ m_rMutex.acquire();
+ }
+
+ void OslMutexFacade::release()
+ {
+ m_rMutex.release();
+ }
+
+ namespace {
+
+ // UndoManagerMethodGuard
+ /** guard for public UNO methods of the UndoManager
+ */
+ class UndoManagerMethodGuard : public ::framework::IMutexGuard
+ {
+ public:
+ explicit UndoManagerMethodGuard( UndoManager_Impl& i_impl )
+ :m_aGuard( i_impl.rMutex )
+ ,m_aMutexFacade( i_impl.rMutex )
+ {
+ // throw if the instance is already disposed
+ if ( i_impl.bDisposed )
+ throw DisposedException( OUString(), i_impl.getThis() );
+ }
+ virtual ~UndoManagerMethodGuard()
+ {
+ }
+
+ // IMutexGuard
+ virtual void clear() override;
+ virtual ::framework::IMutex& getGuardedMutex() override;
+
+ private:
+ osl::ClearableMutexGuard m_aGuard;
+ OslMutexFacade m_aMutexFacade;
+ };
+
+ }
+
+ ::framework::IMutex& UndoManagerMethodGuard::getGuardedMutex()
+ {
+ return m_aMutexFacade;
+ }
+
+ void UndoManagerMethodGuard::clear()
+ {
+ m_aGuard.clear();
+ }
+
+ // UndoManager
+ UndoManager::UndoManager( ::cppu::OWeakObject& i_parent, ::osl::Mutex& i_mutex )
+ :m_xImpl( new UndoManager_Impl( *this, i_parent, i_mutex ) )
+ {
+ }
+
+ UndoManager::~UndoManager()
+ {
+ }
+
+ SfxUndoManager& UndoManager::GetSfxUndoManager() const
+ {
+ return m_xImpl->aUndoManager;
+ }
+
+ void SAL_CALL UndoManager::acquire( ) noexcept
+ {
+ m_xImpl->rParent.acquire();
+ }
+
+ void SAL_CALL UndoManager::release( ) noexcept
+ {
+ m_xImpl->rParent.release();
+ }
+
+ void UndoManager::disposing()
+ {
+ {
+ ::osl::MutexGuard aGuard( m_xImpl->rMutex );
+ m_xImpl->bDisposed = true;
+ }
+ m_xImpl->aUndoHelper.disposing();
+ }
+
+ void SAL_CALL UndoManager::enterUndoContext( const OUString& i_title )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.enterUndoContext( i_title, aGuard );
+ }
+
+ void SAL_CALL UndoManager::enterHiddenUndoContext( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.enterHiddenUndoContext( aGuard );
+ }
+
+ void SAL_CALL UndoManager::leaveUndoContext( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.leaveUndoContext( aGuard );
+ }
+
+ void SAL_CALL UndoManager::addUndoAction( const Reference< XUndoAction >& i_action )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.addUndoAction( i_action, aGuard );
+ }
+
+ void SAL_CALL UndoManager::undo( )
+ {
+ SolarMutexGuard aSolarGuard;
+ // (all our UndoActions work directly on VCL code, usually, so ...)
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.undo( aGuard );
+ }
+
+ void SAL_CALL UndoManager::redo( )
+ {
+ SolarMutexGuard aSolarGuard;
+ // (all our UndoActions work directly on VCL code, usually, so ...)
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.redo( aGuard );
+ }
+
+ sal_Bool SAL_CALL UndoManager::isUndoPossible( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ return m_xImpl->aUndoHelper.isUndoPossible();
+ }
+
+ sal_Bool SAL_CALL UndoManager::isRedoPossible( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ return m_xImpl->aUndoHelper.isRedoPossible();
+ }
+
+ OUString SAL_CALL UndoManager::getCurrentUndoActionTitle( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ return m_xImpl->aUndoHelper.getCurrentUndoActionTitle();
+ }
+
+ OUString SAL_CALL UndoManager::getCurrentRedoActionTitle( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ return m_xImpl->aUndoHelper.getCurrentRedoActionTitle();
+ }
+
+ Sequence< OUString > SAL_CALL UndoManager::getAllUndoActionTitles( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ return m_xImpl->aUndoHelper.getAllUndoActionTitles();
+ }
+
+ Sequence< OUString > SAL_CALL UndoManager::getAllRedoActionTitles( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ return m_xImpl->aUndoHelper.getAllRedoActionTitles();
+ }
+
+ void SAL_CALL UndoManager::clear( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.clear( aGuard );
+ }
+
+ void SAL_CALL UndoManager::clearRedo( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.clearRedo( aGuard );
+ }
+
+ void SAL_CALL UndoManager::reset( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.reset( aGuard );
+ }
+
+ void SAL_CALL UndoManager::addUndoManagerListener( const Reference< XUndoManagerListener >& i_listener )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.addUndoManagerListener( i_listener );
+ }
+
+ void SAL_CALL UndoManager::removeUndoManagerListener( const Reference< XUndoManagerListener >& i_listener )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.removeUndoManagerListener( i_listener );
+ }
+
+ void SAL_CALL UndoManager::lock( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.lock();
+ }
+
+ void SAL_CALL UndoManager::unlock( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ m_xImpl->aUndoHelper.unlock();
+ }
+
+ sal_Bool SAL_CALL UndoManager::isLocked( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ return m_xImpl->aUndoHelper.isLocked();
+ }
+
+ Reference< XInterface > SAL_CALL UndoManager::getParent( )
+ {
+ UndoManagerMethodGuard aGuard( *m_xImpl );
+ return m_xImpl->rParent;
+ }
+
+ void SAL_CALL UndoManager::setParent( const Reference< XInterface >& )
+ {
+ throw NoSupportException( OUString(), m_xImpl->getThis() );
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/dbsubcomponentcontroller.cxx b/dbaccess/source/ui/misc/dbsubcomponentcontroller.cxx
new file mode 100644
index 0000000000..759f202c0d
--- /dev/null
+++ b/dbaccess/source/ui/misc/dbsubcomponentcontroller.cxx
@@ -0,0 +1,605 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <browserids.hxx>
+#include <commontypes.hxx>
+#include <core_resource.hxx>
+#include <dbaccess/dataview.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <dbaccess/dbsubcomponentcontroller.hxx>
+
+#include <com/sun/star/frame/XUntitledNumbers.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/sdb/XDocumentDataSource.hpp>
+#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
+#include <com/sun/star/sdbc/XDataSource.hpp>
+#include <com/sun/star/util/NumberFormatter.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+#include <comphelper/types.hxx>
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbmetadata.hxx>
+#include <connectivity/dbtools.hxx>
+#include <comphelper/interfacecontainer3.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/debug.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::Type;
+ using ::com::sun::star::uno::XComponentContext;
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::container::XChild;
+ using ::com::sun::star::sdbc::XDataSource;
+ using ::com::sun::star::util::NumberFormatter;
+ using ::com::sun::star::util::XNumberFormatter;
+ using ::com::sun::star::util::XNumberFormatsSupplier;
+ using ::com::sun::star::frame::XFrame;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::lang::EventObject;
+ using ::com::sun::star::beans::PropertyValue;
+ using ::com::sun::star::frame::XModel;
+ using ::com::sun::star::sdb::XOfficeDatabaseDocument;
+ using ::com::sun::star::awt::XWindow;
+ using ::com::sun::star::sdbc::XDatabaseMetaData;
+ using ::com::sun::star::sdb::XDocumentDataSource;
+ using ::com::sun::star::document::XEmbeddedScripts;
+ using ::com::sun::star::lang::IllegalArgumentException;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::frame::XUntitledNumbers;
+
+ namespace {
+
+ class DataSourceHolder
+ {
+ public:
+ DataSourceHolder()
+ {
+ }
+
+ explicit DataSourceHolder(const Reference< XDataSource >& _rxDataSource)
+ : m_xDataSource(_rxDataSource)
+ {
+ Reference< XDocumentDataSource > xDocDS( m_xDataSource, UNO_QUERY );
+ if ( xDocDS.is() )
+ m_xDocument = xDocDS->getDatabaseDocument();
+
+ m_xDataSourceProps.set( m_xDataSource, UNO_QUERY );
+ }
+
+ const Reference< XDataSource >& getDataSource() const { return m_xDataSource; }
+ const Reference< XPropertySet >& getDataSourceProps() const { return m_xDataSourceProps; }
+ const Reference< XOfficeDatabaseDocument >& getDatabaseDocument() const { return m_xDocument; }
+
+ bool is() const { return m_xDataSource.is(); }
+
+ void clear()
+ {
+ m_xDataSource.clear();
+ m_xDocument.clear();
+ }
+
+ private:
+ Reference< XDataSource > m_xDataSource;
+ Reference< XPropertySet > m_xDataSourceProps;
+ Reference< XOfficeDatabaseDocument > m_xDocument;
+ };
+
+ }
+
+ struct DBSubComponentController_Impl
+ {
+ private:
+ ::std::optional< bool > m_aDocScriptSupport;
+
+ public:
+ ::dbtools::SQLExceptionInfo m_aCurrentError;
+
+ ::comphelper::OInterfaceContainerHelper3<css::util::XModifyListener>
+ m_aModifyListeners;
+
+ // <properties>
+ SharedConnection m_xConnection;
+ ::dbtools::DatabaseMetaData m_aSdbMetaData;
+ // </properties>
+ OUString m_sDataSourceName; // the data source we're working for
+ DataSourceHolder m_aDataSource;
+ Reference< XNumberFormatter > m_xFormatter; // a number formatter working with the connection's NumberFormatsSupplier
+ sal_Int32 m_nDocStartNumber;
+ bool m_bSuspended; // is true when the controller was already suspended
+ bool m_bEditable; // is the control readonly or not
+ bool m_bModified; // is the data modified
+ bool m_bNotAttached;
+
+ explicit DBSubComponentController_Impl(osl::Mutex& i_rMutex)
+ :m_aModifyListeners( i_rMutex )
+ ,m_nDocStartNumber(0)
+ ,m_bSuspended( false )
+ ,m_bEditable(true)
+ ,m_bModified(false)
+ ,m_bNotAttached(true)
+ {
+ }
+
+ bool documentHasScriptSupport() const
+ {
+ OSL_PRECOND( m_aDocScriptSupport.has_value(),
+ "DBSubComponentController_Impl::documentHasScriptSupport: not completely initialized, yet - don't know!?" );
+ return m_aDocScriptSupport.has_value() && *m_aDocScriptSupport;
+ }
+
+ void setDocumentScriptSupport( const bool _bSupport )
+ {
+ OSL_PRECOND( !m_aDocScriptSupport.has_value(),
+ "DBSubComponentController_Impl::setDocumentScriptSupport: already initialized!" );
+ m_aDocScriptSupport = ::std::optional< bool >( _bSupport );
+ }
+ };
+
+ // DBSubComponentController
+ DBSubComponentController::DBSubComponentController(const Reference< XComponentContext >& _rxORB)
+ :DBSubComponentController_Base( _rxORB )
+ ,m_pImpl( new DBSubComponentController_Impl( getMutex() ) )
+ {
+ }
+
+ DBSubComponentController::~DBSubComponentController()
+ {
+ }
+
+ void DBSubComponentController::impl_initialize()
+ {
+ OGenericUnoController::impl_initialize();
+
+ const ::comphelper::NamedValueCollection& rArguments( getInitParams() );
+
+ Reference< XConnection > xConnection;
+ xConnection = rArguments.getOrDefault( PROPERTY_ACTIVE_CONNECTION, xConnection );
+
+ if ( !xConnection.is() )
+ ::dbtools::isEmbeddedInDatabase( getModel(), xConnection );
+
+ if ( xConnection.is() )
+ initializeConnection( xConnection );
+
+ bool bShowError = true;
+ if ( !isConnected() )
+ {
+ reconnect( false );
+ bShowError = false;
+ }
+ if ( !isConnected() )
+ {
+ if ( bShowError )
+ connectionLostMessage();
+ throw IllegalArgumentException();
+ }
+ }
+
+ Any SAL_CALL DBSubComponentController::queryInterface(const Type& _rType)
+ {
+ if ( _rType.equals( cppu::UnoType<XScriptInvocationContext>::get() ) )
+ {
+ if ( m_pImpl->documentHasScriptSupport() )
+ return Any( Reference< XScriptInvocationContext >( this ) );
+ return Any();
+ }
+
+ return DBSubComponentController_Base::queryInterface( _rType );
+ }
+
+ Sequence< Type > SAL_CALL DBSubComponentController::getTypes( )
+ {
+ Sequence< Type > aTypes( DBSubComponentController_Base::getTypes() );
+ if ( !m_pImpl->documentHasScriptSupport() )
+ {
+ auto [begin, end] = asNonConstRange(aTypes);
+ auto newEnd = std::remove_if( begin, end,
+ [](const Type& type)
+ { return type == cppu::UnoType<XScriptInvocationContext>::get(); } );
+ aTypes.realloc( std::distance(begin, newEnd) );
+ }
+ return aTypes;
+ }
+
+ void DBSubComponentController::initializeConnection( const Reference< XConnection >& _rxForeignConn )
+ {
+ DBG_ASSERT( !isConnected(), "DBSubComponentController::initializeConnection: not to be called when already connected!" );
+ // usually this gets called from within initialize of derived classes ...
+ if ( isConnected() )
+ disconnect();
+
+ m_pImpl->m_xConnection.reset( _rxForeignConn, SharedConnection::NoTakeOwnership );
+ m_pImpl->m_aSdbMetaData.reset( m_pImpl->m_xConnection );
+ startConnectionListening( m_pImpl->m_xConnection );
+
+ // get the data source the connection belongs to
+ try
+ {
+ // determine our data source
+ OSL_PRECOND( !m_pImpl->m_aDataSource.is(), "DBSubComponentController::initializeConnection: already a data source in this phase?" );
+ {
+ Reference< XChild > xConnAsChild( m_pImpl->m_xConnection, UNO_QUERY );
+ Reference< XDataSource > xDS;
+ if ( xConnAsChild.is() )
+ xDS.set( xConnAsChild->getParent(), UNO_QUERY );
+
+ // (take the indirection through XDataSource to ensure we have a correct object...)
+ m_pImpl->m_aDataSource = DataSourceHolder(xDS);
+ }
+ SAL_WARN_IF( !m_pImpl->m_aDataSource.is(), "dbaccess.ui", "DBSubComponentController::initializeConnection: unable to obtain the data source object!" );
+
+ if ( m_pImpl->m_bNotAttached )
+ {
+ Reference< XUntitledNumbers > xUntitledProvider( getDatabaseDocument(), UNO_QUERY );
+ m_pImpl->m_nDocStartNumber = 1;
+ if ( xUntitledProvider.is() )
+ m_pImpl->m_nDocStartNumber = xUntitledProvider->leaseNumber( static_cast< XWeak* >( this ) );
+ }
+
+ // determine the availability of script support in our document. Our own XScriptInvocationContext
+ // interface depends on this
+ m_pImpl->setDocumentScriptSupport( Reference< XEmbeddedScripts >( getDatabaseDocument(), UNO_QUERY ).is() );
+
+ // get a number formatter
+ Reference< XPropertySet > xDataSourceProps( m_pImpl->m_aDataSource.getDataSourceProps(), UNO_SET_THROW );
+ xDataSourceProps->getPropertyValue( PROPERTY_NAME ) >>= m_pImpl->m_sDataSourceName;
+ DBG_ASSERT( !m_pImpl->m_sDataSourceName.isEmpty(), "DBSubComponentController::initializeConnection: invalid data source name!" );
+ Reference< XNumberFormatsSupplier> xSupplier = ::dbtools::getNumberFormats(m_pImpl->m_xConnection);
+ if(xSupplier.is())
+ {
+ m_pImpl->m_xFormatter.set(NumberFormatter::create(getORB()), UNO_QUERY_THROW);
+ m_pImpl->m_xFormatter->attachNumberFormatsSupplier(xSupplier);
+ }
+ OSL_ENSURE(m_pImpl->m_xFormatter.is(),"No NumberFormatter!");
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ void DBSubComponentController::reconnect( bool _bUI )
+ {
+ OSL_ENSURE(!m_pImpl->m_bSuspended, "Cannot reconnect while suspended!");
+
+ stopConnectionListening( m_pImpl->m_xConnection );
+ m_pImpl->m_aSdbMetaData.reset( nullptr );
+ m_pImpl->m_xConnection.clear();
+
+ // reconnect
+ bool bReConnect = true;
+ if ( _bUI )
+ {
+ std::unique_ptr<weld::MessageDialog> xQuery(Application::CreateMessageDialog(getFrameWeld(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ DBA_RES(STR_QUERY_CONNECTION_LOST)));
+ bReConnect = (RET_YES == xQuery->run());
+ }
+
+ // now really reconnect ...
+ if ( bReConnect )
+ {
+ m_pImpl->m_xConnection.reset( connect( m_pImpl->m_aDataSource.getDataSource() ), SharedConnection::TakeOwnership );
+ m_pImpl->m_aSdbMetaData.reset( m_pImpl->m_xConnection );
+ }
+
+ // invalidate all slots
+ InvalidateAll();
+ }
+
+ void DBSubComponentController::disconnect()
+ {
+ stopConnectionListening(m_pImpl->m_xConnection);
+ m_pImpl->m_aSdbMetaData.reset( nullptr );
+ m_pImpl->m_xConnection.clear();
+
+ InvalidateAll();
+ }
+
+ void DBSubComponentController::losingConnection()
+ {
+ // our connection was disposed so we need a new one
+ reconnect( true );
+ InvalidateAll();
+ }
+
+ void SAL_CALL DBSubComponentController::disposing()
+ {
+ DBSubComponentController_Base::disposing();
+
+ disconnect();
+
+ attachFrame( Reference < XFrame >() );
+
+ m_pImpl->m_aDataSource.clear();
+ }
+
+ void SAL_CALL DBSubComponentController::disposing(const EventObject& _rSource)
+ {
+ if ( _rSource.Source == getConnection() )
+ {
+ if ( !m_pImpl->m_bSuspended // when already suspended then we don't have to reconnect
+ && !getBroadcastHelper().bInDispose
+ && !getBroadcastHelper().bDisposed
+ && isConnected()
+ )
+ {
+ losingConnection();
+ }
+ else
+ {
+ m_pImpl->m_xConnection.reset( m_pImpl->m_xConnection, SharedConnection::NoTakeOwnership );
+ // this prevents the "disposeComponent" call in disconnect
+ disconnect();
+ }
+ }
+ else
+ DBSubComponentController_Base::disposing( _rSource );
+ }
+
+ void DBSubComponentController::appendError( const OUString& _rErrorMessage )
+ {
+ m_pImpl->m_aCurrentError.append( ::dbtools::SQLExceptionInfo::TYPE::SQLException, _rErrorMessage,
+ getStandardSQLState( ::dbtools::StandardSQLState::GENERAL_ERROR ),
+ 1000 );
+ }
+ void DBSubComponentController::clearError()
+ {
+ m_pImpl->m_aCurrentError = ::dbtools::SQLExceptionInfo();
+ }
+
+ bool DBSubComponentController::hasError() const
+ {
+ return m_pImpl->m_aCurrentError.isValid();
+ }
+
+ const ::dbtools::SQLExceptionInfo& DBSubComponentController::getError() const
+ {
+ return m_pImpl->m_aCurrentError;
+ }
+
+ void DBSubComponentController::displayError()
+ {
+ showError( m_pImpl->m_aCurrentError );
+ }
+
+ sal_Bool SAL_CALL DBSubComponentController::suspend(sal_Bool bSuspend)
+ {
+ m_pImpl->m_bSuspended = bSuspend;
+ if ( !bSuspend && !isConnected() )
+ reconnect(true);
+
+ return true;
+ }
+
+ sal_Bool SAL_CALL DBSubComponentController::attachModel( const Reference< XModel > & _rxModel)
+ {
+ if ( !_rxModel.is() )
+ return false;
+ if ( !DBSubComponentController_Base::attachModel( _rxModel ) )
+ return false;
+
+ m_pImpl->m_bNotAttached = false;
+ if ( m_pImpl->m_nDocStartNumber == 1 )
+ releaseNumberForComponent();
+
+ Reference< XUntitledNumbers > xUntitledProvider( _rxModel, UNO_QUERY );
+ m_pImpl->m_nDocStartNumber = 1;
+ if ( xUntitledProvider.is() )
+ m_pImpl->m_nDocStartNumber = xUntitledProvider->leaseNumber( static_cast< XWeak* >( this ) );
+
+ return true;
+ }
+
+ void DBSubComponentController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& _rArgs)
+ {
+ if ( _nId == ID_BROWSER_CLOSE )
+ {
+ closeTask();
+ return;
+ }
+
+ DBSubComponentController_Base::Execute( _nId, _rArgs );
+ InvalidateFeature( _nId );
+ }
+
+ OUString DBSubComponentController::getDataSourceName() const
+ {
+ OUString sName;
+ Reference< XPropertySet > xDataSourceProps( m_pImpl->m_aDataSource.getDataSourceProps() );
+ if ( xDataSourceProps.is() )
+ xDataSourceProps->getPropertyValue(PROPERTY_NAME) >>= sName;
+ return sName;
+ }
+ void DBSubComponentController::connectionLostMessage() const
+ {
+ OUString aMessage(DBA_RES(RID_STR_CONNECTION_LOST));
+ Reference< XWindow > xWindow = getTopMostContainerWindow();
+ vcl::Window* pWin = nullptr;
+ if ( xWindow.is() )
+ pWin = VCLUnoHelper::GetWindow(xWindow);
+ if ( !pWin )
+ pWin = getView()->Window::GetParent();
+
+ std::unique_ptr<weld::MessageDialog> xInfo(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
+ VclMessageType::Info, VclButtonsType::Ok, aMessage));
+ xInfo->run();
+ }
+ const Reference< XConnection >& DBSubComponentController::getConnection() const
+ {
+ return m_pImpl->m_xConnection;
+ }
+
+ bool DBSubComponentController::isReadOnly() const
+ {
+ return !m_pImpl->m_bEditable;
+ }
+
+ bool DBSubComponentController::isEditable() const
+ {
+ return m_pImpl->m_bEditable;
+ }
+
+ void DBSubComponentController::setEditable(bool _bEditable)
+ {
+ m_pImpl->m_bEditable = _bEditable;
+ }
+
+ const ::dbtools::DatabaseMetaData& DBSubComponentController::getSdbMetaData() const
+ {
+ return m_pImpl->m_aSdbMetaData;
+ }
+
+ bool DBSubComponentController::isConnected() const
+ {
+ return m_pImpl->m_xConnection.is();
+ }
+
+ Reference< XDatabaseMetaData > DBSubComponentController::getMetaData( ) const
+ {
+ Reference< XDatabaseMetaData > xMeta;
+ try
+ {
+ if ( isConnected() )
+ xMeta.set( m_pImpl->m_xConnection->getMetaData(), UNO_SET_THROW );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return xMeta;
+ }
+
+ const Reference< XPropertySet >& DBSubComponentController::getDataSource() const
+ {
+ return m_pImpl->m_aDataSource.getDataSourceProps();
+ }
+
+ bool DBSubComponentController::haveDataSource() const
+ {
+ return m_pImpl->m_aDataSource.is();
+ }
+
+ Reference< XModel > DBSubComponentController::getDatabaseDocument() const
+ {
+ return Reference< XModel >( m_pImpl->m_aDataSource.getDatabaseDocument(), UNO_QUERY );
+ }
+
+ Reference< XNumberFormatter > const & DBSubComponentController::getNumberFormatter() const
+ {
+ return m_pImpl->m_xFormatter;
+ }
+
+ Reference< XModel > DBSubComponentController::getPrivateModel() const
+ {
+ return getDatabaseDocument();
+ }
+ // XTitle
+ OUString SAL_CALL DBSubComponentController::getTitle()
+ {
+ ::osl::MutexGuard aGuard( getMutex() );
+ if ( m_bExternalTitle )
+ return impl_getTitleHelper_throw()->getTitle ();
+
+ OUStringBuffer sTitle;
+ Reference< XTitle > xTitle(getPrivateModel(),UNO_QUERY);
+ if ( xTitle.is() )
+ {
+ sTitle.append( xTitle->getTitle() + " : ");
+ }
+ sTitle.append( getPrivateTitle() );
+ return sTitle.makeStringAndClear();
+ }
+
+ sal_Int32 DBSubComponentController::getCurrentStartNumber() const
+ {
+ return m_pImpl->m_nDocStartNumber;
+ }
+
+ Reference< XEmbeddedScripts > SAL_CALL DBSubComponentController::getScriptContainer()
+ {
+ ::osl::MutexGuard aGuard( getMutex() );
+ if ( !m_pImpl->documentHasScriptSupport() )
+ return nullptr;
+
+ return Reference< XEmbeddedScripts >( getDatabaseDocument(), UNO_QUERY_THROW );
+ }
+
+ void SAL_CALL DBSubComponentController::addModifyListener( const Reference< XModifyListener >& i_Listener )
+ {
+ ::osl::MutexGuard aGuard( getMutex() );
+ m_pImpl->m_aModifyListeners.addInterface( i_Listener );
+ }
+
+ void SAL_CALL DBSubComponentController::removeModifyListener( const Reference< XModifyListener >& i_Listener )
+ {
+ ::osl::MutexGuard aGuard( getMutex() );
+ m_pImpl->m_aModifyListeners.removeInterface( i_Listener );
+ }
+
+ sal_Bool SAL_CALL DBSubComponentController::isModified( )
+ {
+ ::osl::MutexGuard aGuard( getMutex() );
+ return impl_isModified();
+ }
+
+ void SAL_CALL DBSubComponentController::setModified( sal_Bool i_bModified )
+ {
+ ::osl::ClearableMutexGuard aGuard( getMutex() );
+
+ if ( m_pImpl->m_bModified == bool(i_bModified) )
+ return;
+
+ m_pImpl->m_bModified = i_bModified;
+ impl_onModifyChanged();
+
+ EventObject aEvent( *this );
+ aGuard.clear();
+ m_pImpl->m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvent );
+ }
+
+ bool DBSubComponentController::impl_isModified() const
+ {
+ return m_pImpl->m_bModified;
+ }
+
+ void DBSubComponentController::impl_onModifyChanged()
+ {
+ InvalidateFeature( ID_BROWSER_SAVEDOC );
+ if ( isFeatureSupported( ID_BROWSER_SAVEASDOC ) )
+ InvalidateFeature( ID_BROWSER_SAVEASDOC );
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/defaultobjectnamecheck.cxx b/dbaccess/source/ui/misc/defaultobjectnamecheck.cxx
new file mode 100644
index 0000000000..cc44de2bde
--- /dev/null
+++ b/dbaccess/source/ui/misc/defaultobjectnamecheck.cxx
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include <defaultobjectnamecheck.hxx>
+
+#include <strings.hrc>
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+#include <connectivity/dbexception.hxx>
+#include <connectivity/dbmetadata.hxx>
+
+#include <rtl/ustrbuf.hxx>
+
+#include <comphelper/diagnose_ex.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <memory>
+#include <string_view>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::lang::IllegalArgumentException;
+ using ::com::sun::star::container::XHierarchicalNameAccess;
+ using ::com::sun::star::sdbc::SQLException;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::sdb::tools::XConnectionTools;
+ using ::com::sun::star::uno::UNO_QUERY;
+
+ using namespace dbtools;
+
+ namespace CommandType = ::com::sun::star::sdb::CommandType;
+
+ // helper
+ namespace
+ {
+ void lcl_fillNameExistsError( std::u16string_view _rObjectName, SQLExceptionInfo& _out_rErrorToDisplay )
+ {
+ OUString sErrorMessage = DBA_RES(STR_NAMED_OBJECT_ALREADY_EXISTS);
+ SQLException aError(sErrorMessage.replaceAll("$#$", _rObjectName), {}, {}, 0, {});
+ _out_rErrorToDisplay = aError;
+ }
+
+ }
+
+ // HierarchicalNameCheck
+ HierarchicalNameCheck::HierarchicalNameCheck( const Reference< XHierarchicalNameAccess >& _rxNames, const OUString& _rRelativeRoot )
+ {
+ mxHierarchicalNames = _rxNames;
+ msRelativeRoot = _rRelativeRoot;
+
+ if ( !mxHierarchicalNames.is() )
+ throw IllegalArgumentException();
+ }
+
+ HierarchicalNameCheck::~HierarchicalNameCheck()
+ {
+ }
+
+ bool HierarchicalNameCheck::isNameValid( const OUString& _rObjectName, SQLExceptionInfo& _out_rErrorToDisplay ) const
+ {
+ try
+ {
+ OUStringBuffer aCompleteName;
+ if ( !msRelativeRoot.isEmpty() )
+ {
+ aCompleteName.append( msRelativeRoot + "/" );
+ }
+ aCompleteName.append( _rObjectName );
+
+ OUString sCompleteName( aCompleteName.makeStringAndClear() );
+ if ( !mxHierarchicalNames->hasByHierarchicalName( sCompleteName ) )
+ return true;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ lcl_fillNameExistsError( _rObjectName, _out_rErrorToDisplay );
+ return false;
+ }
+
+ // DynamicTableOrQueryNameCheck
+ DynamicTableOrQueryNameCheck::DynamicTableOrQueryNameCheck( const Reference< XConnection >& _rxSdbLevelConnection, sal_Int32 _nCommandType )
+ {
+ Reference< XConnectionTools > xConnTools( _rxSdbLevelConnection, UNO_QUERY );
+ if ( xConnTools.is() )
+ mxObjectNames.set( xConnTools->getObjectNames() );
+ if ( !mxObjectNames.is() )
+ throw IllegalArgumentException();
+
+ if ( ( _nCommandType != CommandType::QUERY ) && ( _nCommandType != CommandType::TABLE ) )
+ throw IllegalArgumentException();
+ mnCommandType = _nCommandType;
+ }
+
+ DynamicTableOrQueryNameCheck::~DynamicTableOrQueryNameCheck()
+ {
+ }
+
+ bool DynamicTableOrQueryNameCheck::isNameValid( const OUString& _rObjectName, ::dbtools::SQLExceptionInfo& _out_rErrorToDisplay ) const
+ {
+ try
+ {
+ mxObjectNames->checkNameForCreate( mnCommandType, _rObjectName );
+ return true;
+ }
+ catch( const SQLException& )
+ {
+ _out_rErrorToDisplay = ::dbtools::SQLExceptionInfo( ::cppu::getCaughtException() );
+ }
+ return false;
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/dsmeta.cxx b/dbaccess/source/ui/misc/dsmeta.cxx
new file mode 100644
index 0000000000..526a39ecbc
--- /dev/null
+++ b/dbaccess/source/ui/misc/dsmeta.cxx
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dsmeta.hxx>
+#include <connectivity/DriversConfig.hxx>
+#include <dsntypes.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include <map>
+#include <utility>
+
+namespace dbaui
+{
+
+ using namespace dbaccess;
+ using namespace ::com::sun::star;
+
+ namespace {
+
+ struct FeatureSupport
+ {
+ // authentication mode of the data source
+ AuthenticationMode eAuthentication;
+
+ FeatureSupport()
+ :eAuthentication( AuthUserPwd )
+ {
+ }
+
+ explicit FeatureSupport(AuthenticationMode Auth)
+ :eAuthentication( Auth )
+ {
+ }
+ };
+
+ struct FeatureMapping
+ {
+ /// one of the items from dsitems.hxx
+ ItemID nItemID;
+ OUString pAsciiFeatureName;
+ };
+
+ // global tables
+ const FeatureMapping s_aMappings[] = {
+ { DSID_AUTORETRIEVEENABLED, "GeneratedValues" },
+ { DSID_AUTOINCREMENTVALUE, "GeneratedValues" },
+ { DSID_AUTORETRIEVEVALUE, "GeneratedValues" },
+ { DSID_SQL92CHECK, "UseSQL92NamingConstraints" },
+ { DSID_APPEND_TABLE_ALIAS, "AppendTableAliasInSelect" },
+ { DSID_AS_BEFORE_CORRNAME, "UseKeywordAsBeforeAlias" },
+ { DSID_ENABLEOUTERJOIN, "UseBracketedOuterJoinSyntax" },
+ { DSID_IGNOREDRIVER_PRIV, "IgnoreDriverPrivileges" },
+ { DSID_PARAMETERNAMESUBST, "ParameterNameSubstitution" },
+ { DSID_SUPPRESSVERSIONCL, "DisplayVersionColumns" },
+ { DSID_CATALOG, "UseCatalogInSelect" },
+ { DSID_SCHEMA, "UseSchemaInSelect" },
+ { DSID_INDEXAPPENDIX, "UseIndexDirectionKeyword" },
+ { DSID_DOSLINEENDS, "UseDOSLineEnds" },
+ { DSID_BOOLEANCOMPARISON, "BooleanComparisonMode" },
+ { DSID_CHECK_REQUIRED_FIELDS, "FormsCheckRequiredFields" },
+ { DSID_IGNORECURRENCY, "IgnoreCurrency" },
+ { DSID_ESCAPE_DATETIME, "EscapeDateTime" },
+ { DSID_PRIMARY_KEY_SUPPORT, "PrimaryKeySupport" },
+ { DSID_RESPECTRESULTSETTYPE, "RespectDriverResultSetType" },
+ { DSID_MAX_ROW_SCAN, "MaxRowScan" },
+ };
+ }
+
+ static const FeatureSet& lcl_getFeatureSet( const OUString& _rURL )
+ {
+ typedef std::map< OUString, FeatureSet > FeatureSets;
+ static FeatureSets s_aFeatureSets = []()
+ {
+ FeatureSets tmp;
+ ::connectivity::DriversConfig aDriverConfig( ::comphelper::getProcessComponentContext() );
+ const uno::Sequence< OUString > aPatterns = aDriverConfig.getURLs();
+ for ( auto const & pattern : aPatterns )
+ {
+ FeatureSet aCurrentSet;
+ const ::comphelper::NamedValueCollection aCurrentFeatures( aDriverConfig.getFeatures( pattern ).getNamedValues() );
+
+ for ( const FeatureMapping& rFeatureMapping : s_aMappings )
+ {
+ if ( aCurrentFeatures.has( rFeatureMapping.pAsciiFeatureName ) )
+ aCurrentSet.put( rFeatureMapping.nItemID );
+ }
+
+ tmp[ pattern ] = aCurrentSet;
+ }
+ return tmp;
+ }();
+
+ OSL_ENSURE( s_aFeatureSets.find( _rURL ) != s_aFeatureSets.end(), "invalid URL/pattern!" );
+ return s_aFeatureSets[ _rURL ];
+ }
+
+ static AuthenticationMode getAuthenticationMode( const OUString& _sURL )
+ {
+ static std::map< OUString, FeatureSupport > s_aSupport = []()
+ {
+ std::map< OUString, FeatureSupport > tmp;
+ ::connectivity::DriversConfig aDriverConfig(::comphelper::getProcessComponentContext());
+ const uno::Sequence< OUString > aURLs = aDriverConfig.getURLs();
+ const OUString* pIter = aURLs.getConstArray();
+ const OUString* pEnd = pIter + aURLs.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ FeatureSupport aInit( AuthNone );
+ const ::comphelper::NamedValueCollection& aMetaData = aDriverConfig.getMetaData(*pIter);
+ if ( aMetaData.has("Authentication") )
+ {
+ OUString sAuth;
+ aMetaData.get("Authentication") >>= sAuth;
+ if ( sAuth == "UserPassword" )
+ aInit = FeatureSupport(AuthUserPwd);
+ else if ( sAuth == "Password" )
+ aInit = FeatureSupport(AuthPwd);
+ }
+ tmp.insert(std::make_pair(*pIter,aInit));
+ }
+ return tmp;
+ }();
+ OSL_ENSURE(s_aSupport.find(_sURL) != s_aSupport.end(),"Illegal URL!");
+ return s_aSupport[ _sURL ].eAuthentication;
+ }
+
+ // DataSourceMetaData
+ DataSourceMetaData::DataSourceMetaData( const OUString& _sURL )
+ :m_sURL( _sURL )
+ {
+ }
+
+ DataSourceMetaData::~DataSourceMetaData()
+ {
+ }
+
+ const FeatureSet& DataSourceMetaData::getFeatureSet() const
+ {
+ return lcl_getFeatureSet( m_sURL );
+ }
+
+ AuthenticationMode DataSourceMetaData::getAuthentication( const OUString& _sURL )
+ {
+ return getAuthenticationMode( _sURL );
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/imageprovider.cxx b/dbaccess/source/ui/misc/imageprovider.cxx
new file mode 100644
index 0000000000..388df30e27
--- /dev/null
+++ b/dbaccess/source/ui/misc/imageprovider.cxx
@@ -0,0 +1,192 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <imageprovider.hxx>
+#include <bitmaps.hlst>
+
+#include <com/sun/star/graphic/GraphicColorMode.hpp>
+#include <com/sun/star/sdb/application/XTableUIProvider.hpp>
+#include <com/sun/star/sdb/application/DatabaseObject.hpp>
+#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
+
+#include <comphelper/diagnose_ex.hxx>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::sdbc::XConnection;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::container::XNameAccess;
+ using ::com::sun::star::graphic::XGraphic;
+ using ::com::sun::star::sdb::application::XTableUIProvider;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::sdbcx::XViewsSupplier;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+
+ namespace GraphicColorMode = css::graphic::GraphicColorMode;
+ namespace DatabaseObject = css::sdb::application::DatabaseObject;
+
+ namespace
+ {
+ void lcl_getConnectionProvidedTableIcon_nothrow(
+ const css::uno::Reference< css::sdb::application::XTableUIProvider >& _xTableUI,
+ const OUString& _rName, Reference< XGraphic >& _out_rxGraphic )
+ {
+ try
+ {
+ if ( _xTableUI.is() )
+ _out_rxGraphic = _xTableUI->getTableIcon( _rName, GraphicColorMode::NORMAL );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ void lcl_getTableImageResourceID_nothrow(
+ const css::uno::Reference< css::container::XNameAccess >& _xViews,
+ const OUString& _rName,
+ OUString& _out_rResourceID)
+ {
+ _out_rResourceID = OUString();
+ try
+ {
+ bool bIsView = _xViews.is() && _xViews->hasByName( _rName );
+ if ( bIsView )
+ {
+ _out_rResourceID = VIEW_TREE_ICON;
+ }
+ else
+ {
+ _out_rResourceID = TABLE_TREE_ICON;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ }
+ // ImageProvider
+ ImageProvider::ImageProvider()
+ {
+ }
+
+ ImageProvider::ImageProvider( const Reference< XConnection >& _rxConnection )
+ : mxConnection(_rxConnection)
+ {
+ try
+ {
+ Reference< XViewsSupplier > xSuppViews( mxConnection, UNO_QUERY );
+ if ( xSuppViews.is() )
+ mxViews.set( xSuppViews->getViews(), UNO_SET_THROW );
+
+ mxTableUI.set( _rxConnection, UNO_QUERY );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ OUString ImageProvider::getImageId(const OUString& _rName, const sal_Int32 _nDatabaseObjectType)
+ {
+ if (_nDatabaseObjectType != DatabaseObject::TABLE)
+ {
+ // for types other than tables, the icon does not depend on the concrete object
+ return getDefaultImageResourceID( _nDatabaseObjectType );
+ }
+ else
+ {
+ // no -> determine by type
+ OUString sImageResourceID;
+ lcl_getTableImageResourceID_nothrow( mxViews, _rName, sImageResourceID );
+ return sImageResourceID;
+ }
+ }
+
+ Reference<XGraphic> ImageProvider::getXGraphic(const OUString& _rName, const sal_Int32 _nDatabaseObjectType)
+ {
+ Reference<XGraphic> xGraphic;
+ if (_nDatabaseObjectType == DatabaseObject::TABLE)
+ {
+ // check whether the connection can give us an icon
+ lcl_getConnectionProvidedTableIcon_nothrow( mxTableUI, _rName, xGraphic );
+ }
+ return xGraphic;
+ }
+
+ OUString ImageProvider::getDefaultImageResourceID( sal_Int32 _nDatabaseObjectType)
+ {
+ OUString sImageResourceID;
+ switch ( _nDatabaseObjectType )
+ {
+ case DatabaseObject::QUERY:
+ sImageResourceID = QUERY_TREE_ICON;
+ break;
+ case DatabaseObject::FORM:
+ sImageResourceID = FORM_TREE_ICON;
+ break;
+ case DatabaseObject::REPORT:
+ sImageResourceID = REPORT_TREE_ICON;
+ break;
+ case DatabaseObject::TABLE:
+ sImageResourceID = TABLE_TREE_ICON;
+ break;
+ default:
+ OSL_FAIL( "ImageProvider::getDefaultImage: invalid database object type!" );
+ break;
+ }
+ return sImageResourceID;
+ }
+
+ OUString ImageProvider::getFolderImageId( sal_Int32 _nDatabaseObjectType )
+ {
+ OUString sImageResourceID;
+ switch ( _nDatabaseObjectType )
+ {
+ case DatabaseObject::QUERY:
+ sImageResourceID = QUERYFOLDER_TREE_ICON;
+ break;
+ case DatabaseObject::FORM:
+ sImageResourceID = FORMFOLDER_TREE_ICON;
+ break;
+ case DatabaseObject::REPORT:
+ sImageResourceID = REPORTFOLDER_TREE_ICON;
+ break;
+ case DatabaseObject::TABLE:
+ sImageResourceID = TABLEFOLDER_TREE_ICON;
+ break;
+ default:
+ OSL_FAIL( "ImageProvider::getDefaultImage: invalid database object type!" );
+ break;
+ }
+
+ return sImageResourceID;
+ }
+
+ OUString ImageProvider::getDatabaseImage()
+ {
+ return DATABASE_TREE_ICON;
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/indexcollection.cxx b/dbaccess/source/ui/misc/indexcollection.cxx
new file mode 100644
index 0000000000..169512ce72
--- /dev/null
+++ b/dbaccess/source/ui/misc/indexcollection.cxx
@@ -0,0 +1,328 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <indexcollection.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <comphelper/extract.hxx>
+#include <com/sun/star/sdbcx/XDrop.hpp>
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::sdbcx;
+ using namespace ::com::sun::star::sdbc;
+
+ // OIndexCollection
+ OIndexCollection::OIndexCollection()
+ {
+ }
+
+ OIndexCollection::OIndexCollection(const OIndexCollection& _rSource)
+ {
+ *this = _rSource;
+ }
+
+ OIndexCollection& OIndexCollection::operator=(const OIndexCollection& _rSource)
+ {
+ detach();
+ m_xIndexes = _rSource.m_xIndexes;
+ m_aIndexes = _rSource.m_aIndexes;
+ return *this;
+ }
+
+ void OIndexCollection::attach(const Reference< XNameAccess >& _rxIndexes)
+ {
+ implConstructFrom(_rxIndexes);
+ }
+
+ void OIndexCollection::detach()
+ {
+ m_xIndexes.clear();
+ m_aIndexes.clear();
+ }
+
+ Indexes::const_iterator OIndexCollection::find(const OUString& _rName) const
+ {
+ // loop'n'compare
+ return std::find_if(m_aIndexes.cbegin(), m_aIndexes.cend(),
+ [&_rName](const OIndex& rIndex) { return rIndex.sName == _rName; });
+ }
+
+ Indexes::iterator OIndexCollection::find(const OUString& _rName)
+ {
+ // loop'n'compare
+ return std::find_if(m_aIndexes.begin(), m_aIndexes.end(),
+ [&_rName](const OIndex& rIndex) { return rIndex.sName == _rName; });
+ }
+
+ Indexes::const_iterator OIndexCollection::findOriginal(const OUString& _rName) const
+ {
+ // loop'n'compare
+ return std::find_if(m_aIndexes.cbegin(), m_aIndexes.cend(),
+ [&_rName](const OIndex& rIndex) { return rIndex.getOriginalName() == _rName; });
+ }
+
+ Indexes::iterator OIndexCollection::findOriginal(const OUString& _rName)
+ {
+ // loop'n'compare
+ return std::find_if(m_aIndexes.begin(), m_aIndexes.end(),
+ [&_rName](const OIndex& rIndex) { return rIndex.getOriginalName() == _rName; });
+ }
+
+ void OIndexCollection::commitNewIndex(const Indexes::iterator& _rPos)
+ {
+ OSL_ENSURE(_rPos->isNew(), "OIndexCollection::commitNewIndex: index must be new!");
+
+ try
+ {
+ Reference< XDataDescriptorFactory > xIndexFactory(m_xIndexes, UNO_QUERY);
+ Reference< XAppend > xAppendIndex(xIndexFactory, UNO_QUERY);
+ if (!xAppendIndex.is())
+ {
+ OSL_FAIL("OIndexCollection::commitNewIndex: missing an interface of the index container!");
+ return;
+ }
+
+ Reference< XPropertySet > xIndexDescriptor = xIndexFactory->createDataDescriptor();
+ Reference< XColumnsSupplier > xColsSupp(xIndexDescriptor, UNO_QUERY);
+ Reference< XNameAccess > xCols;
+ if (xColsSupp.is())
+ xCols = xColsSupp->getColumns();
+
+ Reference< XDataDescriptorFactory > xColumnFactory(xCols, UNO_QUERY);
+ Reference< XAppend > xAppendCols(xColumnFactory, UNO_QUERY);
+ if (!xAppendCols.is())
+ {
+ OSL_FAIL("OIndexCollection::commitNewIndex: invalid index descriptor returned!");
+ return;
+ }
+
+ // set the properties
+ static constexpr OUString s_sNamePropertyName = u"Name"_ustr;
+ // the index' own props
+ xIndexDescriptor->setPropertyValue("IsUnique", css::uno::Any(_rPos->bUnique));
+ xIndexDescriptor->setPropertyValue(s_sNamePropertyName, Any(_rPos->sName));
+
+ // the fields
+ for (auto const& field : _rPos->aFields)
+ {
+ OSL_ENSURE(!xCols->hasByName(field.sFieldName), "OIndexCollection::commitNewIndex: double column name (need to prevent this outside)!");
+
+ Reference< XPropertySet > xColDescriptor = xColumnFactory->createDataDescriptor();
+ OSL_ENSURE(xColDescriptor.is(), "OIndexCollection::commitNewIndex: invalid column descriptor!");
+ if (xColDescriptor.is())
+ {
+ xColDescriptor->setPropertyValue("IsAscending", css::uno::Any(field.bSortAscending));
+ xColDescriptor->setPropertyValue(s_sNamePropertyName, Any(field.sFieldName));
+ xAppendCols->appendByDescriptor(xColDescriptor);
+ }
+ }
+
+ xAppendIndex->appendByDescriptor(xIndexDescriptor);
+
+ _rPos->flagAsCommitted(GrantIndexAccess());
+ _rPos->clearModified();
+ }
+ catch(SQLException&)
+ { // allowed to pass
+ throw;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ bool OIndexCollection::dropNoRemove(const Indexes::iterator& _rPos)
+ {
+ try
+ {
+ OSL_ENSURE(m_xIndexes->hasByName(_rPos->getOriginalName()), "OIndexCollection::drop: invalid name!");
+
+ Reference< XDrop > xDropIndex(m_xIndexes, UNO_QUERY);
+ if (!xDropIndex.is())
+ {
+ OSL_FAIL("OIndexCollection::drop: no XDrop interface!");
+ return false;
+ }
+
+ xDropIndex->dropByName(_rPos->getOriginalName());
+ }
+ catch(SQLException&)
+ { // allowed to pass
+ throw;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ return false;
+ }
+
+ // adjust the OIndex structure
+ Indexes::iterator aDropped = findOriginal(_rPos->getOriginalName());
+ OSL_ENSURE(aDropped != m_aIndexes.end(), "OIndexCollection::drop: invalid original name, but successful commit?!");
+ aDropped->flagAsNew(GrantIndexAccess());
+
+ return true;
+ }
+
+ bool OIndexCollection::drop(const Indexes::iterator& _rPos)
+ {
+ OSL_ENSURE((_rPos >= m_aIndexes.begin()) && (_rPos < m_aIndexes.end()),
+ "OIndexCollection::drop: invalid position (fasten your seatbelt... this will crash)!");
+
+ if (!_rPos->isNew())
+ if (!dropNoRemove(_rPos))
+ return false;
+
+ // adjust the index array
+ m_aIndexes.erase(_rPos);
+ return true;
+ }
+
+ void OIndexCollection::implFillIndexInfo(OIndex& _rIndex)
+ {
+ // get the UNO descriptor for the index
+ Reference< XPropertySet > xIndex;
+ m_xIndexes->getByName(_rIndex.getOriginalName()) >>= xIndex;
+ if (!xIndex.is())
+ {
+ OSL_FAIL("OIndexCollection::implFillIndexInfo: got an invalid index object!");
+ }
+ else
+ implFillIndexInfo(_rIndex, xIndex);
+ }
+
+ void OIndexCollection::implFillIndexInfo(OIndex& _rIndex, const Reference< XPropertySet >& _rxDescriptor)
+ {
+ _rIndex.bPrimaryKey = ::cppu::any2bool(_rxDescriptor->getPropertyValue("IsPrimaryKeyIndex"));
+ _rIndex.bUnique = ::cppu::any2bool(_rxDescriptor->getPropertyValue("IsUnique"));
+ _rxDescriptor->getPropertyValue("Catalog") >>= _rIndex.sDescription;
+
+ // the columns
+ Reference< XColumnsSupplier > xSuppCols(_rxDescriptor, UNO_QUERY);
+ Reference< XNameAccess > xCols;
+ if (xSuppCols.is())
+ xCols = xSuppCols->getColumns();
+ OSL_ENSURE(xCols.is(), "OIndexCollection::implFillIndexInfo: the index does not have columns!");
+ if (!xCols.is())
+ return;
+
+ Sequence< OUString > aFieldNames = xCols->getElementNames();
+ _rIndex.aFields.resize(aFieldNames.getLength());
+
+ const OUString* pFieldNames = aFieldNames.getConstArray();
+ const OUString* pFieldNamesEnd = pFieldNames + aFieldNames.getLength();
+ IndexFields::iterator aCopyTo = _rIndex.aFields.begin();
+
+ Reference< XPropertySet > xIndexColumn;
+ for (;pFieldNames < pFieldNamesEnd; ++pFieldNames, ++aCopyTo)
+ {
+ // extract the column
+ xIndexColumn.clear();
+ xCols->getByName(*pFieldNames) >>= xIndexColumn;
+ if (!xIndexColumn.is())
+ {
+ OSL_FAIL("OIndexCollection::implFillIndexInfo: invalid index column!");
+ --aCopyTo;
+ continue;
+ }
+
+ // get the relevant properties
+ aCopyTo->sFieldName = *pFieldNames;
+ aCopyTo->bSortAscending = ::cppu::any2bool(xIndexColumn->getPropertyValue("IsAscending"));
+ }
+
+ _rIndex.aFields.resize(aCopyTo - _rIndex.aFields.begin());
+ // (just in case some fields were invalid ...)
+ }
+
+ void OIndexCollection::resetIndex(const Indexes::iterator& _rPos)
+ {
+ OSL_ENSURE(_rPos >= m_aIndexes.begin() && _rPos < m_aIndexes.end(),
+ "OIndexCollection::resetIndex: invalid position!");
+
+ try
+ {
+ _rPos->sName = _rPos->getOriginalName();
+ implFillIndexInfo(*_rPos);
+
+ _rPos->clearModified();
+ _rPos->flagAsCommitted(GrantIndexAccess());
+ }
+ catch(SQLException&)
+ { // allowed to pass
+ throw;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+ Indexes::iterator OIndexCollection::insert(const OUString& _rName)
+ {
+ OSL_ENSURE(end() == find(_rName), "OIndexCollection::insert: invalid new name!");
+ OIndex aNewIndex((OUString())); // the empty string indicates the index is a new one
+ aNewIndex.sName = _rName;
+ m_aIndexes.push_back(aNewIndex);
+ return m_aIndexes.end() - 1; // the last element is the new one ...
+ }
+
+ void OIndexCollection::implConstructFrom(const Reference< XNameAccess >& _rxIndexes)
+ {
+ detach();
+
+ m_xIndexes = _rxIndexes;
+ if (!m_xIndexes.is())
+ return;
+
+ // loop through all the indexes
+ Sequence< OUString > aNames = m_xIndexes->getElementNames();
+ const OUString* pNames = aNames.getConstArray();
+ const OUString* pEnd = pNames + aNames.getLength();
+ for (; pNames < pEnd; ++pNames)
+ {
+ // extract the index object
+ Reference< XPropertySet > xIndex;
+ m_xIndexes->getByName(*pNames) >>= xIndex;
+ if (!xIndex.is())
+ {
+ OSL_FAIL("OIndexCollection::implConstructFrom: got an invalid index object ... ignoring!");
+ continue;
+ }
+
+ // fill the OIndex structure
+ OIndex aCurrentIndex(*pNames);
+ implFillIndexInfo(aCurrentIndex);
+ m_aIndexes.push_back(aCurrentIndex);
+ }
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/linkeddocuments.cxx b/dbaccess/source/ui/misc/linkeddocuments.cxx
new file mode 100644
index 0000000000..dff938e376
--- /dev/null
+++ b/dbaccess/source/ui/misc/linkeddocuments.cxx
@@ -0,0 +1,350 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <core_resource.hxx>
+#include <linkeddocuments.hxx>
+#include <osl/diagnose.h>
+#include <comphelper/diagnose_ex.hxx>
+#include <unotools/confignode.hxx>
+#include <comphelper/classids.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/frame/XComponentLoader.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/ucb/XCommandProcessor.hpp>
+#include <com/sun/star/ucb/OpenCommandArgument.hpp>
+#include <com/sun/star/ucb/OpenMode.hpp>
+#include <com/sun/star/task/XJobExecutor.hpp>
+#include <comphelper/types.hxx>
+#include <strings.hrc>
+#include <strings.hxx>
+#include <svl/filenotation.hxx>
+#include <browserids.hxx>
+#include <com/sun/star/container/XHierarchicalNameContainer.hpp>
+#include <comphelper/mimeconfighelper.hxx>
+#include <utility>
+#include <vcl/weld.hxx>
+
+#include <cppuhelper/exc_hlp.hxx>
+#include <connectivity/dbtools.hxx>
+#include <com/sun/star/io/WrongFormatException.hpp>
+
+namespace dbaui
+{
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::container;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::frame;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::util;
+ using namespace ::com::sun::star::ucb;
+ using namespace ::com::sun::star::sdbc;
+ using namespace ::com::sun::star::sdb::application;
+ using namespace ::com::sun::star::task;
+ using namespace ::svt;
+
+ namespace
+ {
+ Sequence< sal_Int8 > lcl_GetSequenceClassID( sal_uInt32 n1, sal_uInt16 n2, sal_uInt16 n3,
+ sal_uInt8 b8, sal_uInt8 b9, sal_uInt8 b10, sal_uInt8 b11,
+ sal_uInt8 b12, sal_uInt8 b13, sal_uInt8 b14, sal_uInt8 b15 )
+ {
+ Sequence< sal_Int8 > aResult{ /* [ 0] */ static_cast<sal_Int8>(n1 >> 24),
+ /* [ 1] */ static_cast<sal_Int8>(( n1 << 8 ) >> 24),
+ /* [ 2] */ static_cast<sal_Int8>(( n1 << 16 ) >> 24),
+ /* [ 3] */ static_cast<sal_Int8>(( n1 << 24 ) >> 24),
+ /* [ 4] */ static_cast<sal_Int8>(n2 >> 8),
+ /* [ 5] */ static_cast<sal_Int8>(( n2 << 8 ) >> 8),
+ /* [ 6] */ static_cast<sal_Int8>(n3 >> 8),
+ /* [ 7] */ static_cast<sal_Int8>(( n3 << 8 ) >> 8),
+ /* [ 8] */ static_cast<sal_Int8>(b8),
+ /* [ 9] */ static_cast<sal_Int8>(b9),
+ /* [10] */ static_cast<sal_Int8>(b10),
+ /* [11] */ static_cast<sal_Int8>(b11),
+ /* [12] */ static_cast<sal_Int8>(b12),
+ /* [13] */ static_cast<sal_Int8>(b13),
+ /* [14] */ static_cast<sal_Int8>(b14),
+ /* [15] */ static_cast<sal_Int8>(b15) };
+ return aResult;
+ }
+ }
+
+ // OLinkedDocumentsAccess
+ OLinkedDocumentsAccess::OLinkedDocumentsAccess( weld::Window* pDialogParent, const Reference< XDatabaseDocumentUI >& i_rDocumentUI,
+ const Reference< XComponentContext >& _rxContext, const Reference< XNameAccess >& _rxContainer,
+ const Reference< XConnection>& _xConnection, OUString _sDataSourceName )
+ :m_xContext(_rxContext)
+ ,m_xDocumentContainer(_rxContainer)
+ ,m_xConnection(_xConnection)
+ ,m_xDocumentUI( i_rDocumentUI )
+ ,m_pDialogParent(pDialogParent)
+ ,m_sDataSourceName(std::move(_sDataSourceName))
+ {
+ OSL_ENSURE(m_xContext.is(), "OLinkedDocumentsAccess::OLinkedDocumentsAccess: invalid service factory!");
+ assert(m_pDialogParent && "OLinkedDocumentsAccess::OLinkedDocumentsAccess: really need a dialog parent!");
+ }
+ OLinkedDocumentsAccess::~OLinkedDocumentsAccess()
+ {
+ }
+ Reference< XComponent> OLinkedDocumentsAccess::impl_open( const OUString& _rLinkName, Reference< XComponent >& _xDefinition,
+ ElementOpenMode _eOpenMode, const ::comphelper::NamedValueCollection& _rAdditionalArgs )
+ {
+ Reference< XComponent> xRet;
+ OSL_ENSURE(m_xDocumentContainer.is(), "OLinkedDocumentsAccess::OLinkedDocumentsAccess: invalid document container!");
+ Reference< XComponentLoader > xComponentLoader(m_xDocumentContainer,UNO_QUERY);
+ if ( !xComponentLoader.is() )
+ return xRet;
+
+ weld::WaitObject aWaitCursor(m_pDialogParent);
+
+ ::comphelper::NamedValueCollection aArguments;
+ OUString sOpenMode;
+ switch ( _eOpenMode )
+ {
+ case ElementOpenMode::Normal:
+ sOpenMode = "open";
+ break;
+
+ case ElementOpenMode::Mail:
+ aArguments.put( "Hidden", true );
+ [[fallthrough]];
+
+ case ElementOpenMode::Design:
+ sOpenMode = "openDesign";
+ break;
+
+ default:
+ OSL_FAIL( "OLinkedDocumentsAccess::implOpen: invalid open mode!" );
+ break;
+ }
+ aArguments.put( "OpenMode", sOpenMode );
+
+ aArguments.put( PROPERTY_ACTIVE_CONNECTION, m_xConnection );
+
+ Reference<XHierarchicalNameContainer> xHier(m_xDocumentContainer,UNO_QUERY);
+ if ( xHier.is() && xHier->hasByHierarchicalName(_rLinkName) )
+ {
+ _xDefinition.set(xHier->getByHierarchicalName(_rLinkName),UNO_QUERY);
+ }
+
+ aArguments.merge( _rAdditionalArgs, true );
+
+ xRet = xComponentLoader->loadComponentFromURL( _rLinkName, OUString(), 0, aArguments.getPropertyValues() );
+
+ return xRet;
+ }
+ void OLinkedDocumentsAccess::impl_newWithPilot( const char* _pWizardService,
+ const sal_Int32 _nCommandType, const OUString& _rObjectName )
+ {
+ try
+ {
+ ::comphelper::NamedValueCollection aArgs;
+ aArgs.put( "DataSourceName", m_sDataSourceName );
+
+ if ( m_xConnection.is() )
+ aArgs.put( "ActiveConnection", m_xConnection );
+
+ if ( !_rObjectName.isEmpty() && ( _nCommandType != -1 ) )
+ {
+ aArgs.put( "CommandType", _nCommandType );
+ aArgs.put( "Command", _rObjectName );
+ }
+
+ aArgs.put( "DocumentUI", m_xDocumentUI );
+
+ Reference< XJobExecutor > xWizard;
+ {
+ weld::WaitObject aWaitCursor(m_pDialogParent);
+ xWizard.set( m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ OUString::createFromAscii( _pWizardService ),
+ aArgs.getWrappedPropertyValues(),
+ m_xContext
+ ), UNO_QUERY_THROW );
+ }
+
+ xWizard->trigger( "start" );
+ ::comphelper::disposeComponent( xWizard );
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+ void OLinkedDocumentsAccess::newFormWithPilot( const sal_Int32 _nCommandType,const OUString& _rObjectName )
+ {
+ impl_newWithPilot( "com.sun.star.wizards.form.CallFormWizard", _nCommandType, _rObjectName );
+ }
+
+ void OLinkedDocumentsAccess::newReportWithPilot( const sal_Int32 _nCommandType, const OUString& _rObjectName )
+ {
+ impl_newWithPilot( "com.sun.star.wizards.report.CallReportWizard", _nCommandType, _rObjectName );
+ }
+ void OLinkedDocumentsAccess::newTableWithPilot()
+ {
+ impl_newWithPilot( "com.sun.star.wizards.table.CallTableWizard", -1, OUString() );
+ }
+ void OLinkedDocumentsAccess::newQueryWithPilot()
+ {
+ impl_newWithPilot( "com.sun.star.wizards.query.CallQueryWizard", -1, OUString() );
+ }
+ Reference< XComponent > OLinkedDocumentsAccess::newDocument( sal_Int32 i_nActionID,
+ const ::comphelper::NamedValueCollection& i_rCreationArgs, Reference< XComponent >& o_rDefinition )
+ {
+ OSL_ENSURE(m_xDocumentContainer.is(), "OLinkedDocumentsAccess::newDocument: invalid document container!");
+ // determine the class ID to use for the new document
+ Sequence<sal_Int8> aClassId;
+ if ( !i_rCreationArgs.has( "ClassID" )
+ && !i_rCreationArgs.has( "MediaType" )
+ && !i_rCreationArgs.has( "DocumentServiceName" )
+ )
+ {
+ switch ( i_nActionID )
+ {
+ case ID_FORM_NEW_TEXT:
+ aClassId = lcl_GetSequenceClassID(SO3_SW_CLASSID);
+ OSL_ENSURE(aClassId == comphelper::MimeConfigurationHelper::GetSequenceClassID(SO3_SW_CLASSID),"Not equal");
+ break;
+
+ case ID_FORM_NEW_CALC:
+ aClassId = lcl_GetSequenceClassID(SO3_SC_CLASSID);
+ break;
+
+ case ID_FORM_NEW_IMPRESS:
+ aClassId = lcl_GetSequenceClassID(SO3_SIMPRESS_CLASSID);
+ break;
+
+ case ID_REPORT_NEW_TEXT:
+ aClassId = comphelper::MimeConfigurationHelper::GetSequenceClassID(SO3_RPT_CLASSID_90);
+ break;
+
+ default:
+ OSL_FAIL( "OLinkedDocumentsAccess::newDocument: please use newFormWithPilot!" );
+ return Reference< XComponent >();
+
+ }
+ }
+
+ // load the document as template
+ Reference< XComponent > xNewDocument;
+ try
+ { // get the desktop object
+
+ Reference<XMultiServiceFactory> xORB(m_xDocumentContainer,UNO_QUERY);
+ if ( xORB.is() )
+ {
+ ::comphelper::NamedValueCollection aCreationArgs( i_rCreationArgs );
+ if ( aClassId.hasElements() )
+ aCreationArgs.put( "ClassID", aClassId );
+ aCreationArgs.put( PROPERTY_ACTIVE_CONNECTION, m_xConnection );
+
+ // separate values which are real creation args from args relevant for opening the doc
+ ::comphelper::NamedValueCollection aCommandArgs;
+ if ( aCreationArgs.has( "Hidden" ) )
+ {
+ aCommandArgs.put( "Hidden", aCreationArgs.get( "Hidden" ) );
+ aCreationArgs.remove( "Hidden" );
+ }
+
+ Reference< XCommandProcessor > xContent( xORB->createInstanceWithArguments(
+ SERVICE_SDB_DOCUMENTDEFINITION,
+ aCreationArgs.getWrappedPropertyValues()
+ ),
+ UNO_QUERY_THROW
+ );
+ o_rDefinition.set( xContent, UNO_QUERY );
+
+ // put the OpenMode into the OpenArgs
+ OpenCommandArgument aOpenModeArg;
+ aOpenModeArg.Mode = OpenMode::DOCUMENT;
+ aCommandArgs.put( "OpenMode", aOpenModeArg );
+
+ Command aCommand;
+ aCommand.Name = "openDesign";
+ aCommand.Argument <<= aCommandArgs.getPropertyValues();
+ weld::WaitObject aWaitCursor(m_pDialogParent);
+ xNewDocument.set( xContent->execute( aCommand, xContent->createCommandIdentifier(), nullptr ), UNO_QUERY );
+ }
+ }
+ catch(const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+
+ return xNewDocument;
+ }
+
+ Reference< XComponent > OLinkedDocumentsAccess::open( const OUString& _rLinkName, Reference< XComponent >& _xDefinition,
+ ElementOpenMode _eOpenMode, const ::comphelper::NamedValueCollection& _rAdditionalArgs )
+ {
+ dbtools::SQLExceptionInfo aInfo;
+ Reference< XComponent > xRet;
+ try
+ {
+ xRet = impl_open( _rLinkName, _xDefinition, _eOpenMode, _rAdditionalArgs );
+ if ( !xRet.is() )
+ {
+ OUString sMessage = DBA_RES(STR_COULDNOTOPEN_LINKEDDOC);
+ sMessage = sMessage.replaceFirst("$file$",_rLinkName);
+
+ css::sdbc::SQLException aSQLException(sMessage, {}, {}, 0, {});
+ aInfo = dbtools::SQLExceptionInfo(aSQLException);
+ }
+ }
+ catch(const css::io::WrongFormatException &e)
+ {
+ css::sdbc::SQLException aSQLException(e.Message, e.Context, {}, 0, {});
+ aInfo = dbtools::SQLExceptionInfo(aSQLException);
+
+ // more like a hack, insert an empty message
+ OUString sText( DBA_RES( RID_STR_EXTENSION_NOT_PRESENT ) );
+ sText = sText.replaceFirst("$file$",_rLinkName);
+ aInfo.prepend(sText);
+
+ OUString sMessage = DBA_RES(STR_COULDNOTOPEN_LINKEDDOC);
+ sMessage = sMessage.replaceFirst("$file$",_rLinkName);
+ aInfo.prepend(sMessage);
+ }
+ catch(const Exception& e)
+ {
+ Any aAny = ::cppu::getCaughtException();
+ css::sdbc::SQLException a;
+ if ( !(aAny >>= a) || (a.ErrorCode != dbtools::ParameterInteractionCancelled) )
+ {
+ css::sdbc::SQLException aSQLException(e.Message, e.Context, {}, 0, {});
+ aInfo = dbtools::SQLExceptionInfo(aSQLException);
+
+ // more like a hack, insert an empty message
+ aInfo.prepend(" \n");
+
+ OUString sMessage = DBA_RES(STR_COULDNOTOPEN_LINKEDDOC);
+ sMessage = sMessage.replaceFirst("$file$",_rLinkName);
+ aInfo.prepend(sMessage);
+ }
+ }
+ if (aInfo.isValid())
+ {
+ showError(aInfo, m_pDialogParent->GetXWindow(), m_xContext);
+ }
+ return xRet;
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/propertystorage.cxx b/dbaccess/source/ui/misc/propertystorage.cxx
new file mode 100644
index 0000000000..c3c5049942
--- /dev/null
+++ b/dbaccess/source/ui/misc/propertystorage.cxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <propertystorage.hxx>
+
+#include <svl/itemset.hxx>
+#include <svl/stritem.hxx>
+#include <svl/eitem.hxx>
+
+#include <osl/diagnose.h>
+
+#include <cassert>
+#include <memory>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Any;
+
+ // helper
+ namespace
+ {
+ template < class ITEMTYPE, class UNOTYPE >
+ class ItemAdapter
+ {
+ public:
+ static bool trySet( SfxItemSet& _rSet, sal_uInt16 _nItemId, const Any& _rValue )
+ {
+ const SfxPoolItem& rItem( _rSet.Get( _nItemId ) );
+ const ITEMTYPE* pTypedItem = dynamic_cast< const ITEMTYPE* >( &rItem );
+ if ( !pTypedItem )
+ return false;
+
+ UNOTYPE aValue( pTypedItem->GetValue() );
+ OSL_VERIFY( _rValue >>= aValue );
+ // TODO: one could throw an IllegalArgumentException here - finally, this method
+ // is (to be) used from within an XPropertySet::setPropertyValue implementation,
+ // where this would be the appropriate reaction on wrong value types
+ ITEMTYPE* pCloneItem = dynamic_cast< ITEMTYPE* >( pTypedItem->Clone() );
+ if(!pCloneItem)
+ {
+ return false;
+ }
+ std::unique_ptr< ITEMTYPE > pClone( pCloneItem);
+ assert(pClone.get());
+ pClone->SetValue( aValue );
+ _rSet.Put( std::move(pClone) );
+ return true;
+ }
+
+ static bool tryGet( const SfxPoolItem& _rItem, Any& _out_rValue )
+ {
+ const ITEMTYPE* pTypedItem = dynamic_cast< const ITEMTYPE* >( &_rItem );
+ if ( !pTypedItem )
+ return false;
+
+ _out_rValue <<= UNOTYPE( pTypedItem->GetValue() );
+ return true;
+ }
+ };
+ }
+
+ // SetItemPropertyStorage
+ void SetItemPropertyStorage::getPropertyValue( Any& _out_rValue ) const
+ {
+ const SfxPoolItem& rItem( m_rItemSet.Get( m_nItemID ) );
+
+ // try some known item types
+ if ( ItemAdapter< SfxBoolItem, bool >::tryGet( rItem, _out_rValue )
+ || ItemAdapter< SfxStringItem, OUString >::tryGet( rItem, _out_rValue )
+ )
+ return;
+
+ OSL_FAIL( "SetItemPropertyStorage::getPropertyValue: unsupported item type!" );
+ }
+
+ void SetItemPropertyStorage::setPropertyValue( const Any& _rValue )
+ {
+ // try some known item types
+ if ( ItemAdapter< SfxBoolItem, bool >::trySet( m_rItemSet, m_nItemID, _rValue )
+ || ItemAdapter< SfxStringItem, OUString >::trySet( m_rItemSet, m_nItemID, _rValue )
+ )
+ return;
+
+ OSL_FAIL( "SetItemPropertyStorage::setPropertyValue: unsupported item type!" );
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/singledoccontroller.cxx b/dbaccess/source/ui/misc/singledoccontroller.cxx
new file mode 100644
index 0000000000..6f58676629
--- /dev/null
+++ b/dbaccess/source/ui/misc/singledoccontroller.cxx
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dbaccess/dbaundomanager.hxx>
+#include <dbaccess/dataview.hxx>
+#include <core_resource.hxx>
+#include <singledoccontroller.hxx>
+#include <browserids.hxx>
+#include <strings.hrc>
+
+#include <svl/undo.hxx>
+
+namespace dbaui
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::XComponentContext;
+ using ::com::sun::star::document::XUndoManager;
+ using ::com::sun::star::beans::PropertyValue;
+
+ // OSingleDocumentController
+ OSingleDocumentController::OSingleDocumentController( const Reference< XComponentContext >& _rxORB )
+ :OSingleDocumentController_Base( _rxORB )
+ ,m_pUndoManager(new UndoManager(*this, getMutex()))
+ {
+ }
+
+ OSingleDocumentController::~OSingleDocumentController()
+ {
+ }
+
+ void SAL_CALL OSingleDocumentController::disposing()
+ {
+ OSingleDocumentController_Base::disposing();
+ ClearUndoManager();
+ m_pUndoManager->disposing();
+ }
+
+ void OSingleDocumentController::ClearUndoManager()
+ {
+ GetUndoManager().Clear();
+ }
+
+ SfxUndoManager& OSingleDocumentController::GetUndoManager() const
+ {
+ return m_pUndoManager->GetSfxUndoManager();
+ }
+
+ void OSingleDocumentController::addUndoActionAndInvalidate(std::unique_ptr<SfxUndoAction> _pAction)
+ {
+ // add undo action
+ GetUndoManager().AddUndoAction( std::move(_pAction) );
+
+ // when we add an undo action the controller was modified
+ setModified( true );
+
+ // now inform me that or states changed
+ InvalidateFeature( ID_BROWSER_UNDO );
+ InvalidateFeature( ID_BROWSER_REDO );
+ }
+
+ Reference< XUndoManager > SAL_CALL OSingleDocumentController::getUndoManager( )
+ {
+ // see UndoManager::acquire
+ return m_pUndoManager.get();
+ }
+
+ FeatureState OSingleDocumentController::GetState(sal_uInt16 _nId) const
+ {
+ FeatureState aReturn;
+ switch ( _nId )
+ {
+ case ID_BROWSER_UNDO:
+ aReturn.bEnabled = isEditable() && GetUndoManager().GetUndoActionCount() != 0;
+ if ( aReturn.bEnabled )
+ {
+ OUString sUndo = DBA_RES(STR_UNDO_COLON) + " " +
+ GetUndoManager().GetUndoActionComment();
+ aReturn.sTitle = sUndo;
+ }
+ break;
+
+ case ID_BROWSER_REDO:
+ aReturn.bEnabled = isEditable() && GetUndoManager().GetRedoActionCount() != 0;
+ if ( aReturn.bEnabled )
+ {
+ OUString sRedo = DBA_RES(STR_REDO_COLON) + " " +
+ GetUndoManager().GetRedoActionComment();
+ aReturn.sTitle = sRedo;
+ }
+ break;
+
+ case SID_GETUNDOSTRINGS:
+ {
+ size_t nCount(GetUndoManager().GetUndoActionCount());
+ Sequence<OUString> aSeq(nCount);
+ auto aSeqRange = asNonConstRange(aSeq);
+ for (size_t n = 0; n < nCount; ++n)
+ aSeqRange[n] = GetUndoManager().GetUndoActionComment(n);
+ aReturn.aValue <<= aSeq;
+ aReturn.bEnabled = true;
+ break;
+ }
+
+ case SID_GETREDOSTRINGS:
+ {
+ size_t nCount(GetUndoManager().GetRedoActionCount());
+ Sequence<OUString> aSeq(nCount);
+ auto aSeqRange = asNonConstRange(aSeq);
+ for (size_t n = 0; n < nCount; ++n)
+ aSeqRange[n] = GetUndoManager().GetRedoActionComment(n);
+ aReturn.aValue <<= aSeq;
+ aReturn.bEnabled = true;
+ break;
+ }
+
+ default:
+ aReturn = OSingleDocumentController_Base::GetState(_nId);
+ }
+ return aReturn;
+ }
+ void OSingleDocumentController::Execute( sal_uInt16 _nId, const Sequence< PropertyValue >& _rArgs )
+ {
+ switch ( _nId )
+ {
+ case ID_BROWSER_UNDO:
+ case ID_BROWSER_REDO:
+ {
+ sal_Int16 nCount(1);
+ if (_rArgs.hasElements() && _rArgs[0].Name != "KeyModifier")
+ _rArgs[0].Value >>= nCount;
+
+ while (nCount--)
+ {
+ if (_nId == ID_BROWSER_UNDO)
+ GetUndoManager().Undo();
+ else
+ GetUndoManager().Redo();
+ }
+
+ InvalidateFeature( ID_BROWSER_UNDO );
+ InvalidateFeature( ID_BROWSER_REDO );
+ break;
+ }
+
+ default:
+ OSingleDocumentController_Base::Execute( _nId, _rArgs );
+ break;
+ }
+ InvalidateFeature(_nId);
+ }
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/misc/stringlistitem.cxx b/dbaccess/source/ui/misc/stringlistitem.cxx
new file mode 100644
index 0000000000..97e75fe6d4
--- /dev/null
+++ b/dbaccess/source/ui/misc/stringlistitem.cxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <stringlistitem.hxx>
+
+namespace dbaui
+{
+using namespace ::com::sun::star::uno;
+
+// OStringListItem
+OStringListItem::OStringListItem(sal_Int16 _nWhich, const Sequence<OUString>& _rList)
+ : SfxPoolItem(_nWhich)
+ , m_aList(_rList)
+{
+}
+
+OStringListItem::OStringListItem(const OStringListItem& _rSource)
+ : SfxPoolItem(_rSource)
+ , m_aList(_rSource.m_aList)
+{
+}
+
+bool OStringListItem::operator==(const SfxPoolItem& _rItem) const
+{
+ if (!SfxPoolItem::operator==(_rItem))
+ return false;
+ const OStringListItem* pCompare = static_cast<const OStringListItem*>(&_rItem);
+ if (pCompare->m_aList.getLength() != m_aList.getLength())
+ return false;
+
+ // compare all strings individually
+ for (sal_Int32 i = 0; i < m_aList.getLength(); ++i)
+ if (m_aList[i] != pCompare->m_aList[i])
+ return false;
+
+ return true;
+}
+
+OStringListItem* OStringListItem::Clone(SfxItemPool* /* _pPool */) const
+{
+ return new OStringListItem(*this);
+}
+
+} // namespace dbaui
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */