tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / view / viewfun4.cxx
blobd4b7ea83d9a80d201cea409a5001e4705f0a495f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_features.h>
22 #include <memory>
23 #include <editeng/eeitem.hxx>
25 #include <editeng/editobj.hxx>
26 #include <editeng/editstat.hxx>
27 #include <editeng/editview.hxx>
28 #include <editeng/flditem.hxx>
29 #include <sot/storage.hxx>
30 #include <svx/hlnkitem.hxx>
31 #include <editeng/unolingu.hxx>
33 #include <sfx2/bindings.hxx>
34 #include <sfx2/dispatch.hxx>
35 #include <sfx2/docfile.hxx>
36 #include <sfx2/docfilt.hxx>
37 #include <sfx2/fcontnr.hxx>
38 #include <svtools/langtab.hxx>
39 #include <vcl/graphicfilter.hxx>
40 #include <svl/stritem.hxx>
41 #include <vcl/transfer.hxx>
42 #include <svl/urlbmk.hxx>
43 #include <svl/sharedstringpool.hxx>
44 #include <vcl/svapp.hxx>
45 #include <vcl/weld.hxx>
46 #include <avmedia/mediawindow.hxx>
47 #include <osl/diagnose.h>
49 #include <comphelper/propertyvalue.hxx>
50 #include <comphelper/storagehelper.hxx>
52 #include <viewfunc.hxx>
53 #include <docsh.hxx>
54 #include <document.hxx>
55 #include <globstr.hrc>
56 #include <global.hxx>
57 #include <scresid.hxx>
58 #include <undoblk.hxx>
59 #include <undocell.hxx>
60 #include <formulacell.hxx>
61 #include <scmod.hxx>
62 #include <spelleng.hxx>
63 #include <patattr.hxx>
64 #include <tabvwsh.hxx>
65 #include <impex.hxx>
66 #include <editutil.hxx>
67 #include <editable.hxx>
68 #include <dociter.hxx>
69 #include <reffind.hxx>
70 #include <compiler.hxx>
71 #include <tokenarray.hxx>
72 #include <refupdatecontext.hxx>
73 #include <gridwin.hxx>
74 #include <refundo.hxx>
76 using namespace com::sun::star;
78 void ScViewFunc::PasteRTF( SCCOL nStartCol, SCROW nStartRow,
79 const css::uno::Reference< css::datatransfer::XTransferable >& rxTransferable )
81 TransferableDataHelper aDataHelper( rxTransferable );
82 if ( aDataHelper.HasFormat( SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT ) )
84 HideAllCursors();
86 ScDocShell* pDocSh = GetViewData().GetDocShell();
87 ScDocument& rDoc = pDocSh->GetDocument();
88 SCTAB nTab = GetViewData().GetTabNo();
89 const bool bRecord (rDoc.IsUndoEnabled());
91 const ScPatternAttr* pPattern = rDoc.GetPattern( nStartCol, nStartRow, nTab );
92 std::optional<ScTabEditEngine> pEngine(std::in_place, *pPattern, rDoc.GetEnginePool(), &rDoc );
93 pEngine->EnableUndo( false );
95 vcl::Window* pActWin = GetActiveWin();
96 if (pActWin)
98 pEngine->SetPaperSize(Size(100000,100000));
99 ScopedVclPtrInstance< vcl::Window > aWin( pActWin );
100 EditView aEditView( &*pEngine, aWin.get() );
101 aEditView.SetOutputArea(tools::Rectangle(0,0,100000,100000));
103 // same method now for clipboard or drag&drop
104 // mba: clipboard always must contain absolute URLs (could be from alien source)
105 aEditView.InsertText( rxTransferable, OUString(), true );
108 sal_Int32 nParCnt = pEngine->GetParagraphCount();
109 if (nParCnt)
111 SCROW nEndRow = nStartRow + static_cast<SCROW>(nParCnt) - 1;
112 if (nEndRow > rDoc.MaxRow())
113 nEndRow = rDoc.MaxRow();
115 ScDocumentUniquePtr pUndoDoc;
116 if (bRecord)
118 pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
119 pUndoDoc->InitUndo( rDoc, nTab, nTab );
120 rDoc.CopyToDocument( nStartCol,nStartRow,nTab, nStartCol,nEndRow,nTab, InsertDeleteFlags::ALL, false, *pUndoDoc );
123 SCROW nRow = nStartRow;
125 // Temporarily turn off undo generation for this lot
126 bool bUndoEnabled = rDoc.IsUndoEnabled();
127 rDoc.EnableUndo( false );
128 for( sal_Int32 n = 0; n < nParCnt; n++ )
130 std::unique_ptr<EditTextObject> pObject(pEngine->CreateTextObject(n));
131 EnterData(nStartCol, nRow, nTab, *pObject, true);
132 if( ++nRow > rDoc.MaxRow() )
133 break;
135 rDoc.EnableUndo(bUndoEnabled);
137 if (bRecord)
139 ScDocumentUniquePtr pRedoDoc(new ScDocument( SCDOCMODE_UNDO ));
140 pRedoDoc->InitUndo( rDoc, nTab, nTab );
141 rDoc.CopyToDocument( nStartCol,nStartRow,nTab, nStartCol,nEndRow,nTab, InsertDeleteFlags::ALL|InsertDeleteFlags::NOCAPTIONS, false, *pRedoDoc );
143 ScRange aMarkRange(nStartCol, nStartRow, nTab, nStartCol, nEndRow, nTab);
144 ScMarkData aDestMark(rDoc.GetSheetLimits());
145 aDestMark.SetMarkArea( aMarkRange );
146 pDocSh->GetUndoManager()->AddUndoAction(
147 std::make_unique<ScUndoPaste>( pDocSh, aMarkRange, aDestMark,
148 std::move(pUndoDoc), std::move(pRedoDoc), InsertDeleteFlags::ALL, nullptr));
152 pEngine.reset();
154 ShowAllCursors();
156 else
158 HideAllCursors();
159 ScDocShell* pDocSh = GetViewData().GetDocShell();
160 ScImportExport aImpEx( pDocSh->GetDocument(),
161 ScAddress( nStartCol, nStartRow, GetViewData().GetTabNo() ) );
163 OUString aStr;
164 std::unique_ptr<SvStream> xStream;
165 if ( (xStream = aDataHelper.GetSotStorageStream( SotClipboardFormatId::RTF )) )
166 // mba: clipboard always must contain absolute URLs (could be from alien source)
167 aImpEx.ImportStream( *xStream, OUString(), SotClipboardFormatId::RTF );
168 else if ( aDataHelper.GetString( SotClipboardFormatId::RTF, aStr ) )
169 aImpEx.ImportString( aStr, SotClipboardFormatId::RTF );
170 else if ( (xStream = aDataHelper.GetSotStorageStream( SotClipboardFormatId::RICHTEXT)) )
171 aImpEx.ImportStream( *xStream, OUString(), SotClipboardFormatId::RICHTEXT );
172 else if ( aDataHelper.GetString( SotClipboardFormatId::RICHTEXT, aStr ) )
173 aImpEx.ImportString( aStr, SotClipboardFormatId::RICHTEXT );
175 AdjustRowHeight( nStartRow, aImpEx.GetRange().aEnd.Row(), true );
176 pDocSh->UpdateOle(GetViewData());
177 ShowAllCursors();
180 void ScViewFunc::DoRefConversion()
182 ScDocument& rDoc = GetViewData().GetDocument();
183 ScMarkData& rMark = GetViewData().GetMarkData();
184 SCTAB nTabCount = rDoc.GetTableCount();
185 bool bRecord = true;
186 if (!rDoc.IsUndoEnabled())
187 bRecord = false;
189 ScRange aMarkRange;
190 rMark.MarkToSimple();
191 bool bMulti = rMark.IsMultiMarked();
192 if (bMulti)
193 aMarkRange = rMark.GetMultiMarkArea();
194 else if (rMark.IsMarked())
195 aMarkRange = rMark.GetMarkArea();
196 else
198 aMarkRange = ScRange( GetViewData().GetCurX(),
199 GetViewData().GetCurY(), GetViewData().GetTabNo() );
201 ScEditableTester aTester( rDoc, aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
202 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),rMark );
203 if (!aTester.IsEditable())
205 ErrorMessage(aTester.GetMessageId());
206 return;
209 ScDocShell* pDocSh = GetViewData().GetDocShell();
210 bool bOk = false;
212 ScDocumentUniquePtr pUndoDoc;
213 if (bRecord)
215 pUndoDoc.reset( new ScDocument( SCDOCMODE_UNDO ) );
216 SCTAB nTab = aMarkRange.aStart.Tab();
217 pUndoDoc->InitUndo( rDoc, nTab, nTab );
219 if ( rMark.GetSelectCount() > 1 )
221 for (const auto& rTab : rMark)
222 if ( rTab != nTab )
223 pUndoDoc->AddUndoTab( rTab, rTab );
225 ScRange aCopyRange = aMarkRange;
226 aCopyRange.aStart.SetTab(0);
227 aCopyRange.aEnd.SetTab(nTabCount-1);
228 rDoc.CopyToDocument( aCopyRange, InsertDeleteFlags::ALL, bMulti, *pUndoDoc, &rMark );
231 ScRangeListRef xRanges;
232 GetViewData().GetMultiArea( xRanges );
233 size_t nCount = xRanges->size();
235 for (const SCTAB& i : rMark)
237 for (size_t j = 0; j < nCount; ++j)
239 ScRange aRange = (*xRanges)[j];
240 aRange.aStart.SetTab(i);
241 aRange.aEnd.SetTab(i);
242 ScCellIterator aIter( rDoc, aRange );
243 for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
245 if (aIter.getType() != CELLTYPE_FORMULA)
246 continue;
248 ScFormulaCell* pCell = aIter.getFormulaCell();
249 ScMatrixMode eMatrixMode = pCell->GetMatrixFlag();
250 if (eMatrixMode == ScMatrixMode::Reference)
251 continue;
253 OUString aOld = pCell->GetFormula();
254 sal_Int32 nLen = aOld.getLength();
255 if (eMatrixMode == ScMatrixMode::Formula)
257 assert(nLen >= 2 && aOld[0] == '{' && aOld[nLen-1] == '}');
258 nLen -= 2;
259 aOld = aOld.copy( 1, nLen);
261 ScRefFinder aFinder( aOld, aIter.GetPos(), rDoc, rDoc.GetAddressConvention() );
262 aFinder.ToggleRel( 0, nLen );
263 if (aFinder.GetFound())
265 ScAddress aPos = pCell->aPos;
266 const OUString& aNew = aFinder.GetText();
267 ScCompiler aComp( rDoc, aPos, rDoc.GetGrammar());
268 std::unique_ptr<ScTokenArray> pArr(aComp.CompileString(aNew));
269 ScFormulaCell* pNewCell =
270 new ScFormulaCell(
271 rDoc, aPos, *pArr, formula::FormulaGrammar::GRAM_DEFAULT, eMatrixMode);
273 rDoc.SetFormulaCell(aPos, pNewCell);
274 bOk = true;
279 if (bRecord)
281 ScDocumentUniquePtr pRedoDoc(new ScDocument( SCDOCMODE_UNDO ));
282 SCTAB nTab = aMarkRange.aStart.Tab();
283 pRedoDoc->InitUndo( rDoc, nTab, nTab );
285 if ( rMark.GetSelectCount() > 1 )
287 for (const auto& rTab : rMark)
288 if ( rTab != nTab )
289 pRedoDoc->AddUndoTab( rTab, rTab );
291 ScRange aCopyRange = aMarkRange;
292 aCopyRange.aStart.SetTab(0);
293 aCopyRange.aEnd.SetTab(nTabCount-1);
294 rDoc.CopyToDocument( aCopyRange, InsertDeleteFlags::ALL, bMulti, *pRedoDoc, &rMark );
296 pDocSh->GetUndoManager()->AddUndoAction(
297 std::make_unique<ScUndoRefConversion>( pDocSh,
298 aMarkRange, rMark, std::move(pUndoDoc), std::move(pRedoDoc), bMulti) );
301 pDocSh->PostPaint( aMarkRange, PaintPartFlags::Grid );
302 pDocSh->UpdateOle(GetViewData());
303 pDocSh->SetDocumentModified();
304 CellContentChanged();
306 if (!bOk)
307 ErrorMessage(STR_ERR_NOREF);
310 // Thesaurus - Undo ok
311 void ScViewFunc::DoThesaurus()
313 SCCOL nCol;
314 SCROW nRow;
315 SCTAB nTab;
316 ScDocShell* pDocSh = GetViewData().GetDocShell();
317 ScDocument& rDoc = pDocSh->GetDocument();
318 ScMarkData& rMark = GetViewData().GetMarkData();
319 ScSplitPos eWhich = GetViewData().GetActivePart();
320 EESpellState eState;
321 EditView* pEditView = nullptr;
322 std::unique_ptr<ESelection> pEditSel;
323 std::unique_ptr<ScEditEngineDefaulter> pThesaurusEngine;
324 bool bIsEditMode = GetViewData().HasEditView(eWhich);
325 bool bRecord = true;
326 if (!rDoc.IsUndoEnabled())
327 bRecord = false;
328 if (bIsEditMode) // edit mode active
330 GetViewData().GetEditView(eWhich, pEditView, nCol, nRow);
331 pEditSel.reset(new ESelection(pEditView->GetSelection()));
332 ScModule::get()->InputEnterHandler();
333 GetViewData().GetBindings().Update(); // otherwise the Sfx becomes mixed-up...
335 else
337 nCol = GetViewData().GetCurX();
338 nRow = GetViewData().GetCurY();
340 nTab = GetViewData().GetTabNo();
342 ScAddress aPos(nCol, nRow, nTab);
343 ScEditableTester aTester( rDoc, nCol, nRow, nCol, nRow, rMark );
344 if (!aTester.IsEditable())
346 ErrorMessage(aTester.GetMessageId());
347 return;
350 ScCellValue aOldText;
351 aOldText.assign(rDoc, aPos);
352 if (aOldText.getType() != CELLTYPE_STRING && aOldText.getType() != CELLTYPE_EDIT)
354 ErrorMessage(STR_THESAURUS_NO_STRING);
355 return;
358 uno::Reference<linguistic2::XSpellChecker1> xSpeller = LinguMgr::GetSpellChecker();
360 pThesaurusEngine.reset(new ScEditEngineDefaulter(rDoc.GetEnginePool()));
361 pThesaurusEngine->SetEditTextObjectPool( rDoc.GetEditPool() );
362 pThesaurusEngine->SetRefDevice(GetViewData().GetActiveWin()->GetOutDev());
363 pThesaurusEngine->SetSpeller(xSpeller);
364 MakeEditView(pThesaurusEngine.get(), nCol, nRow );
365 const ScPatternAttr* pPattern = rDoc.GetPattern(nCol, nRow, nTab);
366 if (pPattern)
368 auto pEditDefaults = std::make_unique<SfxItemSet>(pThesaurusEngine->GetEmptyItemSet());
369 pPattern->FillEditItemSet(pEditDefaults.get());
370 pThesaurusEngine->SetDefaults(std::move(pEditDefaults));
373 if (aOldText.getType() == CELLTYPE_EDIT)
374 pThesaurusEngine->SetTextCurrentDefaults(*aOldText.getEditText());
375 else
376 pThesaurusEngine->SetTextCurrentDefaults(aOldText.getString(rDoc));
378 pEditView = GetViewData().GetEditView(GetViewData().GetActivePart());
379 if (pEditSel)
380 pEditView->SetSelection(*pEditSel);
381 else
382 pEditView->SetSelection(ESelection());
384 pThesaurusEngine->ClearModifyFlag();
386 // language is now in EditEngine attributes -> no longer passed to StartThesaurus
388 eState = pEditView->StartThesaurus(GetViewData().GetDialogParent());
389 OSL_ENSURE(eState != EESpellState::NoSpeller, "No SpellChecker");
391 if (eState == EESpellState::ErrorFound) // should happen later through Wrapper!
393 LanguageType eLnge = ScViewUtil::GetEffLanguage( rDoc, ScAddress( nCol, nRow, nTab ) );
394 OUString aErr = SvtLanguageTable::GetLanguageString(eLnge) + ScResId( STR_SPELLING_NO_LANG );
396 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetViewData().GetDialogParent(),
397 VclMessageType::Info, VclButtonsType::Ok,
398 aErr));
399 xInfoBox->run();
401 if (pThesaurusEngine->IsModified())
403 ScCellValue aNewText;
405 if (aOldText.getType() == CELLTYPE_EDIT)
407 // The cell will own the text object instance.
408 std::unique_ptr<EditTextObject> pText = pThesaurusEngine->CreateTextObject();
409 auto tmp = pText.get();
410 if (rDoc.SetEditText(ScAddress(nCol,nRow,nTab), std::move(pText)))
411 aNewText.set(*tmp);
413 else
415 OUString aStr = pThesaurusEngine->GetText();
416 aNewText.set(rDoc.GetSharedStringPool().intern(aStr));
417 rDoc.SetString(nCol, nRow, nTab, aStr);
420 pDocSh->SetDocumentModified();
421 if (bRecord)
423 GetViewData().GetDocShell()->GetUndoManager()->AddUndoAction(
424 std::make_unique<ScUndoThesaurus>(
425 GetViewData().GetDocShell(), nCol, nRow, nTab, aOldText, aNewText));
429 KillEditView(true);
430 pDocSh->PostPaintGridAll();
433 void ScViewFunc::DoHangulHanjaConversion()
435 ScConversionParam aConvParam( SC_CONVERSION_HANGULHANJA, LANGUAGE_KOREAN, 0, true );
436 DoSheetConversion( aConvParam );
439 void ScViewFunc::DoSheetConversion( const ScConversionParam& rConvParam )
441 SCCOL nCol;
442 SCROW nRow;
443 SCTAB nTab;
444 ScViewData& rViewData = GetViewData();
445 ScDocShell* pDocSh = rViewData.GetDocShell();
446 ScDocument& rDoc = pDocSh->GetDocument();
447 ScMarkData& rMark = rViewData.GetMarkData();
448 ScSplitPos eWhich = rViewData.GetActivePart();
449 EditView* pEditView = nullptr;
450 bool bIsEditMode = rViewData.HasEditView(eWhich);
451 bool bRecord = true;
452 if (!rDoc.IsUndoEnabled())
453 bRecord = false;
454 if (bIsEditMode) // edit mode active
456 rViewData.GetEditView(eWhich, pEditView, nCol, nRow);
457 ScModule::get()->InputEnterHandler();
459 else
461 nCol = rViewData.GetCurX();
462 nRow = rViewData.GetCurY();
464 AlignToCursor( nCol, nRow, SC_FOLLOW_JUMP);
466 nTab = rViewData.GetTabNo();
468 rMark.MarkToMulti();
469 bool bMarked = rMark.IsMultiMarked();
470 if (bMarked)
472 ScEditableTester aTester( rDoc, rMark );
473 if (!aTester.IsEditable())
475 ErrorMessage(aTester.GetMessageId());
476 return;
480 ScDocumentUniquePtr pUndoDoc;
481 ScDocumentUniquePtr pRedoDoc;
482 if (bRecord)
484 pUndoDoc.reset( new ScDocument( SCDOCMODE_UNDO ) );
485 pUndoDoc->InitUndo( rDoc, nTab, nTab );
486 pRedoDoc.reset( new ScDocument( SCDOCMODE_UNDO ) );
487 pRedoDoc->InitUndo( rDoc, nTab, nTab );
489 if ( rMark.GetSelectCount() > 1 )
491 for (const auto& rTab : rMark)
492 if ( rTab != nTab )
494 pUndoDoc->AddUndoTab( rTab, rTab );
495 pRedoDoc->AddUndoTab( rTab, rTab );
500 // from here no return
502 bool bOldEnabled = rDoc.IsIdleEnabled();
503 rDoc.EnableIdle(false); // stop online spelling
505 // *** create and init the edit engine *** --------------------------------
507 std::unique_ptr<ScConversionEngineBase> pEngine;
508 switch( rConvParam.GetType() )
510 case SC_CONVERSION_SPELLCHECK:
511 pEngine.reset(new ScSpellingEngine(
512 rDoc.GetEnginePool(), rViewData, pUndoDoc.get(), pRedoDoc.get(), LinguMgr::GetSpellChecker() ));
513 break;
514 case SC_CONVERSION_HANGULHANJA:
515 case SC_CONVERSION_CHINESE_TRANSL:
516 pEngine.reset(new ScTextConversionEngine(
517 rDoc.GetEnginePool(), rViewData, rConvParam, pUndoDoc.get(), pRedoDoc.get() ));
518 break;
521 assert(pEngine && "all cases result in pEngine set");
523 MakeEditView( pEngine.get(), nCol, nRow );
524 pEngine->SetRefDevice( rViewData.GetActiveWin()->GetOutDev() );
525 // simulate dummy cell:
526 pEditView = rViewData.GetEditView( rViewData.GetActivePart() );
527 rViewData.SetSpellingView( pEditView );
528 tools::Rectangle aRect( Point( 0, 0 ), Point( 0, 0 ) );
529 pEditView->SetOutputArea( aRect );
530 pEngine->SetControlWord( EEControlBits::USECHARATTRIBS );
531 pEngine->EnableUndo( false );
532 pEngine->SetPaperSize( aRect.GetSize() );
533 pEngine->SetTextCurrentDefaults( OUString() );
535 // *** do the conversion *** ----------------------------------------------
537 pEngine->ClearModifyFlag();
538 pEngine->ConvertAll(GetViewData().GetDialogParent(), *pEditView);
540 // *** undo/redo *** ------------------------------------------------------
542 if( pEngine->IsAnyModified() )
544 if (bRecord)
546 SCCOL nNewCol = rViewData.GetCurX();
547 SCROW nNewRow = rViewData.GetCurY();
548 rViewData.GetDocShell()->GetUndoManager()->AddUndoAction(
549 std::make_unique<ScUndoConversion>(
550 pDocSh, rMark,
551 nCol, nRow, nTab, std::move(pUndoDoc),
552 nNewCol, nNewRow, nTab, std::move(pRedoDoc), rConvParam ) );
555 sc::SetFormulaDirtyContext aCxt;
556 rDoc.SetAllFormulasDirty(aCxt);
558 pDocSh->SetDocumentModified();
560 else
562 pUndoDoc.reset();
563 pRedoDoc.reset();
566 // *** final cleanup *** --------------------------------------------------
568 rViewData.SetSpellingView( nullptr );
569 KillEditView(true);
570 pEngine.reset();
571 pDocSh->PostPaintGridAll();
572 rViewData.GetViewShell()->UpdateInputHandler();
573 rDoc.EnableIdle(bOldEnabled);
576 // past from SotClipboardFormatId::FILE items
577 // is not called directly from Drop, but asynchronously -> dialogs are allowed
579 bool ScViewFunc::PasteFile( const Point& rPos, const OUString& rFile, bool bLink )
581 INetURLObject aURL;
582 aURL.SetSmartURL( rFile );
583 OUString aStrURL = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
585 // is it a media URL?
586 #if HAVE_FEATURE_AVMEDIA
587 if( ::avmedia::MediaWindow::isMediaURL( aStrURL, u""_ustr/*TODO?*/ ) )
589 const SfxStringItem aMediaURLItem( SID_INSERT_AVMEDIA, aStrURL );
590 const SfxPoolItemHolder aResult(GetViewData().GetDispatcher().ExecuteList(
591 SID_INSERT_AVMEDIA, SfxCallMode::SYNCHRON,
592 { &aMediaURLItem }));
593 return aResult.is();
595 #endif
597 if (!bLink) // for bLink only graphics or URL
599 // 1. can I open the file?
600 std::shared_ptr<const SfxFilter> pFlt;
602 // search only for its own filters, without selection box (as in ScDocumentLoader)
603 SfxFilterMatcher aMatcher( ScDocShell::Factory().GetFilterContainer()->GetName() );
604 SfxMedium aSfxMedium( aStrURL, (StreamMode::READ | StreamMode::SHARE_DENYNONE) );
605 // #i73992# GuessFilter no longer calls UseInteractionHandler.
606 // This is UI, so it can be called here.
607 aSfxMedium.UseInteractionHandler(true);
608 ErrCode nErr = aMatcher.GuessFilter( aSfxMedium, pFlt );
610 if ( pFlt && !nErr )
612 // code stolen from the SFX!
613 SfxDispatcher &rDispatcher = GetViewData().GetDispatcher();
614 SfxStringItem aFileNameItem( SID_FILE_NAME, aStrURL );
615 SfxStringItem aFilterItem( SID_FILTER_NAME, pFlt->GetName() );
616 // #i69524# add target, as in SfxApplication when the Open dialog is used
617 SfxStringItem aTargetItem( SID_TARGETNAME, u"_default"_ustr );
619 // Open Asynchronously, because it can also happen from D&D
620 // and that is not so good for the MAC...
621 const SfxPoolItemHolder aResult(rDispatcher.ExecuteList(SID_OPENDOC,
622 SfxCallMode::ASYNCHRON,
623 { &aFileNameItem, &aFilterItem, &aTargetItem}));
624 return aResult.is();
628 // 2. can the file be inserted using the graphics filter?
629 // (as a link, since the Gallery provides it in this way)
631 Graphic aGraphic;
632 GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
634 if (!rGraphicFilter.ImportGraphic(aGraphic, aURL,
635 GRFILTER_FORMAT_DONTKNOW ))
637 if ( bLink )
639 return PasteGraphic( rPos, aGraphic, aStrURL );
641 else
643 // #i76709# if bLink isn't set, pass empty URL/filter, so a non-linked image is inserted
644 return PasteGraphic( rPos, aGraphic, OUString() );
648 if (bLink) // for bLink everything, which is not graphics, as URL
650 tools::Rectangle aRect( rPos, Size(0,0) );
651 ScRange aRange = GetViewData().GetDocument().
652 GetRange( GetViewData().GetTabNo(), aRect );
653 SCCOL nPosX = aRange.aStart.Col();
654 SCROW nPosY = aRange.aStart.Row();
656 InsertBookmark( aStrURL, aStrURL, nPosX, nPosY );
657 return true;
659 else
661 // 3. can the file be inserted as OLE?
662 // also non-storages, for instance sounds (#38282#)
663 uno::Reference < embed::XStorage > xStorage = comphelper::OStorageHelper::GetTemporaryStorage();
665 //TODO/LATER: what about "bLink"?
667 uno::Sequence < beans::PropertyValue > aMedium{ comphelper::makePropertyValue(u"URL"_ustr,
668 aStrURL) };
670 comphelper::EmbeddedObjectContainer aCnt( xStorage );
671 OUString aName;
672 uno::Reference < embed::XEmbeddedObject > xObj = aCnt.InsertEmbeddedObject( aMedium, aName );
673 if( xObj.is() )
674 return PasteObject( rPos, xObj, nullptr );
676 // If an OLE object can't be created, insert a URL button
678 GetViewData().GetViewShell()->InsertURLButton( aStrURL, aStrURL, OUString(), &rPos );
679 return true;
683 bool ScViewFunc::PasteBookmark( SotClipboardFormatId nFormatId,
684 const css::uno::Reference< css::datatransfer::XTransferable >& rxTransferable,
685 SCCOL nPosX, SCROW nPosY )
687 INetBookmark aBookmark;
688 TransferableDataHelper aDataHelper( rxTransferable );
689 if ( !aDataHelper.GetINetBookmark( nFormatId, aBookmark ) )
690 return false;
692 InsertBookmark( aBookmark.GetDescription(), aBookmark.GetURL(), nPosX, nPosY );
693 return true;
696 void ScViewFunc::InsertBookmark( const OUString& rDescription, const OUString& rURL,
697 SCCOL nPosX, SCROW nPosY, const OUString* pTarget,
698 bool bTryReplace )
700 ScViewData& rViewData = GetViewData();
701 if ( rViewData.HasEditView( rViewData.GetActivePart() ) &&
702 nPosX >= rViewData.GetEditStartCol() && nPosX <= rViewData.GetEditEndCol() &&
703 nPosY >= rViewData.GetEditStartRow() && nPosY <= rViewData.GetEditEndRow() )
705 // insert into the cell which just got edited
707 OUString aTargetFrame;
708 if (pTarget)
709 aTargetFrame = *pTarget;
710 rViewData.GetViewShell()->InsertURLField( rDescription, rURL, aTargetFrame );
711 return;
714 // insert into not edited cell
716 ScDocument& rDoc = GetViewData().GetDocument();
717 SCTAB nTab = GetViewData().GetTabNo();
718 ScAddress aCellPos( nPosX, nPosY, nTab );
719 EditEngine aEngine( rDoc.GetEnginePool() );
721 const EditTextObject* pOld = rDoc.GetEditText(aCellPos);
722 if (pOld)
723 aEngine.SetText(*pOld);
724 else
726 OUString aOld = rDoc.GetInputString(nPosX, nPosY, nTab);
727 if (!aOld.isEmpty())
728 aEngine.SetText(aOld);
731 ESelection aInsSel(ESelection::AtEnd());
733 if ( bTryReplace && HasBookmarkAtCursor( nullptr ) )
735 // if called from hyperlink slot and cell contains only a URL,
736 // replace old URL with new one
738 aInsSel = ESelection( 0, 0, 0, 1 ); // replace first character (field)
741 SvxURLField aField( rURL, rDescription, SvxURLFormat::AppDefault );
742 if (pTarget)
743 aField.SetTargetFrame(*pTarget);
744 aEngine.QuickInsertField( SvxFieldItem( aField, EE_FEATURE_FIELD ), aInsSel );
746 std::unique_ptr<EditTextObject> pData(aEngine.CreateTextObject());
747 EnterData(nPosX, nPosY, nTab, *pData);
750 bool ScViewFunc::HasBookmarkAtCursor( SvxHyperlinkItem* pContent )
752 ScAddress aPos( GetViewData().GetCurX(), GetViewData().GetCurY(), GetViewData().GetTabNo() );
753 ScDocument& rDoc = GetViewData().GetDocShell()->GetDocument();
755 const EditTextObject* pData = rDoc.GetEditText(aPos);
756 if (!pData)
757 return false;
759 if (!pData->IsFieldObject())
760 // not a field object.
761 return false;
763 const SvxFieldItem* pFieldItem = pData->GetField();
764 if (!pFieldItem)
765 // doesn't have a field item.
766 return false;
768 const SvxFieldData* pField = pFieldItem->GetField();
769 if (!pField)
770 // doesn't have a field item data.
771 return false;
773 if (pField->GetClassId() != css::text::textfield::Type::URL)
774 // not a URL field.
775 return false;
777 if (pContent)
779 const SvxURLField* pURLField = static_cast<const SvxURLField*>(pField);
780 pContent->SetName( pURLField->GetRepresentation() );
781 pContent->SetURL( pURLField->GetURL() );
782 pContent->SetTargetFrame( pURLField->GetTargetFrame() );
784 return true;
787 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */