LibreOffice Module filter (master) 1
xmlfiltersettingsdialog.cxx
Go to the documentation of this file.
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/beans/XPropertySet.hpp>
21#include <com/sun/star/util/XFlushable.hpp>
22#include <com/sun/star/uno/XComponentContext.hpp>
23
24#include <com/sun/star/beans/PropertyValue.hpp>
25
26#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
27
29#include <o3tl/string_view.hxx>
31#include <tools/urlobj.hxx>
34#include <osl/file.hxx>
35#include <o3tl/enumrange.hxx>
36#include <vcl/svapp.hxx>
37#include <vcl/weld.hxx>
39#include <tools/stream.hxx>
40
41#include <rtl/uri.hxx>
42
43#include <algorithm>
44#include <memory>
45
46#include <strings.hrc>
50#include "xmlfilterjar.hxx"
51#include <strings.hxx>
52
53using namespace osl;
54using namespace com::sun::star::lang;
55using namespace com::sun::star::uno;
56using namespace com::sun::star::io;
57using namespace com::sun::star::container;
58using namespace com::sun::star::beans;
59using namespace com::sun::star::util;
60
61using ::rtl::Uri;
62
64 const css::uno::Reference<css::uno::XComponentContext>& rxContext)
65 : GenericDialogController(pParent, "filter/ui/xmlfiltersettings.ui", "XMLFilterSettingsDialog")
66 , mxContext( rxContext )
67 , m_sTemplatePath("$(user)/template/")
68 , m_sDocTypePrefix("doctype:")
69 , m_xPBNew(m_xBuilder->weld_button("new"))
70 , m_xPBEdit(m_xBuilder->weld_button("edit"))
71 , m_xPBTest(m_xBuilder->weld_button("test"))
72 , m_xPBDelete(m_xBuilder->weld_button("delete"))
73 , m_xPBSave(m_xBuilder->weld_button("save"))
74 , m_xPBOpen(m_xBuilder->weld_button("open"))
75 , m_xPBClose(m_xBuilder->weld_button("close"))
76 , m_xFilterListBox(m_xBuilder->weld_tree_view("filterlist"))
77{
78 m_xFilterListBox->set_selection_mode(SelectionMode::Multiple);
79
80 m_xFilterListBox->set_size_request(m_xFilterListBox->get_approximate_digit_width() * 65,
81 m_xFilterListBox->get_height_rows(12));
82
83 m_xFilterListBox->connect_changed( LINK( this, XMLFilterSettingsDialog, SelectionChangedHdl_Impl ) );
84 m_xFilterListBox->connect_row_activated( LINK( this, XMLFilterSettingsDialog, DoubleClickHdl_Impl ) );
85 m_xFilterListBox->set_accessible_name(FilterResId(STR_XML_FILTER_LISTBOX));
86
87 m_xPBNew->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
88 m_xPBEdit->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
89 m_xPBTest->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
90 m_xPBDelete->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
91 m_xPBSave->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
92 m_xPBOpen->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
93 m_xPBClose->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
94
95 try
96 {
97 mxFilterContainer.set( rxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", rxContext ), UNO_QUERY );
98 mxTypeDetection.set( rxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.TypeDetection", rxContext ), UNO_QUERY );
99 mxExtendedTypeDetection.set( rxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.ExtendedTypeDetectionFactory", rxContext ), UNO_QUERY );
100
101 SvtPathOptions aOptions;
103 }
104 catch(const Exception&)
105 {
106 TOOLS_WARN_EXCEPTION("filter.xslt", "");
107 }
108}
109
111{
112}
113
114IMPL_LINK(XMLFilterSettingsDialog, ClickHdl_Impl, weld::Button&, rButton, void)
115{
116 // tdf#122171 block closing libreoffice until the following dialog is dismissed
117 incBusy();
118
119 if (m_xPBNew.get() == &rButton)
120 {
121 onNew();
122 }
123 else if (m_xPBEdit.get() == &rButton)
124 {
125 onEdit();
126 }
127 else if (m_xPBTest.get() == &rButton)
128 {
129 onTest();
130 }
131 else if (m_xPBDelete.get() == &rButton)
132 {
133 onDelete();
134 }
135 else if (m_xPBSave.get() == &rButton)
136 {
137 onSave();
138 }
139 else if (m_xPBOpen.get() == &rButton)
140 {
141 onOpen();
142 }
143
144 decBusy();
145
146 if (m_xPBClose.get() == &rButton)
147 m_xDialog->response(RET_CLOSE);
148}
149
151{
152 updateStates();
153}
154
156{
157 onEdit();
158 return true;
159}
160
162{
163 m_xFilterListBox->grab_focus();
165 m_xFilterListBox->clear();
167 updateStates();
168}
169
171{
172 std::vector<int> aRows = m_xFilterListBox->get_selected_rows();
173
174 bool bHasSelection = !aRows.empty();
175
176 bool bMultiSelection = aRows.size() > 1;
177 bool bIsReadonly = false;
178 bool bIsDefault = false;
179 if (bHasSelection)
180 {
181 filter_info_impl* pInfo = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_id(aRows[0]));
182 bIsReadonly = pInfo->mbReadonly;
183
185 {
186 OUString sDefault = maModuleOpt.GetFactoryDefaultFilter(nFact);
187 if( sDefault == pInfo->maFilterName )
188 {
189 bIsDefault = true;
190 break;
191 }
192 }
193 }
194 m_xPBEdit->set_sensitive( bHasSelection && !bMultiSelection && !bIsReadonly);
195 m_xPBTest->set_sensitive( bHasSelection && !bMultiSelection );
196 m_xPBDelete->set_sensitive( bHasSelection && !bMultiSelection && !bIsReadonly && !bIsDefault);
197 m_xPBSave->set_sensitive( bHasSelection );
198}
199
202{
203 filter_info_impl aTempInfo;
204
205 // create a unique filter name
206 aTempInfo.maFilterName = createUniqueFilterName(FilterResId(STR_DEFAULT_FILTER_NAME));
207
208 // init default extension
210
211 // set default ui name
212 aTempInfo.maInterfaceName = createUniqueInterfaceName(FilterResId(STR_DEFAULT_UI_NAME));
213
214 // set default application
215 aTempInfo.maDocumentService = "com.sun.star.text.TextDocument";
216
217 // execute XML Filter Dialog
218 XMLFilterTabDialog aDlg(m_xDialog.get(), mxContext, &aTempInfo);
219 if (aDlg.run() == RET_OK)
220 {
221 // insert the new filter
223 }
224}
225
228{
229 // get selected filter info
230 filter_info_impl* pOldInfo = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_selected_id());
231 if (!pOldInfo)
232 return;
233
234 // execute XML Filter Dialog
235 XMLFilterTabDialog aDlg(m_xDialog.get(), mxContext, pOldInfo);
236 if (aDlg.run() == RET_OK)
237 {
238 filter_info_impl* pNewInfo = aDlg.getNewFilterInfo();
239
240 if( !(*pOldInfo == *pNewInfo) )
241 {
242 // change filter
243 insertOrEdit( pNewInfo, pOldInfo );
244 }
245 }
246}
247
250static Sequence< OUString > createExtensionsSequence( const OUString& rExtensions )
251{
252 // first count how many extensions we have inside the string
253 int nExtensions = 0;
254
255 int nLength = rExtensions.getLength();
256 if( nLength )
257 {
258 // a non empty string has at least one extension
259 nExtensions++;
260
261 // now count the delimiters ';'
262 const sal_Unicode * pString = rExtensions.getStr();
263 int i;
264 for( i = 0; i < nLength; i++, pString++ )
265 {
266 if( *pString == ';' )
267 nExtensions++;
268 }
269 }
270
271 Sequence< OUString > aExtensions( nExtensions );
272 auto aExtensionsRange = asNonConstRange(aExtensions);
273
274 // extract the extensions from the source string and fill the sequence
275
276 int nLastIndex = 0;
277 int nCurrentIndex = 0;
278 int i;
279
280 for( i = 0; i < nExtensions; i++ )
281 {
282 nLastIndex = rExtensions.indexOf( ';', nLastIndex );
283
284 if( nLastIndex == -1 )
285 {
286 aExtensionsRange[i] = rExtensions.copy( nCurrentIndex );
287 break;
288 }
289 else
290 {
291 aExtensionsRange[i] = rExtensions.copy( nCurrentIndex, nLastIndex - nCurrentIndex );
292 nCurrentIndex = nLastIndex + 1;
293 nLastIndex = nCurrentIndex;
294 }
295 }
296
297 return aExtensions;
298}
299
302OUString XMLFilterSettingsDialog::createUniqueFilterName( const OUString& rFilterName )
303{
304 OUString aFilterName( rFilterName );
305
306 sal_Int32 nId = 2;
307
308 while( mxFilterContainer->hasByName( aFilterName ) )
309 {
310 aFilterName = rFilterName + " " + OUString::number( nId++ );
311 }
312
313 return aFilterName;
314}
315
318OUString XMLFilterSettingsDialog::createUniqueTypeName( const OUString& rTypeName )
319{
320 OUString aTypeName( rTypeName );
321
322 sal_Int32 nId = 2;
323
324 while( mxFilterContainer->hasByName( aTypeName ) )
325 {
326 aTypeName = rTypeName + " " + OUString::number( nId++ );
327 }
328
329 return aTypeName;
330}
331
334OUString XMLFilterSettingsDialog::createUniqueInterfaceName( const OUString& rInterfaceName )
335{
336 sal_Int32 nDefaultNumber = 0;
337
338 try
339 {
340 const Sequence< OUString > aFilterNames( mxFilterContainer->getElementNames() );
341
343 for( OUString const & filterName : aFilterNames)
344 {
345 Any aAny( mxFilterContainer->getByName( filterName ) );
346 if( !(aAny >>= aValues) )
347 continue;
348
349 const sal_Int32 nValueCount( aValues.getLength() );
350 PropertyValue* pValues = aValues.getArray();
351 sal_Int32 nValue;
352
353 for( nValue = 0; nValue < nValueCount; nValue++, pValues++ )
354 {
355 if ( pValues->Name == "UIName" )
356 {
357 OUString aInterfaceName;
358 pValues->Value >>= aInterfaceName;
359
360
361 // see if this filter matches our default filter name
362 if( aInterfaceName.match( rInterfaceName ) )
363 {
364 // if yes, make sure we generate a unique name with a higher number
365 // this is dump but fast
366 sal_Int32 nNumber = o3tl::toInt32(aInterfaceName.subView( rInterfaceName.getLength() ));
367 if( nNumber >= nDefaultNumber )
368 nDefaultNumber = nNumber + 1;
369 }
370 }
371 }
372 }
373 }
374 catch( const Exception& )
375 {
376 TOOLS_WARN_EXCEPTION("filter.xslt", "");
377 }
378
379 OUString aInterfaceName( rInterfaceName );
380 if( nDefaultNumber )
381 {
382 aInterfaceName += " " + OUString::number( nDefaultNumber );
383 }
384
385 return aInterfaceName;
386}
387
391{
392 bool bOk = true;
393
394 if( pOldInfo )
395 {
396 // see if we need to update the type name
397 if( pOldInfo->maFilterName != pNewInfo->maFilterName )
398 {
399 if( pOldInfo->maType == pOldInfo->maFilterName )
400 {
401 pNewInfo->maType.clear();
402 }
403 }
404
405 // see if we need to clean up old stuff first
406 try
407 {
408 // if filter name changed, we need to remove the old filter first
409 if( pOldInfo->maFilterName != pNewInfo->maFilterName )
410 mxFilterContainer->removeByName( pOldInfo->maFilterName );
411
412 // if type name changed, we need to remove the old type first
413 if( pOldInfo->maType != pNewInfo->maType )
414 mxTypeDetection->removeByName( pOldInfo->maType );
415 }
416 catch( const Exception& )
417 {
418 TOOLS_WARN_EXCEPTION("filter.xslt", "");
419 bOk = false;
420 }
421 }
422
423 filter_info_impl* pFilterEntry( nullptr );
424
425 if( bOk )
426 {
427 // create or copy filter info
428 if( pOldInfo )
429 {
430 // change existing filter entry in filter list box
431 pFilterEntry = const_cast<filter_info_impl*>(pOldInfo);
432 *pFilterEntry = *pNewInfo;
433 }
434 else
435 {
436 // add new entry to filter list box
437 pFilterEntry = new filter_info_impl( *pNewInfo );
438 }
439 }
440
441 // check if we need to copy the template
442 if( bOk && !pFilterEntry->maImportTemplate.isEmpty() )
443 {
444 if( !pFilterEntry->maImportTemplate.matchIgnoreAsciiCase( m_sTemplatePath ) )
445 {
446 INetURLObject aSourceURL( pFilterEntry->maImportTemplate );
447 if (!aSourceURL.GetLastName().isEmpty())
448 {
449 OUString aDestURL = m_sTemplatePath + pFilterEntry->maFilterName + "/";
450 if( createDirectory( aDestURL ) )
451 {
452 aDestURL += aSourceURL.GetLastName();
453
454 SvFileStream aInputStream(pFilterEntry->maImportTemplate, StreamMode::READ );
455 Reference< XInputStream > xIS( new utl::OInputStreamWrapper( aInputStream ) );
456 SvFileStream aOutputStream(aDestURL, StreamMode::WRITE );
457 Reference< XOutputStream > xOS( new utl::OOutputStreamWrapper( aOutputStream ) );
458
459 if( copyStreams( xIS, xOS ) )
460 pFilterEntry->maImportTemplate = aDestURL;
461 }
462 }
463 }
464 }
465
466 if( bOk )
467 {
468 if( pFilterEntry->maType.isEmpty() )
469 {
470 pFilterEntry->maType = createUniqueTypeName( pNewInfo->maFilterName );
471 }
472
473 // update import/export flags
474 if( !pFilterEntry->maImportXSLT.isEmpty() )
475 {
476 pFilterEntry->maFlags |= 1;
477 }
478 else
479 {
480 pFilterEntry->maFlags &= ~1;
481 }
482
483 if( !pFilterEntry->maExportXSLT.isEmpty() )
484 {
485 pFilterEntry->maFlags |= 2;
486 }
487 else
488 {
489 pFilterEntry->maFlags &= ~2;
490 }
491 pFilterEntry->maFlags |= 0x80040;
492
493 // 2. create user data for filter entry
494 Sequence< OUString > aUserData( pFilterEntry->getFilterUserData());
495
496 // 3. create property values for filter entry
497 Sequence< PropertyValue > aFilterData{
498 comphelper::makePropertyValue("Type", pFilterEntry->maType),
499 comphelper::makePropertyValue("UIName", pFilterEntry->maInterfaceName),
500 comphelper::makePropertyValue("DocumentService", pFilterEntry->maDocumentService),
501 comphelper::makePropertyValue("FilterService", OUString( "com.sun.star.comp.Writer.XmlFilterAdaptor" )),
502 comphelper::makePropertyValue("Flags", pFilterEntry->maFlags),
503 comphelper::makePropertyValue("UserData", aUserData),
504 comphelper::makePropertyValue("FileFormatVersion", pFilterEntry->maFileFormatVersion),
505 comphelper::makePropertyValue("TemplateName", pFilterEntry->maImportTemplate)
506 };
507
508 // 4. insert new or replace existing filter
509 try
510 {
511 Any aAny( aFilterData );
512 if( mxFilterContainer->hasByName( pFilterEntry->maFilterName ) )
513 {
514 mxFilterContainer->replaceByName( pFilterEntry->maFilterName, aAny );
515 }
516 else
517 {
518 mxFilterContainer->insertByName( pFilterEntry->maFilterName, aAny );
519 }
520 }
521 catch( const Exception& )
522 {
523 TOOLS_WARN_EXCEPTION("filter.xslt", "");
524 bOk = false;
525 }
526 }
527
528 // 5. prepare type information
529 if( bOk )
530 {
531 OUString aDocType;
532 if( !pFilterEntry->maDocType.match( m_sDocTypePrefix ) )
533 {
534 aDocType = m_sDocTypePrefix + pFilterEntry->maDocType;
535 }
536 else
537 {
538 aDocType = pFilterEntry->maDocType;
539 }
540 if (aDocType == m_sDocTypePrefix)
541 aDocType.clear();
542
544 comphelper::makePropertyValue("UIName", pFilterEntry->maInterfaceName),
545 comphelper::makePropertyValue("ClipboardFormat", aDocType),
546 comphelper::makePropertyValue("DocumentIconID", pFilterEntry->mnDocumentIconID),
548 };
549
550 // the detect service will only be registered, if a doctype/search token was specified
551 if (aDocType.getLength() > m_sDocTypePrefix.getLength())
552 {
553 aValues.realloc(5);
554 auto pValues = aValues.getArray();
555 pValues[4].Name = "DetectService";
556 pValues[4].Value <<= OUString( "com.sun.star.comp.filters.XMLFilterDetect" );
557 }
558
559 // 6. insert new or replace existing type information
560 if( mxTypeDetection.is() )
561 {
562 try
563 {
564 Any aAny( aValues );
565 if( mxTypeDetection->hasByName( pFilterEntry->maType ) )
566 {
567 mxTypeDetection->replaceByName( pFilterEntry->maType, aAny );
568 }
569 else
570 {
571 mxTypeDetection->insertByName( pFilterEntry->maType, aAny );
572 }
573 }
574 catch( const Exception& )
575 {
576 TOOLS_WARN_EXCEPTION("filter.xslt", "");
577 bOk = false;
578 }
579 }
580
581 if( bOk )
582 {
583 try
584 {
585 Reference< XFlushable > xFlushable( mxTypeDetection, UNO_QUERY );
586 if( xFlushable.is() )
587 xFlushable->flush();
588 }
589 catch( const Exception& )
590 {
591 TOOLS_WARN_EXCEPTION("filter.xslt", "");
592 bOk = false;
593 }
594 }
595
596 if( !bOk )
597 {
598 // we failed to add the type, so lets remove the filter
599 try
600 {
601 mxFilterContainer->removeByName( pFilterEntry->maFilterName );
602 }
603 catch( const Exception& )
604 {
605 TOOLS_WARN_EXCEPTION("filter.xslt", "");
606 bOk = false;
607 }
608 }
609 else // bOk
610 {
611 try
612 {
613 Reference< XFlushable > xFlushable( mxFilterContainer, UNO_QUERY );
614 if( xFlushable.is() )
615 xFlushable->flush();
616 }
617 catch( const Exception& )
618 {
619 TOOLS_WARN_EXCEPTION("filter.xslt", "");
620 bOk = false;
621 }
622
623 if( !bOk )
624 {
625 // we failed to add the filter, so lets remove the type
626 try
627 {
628 mxTypeDetection->removeByName( pFilterEntry->maType );
629 }
630 catch( const Exception& )
631 {
632 TOOLS_WARN_EXCEPTION("filter.xslt", "");
633 }
634
635 }
636 }
637 }
638
639 if( bOk )
640 {
641 if( mxExtendedTypeDetection.is() )
642 {
643 OUString sFilterDetectService( "com.sun.star.comp.filters.XMLFilterDetect" );
644 if( mxExtendedTypeDetection->hasByName( sFilterDetectService ) )
645 {
647 if( mxExtendedTypeDetection->getByName( sFilterDetectService ) >>= aSequence )
648 {
649 auto aSequenceRange = asNonConstRange(aSequence);
650 sal_Int32 nCount = aSequence.getLength();
651 sal_Int32 nIndex;
652 for( nIndex = 0; nIndex < nCount; nIndex++ )
653 {
654 if ( aSequence[nIndex].Name == "Types" )
655 {
657 if( aSequence[nIndex].Value >>= aTypes )
658 {
659 sal_Int32 nStrCount = aTypes.getLength();
660 sal_Int32 nStr;
661 for( nStr = 0; nStr < nStrCount; nStr++ )
662 {
663 if( aTypes[nStr] == pFilterEntry->maType )
664 break;
665 }
666
667 if( nStr == nStrCount )
668 {
669 aTypes.realloc( nStrCount + 1 );
670 aTypes.getArray()[nStrCount] = pFilterEntry->maType;
671
672 aSequenceRange[nIndex].Value <<= aTypes;
673
674 mxExtendedTypeDetection->replaceByName( sFilterDetectService, Any( aSequence ) );
675
676 Reference< XFlushable > xFlushable( mxExtendedTypeDetection, UNO_QUERY );
677 if( xFlushable.is() )
678 xFlushable->flush();
679 }
680 }
681
682 break;
683 }
684 }
685 }
686 }
687 }
688 }
689
690 // update ui
691 if( bOk )
692 {
693 if( pOldInfo )
694 {
695 changeEntry( pFilterEntry );
696 }
697 else
698 {
699 addFilterEntry( pFilterEntry );
700 maFilterVector.push_back( std::unique_ptr<filter_info_impl>(pFilterEntry) );
701 }
702 }
703
704 return bOk;
705}
706
709{
710 // get the first selected filter
711 filter_info_impl* pInfo = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_selected_id());
712 if (pInfo)
713 {
715 aDlg.test( *pInfo );
716 }
717}
718
720{
721 int nIndex = m_xFilterListBox->get_selected_index();
722 if (nIndex == -1)
723 return;
724 filter_info_impl* pInfo = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_id(nIndex));
725 if (pInfo)
726 {
727 OUString aMessage(FilterResId(STR_WARN_DELETE));
728 aMessage = aMessage.replaceFirst( "%s", pInfo->maFilterName );
729
730 std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(m_xDialog.get(),
731 VclMessageType::Warning, VclButtonsType::YesNo,
732 aMessage));
733 xWarn->set_default_response(RET_YES);
734 if (xWarn->run() == RET_YES)
735 {
736 try
737 {
738 if( mxFilterContainer->hasByName( pInfo->maFilterName ) )
739 {
740 mxFilterContainer->removeByName( pInfo->maFilterName );
741
742 bool bTypeStillUsed = false;
743
744 // now loop over all filter and see if someone else uses the same type
745 Sequence< OUString > aFilterNames( mxFilterContainer->getElementNames() );
746 OUString* pFilterName = aFilterNames.getArray();
747
748 const sal_Int32 nCount = aFilterNames.getLength();
749 sal_Int32 nFilter;
751
752 for( nFilter = 0; (nFilter < nCount) && !bTypeStillUsed; nFilter++, pFilterName++ )
753 {
754 Any aAny( mxFilterContainer->getByName( *pFilterName ) );
755 if( !(aAny >>= aValues) )
756 continue;
757
758 const sal_Int32 nValueCount( aValues.getLength() );
759 PropertyValue* pValues = aValues.getArray();
760 sal_Int32 nValue;
761
762 for (nValue = 0; nValue < nValueCount; nValue++, pValues++)
763 {
764 if ( pValues->Name == "Type" )
765 {
766 OUString aType;
767 pValues->Value >>= aType;
768 if( aType == pInfo->maType )
769 bTypeStillUsed = true;
770
771 break;
772 }
773 }
774 }
775
776 // if the type is not used anymore, remove it also
777 if( !bTypeStillUsed )
778 {
779 if( mxTypeDetection->hasByName( pInfo->maType ) )
780 {
781 mxTypeDetection->removeByName( pInfo->maType );
782 }
783 }
784
785 Reference< XFlushable > xFlushable( mxFilterContainer, UNO_QUERY );
786 if( xFlushable.is() )
787 xFlushable->flush();
788
789 xFlushable.set( mxTypeDetection, UNO_QUERY );
790 if( xFlushable.is() )
791 xFlushable->flush();
792
793 // now remove entry from ui
794 m_xFilterListBox->remove(nIndex);
795
796 // and delete the filter entry
797 maFilterVector.erase(std::find_if( maFilterVector.begin(), maFilterVector.end(),
798 [&] (std::unique_ptr<filter_info_impl> const & p)
799 { return p.get() == pInfo; }));
800 }
801 }
802 catch( const Exception& )
803 {
804 TOOLS_WARN_EXCEPTION("filter.xslt", "");
805 }
806 }
807 }
808
809 updateStates();
810}
811
813{
814 std::vector<filter_info_impl*> aFilters;
815
816 int nFilters = 0;
817
818 m_xFilterListBox->selected_foreach([&](weld::TreeIter& rEntry){
819 filter_info_impl* pInfo = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_id(rEntry));
820 aFilters.push_back(pInfo);
821 ++nFilters;
822 return false;
823 });
824
825 // Open Fileopen-Dialog
827 css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
828 FileDialogFlags::NONE, m_xDialog.get());
830
831 OUString aExtensions( "*.jar" );
832 OUString aFilterName = FilterResId(STR_FILTER_PACKAGE) +
833 " (" + aExtensions + ")";
834
835 aDlg.AddFilter( aFilterName, aExtensions );
836
837 if ( aDlg.Execute() != ERRCODE_NONE )
838 return;
839
840 XMLFilterJarHelper aJarHelper( mxContext );
841 aJarHelper.savePackage( aDlg.GetPath(), aFilters );
842
843 INetURLObject aURL( aDlg.GetPath() );
844
845 OUString sPlaceholder( "%s" );
846
847 OUString aMsg;
848 if( nFilters > 0 )
849 {
850 aMsg = FilterResId(STR_FILTERS_HAVE_BEEN_SAVED);
851 aMsg = aMsg.replaceFirst( sPlaceholder, OUString::number( nFilters ) );
852 aMsg = aMsg.replaceFirst(sPlaceholder, aURL.GetLastName());
853 }
854 else
855 {
856 aMsg = FilterResId(STR_FILTER_HAS_BEEN_SAVED);
857 aMsg = aMsg.replaceFirst( sPlaceholder, (*aFilters.begin())->maFilterName );
858 aMsg = aMsg.replaceFirst(sPlaceholder, aURL.GetLastName());
859 }
860
861 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
862 VclMessageType::Info, VclButtonsType::Ok,
863 aMsg));
864 xInfoBox->run();
865}
866
868{
869 std::vector< std::unique_ptr<filter_info_impl> > aFilters;
870
871 // Open Fileopen-Dialog
873 css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
874 FileDialogFlags::NONE, m_xDialog.get());
876
877 OUString aExtensions( "*.jar" );
878 OUString aFilterName = FilterResId(STR_FILTER_PACKAGE) +
879 " (" + aExtensions + ")";
880
881 aDlg.AddFilter( aFilterName, aExtensions );
882
883 if ( aDlg.Execute() != ERRCODE_NONE )
884 return;
885
886 OUString aURL( aDlg.GetPath() );
887
888 XMLFilterJarHelper aJarHelper( mxContext );
889 aJarHelper.openPackage( aURL, aFilters );
890
891 int nFilters = 0;
892 for (auto& filter : aFilters)
893 {
894 if( insertOrEdit(filter.get()) )
895 {
896 aFilterName = filter->maFilterName;
897 nFilters++;
898 }
899
900 filter.reset();
901 }
902
905
906 OUString sPlaceholder( "%s" );
907 OUString aMsg;
908 if( nFilters == 0 )
909 {
910 INetURLObject aURLObj( aURL );
911 aMsg = FilterResId(STR_NO_FILTERS_FOUND);
912 aMsg = aMsg.replaceFirst(sPlaceholder, aURLObj.GetLastName());
913 }
914 else if( nFilters == 1 )
915 {
916 aMsg = FilterResId(STR_FILTER_INSTALLED);
917 aMsg = aMsg.replaceFirst( sPlaceholder, aFilterName );
918
919 }
920 else
921 {
922 aMsg = FilterResId(STR_FILTERS_INSTALLED);
923 aMsg = aMsg.replaceFirst( sPlaceholder, OUString::number( nFilters ) );
924 }
925
926 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
927 VclMessageType::Info, VclButtonsType::Ok,
928 aMsg));
929 xInfoBox->run();
930}
931
933{
934 maFilterVector.clear();
935 m_xFilterListBox->clear();
936}
937
939{
940 if( mxFilterContainer.is() )
941 {
942 const Sequence< OUString > aFilterNames( mxFilterContainer->getElementNames() );
943
945
946 std::unique_ptr<filter_info_impl> pTempFilter( new filter_info_impl );
947 Sequence< OUString > aUserData;
948
949 for( OUString const & filterName : aFilterNames )
950 {
951 aUserData.realloc(0);
952
953 try
954 {
955 Any aAny( mxFilterContainer->getByName( filterName ) );
956 if( !(aAny >>= aValues) )
957 continue;
958
959 OUString aFilterService;
960 pTempFilter->maFilterName = filterName;
961
962 const sal_Int32 nValueCount( aValues.getLength() );
963 PropertyValue* pValues = aValues.getArray();
964 sal_Int32 nValue;
965
966 for( nValue = 0; nValue < nValueCount; nValue++, pValues++ )
967 {
968 if ( pValues->Name == "Type" )
969 {
970 pValues->Value >>= pTempFilter->maType;
971 }
972 else if ( pValues->Name == "UIName" )
973 {
974 pValues->Value >>= pTempFilter->maInterfaceName;
975 }
976 else if ( pValues->Name == "DocumentService" )
977 {
978 pValues->Value >>= pTempFilter->maDocumentService;
979 }
980 else if ( pValues->Name == "FilterService" )
981 {
982 pValues->Value >>= aFilterService;
983 }
984 else if ( pValues->Name == "Flags" )
985 {
986 pValues->Value >>= pTempFilter->maFlags;
987 }
988 else if ( pValues->Name == "UserData" )
989 {
990 pValues->Value >>= aUserData;
991 }
992 else if ( pValues->Name == "FileFormatVersion" )
993 {
994 pValues->Value >>= pTempFilter->maFileFormatVersion;
995 }
996 else if ( pValues->Name == "TemplateName" )
997 {
998 pValues->Value >>= pTempFilter->maImportTemplate;
999 }
1000 else if ( pValues->Name == "Finalized" )
1001 {
1002 pValues->Value >>= pTempFilter->mbReadonly;
1003 }
1004 }
1005
1006 // if this is not a XmlFilterAdaptor entry, skip it
1007 if( aFilterService != "com.sun.star.comp.Writer.XmlFilterAdaptor" )
1008 continue;
1009
1010
1011 // if we don't have the needed user data, skip it
1012 if( aUserData.getLength() < 6 )
1013 continue;
1014
1015 // if this is not an XSLTFilter entry, skip it
1016 if( aUserData[0] != "com.sun.star.documentconversion.XSLTFilter" )
1017 continue;
1018
1019 // get filter information from userdata
1020 pTempFilter->mbNeedsXSLT2 = aUserData[1].toBoolean();
1021 pTempFilter->maImportService = aUserData[2];
1022 pTempFilter->maExportService = aUserData[3];
1023 pTempFilter->maImportXSLT = aUserData[4];
1024 pTempFilter->maExportXSLT = aUserData[5];
1025 if( aUserData.getLength() >= 8 )
1026 pTempFilter->maComment = aUserData[7];
1027
1028 // get type information
1029 if( mxTypeDetection.is() )
1030 {
1031 try
1032 {
1033 aAny = mxTypeDetection->getByName( pTempFilter->maType );
1035
1036 if( aAny >>= aValues2 )
1037 {
1038 const sal_Int32 nValueCount2( aValues2.getLength() );
1039 PropertyValue* pValues2 = aValues2.getArray();
1040 sal_Int32 nValue2;
1041
1042 for( nValue2 = 0; nValue2 < nValueCount2; nValue2++, pValues2++ )
1043 {
1044 if ( pValues2->Name == "ClipboardFormat" )
1045 {
1046 OUString aDocType;
1047 pValues2->Value >>= aDocType;
1048
1049 if( aDocType.match( m_sDocTypePrefix ) )
1050 aDocType = aDocType.copy( m_sDocTypePrefix.getLength() );
1051
1052 pTempFilter->maDocType = aDocType;
1053 }
1054 else if ( pValues2->Name == "Extensions" )
1055 {
1056 Sequence< OUString > aExtensions;
1057 if( pValues2->Value >>= aExtensions )
1058 {
1059 pTempFilter->maExtension.clear();
1060
1061 sal_Int32 nCount3( aExtensions.getLength() );
1062 OUString* pExtensions = aExtensions.getArray();
1063 sal_Int32 n;
1064 for( n = 0; n < nCount3; n++ )
1065 {
1066 if( n > 0 )
1067 pTempFilter->maExtension += ";";
1068 pTempFilter->maExtension += *pExtensions++;
1069 }
1070 }
1071 }
1072 else if ( pValues2->Name == "DocumentIconID" )
1073 {
1074 pValues2->Value >>= pTempFilter->mnDocumentIconID;
1075 }
1076 else if ( pValues2->Name == "Finalized" )
1077 {
1078 // both the filter and the type may be finalized
1079 bool bTemp = false;
1080 pValues2->Value >>= bTemp;
1081 pTempFilter->mbReadonly |= bTemp;
1082 }
1083 }
1084 }
1085 }
1086 catch( const css::container::NoSuchElementException& )
1087 {
1088 OSL_FAIL( "Type not found, user error?" ); // TODO: error?
1089 }
1090 }
1091
1092 // add entry to internal container and to ui filter list box
1093 maFilterVector.push_back( std::unique_ptr<filter_info_impl>(pTempFilter.get()) );
1094 addFilterEntry( pTempFilter.release() );
1095
1096
1097 pTempFilter.reset( new filter_info_impl );
1098 }
1099 catch( const Exception& )
1100 {
1101 TOOLS_WARN_EXCEPTION("filter.xslt", "");
1102 }
1103
1104 }
1105 }
1106
1107 if (m_xFilterListBox->n_children())
1108 {
1109 m_xFilterListBox->columns_autosize();
1110 m_xFilterListBox->select(0);
1111 }
1112}
1113
1114application_info_impl::application_info_impl( const char * pDocumentService, const OUString& rUINameRes, const char * mpXMLImporter, const char * mpXMLExporter )
1115: maDocumentService( pDocumentService, strlen( pDocumentService ), RTL_TEXTENCODING_ASCII_US ),
1116 maDocumentUIName(Translate::ExpandVariables(rUINameRes)),
1117 maXMLImporter( mpXMLImporter, strlen( mpXMLImporter ), RTL_TEXTENCODING_ASCII_US ),
1118 maXMLExporter( mpXMLExporter, strlen( mpXMLExporter ), RTL_TEXTENCODING_ASCII_US )
1119{
1120}
1121
1122std::vector< application_info_impl > const & getApplicationInfos()
1123{
1124 static std::vector< application_info_impl > const aInfos
1125 {
1126 { "com.sun.star.text.TextDocument",
1128 "com.sun.star.comp.Writer.XMLImporter",
1129 "com.sun.star.comp.Writer.XMLExporter" },
1130
1131 { "com.sun.star.sheet.SpreadsheetDocument",
1133 "com.sun.star.comp.Calc.XMLImporter",
1134 "com.sun.star.comp.Calc.XMLExporter" },
1135
1136 { "com.sun.star.presentation.PresentationDocument",
1138 "com.sun.star.comp.Impress.XMLImporter",
1139 "com.sun.star.comp.Impress.XMLExporter" },
1140
1141 { "com.sun.star.drawing.DrawingDocument",
1143 "com.sun.star.comp.Draw.XMLImporter",
1144 "com.sun.star.comp.Draw.XMLExporter" },
1145
1146 // --- oasis file formats...
1147 { "com.sun.star.text.TextDocument",
1149 "com.sun.star.comp.Writer.XMLOasisImporter",
1150 "com.sun.star.comp.Writer.XMLOasisExporter" },
1151
1152 { "com.sun.star.sheet.SpreadsheetDocument",
1154 "com.sun.star.comp.Calc.XMLOasisImporter",
1155 "com.sun.star.comp.Calc.XMLOasisExporter" },
1156
1157 { "com.sun.star.presentation.PresentationDocument",
1159 "com.sun.star.comp.Impress.XMLOasisImporter",
1160 "com.sun.star.comp.Impress.XMLOasisExporter" },
1161
1162 { "com.sun.star.drawing.DrawingDocument",
1164 "com.sun.star.comp.Draw.XMLOasisImporter",
1165 "com.sun.star.comp.Draw.XMLOasisExporter" },
1166 };
1167
1168 return aInfos;
1169}
1170
1171const application_info_impl* getApplicationInfo( std::u16string_view rServiceName )
1172{
1173 std::vector< application_info_impl > const & rInfos = getApplicationInfos();
1174 for (auto const& info : rInfos)
1175 {
1176 if( rServiceName == info.maXMLExporter ||
1177 rServiceName == info.maXMLImporter)
1178 {
1179 return &info;
1180 }
1181 }
1182 return nullptr;
1183}
1184
1185OUString getApplicationUIName( std::u16string_view rServiceName )
1186{
1187 const application_info_impl* pInfo = getApplicationInfo( rServiceName );
1188 if( pInfo )
1189 {
1190 return pInfo->maDocumentUIName;
1191 }
1192 else
1193 {
1194 OUString aRet = FilterResId(STR_UNKNOWN_APPLICATION);
1195 if( !rServiceName.empty() )
1196 {
1197 aRet += OUString::Concat(" (") + rServiceName + ")";
1198 }
1199 return aRet;
1200 }
1201}
1202
1205{
1206 int nRow = m_xFilterListBox->n_children();
1207 OUString sId(weld::toId(pInfo));
1208 m_xFilterListBox->append(sId, pInfo->maFilterName);
1209 m_xFilterListBox->set_text(nRow, getEntryString(pInfo), 1);
1210}
1211
1213{
1214 const int nCount = m_xFilterListBox->n_children();
1215 for(int nPos = 0; nPos < nCount; ++nPos)
1216 {
1217 filter_info_impl* pEntry = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_id(nPos));
1218 if (pEntry == pInfo)
1219 {
1220 m_xFilterListBox->set_text(nPos, pInfo->maFilterName, 0);
1221 m_xFilterListBox->set_text(nPos, getEntryString(pInfo), 1);
1222 break;
1223 }
1224 }
1225}
1226
1228{
1229 OUString aEntryStr;
1230 if ( !pInfo->maExportService.isEmpty() )
1231 aEntryStr = getApplicationUIName( pInfo->maExportService );
1232 else
1233 aEntryStr = getApplicationUIName( pInfo->maImportService );
1234 aEntryStr += " - ";
1235
1236 if( pInfo->maFlags & 1 )
1237 {
1238 if( pInfo->maFlags & 2 )
1239 {
1240 aEntryStr += FilterResId(STR_IMPORT_EXPORT);
1241 }
1242 else
1243 {
1244 aEntryStr += FilterResId(STR_IMPORT_ONLY);
1245 }
1246 }
1247 else if( pInfo->maFlags & 2 )
1248 {
1249 aEntryStr += FilterResId(STR_EXPORT_ONLY);
1250 }
1251 else
1252 {
1253 aEntryStr += FilterResId(STR_UNDEFINED_FILTER);
1254 }
1255
1256 return aEntryStr;
1257}
1258
1260 : maFlags(0x00080040)
1261 , maFileFormatVersion(0)
1262 , mnDocumentIconID(0)
1263 , mbReadonly(false)
1264 , mbNeedsXSLT2(false)
1265{
1266}
1267
1269{
1270 return maFilterName == r.maFilterName &&
1271 maType == r.maType &&
1274 maComment == r.maComment &&
1275 maExtension == r.maExtension &&
1276 maDocType == r.maDocType &&
1282 maFlags == r.maFlags &&
1285}
1286
1287
1289{
1290 return
1291 {
1292 "com.sun.star.documentconversion.XSLTFilter",
1293 OUString::boolean( mbNeedsXSLT2 ),
1298 maComment
1299 };
1300}
1301
1302OUString string_encode( const OUString & rText )
1303{
1304 static constexpr auto uricNoSlash = rtl::createUriCharClass(
1305 u8"!$&'()*+-.0123456789:=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~");
1306
1307
1308 return
1309 Uri::encode( rText, uricNoSlash.data(), rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_UTF8 );
1310}
1311
1312OUString string_decode( const OUString & rText )
1313{
1314 return Uri::decode( rText, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
1315}
1316
1318{
1319 try
1320 {
1321 sal_Int32 nBufferSize = 512;
1322 Sequence< sal_Int8 > aDataBuffer(nBufferSize);
1323
1324 sal_Int32 nRead;
1325 do
1326 {
1327 nRead = xIS->readBytes( aDataBuffer, nBufferSize );
1328
1329 if( nRead )
1330 {
1331 if( nRead < nBufferSize )
1332 {
1333 nBufferSize = nRead;
1334 aDataBuffer.realloc(nRead);
1335 }
1336
1337 xOS->writeBytes( aDataBuffer );
1338 }
1339 }
1340 while( nRead );
1341
1342 xOS->flush();
1343
1344 return true;
1345 }
1346 catch(const Exception&)
1347 {
1348 TOOLS_WARN_EXCEPTION("filter.xslt", "");
1349 }
1350
1351 return false;
1352}
1353
1354bool createDirectory( std::u16string_view rURL )
1355{
1356 size_t nLastIndex = sizeof( "file:///" ) - 2;
1357 while( nLastIndex != std::u16string_view::npos )
1358 {
1359 nLastIndex = rURL.find( '/', nLastIndex + 1);
1360 if( nLastIndex != std::u16string_view::npos )
1361 {
1362 OUString aDirURL( rURL.substr( 0, nLastIndex ) );
1363 Directory aDir( aDirURL );
1364 Directory::RC rc = aDir.open();
1365 if( rc == Directory::E_NOENT )
1366 rc = osl::Directory::create( aDirURL );
1367
1368 if( rc != Directory::E_None )
1369 {
1370 return false;
1371 }
1372 }
1373 }
1374
1375 return true;
1376}
1377
1378/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const PropertyValue * pValues
Reference< XExecutableDialog > m_xDialog
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, const ILibreOfficeKitNotifier *pNotifier=nullptr)
OUString GetLastName(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
OUString GetFactoryDefaultFilter(EFactory eFactory) const
OUString SubstituteVariable(const OUString &rVar) const
void openPackage(const OUString &rPackageURL, std::vector< std::unique_ptr< filter_info_impl > > &rFilters)
bool savePackage(const OUString &rPackageURL, const std::vector< filter_info_impl * > &rFilters)
void onEdit()
is called when the user clicks on the "Edit" Button
bool insertOrEdit(filter_info_impl *pNewInfo, const filter_info_impl *pOldInfo=nullptr)
inserts a new filter into the ui and configuration if pOldInfo is NULL.
css::uno::Reference< css::uno::XComponentContext > mxContext
void onTest()
is called when the user clicks the "Test" button
virtual ~XMLFilterSettingsDialog() override
css::uno::Reference< css::container::XNameContainer > mxTypeDetection
void onNew()
is called when the user clicks on the "New" button
std::unique_ptr< weld::TreeView > m_xFilterListBox
css::uno::Reference< css::container::XNameContainer > mxFilterContainer
std::unique_ptr< weld::Button > m_xPBEdit
OUString createUniqueInterfaceName(const OUString &rInterfaceName)
checks if the given name is a unique ui name inside the filter factory.
XMLFilterSettingsDialog(weld::Window *pParent, const css::uno::Reference< css::uno::XComponentContext > &rxContext)
OUString createUniqueTypeName(const OUString &rTypeName)
checks if the given name is unique inside the type detection.
void changeEntry(const filter_info_impl *pInfo)
std::unique_ptr< weld::Button > m_xPBDelete
std::unique_ptr< weld::Button > m_xPBTest
OUString createUniqueFilterName(const OUString &rUIName)
checks if the given name is unique inside the filter factory.
css::uno::Reference< css::container::XNameContainer > mxExtendedTypeDetection
std::unique_ptr< weld::Button > m_xPBClose
std::unique_ptr< weld::Button > m_xPBSave
void addFilterEntry(const filter_info_impl *pInfo)
adds a new filter info entry to the ui filter list
static OUString getEntryString(const filter_info_impl *pInfo)
std::unique_ptr< weld::Button > m_xPBNew
std::unique_ptr< weld::Button > m_xPBOpen
std::vector< std::unique_ptr< filter_info_impl > > maFilterVector
filter_info_impl * getNewFilterInfo() const
void test(const filter_info_impl &rFilterInfo)
OUString maDocumentService
sal_Int32 maFileFormatVersion
sal_Int32 mnDocumentIconID
bool operator==(const filter_info_impl &) const
css::uno::Sequence< OUString > getFilterUserData() const
OUString GetPath() const
void AddFilter(const OUString &rFilterName, const OUString &rExtension)
void SetContext(Context _eNewContext)
virtual short run()
std::shared_ptr< weld::Dialog > m_xDialog
int nCount
#define TOOLS_WARN_EXCEPTION(area, stream)
URL aURL
uno::Reference< uno::XComponentContext > mxContext
#define ERRCODE_NONE
sal_Int16 nValue
sal_Int32 nIndex
void * p
sal_Int64 n
sal_uInt16 nPos
OUString ExpandVariables(const OUString &rString)
@ Exception
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
Value
int i
Definition: gentoken.py:48
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
OUString toId(const void *pValue)
sal_Int16 nId
Sequence< Property > aInfos
constexpr OUStringLiteral STR_DEFAULT_EXTENSION
Definition: strings.hxx:22
constexpr OUStringLiteral STR_APPL_NAME_WRITER
Definition: strings.hxx:14
constexpr OUStringLiteral STR_APPL_NAME_IMPRESS
Definition: strings.hxx:16
constexpr OUStringLiteral STR_APPL_NAME_OASIS_CALC
Definition: strings.hxx:19
constexpr OUStringLiteral STR_APPL_NAME_OASIS_IMPRESS
Definition: strings.hxx:20
constexpr OUStringLiteral STR_APPL_NAME_OASIS_WRITER
Definition: strings.hxx:18
constexpr OUStringLiteral STR_APPL_NAME_DRAW
Definition: strings.hxx:17
constexpr OUStringLiteral STR_APPL_NAME_OASIS_DRAW
Definition: strings.hxx:21
constexpr OUStringLiteral STR_APPL_NAME_CALC
Definition: strings.hxx:15
application_info_impl(const char *pDocumentService, const OUString &rUINameRes, const char *mpXMLImporter, const char *mpXMLExporter)
OUString Name
sal_uInt16 sal_Unicode
OUString sId
RET_OK
RET_CLOSE
RET_YES
const SvXMLTokenMapEntry aTypes[]
OUString string_encode(const OUString &rText)
IMPL_LINK(XMLFilterSettingsDialog, ClickHdl_Impl, weld::Button &, rButton, void)
std::vector< application_info_impl > const & getApplicationInfos()
const application_info_impl * getApplicationInfo(std::u16string_view rServiceName)
IMPL_LINK_NOARG(XMLFilterSettingsDialog, SelectionChangedHdl_Impl, weld::TreeView &, void)
bool copyStreams(const Reference< XInputStream > &xIS, const Reference< XOutputStream > &xOS)
static Sequence< OUString > createExtensionsSequence(const OUString &rExtensions)
helper to create a sequence of strings from an extensions strings "ext1;ext2;ext3" will become { "ext...
bool createDirectory(std::u16string_view rURL)
OUString getApplicationUIName(std::u16string_view rServiceName)
OUString string_decode(const OUString &rText)
sal_Int32 nLength