/* -*- 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 <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
#include <tools/urlobj.hxx>
#include <vcl/svapp.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <connectivity/dbtools.hxx>
#include <osl/diagnose.h>
#include <filtuno.hxx>
#include <miscuno.hxx>
#include <scdll.hxx>
#include <imoptdlg.hxx>
#include <asciiopt.hxx>
#include <docsh.hxx>
#include <globstr.hrc>
#include <scresid.hxx>
#include <scabstdlg.hxx>
#include <i18nlangtag/lang.h>
#include <optutil.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Sequence.hxx>
#include <comphelper/namedvaluecollection.hxx>
#include <comphelper/propertysequence.hxx>
#include <memory>
using namespace com::sun::star;
using namespace com::sun::star::uno;
using namespace connectivity::dbase;
constexpr OUString SCFILTEROPTIONSOBJ_SERVICE = u"com.sun.star.ui.dialogs.FilterOptionsDialog"_ustr;
constexpr OUStringLiteral SCFILTEROPTIONSOBJ_IMPLNAME = u"com.sun.star.comp.Calc.FilterOptionsDialog";
SC_SIMPLE_SERVICE_INFO( ScFilterOptionsObj, SCFILTEROPTIONSOBJ_IMPLNAME, SCFILTEROPTIONSOBJ_SERVICE )
constexpr OUStringLiteral SC_UNONAME_FILENAME = u"URL";
constexpr OUStringLiteral SC_UNONAME_FILTERNAME = u"FilterName";
constexpr OUString SC_UNONAME_FILTEROPTIONS = u"FilterOptions"_ustr;
constexpr OUStringLiteral SC_UNONAME_INPUTSTREAM = u"InputStream";
constexpr OUString DBF_CHAR_SET = u"CharSet"_ustr;
constexpr OUString DBF_SEP_PATH_IMPORT = u"Office.Calc/Dialogs/DBFImport"_ustr;
constexpr OUString DBF_SEP_PATH_EXPORT = u"Office.Calc/Dialogs/DBFExport"_ustr;
namespace
{
enum class charsetSource
{
charset_from_file,
charset_from_user_setting,
charset_default
};
charsetSource load_CharSet(rtl_TextEncoding &nCharSet, bool bExport, SvStream* dbf_Stream)
{
if (dbf_Stream && dbfReadCharset(nCharSet, dbf_Stream))
{
return charsetSource::charset_from_file;
}
Sequence<Any> aValues;
const Any *pProperties;
Sequence<OUString> aNames { DBF_CHAR_SET };
ScLinkConfigItem aItem( bExport ? DBF_SEP_PATH_EXPORT : DBF_SEP_PATH_IMPORT );
aValues = aItem.GetProperties( aNames );
pProperties = aValues.getConstArray();
if( pProperties[0].hasValue() )
{
sal_Int32 nChar = 0;
pProperties[0] >>= nChar;
if( nChar >= 0)
{
nCharSet = static_cast<rtl_TextEncoding>(nChar);
return charsetSource::charset_from_user_setting;
}
}
// Default choice
nCharSet = RTL_TEXTENCODING_IBM_850;
return charsetSource::charset_default;
}
void save_CharSet( rtl_TextEncoding nCharSet, bool bExport )
{
Sequence<Any> aValues;
Any *pProperties;
Sequence<OUString> aNames { DBF_CHAR_SET };
ScLinkConfigItem aItem( bExport ? DBF_SEP_PATH_EXPORT : DBF_SEP_PATH_IMPORT );
aValues = aItem.GetProperties( aNames );
pProperties = aValues.getArray();
pProperties[0] <<= static_cast<sal_Int32>(nCharSet);
aItem.PutProperties(aNames, aValues);
}
}
ScFilterOptionsObj::ScFilterOptionsObj() :
bExport( false )
{
}
ScFilterOptionsObj::~ScFilterOptionsObj()
{
}
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
Calc_FilterOptionsDialog_get_implementation(css::uno::XComponentContext*, css::uno::Sequence<css::uno::Any> const &)
{
SolarMutexGuard aGuard;
ScDLL::Init();
return cppu::acquire(new ScFilterOptionsObj);
}
// XPropertyAccess
uno::Sequence<beans::PropertyValue> SAL_CALL ScFilterOptionsObj::getPropertyValues()
{
return comphelper::InitPropertySequence({
{ SC_UNONAME_FILTEROPTIONS, Any(aFilterOptions) }
});
}
void SAL_CALL ScFilterOptionsObj::setPropertyValues( const uno::Sequence<beans::PropertyValue>& aProps )
{
for (const beans::PropertyValue& rProp : aProps)
{
OUString aPropName(rProp.Name);
if ( aPropName == SC_UNONAME_FILENAME )
rProp.Value >>= aFileName;
else if ( aPropName == SC_UNONAME_FILTERNAME )
rProp.Value >>= aFilterName;
else if ( aPropName == SC_UNONAME_FILTEROPTIONS )
rProp.Value >>= aFilterOptions;
else if ( aPropName == SC_UNONAME_INPUTSTREAM )
rProp.Value >>= xInputStream;
}
}
// XExecutableDialog
void SAL_CALL ScFilterOptionsObj::setTitle( const OUString& /* aTitle */ )
{
// not used
}
sal_Int16 SAL_CALL ScFilterOptionsObj::execute()
{
sal_Int16 nRet = ui::dialogs::ExecutableDialogResults::CANCEL;
OUString aFilterString( aFilterName );
ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
if ( !bExport && aFilterString == ScDocShell::GetAsciiFilterName() )
{
// ascii import is special...
INetURLObject aURL( aFileName );
// tdf#132421 - don't URL encode filename for the import ASCII dialog title
OUString aPrivDatName(aURL.GetLastName(INetURLObject::DecodeMechanism::Unambiguous));
std::unique_ptr<SvStream> pInStream;
if ( xInputStream.is() )
pInStream = utl::UcbStreamHelper::CreateStream( xInputStream );
ScopedVclPtr<AbstractScImportAsciiDlg> pDlg(pFact->CreateScImportAsciiDlg(Application::GetFrameWeld(xDialogParent), aPrivDatName,
pInStream.get(), SC_IMPORTFILE));
if ( pDlg->Execute() == RET_OK )
{
ScAsciiOptions aOptions;
pDlg->GetOptions( aOptions );
pDlg->SaveParameters();
aFilterOptions = aOptions.WriteToString();
nRet = ui::dialogs::ExecutableDialogResults::OK;
}
}
else if ( aFilterString == ScDocShell::GetWebQueryFilterName() || aFilterString == ScDocShell::GetHtmlFilterName() )
{
if (bExport)
nRet = ui::dialogs::ExecutableDialogResults::OK; // export HTML without dialog
else
{
// HTML import.
ScopedVclPtr<AbstractScTextImportOptionsDlg> pDlg(
pFact->CreateScTextImportOptionsDlg(Application::GetFrameWeld(xDialogParent)));
if (pDlg->Execute() == RET_OK)
{
LanguageType eLang = pDlg->GetLanguageType();
OUStringBuffer aBuf;
aBuf.append(static_cast<sal_Int32>(static_cast<sal_uInt16>(eLang)));
aBuf.append(' ');
aBuf.append(pDlg->IsDateConversionSet() ? u'1' : u'0');
aBuf.append(' ');
aBuf.append(pDlg->IsScientificConversionSet() ? u'1' : u'0');
aFilterOptions = aBuf.makeStringAndClear();
nRet = ui::dialogs::ExecutableDialogResults::OK;
}
}
}
else
{
bool bDBEnc = false;
bool bAscii = false;
bool skipDialog = false;
sal_Unicode const cStrDel = '"';
sal_Unicode cAsciiDel = ';';
rtl_TextEncoding eEncoding = RTL_TEXTENCODING_DONTKNOW;
OUString aTitle;
bool bIncludeBOM = false;
if ( aFilterString == ScDocShell::GetAsciiFilterName() )
{
// ascii export (import is handled above)
INetURLObject aURL( aFileName );
OUString aExt(aURL.getExtension());
if (aExt.equalsIgnoreAsciiCase("CSV"))
cAsciiDel = ',';
else
cAsciiDel = '\t';
aTitle = ScResId( STR_EXPORT_ASCII );
bAscii = true;
ScAsciiOptions aOptions;
aOptions.ReadFromString(aFilterOptions);
bIncludeBOM = aOptions.GetIncludeBOM();
}
else if ( aFilterString == ScDocShell::GetLotusFilterName() )
{
// lotus is only imported
OSL_ENSURE( !bExport, "Filter Options for Lotus Export is not implemented" );
aTitle = ScResId( STR_IMPORT_LOTUS );
eEncoding = RTL_TEXTENCODING_IBM_437;
}
else if ( aFilterString == ScDocShell::GetDBaseFilterName() )
{
if ( bExport )
{
// dBase export
aTitle = ScResId( STR_EXPORT_DBF );
}
else
{
// dBase import
aTitle = ScResId( STR_IMPORT_DBF );
}
std::unique_ptr<SvStream> pInStream;
if ( xInputStream.is() )
pInStream = utl::UcbStreamHelper::CreateStream( xInputStream );
switch(load_CharSet( eEncoding, bExport, pInStream.get()))
{
case charsetSource::charset_from_file:
skipDialog = true;
break;
case charsetSource::charset_from_user_setting:
case charsetSource::charset_default:
break;
}
bDBEnc = true;
// pInStream goes out of scope, the stream is automatically closed
}
else if ( aFilterString == ScDocShell::GetDifFilterName() )
{
if ( bExport )
{
// DIF export
aTitle = ScResId( STR_EXPORT_DIF );
}
else
{
// DIF import
aTitle = ScResId( STR_IMPORT_DIF );
}
// common for DIF import/export
eEncoding = RTL_TEXTENCODING_MS_1252;
}
ScImportOptions aOptions( cAsciiDel, cStrDel, eEncoding);
aOptions.bIncludeBOM = bIncludeBOM;
if(skipDialog)
{
// TODO: check we are not missing some of the stuff that ScImportOptionsDlg::GetImportOptions
// (file sc/source/ui/dbgui/scuiimoptdlg.cxx) does
// that is, if the dialog sets options that are not selected by the user (!)
// then we are missing them here.
// Then we may need to rip them out of the dialog.
// Or we actually change the dialog to not display if skipDialog==true
// in that case, add an argument skipDialog to CreateScImportOptionsDlg
nRet = ui::dialogs::ExecutableDialogResults::OK;
}
else
{
ScopedVclPtr<AbstractScImportOptionsDlg> pDlg(pFact->CreateScImportOptionsDlg(Application::GetFrameWeld(xDialogParent),
bAscii, &aOptions, &aTitle,
bDBEnc, !bExport));
if ( pDlg->Execute() == RET_OK )
{
pDlg->SaveImportOptions();
pDlg->GetImportOptions( aOptions );
save_CharSet( aOptions.eCharSet, bExport );
nRet = ui::dialogs::ExecutableDialogResults::OK;
}
}
if (nRet == ui::dialogs::ExecutableDialogResults::OK)
{
if ( bAscii )
aFilterOptions = aOptions.BuildString();
else
aFilterOptions = aOptions.aStrFont;
}
}
xInputStream.clear(); // don't hold the stream longer than necessary
return nRet;
}
// XImporter
void SAL_CALL ScFilterOptionsObj::setTargetDocument( const uno::Reference<lang::XComponent>& /* xDoc */ )
{
bExport = false;
}
// XExporter
void SAL_CALL ScFilterOptionsObj::setSourceDocument( const uno::Reference<lang::XComponent>& /* xDoc */ )
{
bExport = true;
}
// XInitialization
void SAL_CALL ScFilterOptionsObj::initialize(const uno::Sequence<uno::Any>& rArguments)
{
::comphelper::NamedValueCollection aProperties(rArguments);
if (aProperties.has(u"ParentWindow"_ustr))
aProperties.get(u"ParentWindow"_ustr) >>= xDialogParent;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.