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/viewfrm.hxx>
23 #include <sfx2/docfilt.hxx>
24 #include <svl/stritem.hxx>
25 #include <com/sun/star/awt/XTopWindow.hpp>
26 #include <com/sun/star/uno/Reference.h>
27 #include <com/sun/star/uno/Sequence.h>
28 #include <com/sun/star/beans/PropertyValue.hpp>
29 #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/FolderPicker.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 |************************************************************************/
58 struct DocumentTypeData
62 DocumentTypeData (const OUString
& aURL
, const OUString
& aExt
) : aStrURL(aURL
), aStrExt(aExt
)
66 bool SvxHyperlinkNewDocTp::ImplGetURLObject( const OUString
& rPath
, const OUString
& rBase
, INetURLObject
& aURLObject
) const
68 bool bIsValidURL
= !rPath
.isEmpty();
71 aURLObject
.SetURL( rPath
);
72 if ( aURLObject
.GetProtocol() == INetProtocol::NotValid
) // test if the source is already a valid url
73 { // if not we have to create a url from a physical file name
75 INetURLObject
base(rBase
);
77 aURLObject
= base
.smartRel2Abs(
78 rPath
, wasAbs
, true, INetURLObject::EncodeMechanism::All
,
79 RTL_TEXTENCODING_UTF8
, true);
81 bIsValidURL
= aURLObject
.GetProtocol() != INetProtocol::NotValid
;
84 OUString
aBase( aURLObject
.getName( INetURLObject::LAST_SEGMENT
, false ) );
85 if ( aBase
.isEmpty() || ( aBase
[0] == '.' ) )
90 sal_Int32 nPos
= m_xLbDocTypes
->get_selected_index();
92 aURLObject
.SetExtension(reinterpret_cast<DocumentTypeData
*>(m_xLbDocTypes
->get_id(nPos
).toInt64())->aStrExt
);
99 /*************************************************************************
101 |* Constructor / Destructor
103 |************************************************************************/
105 SvxHyperlinkNewDocTp::SvxHyperlinkNewDocTp(weld::Container
* pParent
, SvxHpLinkDlg
* pDlg
, const SfxItemSet
* pItemSet
)
106 : SvxHyperlinkTabPageBase(pParent
, pDlg
, "cui/ui/hyperlinknewdocpage.ui", "HyperlinkNewDocPage", pItemSet
)
107 , m_xRbtEditNow(xBuilder
->weld_radio_button("editnow"))
108 , m_xRbtEditLater(xBuilder
->weld_radio_button("editlater"))
109 , m_xCbbPath(new SvxHyperURLBox(xBuilder
->weld_combo_box("path")))
110 , m_xBtCreate(xBuilder
->weld_button("create"))
111 , m_xLbDocTypes(xBuilder
->weld_tree_view("types"))
113 m_xCbbPath
->SetSmartProtocol(INetProtocol::File
);
114 m_xLbDocTypes
->set_size_request(-1, m_xLbDocTypes
->get_height_rows(5));
118 SetExchangeSupport ();
121 m_xCbbPath
->SetBaseURL(SvtPathOptions().GetWorkPath());
124 m_xRbtEditNow
->set_active(true);
126 m_xBtCreate
->connect_clicked(LINK(this, SvxHyperlinkNewDocTp
, ClickNewHdl_Impl
));
131 SvxHyperlinkNewDocTp::~SvxHyperlinkNewDocTp ()
135 for (sal_Int32 n
= 0, nEntryCount
= m_xLbDocTypes
->n_children(); n
< nEntryCount
; ++n
)
136 delete reinterpret_cast<DocumentTypeData
*>(m_xLbDocTypes
->get_id(n
).toInt64());
137 m_xLbDocTypes
= nullptr;
141 /*************************************************************************
143 |* Fill the all dialog-controls except controls in groupbox "more..."
145 |************************************************************************/
148 void SvxHyperlinkNewDocTp::FillDlgFields(const OUString
& /*rStrURL*/)
152 void SvxHyperlinkNewDocTp::FillDocumentList()
154 weld::WaitObject
aWaitObj(mpDialog
->getDialog());
156 uno::Sequence
< uno::Sequence
< beans::PropertyValue
> >
157 aDynamicMenuEntries( SvtDynamicMenuOptions().GetMenu( EDynamicMenuType::NewMenu
) );
159 sal_uInt32 i
, nCount
= aDynamicMenuEntries
.getLength();
160 for ( i
= 0; i
< nCount
; i
++ )
162 uno::Sequence
< beans::PropertyValue
>& rDynamicMenuEntry
= aDynamicMenuEntries
[ i
];
164 OUString aDocumentUrl
, aTitle
;
166 for ( int e
= 0; e
< rDynamicMenuEntry
.getLength(); e
++ )
168 if ( rDynamicMenuEntry
[ e
].Name
== DYNAMICMENU_PROPERTYNAME_URL
)
169 rDynamicMenuEntry
[ e
].Value
>>= aDocumentUrl
;
170 else if ( rDynamicMenuEntry
[e
].Name
== DYNAMICMENU_PROPERTYNAME_TITLE
)
171 rDynamicMenuEntry
[e
].Value
>>= aTitle
;
173 //#i96822# business cards, labels and database should not be inserted here
174 if( aDocumentUrl
== "private:factory/swriter?slot=21051" ||
175 aDocumentUrl
== "private:factory/swriter?slot=21052" ||
176 aDocumentUrl
== "private:factory/sdatabase?Interactive" )
179 // Insert into listbox
180 if ( !aDocumentUrl
.isEmpty() )
182 if ( aDocumentUrl
== "private:factory/simpress?slot=6686" ) // SJ: #106216# do not start
183 aDocumentUrl
= "private:factory/simpress"; // the AutoPilot for impress
185 // insert private-url and default-extension as user-data
186 std::shared_ptr
<const SfxFilter
> pFilter
= SfxFilter::GetDefaultFilterFromFactory( aDocumentUrl
);
189 // insert doc-name and image
190 OUString aTitleName
= aTitle
.replaceFirst( "~", "" );
192 OUString
aStrDefExt(pFilter
->GetDefaultExtension());
193 DocumentTypeData
*pTypeData
= new DocumentTypeData(aDocumentUrl
, aStrDefExt
.copy(2));
194 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(pTypeData
)));
195 m_xLbDocTypes
->append(sId
, aTitleName
);
199 m_xLbDocTypes
->select(0);
202 /*************************************************************************
204 |* retrieve and prepare data from dialog-fields
206 |************************************************************************/
208 void SvxHyperlinkNewDocTp::GetCurentItemData ( OUString
& rStrURL
, OUString
& aStrName
,
209 OUString
& aStrIntName
, OUString
& aStrFrame
,
210 SvxLinkInsertMode
& eMode
)
212 // get data from dialog-controls
213 rStrURL
= m_xCbbPath
->get_active_text();
215 if ( ImplGetURLObject( rStrURL
, m_xCbbPath
->GetBaseURL(), aURL
) )
217 rStrURL
= aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
220 GetDataFromCommonFields( aStrName
, aStrIntName
, aStrFrame
, eMode
);
223 /*************************************************************************
225 |* static method to create Tabpage
227 |************************************************************************/
229 std::unique_ptr
<IconChoicePage
> SvxHyperlinkNewDocTp::Create(weld::Container
* pWindow
, SvxHpLinkDlg
* pDlg
, const SfxItemSet
* pItemSet
)
231 return std::make_unique
<SvxHyperlinkNewDocTp
>(pWindow
, pDlg
, pItemSet
);
234 /*************************************************************************
238 |************************************************************************/
239 void SvxHyperlinkNewDocTp::SetInitFocus()
241 m_xCbbPath
->grab_focus();
244 /*************************************************************************
246 |* Ask page whether an insert is possible
248 \************************************************************************/
249 bool SvxHyperlinkNewDocTp::AskApply()
251 INetURLObject aINetURLObject
;
252 bool bRet
= ImplGetURLObject(m_xCbbPath
->get_active_text(), m_xCbbPath
->GetBaseURL(), aINetURLObject
);
255 std::unique_ptr
<weld::MessageDialog
> xWarn(Application::CreateMessageDialog(mpDialog
->getDialog(),
256 VclMessageType::Warning
, VclButtonsType::Ok
,
257 CuiResId(RID_SVXSTR_HYPDLG_NOVALIDFILENAME
)));
270 OUString aStrDocName
;
272 css::uno::Reference
<css::frame::XFrame
> xFrame
;
273 SfxDispatcher
* pDispatcher
;
277 IMPL_STATIC_LINK(SvxHyperlinkNewDocTp
, DispatchDocument
, void*, p
, void)
279 std::unique_ptr
<ExecuteInfo
> xExecuteInfo(static_cast<ExecuteInfo
*>(p
));
280 if (!xExecuteInfo
->xFrame
.is())
284 //if it throws dispatcher is invalid
285 css::uno::Reference
<css::awt::XTopWindow
>(xExecuteInfo
->xFrame
->getContainerWindow(), css::uno::UNO_QUERY_THROW
);
287 SfxViewFrame
*pViewFrame
= nullptr;
290 SfxStringItem
aName( SID_FILE_NAME
, xExecuteInfo
->aStrDocName
);
291 SfxStringItem
aReferer( SID_REFERER
, "private:user" );
292 SfxStringItem
aFrame( SID_TARGETNAME
, "_blank");
294 OUString
aStrFlags('S');
295 if (xExecuteInfo
->bRbtEditLater
)
299 SfxStringItem
aFlags (SID_OPTIONS
, aStrFlags
);
302 const SfxPoolItem
* pReturn
= xExecuteInfo
->pDispatcher
->ExecuteList(
303 SID_OPENDOC
, SfxCallMode::SYNCHRON
,
304 { &aName
, &aFlags
, &aFrame
, &aReferer
});
307 const SfxViewFrameItem
*pItem
= dynamic_cast<const SfxViewFrameItem
*>( pReturn
); // SJ: pReturn is NULL if the Hyperlink
308 if ( pItem
) // creation is cancelled #106216#
310 pViewFrame
= pItem
->GetFrame();
313 SfxStringItem
aNewName( SID_FILE_NAME
, xExecuteInfo
->aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
314 SfxUnoFrameItem
aDocFrame( SID_FILLFRAME
, pViewFrame
->GetFrame().GetFrameInterface() );
315 fprintf(stderr
, "is there a frame int %p\n", pViewFrame
->GetFrame().GetFrameInterface().get() );
316 pViewFrame
->GetDispatcher()->ExecuteList(
317 SID_SAVEASDOC
, SfxCallMode::SYNCHRON
,
318 { &aNewName
}, { &aDocFrame
});
322 if (xExecuteInfo
->bRbtEditNow
)
324 css::uno::Reference
<css::awt::XTopWindow
> xWindow(xExecuteInfo
->xFrame
->getContainerWindow(), css::uno::UNO_QUERY
);
325 if (xWindow
.is()) //will be false if the frame was exited while the document was loading (e.g. we waited for warning dialogs)
329 if (pViewFrame
&& xExecuteInfo
->bRbtEditLater
)
331 SfxObjectShell
* pObjShell
= pViewFrame
->GetObjectShell();
332 pObjShell
->DoClose();
340 /*************************************************************************
342 |* Any action to do after apply-button is pressed
344 \************************************************************************/
345 void SvxHyperlinkNewDocTp::DoApply()
347 weld::WaitObject
aWait(mpDialog
->getDialog());
349 // get data from dialog-controls
350 OUString aStrNewName
= m_xCbbPath
->get_active_text();
352 if ( aStrNewName
.isEmpty() )
353 aStrNewName
= maStrInitURL
;
355 // create a real URL-String
357 if ( ImplGetURLObject( aStrNewName
, m_xCbbPath
->GetBaseURL(), aURL
) )
360 aStrNewName
= aURL
.GetURLPath( INetURLObject::DecodeMechanism::NONE
);
364 // check if file exists, warn before we overwrite it
365 std::unique_ptr
<SvStream
> pIStm
= ::utl::UcbStreamHelper::CreateStream( aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), StreamMode::READ
);
367 bool bOk
= pIStm
&& ( pIStm
->GetError() == ERRCODE_NONE
);
373 std::unique_ptr
<weld::MessageDialog
> xWarn(Application::CreateMessageDialog(mpDialog
->getDialog(),
374 VclMessageType::Warning
, VclButtonsType::YesNo
,
375 CuiResId(RID_SVXSTR_HYPERDLG_QUERYOVERWRITE
)));
376 bCreate
= xWarn
->run() == RET_YES
;
379 catch (const uno::Exception
&)
383 if (bCreate
&& !aStrNewName
.isEmpty())
385 ExecuteInfo
* pExecuteInfo
= new ExecuteInfo
;
387 pExecuteInfo
->bRbtEditLater
= m_xRbtEditLater
->get_active();
388 pExecuteInfo
->bRbtEditNow
= m_xRbtEditNow
->get_active();
390 sal_Int32 nPos
= m_xLbDocTypes
->get_selected_index();
393 pExecuteInfo
->aURL
= aURL
;
394 pExecuteInfo
->aStrDocName
= reinterpret_cast<DocumentTypeData
*>(m_xLbDocTypes
->get_id(nPos
).toInt64())->aStrURL
;
397 pExecuteInfo
->xFrame
= GetDispatcher()->GetFrame()->GetFrame().GetFrameInterface();
398 pExecuteInfo
->pDispatcher
= GetDispatcher();
400 Application::PostUserEvent(LINK(nullptr, SvxHyperlinkNewDocTp
, DispatchDocument
), pExecuteInfo
);
405 /*************************************************************************
407 |* Click on imagebutton : new
409 |************************************************************************/
410 IMPL_LINK_NOARG(SvxHyperlinkNewDocTp
, ClickNewHdl_Impl
, weld::Button
&, void)
412 DisableClose( true );
413 uno::Reference
< XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
414 uno::Reference
< XFolderPicker2
> xFolderPicker
= FolderPicker::create(xContext
);
417 OUString
aTempStrURL( m_xCbbPath
->get_active_text() );
418 osl::FileBase::getFileURLFromSystemPath( aTempStrURL
, aStrURL
);
420 OUString aStrPath
= aStrURL
;
421 bool bZeroPath
= aStrPath
.isEmpty();
422 bool bHandleFileName
= bZeroPath
; // when path has length of 0, then the rest should always be handled
423 // as file name, otherwise we do not yet know
426 aStrPath
= SvtPathOptions().GetWorkPath();
427 else if( !::utl::UCBContentHelper::IsFolder( aStrURL
) )
428 bHandleFileName
= true;
430 xFolderPicker
->setDisplayDirectory( aStrPath
);
431 sal_Int16 nResult
= xFolderPicker
->execute();
432 DisableClose( false );
433 if( ExecutableDialogResults::OK
== nResult
)
435 sal_Char
const sSlash
[] = "/";
437 INetURLObject
aURL( aStrURL
, INetProtocol::File
);
439 if( bHandleFileName
)
440 aStrName
= bZeroPath
? aTempStrURL
: aURL
.getName();
442 m_xCbbPath
->SetBaseURL( xFolderPicker
->getDirectory() );
443 OUString
aStrTmp( xFolderPicker
->getDirectory() );
445 if( aStrTmp
[ aStrTmp
.getLength() - 1 ] != sSlash
[0] )
448 // append old file name
449 if( bHandleFileName
)
452 INetURLObject
aNewURL( aStrTmp
);
454 if (!aStrName
.isEmpty() && !aNewURL
.getExtension().isEmpty() &&
455 m_xLbDocTypes
->get_selected_index() != -1)
458 const sal_Int32 nPos
= m_xLbDocTypes
->get_selected_index();
459 aNewURL
.setExtension(reinterpret_cast<DocumentTypeData
*>(m_xLbDocTypes
->get_id(nPos
).toInt64())->aStrExt
);
462 if( aNewURL
.GetProtocol() == INetProtocol::File
)
464 osl::FileBase::getSystemPathFromFileURL(aNewURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), aStrTmp
);
468 aStrTmp
= aNewURL
.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous
);
471 m_xCbbPath
->set_entry_text( aStrTmp
);
475 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */