summaryrefslogtreecommitdiff
path: root/sfx2/source
diff options
context:
space:
mode:
authorBalazs Varga <balazs.varga.extern@allotropia.de>2022-09-23 10:57:09 +0200
committerThorsten Behrens <thorsten.behrens@allotropia.de>2023-11-19 18:16:49 +0100
commit3ff6be408d541deb2df6d7f6c6d6ad3138169935 (patch)
tree3237c01d2544ab19773ad778022d54d4d3b66d8f /sfx2/source
parent664dca306f5d72fa4ca35c74cdaef47947e1b1fe (diff)
WASM pdf conversion through emscripten and qt5
Exporting files to pdf and downloading it from the emscripten virtual memory file system to the local file system with qt5 and emscripten. What is working: 1. Uploading a file from the local file system to the emscripten memory with 'Open file dialoge' and then opening it. In the same time export it to pdf. 2. Load an uploaded document with the LibreOffice Kit command: - lodoc = _libreofficekit_hook(0) - _doc_postUnoCommand(lodoc, allocateUTF8(".uno:Open"), allocateUTF8( "{ \"URL\" : { \"type\":\"string\", \"value\":\"file:///android/default-document/{UPLOADED_FILE_NAME}\" }}"), 0) 3. Export the loaded document to pdf with the ExportDirectlyToPDF UI or with the LibreOffice Kit command: - lodoc = _libreofficekit_hook(0) - _doc_postUnoCommand(lodoc, allocateUTF8(".uno:ExportDirectToPDF"), allocateUTF8(""), 0) 4. alternatively, you can plant a file in the virtual filesystem prior to LibreOffice bootstrap, and export headless, via soffice cmdline args Change-Id: I8f03b0a057155afaa5f1ca0e3e451bb362a99769
Diffstat (limited to 'sfx2/source')
-rw-r--r--sfx2/source/dialog/filedlghelper.cxx7
-rw-r--r--sfx2/source/doc/guisaveas.cxx47
-rw-r--r--sfx2/source/doc/objstor.cxx73
-rw-r--r--sfx2/source/doc/objxtor.cxx2
4 files changed, 125 insertions, 4 deletions
diff --git a/sfx2/source/dialog/filedlghelper.cxx b/sfx2/source/dialog/filedlghelper.cxx
index 96955837c8a6..9a8b938aab23 100644
--- a/sfx2/source/dialog/filedlghelper.cxx
+++ b/sfx2/source/dialog/filedlghelper.cxx
@@ -1628,7 +1628,12 @@ void FileDialogHelper_Impl::getRealFilter( OUString& _rFilter ) const
_rFilter = getCurrentFilterUIName();
if ( _rFilter.isEmpty() )
- _rFilter = maCurFilter;
+ {
+ if (isShowFilterExtensionEnabled())
+ _rFilter = getFilterName(maCurFilter);
+ else
+ _rFilter = maCurFilter;
+ }
if ( !_rFilter.isEmpty() && mpMatcher )
{
diff --git a/sfx2/source/doc/guisaveas.cxx b/sfx2/source/doc/guisaveas.cxx
index 1c013c4a382b..5b17b2a1b029 100644
--- a/sfx2/source/doc/guisaveas.cxx
+++ b/sfx2/source/doc/guisaveas.cxx
@@ -1641,10 +1641,53 @@ bool SfxStoringHelper::FinishGUIStoreModel(::comphelper::SequenceAsHashMap::cons
if ( aDenyListIter != aModelData.GetMediaDescr().end() )
aDenyListIter->second >>= aDenyList;
+ bool bWasmPdfExport = false;
+#ifdef EMSCRIPTEN
+ // Do not create file dialoge for direct pdf export, (just a workaround for WASM pdf export now)
+ // because that is still buggy on the Qt side
+ if ( nStoreMode & PDFDIRECTEXPORT_REQUESTED )
+ {
+ // preselect a filter for the storing process
+ ::comphelper::SequenceAsHashMap aFilterPropsHM( aFilterProps );
+
+ // this is a WASM direct pdf export
+ const OUString aFilterUIName = aFilterPropsHM.getUnpackedValueOrDefault( "UIName", OUString() );
+ if (aFilterUIName == "PDF - Portable Document Format")
+ {
+ OUString realfiltername;
+ const OUString aDocServiceName{ aModelData.GetDocServiceName() };
+ if ( aDocServiceName == "com.sun.star.drawing.DrawingDocument" )
+ realfiltername = "draw_pdf_Export";
+ else if ( aDocServiceName == "com.sun.star.presentation.PresentationDocument" )
+ realfiltername = "impress_pdf_Export";
+ else if ( aDocServiceName == "com.sun.star.text.TextDocument" )
+ realfiltername = "writer_pdf_Export";
+ else if ( aDocServiceName == "com.sun.star.sheet.SpreadsheetDocument" )
+ realfiltername = "calc_pdf_Export";
+
+ if (realfiltername.endsWith("pdf_Export"))
+ {
+ const OUString aRecommendedDir {aModelData.GetRecommendedDir( aSuggestedDir )};
+ OUString aAdjustToType = aFilterPropsHM.getUnpackedValueOrDefault( "Type", OUString() );
+ const OUString aRecommendedName {aModelData.GetRecommendedName( aSuggestedName, aAdjustToType )};
+ OUString aTempURL = aRecommendedDir + aRecommendedName;
+ INetURLObject aURL2(aTempURL);
+ aModelData.GetMediaDescr()[OUString("URL")] <<= aURL2.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ aModelData.GetMediaDescr()[sFilterNameString] <<= realfiltername;
+ bWasmPdfExport = true;
+ }
+ }
+ }
+#endif // EMSCRIPTEN
+
for (;;)
{
// in case the dialog is opened a second time the folder should be the same as previously navigated to by the user, not what was handed over by initial parameters
- bUseFilterOptions = aModelData.OutputFileDialog( nStoreMode, aFilterProps, bSetStandardName, aSuggestedName, bPreselectPassword, aSuggestedDir, nDialog, sStandardDir, aDenyList );
+ if (!bWasmPdfExport)
+ bUseFilterOptions = aModelData.OutputFileDialog( nStoreMode, aFilterProps, bSetStandardName, aSuggestedName, bPreselectPassword, aSuggestedDir, nDialog, sStandardDir, aDenyList );
+ else
+ bUseFilterOptions = true;
+
if ( nStoreMode == SAVEAS_REQUESTED )
{
// in case of saving check filter for possible alien warning
@@ -1665,7 +1708,7 @@ bool SfxStoringHelper::FinishGUIStoreModel(::comphelper::SequenceAsHashMap::cons
break;
}
- bDialogUsed = true;
+ bDialogUsed = !bWasmPdfExport;
aFileNameIter = aModelData.GetMediaDescr().find( OUString("URL") );
}
else
diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx
index b39b5d14ee38..4bfb92111037 100644
--- a/sfx2/source/doc/objstor.cxx
+++ b/sfx2/source/doc/objstor.cxx
@@ -3006,6 +3006,39 @@ bool SfxObjectShell::PreDoSaveAs_Impl(const OUString& rFileName, const OUString&
if( bOk )
{
+#ifdef EMSCRIPTEN
+ if (aFilterName.endsWith("pdf_Export"))
+ {
+ try
+ {
+ sal_Int32 nRead;
+ Reference<io::XInputStream> aTempInput = pNewFile->GetInputStream();
+ sal_Int32 nBufferSize = 32767;
+ Sequence<sal_Int8> aSequence(nBufferSize);
+ emscripten::val contentArray = emscripten::val::array();
+
+ do
+ {
+ nRead = aTempInput->readBytes(aSequence, nBufferSize);
+ if (nRead < nBufferSize)
+ {
+ Sequence<sal_Int8> aTempBuf(aSequence.getConstArray(), nRead);
+ ReadWASMFile(contentArray, nRead, aTempBuf);
+ }
+ else
+ {
+ ReadWASMFile(contentArray, nRead, aSequence);
+ }
+ } while (nRead == nBufferSize);
+
+ WriteWASMFile(contentArray, pNewFile->GetName());
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+#endif
+
if( !bCopyTo )
SetModified( false );
}
@@ -3050,6 +3083,46 @@ bool SfxObjectShell::PreDoSaveAs_Impl(const OUString& rFileName, const OUString&
return bOk;
}
+#ifdef EMSCRIPTEN
+void SfxObjectShell::ReadWASMFile(emscripten::val& contentArray, sal_Int32 nRead, css::uno::Sequence<sal_Int8>& aContent)
+{
+ emscripten::val fileContentView = emscripten::val(emscripten::typed_memory_view(
+ nRead,
+ reinterpret_cast<const char*>(aContent.getConstArray())));
+ emscripten::val fileContentCopy = emscripten::val::global("ArrayBuffer").new_(nRead);
+ emscripten::val fileContentCopyView = emscripten::val::global("Uint8Array").new_(fileContentCopy);
+ fileContentCopyView.call<void>("set", fileContentView);
+ contentArray.call<void>("push", fileContentCopyView);
+}
+
+
+void SfxObjectShell::WriteWASMFile(emscripten::val& contentArray, const OUString& rFileName)
+{
+ INetURLObject aURL(rFileName);
+ OUString aNewname = aURL.GetLastName(INetURLObject::DecodeMechanism::WithCharset);
+
+ emscripten::val document = emscripten::val::global("document");
+ emscripten::val window = emscripten::val::global("window");
+
+ emscripten::val type = emscripten::val::object();
+ type.set("type","application/octet-stream");
+ emscripten::val contentBlob = emscripten::val::global("Blob").new_(contentArray, type);
+
+ emscripten::val contentUrl = window["URL"].call<emscripten::val>("createObjectURL", contentBlob);
+ emscripten::val contentLink = document.call<emscripten::val>("createElement", std::string("a"));
+ contentLink.set("href", contentUrl);
+ contentLink.set("download", aNewname.toUtf8().getStr());
+ contentLink.set("style", "display:none");
+
+ emscripten::val body = document["body"];
+ body.call<void>("appendChild", contentLink);
+ contentLink.call<void>("click");
+ body.call<void>("removeChild", contentLink);
+
+ window["URL"].call<emscripten::val>("revokeObjectURL", contentUrl);
+}
+#endif
+
bool SfxObjectShell::LoadFrom( SfxMedium& /*rMedium*/ )
{
diff --git a/sfx2/source/doc/objxtor.cxx b/sfx2/source/doc/objxtor.cxx
index 2fd5df242fcc..5ee43348d0b2 100644
--- a/sfx2/source/doc/objxtor.cxx
+++ b/sfx2/source/doc/objxtor.cxx
@@ -877,6 +877,7 @@ void SfxObjectShell::SetCurrentComponent( const Reference< XInterface >& _rxComp
if ( _rxComponent == xOldCurrentComp )
// nothing to do
return;
+ rTheCurrentComponent = _rxComponent;
// note that "_rxComponent.get() == s_xCurrentComponent.get().get()" is /sufficient/, but not
// /required/ for "_rxComponent == s_xCurrentComponent.get()".
// In other words, it's still possible that we here do something which is not necessary,
@@ -884,7 +885,6 @@ void SfxObjectShell::SetCurrentComponent( const Reference< XInterface >& _rxComp
#if HAVE_FEATURE_SCRIPTING
BasicManager* pAppMgr = SfxApplication::GetBasicManager();
- rTheCurrentComponent = _rxComponent;
if ( !pAppMgr )
return;