xref: /core/sc/source/ui/unoobj/filtuno.cxx (revision 1e97ca02)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
21 #include <tools/urlobj.hxx>
22 #include <vcl/svapp.hxx>
23 #include <unotools/ucbstreamhelper.hxx>
24 #include <connectivity/dbtools.hxx>
25 #include <osl/diagnose.h>
26 
27 #include <filtuno.hxx>
28 #include <miscuno.hxx>
29 #include <scdll.hxx>
30 #include <imoptdlg.hxx>
31 #include <asciiopt.hxx>
32 #include <docsh.hxx>
33 #include <globstr.hrc>
34 #include <scresid.hxx>
35 
36 #include <scabstdlg.hxx>
37 #include <i18nlangtag/lang.h>
38 
39 #include <optutil.hxx>
40 #include <com/sun/star/uno/Any.hxx>
41 #include <com/sun/star/uno/Sequence.hxx>
42 #include <comphelper/namedvaluecollection.hxx>
43 #include <comphelper/propertysequence.hxx>
44 #include <memory>
45 
46 using namespace com::sun::star;
47 using namespace com::sun::star::uno;
48 using namespace connectivity::dbase;
49 
50 #define SCFILTEROPTIONSOBJ_SERVICE      "com.sun.star.ui.dialogs.FilterOptionsDialog"
51 #define SCFILTEROPTIONSOBJ_IMPLNAME     "com.sun.star.comp.Calc.FilterOptionsDialog"
52 
53 SC_SIMPLE_SERVICE_INFO( ScFilterOptionsObj, SCFILTEROPTIONSOBJ_IMPLNAME, SCFILTEROPTIONSOBJ_SERVICE )
54 
55 #define SC_UNONAME_FILENAME         "URL"
56 #define SC_UNONAME_FILTERNAME       "FilterName"
57 #define SC_UNONAME_FILTEROPTIONS    "FilterOptions"
58 #define SC_UNONAME_INPUTSTREAM      "InputStream"
59 
60 #define DBF_CHAR_SET                "CharSet"
61 #define DBF_SEP_PATH_IMPORT         "Office.Calc/Dialogs/DBFImport"
62 #define DBF_SEP_PATH_EXPORT         "Office.Calc/Dialogs/DBFExport"
63 
64 namespace
65 {
66 
67     enum class charsetSource
68     {
69         charset_from_file,
70         charset_from_user_setting,
71         charset_default
72     };
73 
74     charsetSource load_CharSet(rtl_TextEncoding &nCharSet, bool bExport, SvStream* dbf_Stream)
75     {
76         if (dbf_Stream && dbfReadCharset(nCharSet, dbf_Stream))
77         {
78             return charsetSource::charset_from_file;
79         }
80 
81         Sequence<Any> aValues;
82         const Any *pProperties;
83         Sequence<OUString> aNames { DBF_CHAR_SET };
84         ScLinkConfigItem aItem( OUString::createFromAscii(
85                                     bExport?DBF_SEP_PATH_EXPORT:DBF_SEP_PATH_IMPORT ) );
86 
87         aValues = aItem.GetProperties( aNames );
88         pProperties = aValues.getConstArray();
89 
90         if( pProperties[0].hasValue() )
91         {
92             sal_Int32 nChar = 0;
93             pProperties[0] >>= nChar;
94             if( nChar >= 0)
95             {
96                 nCharSet = static_cast<rtl_TextEncoding>(nChar);
97                 return charsetSource::charset_from_user_setting;
98             }
99         }
100 
101         // Default choice
102         nCharSet = RTL_TEXTENCODING_IBM_850;
103         return charsetSource::charset_default;
104     }
105 
106     void save_CharSet( rtl_TextEncoding nCharSet, bool bExport )
107     {
108         Sequence<Any> aValues;
109         Any *pProperties;
110         Sequence<OUString> aNames { DBF_CHAR_SET };
111         ScLinkConfigItem aItem( OUString::createFromAscii(
112                                     bExport?DBF_SEP_PATH_EXPORT:DBF_SEP_PATH_IMPORT ) );
113 
114         aValues = aItem.GetProperties( aNames );
115         pProperties = aValues.getArray();
116         pProperties[0] <<= static_cast<sal_Int32>(nCharSet);
117 
118         aItem.PutProperties(aNames, aValues);
119     }
120 }
121 
122 ScFilterOptionsObj::ScFilterOptionsObj() :
123     bExport( false )
124 {
125 }
126 
127 ScFilterOptionsObj::~ScFilterOptionsObj()
128 {
129 }
130 
131 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
132 Calc_FilterOptionsDialog_get_implementation(css::uno::XComponentContext*, css::uno::Sequence<css::uno::Any> const &)
133 {
134     SolarMutexGuard aGuard;
135     ScDLL::Init();
136     return cppu::acquire(new ScFilterOptionsObj);
137 }
138 
139 // XPropertyAccess
140 
141 uno::Sequence<beans::PropertyValue> SAL_CALL ScFilterOptionsObj::getPropertyValues()
142 {
143     return comphelper::InitPropertySequence({
144         { SC_UNONAME_FILTEROPTIONS, Any(aFilterOptions) }
145     });
146 }
147 
148 void SAL_CALL ScFilterOptionsObj::setPropertyValues( const uno::Sequence<beans::PropertyValue>& aProps )
149 {
150     for (const beans::PropertyValue& rProp : aProps)
151     {
152         OUString aPropName(rProp.Name);
153 
154         if ( aPropName == SC_UNONAME_FILENAME )
155             rProp.Value >>= aFileName;
156         else if ( aPropName == SC_UNONAME_FILTERNAME )
157             rProp.Value >>= aFilterName;
158         else if ( aPropName == SC_UNONAME_FILTEROPTIONS )
159             rProp.Value >>= aFilterOptions;
160         else if ( aPropName == SC_UNONAME_INPUTSTREAM )
161             rProp.Value >>= xInputStream;
162     }
163 }
164 
165 // XExecutableDialog
166 
167 void SAL_CALL ScFilterOptionsObj::setTitle( const OUString& /* aTitle */ )
168 {
169     // not used
170 }
171 
172 sal_Int16 SAL_CALL ScFilterOptionsObj::execute()
173 {
174     sal_Int16 nRet = ui::dialogs::ExecutableDialogResults::CANCEL;
175 
176     OUString aFilterString( aFilterName );
177 
178     ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
179 
180     if ( !bExport && aFilterString == ScDocShell::GetAsciiFilterName() )
181     {
182         //  ascii import is special...
183 
184         INetURLObject aURL( aFileName );
185         OUString aPrivDatName(aURL.getName());
186         std::unique_ptr<SvStream> pInStream;
187         if ( xInputStream.is() )
188             pInStream = utl::UcbStreamHelper::CreateStream( xInputStream );
189 
190         ScopedVclPtr<AbstractScImportAsciiDlg> pDlg(pFact->CreateScImportAsciiDlg(Application::GetFrameWeld(xDialogParent), aPrivDatName,
191                                                                                   pInStream.get(), SC_IMPORTFILE));
192         if ( pDlg->Execute() == RET_OK )
193         {
194             ScAsciiOptions aOptions;
195             pDlg->GetOptions( aOptions );
196             pDlg->SaveParameters();
197             aFilterOptions = aOptions.WriteToString();
198             nRet = ui::dialogs::ExecutableDialogResults::OK;
199         }
200     }
201     else if ( aFilterString == ScDocShell::GetWebQueryFilterName() || aFilterString == ScDocShell::GetHtmlFilterName() )
202     {
203         if (bExport)
204             nRet = ui::dialogs::ExecutableDialogResults::OK;    // export HTML without dialog
205         else
206         {
207             // HTML import.
208             ScopedVclPtr<AbstractScTextImportOptionsDlg> pDlg(
209                 pFact->CreateScTextImportOptionsDlg(Application::GetFrameWeld(xDialogParent)));
210 
211             if (pDlg->Execute() == RET_OK)
212             {
213                 LanguageType eLang = pDlg->GetLanguageType();
214                 OUStringBuffer aBuf;
215 
216                 aBuf.append(OUString::number(static_cast<sal_uInt16>(eLang)));
217                 aBuf.append(' ');
218                 aBuf.append(pDlg->IsDateConversionSet() ? u'1' : u'0');
219                 aFilterOptions = aBuf.makeStringAndClear();
220                 nRet = ui::dialogs::ExecutableDialogResults::OK;
221             }
222         }
223     }
224     else
225     {
226         bool bDBEnc     = false;
227         bool bAscii     = false;
228         bool skipDialog = false;
229 
230         sal_Unicode const cStrDel = '"';
231         sal_Unicode cAsciiDel = ';';
232         rtl_TextEncoding eEncoding = RTL_TEXTENCODING_DONTKNOW;
233 
234         OUString aTitle;
235 
236         if ( aFilterString == ScDocShell::GetAsciiFilterName() )
237         {
238             //  ascii export (import is handled above)
239 
240             INetURLObject aURL( aFileName );
241             OUString aExt(aURL.getExtension());
242             if (aExt.equalsIgnoreAsciiCase("CSV"))
243                 cAsciiDel = ',';
244             else
245                 cAsciiDel = '\t';
246 
247             aTitle = ScResId( STR_EXPORT_ASCII );
248             bAscii = true;
249         }
250         else if ( aFilterString == ScDocShell::GetLotusFilterName() )
251         {
252             //  lotus is only imported
253             OSL_ENSURE( !bExport, "Filter Options for Lotus Export is not implemented" );
254 
255             aTitle = ScResId( STR_IMPORT_LOTUS );
256             eEncoding = RTL_TEXTENCODING_IBM_437;
257         }
258         else if ( aFilterString == ScDocShell::GetDBaseFilterName() )
259         {
260             if ( bExport )
261             {
262                 //  dBase export
263                 aTitle = ScResId( STR_EXPORT_DBF );
264             }
265             else
266             {
267                 //  dBase import
268                 aTitle = ScResId( STR_IMPORT_DBF );
269             }
270 
271             std::unique_ptr<SvStream> pInStream;
272             if ( xInputStream.is() )
273                 pInStream = utl::UcbStreamHelper::CreateStream( xInputStream );
274             switch(load_CharSet( eEncoding, bExport, pInStream.get()))
275             {
276                 case charsetSource::charset_from_file:
277                   skipDialog = true;
278                   break;
279                 case charsetSource::charset_from_user_setting:
280                 case charsetSource::charset_default:
281                    break;
282             }
283             bDBEnc = true;
284             // pInStream goes out of scope, the stream is automatically closed
285         }
286         else if ( aFilterString == ScDocShell::GetDifFilterName() )
287         {
288             if ( bExport )
289             {
290                 //  DIF export
291                 aTitle = ScResId( STR_EXPORT_DIF );
292             }
293             else
294             {
295                 //  DIF import
296                 aTitle = ScResId( STR_IMPORT_DIF );
297             }
298             // common for DIF import/export
299             eEncoding = RTL_TEXTENCODING_MS_1252;
300         }
301 
302         ScImportOptions aOptions( cAsciiDel, cStrDel, eEncoding);
303         if(skipDialog)
304         {
305             // TODO: check we are not missing some of the stuff that ScImportOptionsDlg::GetImportOptions
306             // (file sc/source/ui/dbgui/scuiimoptdlg.cxx) does
307             // that is, if the dialog sets options that are not selected by the user (!)
308             // then we are missing them here.
309             // Then we may need to rip them out of the dialog.
310             // Or we actually change the dialog to not display if skipDialog==true
311             // in that case, add an argument skipDialog to CreateScImportOptionsDlg
312             nRet = ui::dialogs::ExecutableDialogResults::OK;
313         }
314         else
315         {
316             ScopedVclPtr<AbstractScImportOptionsDlg> pDlg(pFact->CreateScImportOptionsDlg(Application::GetFrameWeld(xDialogParent),
317                                                                             bAscii, &aOptions, &aTitle,
318                                                                             bDBEnc, !bExport));
319             if ( pDlg->Execute() == RET_OK )
320             {
321                 pDlg->SaveImportOptions();
322                 pDlg->GetImportOptions( aOptions );
323                 save_CharSet( aOptions.eCharSet, bExport );
324                 nRet = ui::dialogs::ExecutableDialogResults::OK;
325             }
326         }
327         if (nRet == ui::dialogs::ExecutableDialogResults::OK)
328         {
329             if ( bAscii )
330                 aFilterOptions = aOptions.BuildString();
331             else
332                 aFilterOptions = aOptions.aStrFont;
333         }
334     }
335 
336     xInputStream.clear();   // don't hold the stream longer than necessary
337 
338     return nRet;
339 }
340 
341 // XImporter
342 
343 void SAL_CALL ScFilterOptionsObj::setTargetDocument( const uno::Reference<lang::XComponent>& /* xDoc */ )
344 {
345     bExport = false;
346 }
347 
348 // XExporter
349 
350 void SAL_CALL ScFilterOptionsObj::setSourceDocument( const uno::Reference<lang::XComponent>& /* xDoc */ )
351 {
352     bExport = true;
353 }
354 
355 // XInitialization
356 
357 void SAL_CALL ScFilterOptionsObj::initialize(const uno::Sequence<uno::Any>& rArguments)
358 {
359     ::comphelper::NamedValueCollection aProperties(rArguments);
360     if (aProperties.has("ParentWindow"))
361         aProperties.get("ParentWindow") >>= xDialogParent;
362 }
363 
364 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
365