1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <hldocntp.hxx>
21 #include <osl/file.hxx>
22 #include <sfx2/filedlghelper.hxx>
23 #include <sfx2/viewfrm.hxx>
24 #include <sfx2/docfilt.hxx>
25 #include <svl/stritem.hxx>
26 #include <com/sun/star/awt/XTopWindow.hpp>
27 #include <com/sun/star/uno/Reference.h>
28 #include <com/sun/star/uno/Exception.hpp>
30 #include <vcl/svapp.hxx>
31 #include <vcl/weld.hxx>
32 #include <tools/urlobj.hxx>
33 #include <unotools/pathoptions.hxx>
34 #include <unotools/dynamicmenuoptions.hxx>
35 #include <unotools/ucbstreamhelper.hxx>
36 #include <unotools/ucbhelper.hxx>
38 #include <comphelper/processfactory.hxx>
39 #include <com/sun/star/ui/dialogs/XFolderPicker2.hpp>
40 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
42 #include <cuihyperdlg.hxx>
43 #include <dialmgr.hxx>
44 #include <strings.hrc>
46 using namespace ::com::sun::star::lang
;
47 using namespace ::com::sun::star::ui::dialogs
;
48 using namespace ::com::sun::star::uno
;
50 using namespace ::com::sun::star
;
52 /*************************************************************************
54 |* Data-struct for documenttypes in listbox
56 |************************************************************************/
60 struct DocumentTypeData
64 DocumentTypeData (OUString aURL
, OUString aExt
) : aStrURL(std::move(aURL
)), aStrExt(std::move(aExt
))
70 bool SvxHyperlinkNewDocTp::ImplGetURLObject( const OUString
& rPath
, std::u16string_view rBase
, INetURLObject
& aURLObject
) const
72 bool bIsValidURL
= !rPath
.isEmpty();
75 aURLObject
.SetURL( rPath
);
76 if ( aURLObject
.GetProtocol() == INetProtocol::NotValid
) // test if the source is already a valid url
77 { // if not we have to create a url from a physical file name
79 INetURLObject
base(rBase
);
81 aURLObject
= base
.smartRel2Abs(
82 rPath
, wasAbs
, true, INetURLObject::EncodeMechanism::All
,
83 RTL_TEXTENCODING_UTF8
, true);
85 bIsValidURL
= aURLObject
.GetProtocol() != INetProtocol::NotValid
;
88 OUString
aBase( aURLObject
.getName( INetURLObject::LAST_SEGMENT
, false ) );
89 if ( aBase
.isEmpty() || ( aBase
[0] == '.' ) )
94 sal_Int32 nPos
= m_xLbDocTypes
->get_selected_index();
96 aURLObject
.SetExtension(weld::fromId
<DocumentTypeData
*>(m_xLbDocTypes
->get_id(nPos
))->aStrExt
);
103 /*************************************************************************
105 |* Constructor / Destructor
107 |************************************************************************/
109 SvxHyperlinkNewDocTp::SvxHyperlinkNewDocTp(weld::Container
* pParent
, SvxHpLinkDlg
* pDlg
, const SfxItemSet
* pItemSet
)
110 : SvxHyperlinkTabPageBase(pParent
, pDlg
, "cui/ui/hyperlinknewdocpage.ui", "HyperlinkNewDocPage", pItemSet
)
111 , m_xRbtEditNow(xBuilder
->weld_radio_button("editnow"))
112 , m_xRbtEditLater(xBuilder
->weld_radio_button("editlater"))
113 , m_xCbbPath(new SvxHyperURLBox(xBuilder
->weld_combo_box("path")))
114 , m_xBtCreate(xBuilder
->weld_button("create"))
115 , m_xLbDocTypes(xBuilder
->weld_tree_view("types"))
117 m_xCbbPath
->SetSmartProtocol(INetProtocol::File
);
118 m_xLbDocTypes
->set_size_request(-1, m_xLbDocTypes
->get_height_rows(5));
122 SetExchangeSupport ();
125 m_xCbbPath
->SetBaseURL(SvtPathOptions().GetWorkPath());
128 m_xRbtEditNow
->set_active(true);
130 m_xBtCreate
->connect_clicked(LINK(this, SvxHyperlinkNewDocTp
, ClickNewHdl_Impl
));
135 SvxHyperlinkNewDocTp::~SvxHyperlinkNewDocTp ()
139 for (sal_Int32 n
= 0, nEntryCount
= m_xLbDocTypes
->n_children(); n
< nEntryCount
; ++n
)
140 delete weld::fromId
<DocumentTypeData
*>(m_xLbDocTypes
->get_id(n
));
141 m_xLbDocTypes
= nullptr;
145 /*************************************************************************
147 |* Fill the all dialog-controls except controls in groupbox "more..."
149 |************************************************************************/
152 void SvxHyperlinkNewDocTp::FillDlgFields(const OUString
& /*rStrURL*/)
156 void SvxHyperlinkNewDocTp::FillDocumentList()
158 weld::WaitObject
aWaitObj(mpDialog
->getDialog());
160 std::vector
<SvtDynMenuEntry
> aDynamicMenuEntries( SvtDynamicMenuOptions::GetMenu( EDynamicMenuType::NewMenu
) );
162 for ( const SvtDynMenuEntry
& rDynamicMenuEntry
: aDynamicMenuEntries
)
164 OUString aDocumentUrl
= rDynamicMenuEntry
.sURL
;
165 OUString aTitle
= rDynamicMenuEntry
.sTitle
;
167 //#i96822# business cards, labels and database should not be inserted here
168 if( aDocumentUrl
== "private:factory/swriter?slot=21051" ||
169 aDocumentUrl
== "private:factory/swriter?slot=21052" ||
170 aDocumentUrl
== "private:factory/sdatabase?Interactive" )
173 // Insert into listbox
174 if ( !aDocumentUrl
.isEmpty() )
176 if ( aDocumentUrl
== "private:factory/simpress?slot=6686" ) // SJ: #106216# do not start
177 aDocumentUrl
= "private:factory/simpress"; // the AutoPilot for impress
179 // insert private-url and default-extension as user-data
180 std::shared_ptr
<const SfxFilter
> pFilter
= SfxFilter::GetDefaultFilterFromFactory( aDocumentUrl
);
183 // insert doc-name and image
184 OUString aTitleName
= aTitle
.replaceFirst( "~", "" );
186 OUString
aStrDefExt(pFilter
->GetDefaultExtension());
187 DocumentTypeData
*pTypeData
= new DocumentTypeData(aDocumentUrl
, aStrDefExt
.copy(2));
188 OUString
sId(weld::toId(pTypeData
));
189 m_xLbDocTypes
->append(sId
, aTitleName
);
193 m_xLbDocTypes
->select(0);
196 /*************************************************************************
198 |* retrieve and prepare data from dialog-fields
200 |************************************************************************/
202 void SvxHyperlinkNewDocTp::GetCurrentItemData ( OUString
& rStrURL
, OUString
& aStrName
,
203 OUString
& aStrIntName
, OUString
& aStrFrame
,
204 SvxLinkInsertMode
& eMode
)
206 // get data from dialog-controls
207 rStrURL
= m_xCbbPath
->get_active_text();
209 if ( ImplGetURLObject( rStrURL
, m_xCbbPath
->GetBaseURL(), aURL
) )
211 rStrURL
= aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
214 GetDataFromCommonFields( aStrName
, aStrIntName
, aStrFrame
, eMode
);
217 /*************************************************************************
219 |* static method to create Tabpage
221 |************************************************************************/
223 std::unique_ptr
<IconChoicePage
> SvxHyperlinkNewDocTp::Create(weld::Container
* pWindow
, SvxHpLinkDlg
* pDlg
, const SfxItemSet
* pItemSet
)
225 return std::make_unique
<SvxHyperlinkNewDocTp
>(pWindow
, pDlg
, pItemSet
);
228 /*************************************************************************
232 |************************************************************************/
233 void SvxHyperlinkNewDocTp::SetInitFocus()
235 m_xCbbPath
->grab_focus();
245 OUString aStrDocName
;
247 css::uno::Reference
<css::frame::XFrame
> xFrame
;
248 SfxDispatcher
* pDispatcher
;
252 IMPL_STATIC_LINK(SvxHyperlinkNewDocTp
, DispatchDocument
, void*, p
, void)
254 std::unique_ptr
<ExecuteInfo
> xExecuteInfo(static_cast<ExecuteInfo
*>(p
));
255 if (!xExecuteInfo
->xFrame
.is())
259 //if it throws dispatcher is invalid
260 css::uno::Reference
<css::awt::XTopWindow
>(xExecuteInfo
->xFrame
->getContainerWindow(), css::uno::UNO_QUERY_THROW
);
262 SfxViewFrame
*pViewFrame
= nullptr;
265 SfxStringItem
aName( SID_FILE_NAME
, xExecuteInfo
->aStrDocName
);
266 SfxStringItem
aReferer( SID_REFERER
, "private:user" );
267 SfxStringItem
aFrame( SID_TARGETNAME
, "_blank");
269 OUString
aStrFlags('S');
270 if (xExecuteInfo
->bRbtEditLater
)
274 SfxStringItem
aFlags (SID_OPTIONS
, aStrFlags
);
277 const SfxPoolItem
* pReturn
= xExecuteInfo
->pDispatcher
->ExecuteList(
278 SID_OPENDOC
, SfxCallMode::SYNCHRON
,
279 { &aName
, &aFlags
, &aFrame
, &aReferer
});
282 const SfxViewFrameItem
*pItem
= dynamic_cast<const SfxViewFrameItem
*>( pReturn
); // SJ: pReturn is NULL if the Hyperlink
283 if ( pItem
) // creation is cancelled #106216#
285 pViewFrame
= pItem
->GetFrame();
288 SfxStringItem
aNewName( SID_FILE_NAME
, xExecuteInfo
->aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
289 SfxUnoFrameItem
aDocFrame( SID_FILLFRAME
, pViewFrame
->GetFrame().GetFrameInterface() );
290 pViewFrame
->GetDispatcher()->ExecuteList(
291 SID_SAVEASDOC
, SfxCallMode::SYNCHRON
,
292 { &aNewName
}, { &aDocFrame
});
296 if (xExecuteInfo
->bRbtEditNow
)
298 css::uno::Reference
<css::awt::XTopWindow
> xWindow(xExecuteInfo
->xFrame
->getContainerWindow(), css::uno::UNO_QUERY
);
299 if (xWindow
.is()) //will be false if the frame was exited while the document was loading (e.g. we waited for warning dialogs)
303 if (pViewFrame
&& xExecuteInfo
->bRbtEditLater
)
305 SfxObjectShell
* pObjShell
= pViewFrame
->GetObjectShell();
306 pObjShell
->DoClose();
314 /*************************************************************************
316 |* Any action to do after apply-button is pressed
318 \************************************************************************/
319 void SvxHyperlinkNewDocTp::DoApply()
321 weld::WaitObject
aWait(mpDialog
->getDialog());
323 // get data from dialog-controls
324 OUString aStrNewName
= m_xCbbPath
->get_active_text();
326 if ( aStrNewName
.isEmpty() )
327 aStrNewName
= maStrInitURL
;
329 // create a real URL-String
331 if ( !ImplGetURLObject( aStrNewName
, m_xCbbPath
->GetBaseURL(), aURL
) )
335 aStrNewName
= aURL
.GetURLPath( INetURLObject::DecodeMechanism::NONE
);
339 // check if file exists, warn before we overwrite it
340 std::unique_ptr
<SvStream
> pIStm
= ::utl::UcbStreamHelper::CreateStream( aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), StreamMode::READ
);
342 bool bOk
= pIStm
&& ( pIStm
->GetError() == ERRCODE_NONE
);
348 std::unique_ptr
<weld::MessageDialog
> xWarn(Application::CreateMessageDialog(mpDialog
->getDialog(),
349 VclMessageType::Warning
, VclButtonsType::YesNo
,
350 CuiResId(RID_CUISTR_HYPERDLG_QUERYOVERWRITE
)));
351 bCreate
= xWarn
->run() == RET_YES
;
354 catch (const uno::Exception
&)
358 if (!bCreate
|| aStrNewName
.isEmpty())
361 ExecuteInfo
* pExecuteInfo
= new ExecuteInfo
;
363 pExecuteInfo
->bRbtEditLater
= m_xRbtEditLater
->get_active();
364 pExecuteInfo
->bRbtEditNow
= m_xRbtEditNow
->get_active();
366 sal_Int32 nPos
= m_xLbDocTypes
->get_selected_index();
369 pExecuteInfo
->aURL
= aURL
;
370 pExecuteInfo
->aStrDocName
= weld::fromId
<DocumentTypeData
*>(m_xLbDocTypes
->get_id(nPos
))->aStrURL
;
373 pExecuteInfo
->xFrame
= GetDispatcher()->GetFrame()->GetFrame().GetFrameInterface();
374 pExecuteInfo
->pDispatcher
= GetDispatcher();
376 Application::PostUserEvent(LINK(nullptr, SvxHyperlinkNewDocTp
, DispatchDocument
), pExecuteInfo
);
379 /*************************************************************************
381 |* Click on imagebutton : new
383 |************************************************************************/
384 IMPL_LINK_NOARG(SvxHyperlinkNewDocTp
, ClickNewHdl_Impl
, weld::Button
&, void)
386 DisableClose( true );
387 uno::Reference
< XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
388 uno::Reference
< XFolderPicker2
> xFolderPicker
= sfx2::createFolderPicker(xContext
, mpDialog
->getDialog());
391 OUString
aTempStrURL( m_xCbbPath
->get_active_text() );
392 osl::FileBase::getFileURLFromSystemPath( aTempStrURL
, aStrURL
);
394 OUString aStrPath
= aStrURL
;
395 bool bZeroPath
= aStrPath
.isEmpty();
396 bool bHandleFileName
= bZeroPath
; // when path has length of 0, then the rest should always be handled
397 // as file name, otherwise we do not yet know
400 aStrPath
= SvtPathOptions().GetWorkPath();
401 else if( !::utl::UCBContentHelper::IsFolder( aStrURL
) )
402 bHandleFileName
= true;
404 xFolderPicker
->setDisplayDirectory( aStrPath
);
405 sal_Int16 nResult
= xFolderPicker
->execute();
406 DisableClose( false );
407 if( ExecutableDialogResults::OK
!= nResult
)
410 char const sSlash
[] = "/";
412 INetURLObject
aURL( aStrURL
, INetProtocol::File
);
414 if( bHandleFileName
)
415 aStrName
= bZeroPath
? aTempStrURL
: aURL
.getName();
417 m_xCbbPath
->SetBaseURL( xFolderPicker
->getDirectory() );
418 OUString
aStrTmp( xFolderPicker
->getDirectory() );
420 if( aStrTmp
[ aStrTmp
.getLength() - 1 ] != sSlash
[0] )
423 // append old file name
424 if( bHandleFileName
)
427 INetURLObject
aNewURL( aStrTmp
);
429 if (!aStrName
.isEmpty() && !aNewURL
.getExtension().isEmpty() &&
430 m_xLbDocTypes
->get_selected_index() != -1)
433 const sal_Int32 nPos
= m_xLbDocTypes
->get_selected_index();
434 aNewURL
.setExtension(weld::fromId
<DocumentTypeData
*>(m_xLbDocTypes
->get_id(nPos
))->aStrExt
);
437 if( aNewURL
.GetProtocol() == INetProtocol::File
)
439 osl::FileBase::getSystemPathFromFileURL(aNewURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), aStrTmp
);
443 aStrTmp
= aNewURL
.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous
);
446 m_xCbbPath
->set_entry_text( aStrTmp
);
449 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */