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/docfac.hxx>
24 #include <sfx2/docfilt.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 <sfx2/filedlghelper.hxx>
36 #include <unotools/ucbstreamhelper.hxx>
37 #include <unotools/ucbhelper.hxx>
39 #include <comphelper/processfactory.hxx>
40 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <com/sun/star/ui/dialogs/FolderPicker.hpp>
42 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
44 #include <bitmaps.hlst>
45 #include <dialmgr.hxx>
46 #include <strings.hrc>
48 using namespace ::com::sun::star::lang
;
49 using namespace ::com::sun::star::ui::dialogs
;
50 using namespace ::com::sun::star::uno
;
52 using namespace ::com::sun::star
;
54 /*************************************************************************
56 |* Data-struct for documenttypes in listbox
58 |************************************************************************/
60 struct DocumentTypeData
64 DocumentTypeData (const OUString
& aURL
, const OUString
& aExt
) : aStrURL(aURL
), aStrExt(aExt
)
68 bool SvxHyperlinkNewDocTp::ImplGetURLObject( const OUString
& rPath
, const OUString
& rBase
, INetURLObject
& aURLObject
) const
70 bool bIsValidURL
= !rPath
.isEmpty();
73 aURLObject
.SetURL( rPath
);
74 if ( aURLObject
.GetProtocol() == INetProtocol::NotValid
) // test if the source is already a valid url
75 { // if not we have to create a url from a physical file name
77 INetURLObject
base(rBase
);
79 aURLObject
= base
.smartRel2Abs(
80 rPath
, wasAbs
, true, INetURLObject::EncodeMechanism::All
,
81 RTL_TEXTENCODING_UTF8
, true);
83 bIsValidURL
= aURLObject
.GetProtocol() != INetProtocol::NotValid
;
86 OUString
aBase( aURLObject
.getName( INetURLObject::LAST_SEGMENT
, false ) );
87 if ( aBase
.isEmpty() || ( aBase
[0] == '.' ) )
92 sal_Int32 nPos
= m_pLbDocTypes
->GetSelectedEntryPos();
93 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
94 aURLObject
.SetExtension( static_cast<DocumentTypeData
*>(m_pLbDocTypes
->GetEntryData( nPos
))->aStrExt
);
101 /*************************************************************************
103 |* Constructor / Destructor
105 |************************************************************************/
107 SvxHyperlinkNewDocTp::SvxHyperlinkNewDocTp ( vcl::Window
*pParent
, IconChoiceDialog
* pDlg
, const SfxItemSet
* pItemSet
)
108 : SvxHyperlinkTabPageBase ( pParent
, pDlg
, "HyperlinkNewDocPage", "cui/ui/hyperlinknewdocpage.ui", pItemSet
)
110 get(m_pRbtEditNow
, "editnow");
111 get(m_pRbtEditLater
, "editlater");
112 get(m_pCbbPath
, "path");
113 m_pCbbPath
->SetSmartProtocol(INetProtocol::File
);
114 get(m_pBtCreate
, "create");
115 m_pBtCreate
->SetModeImage(Image(StockImage::Yes
, RID_SVXBMP_NEWDOC
));
116 get(m_pLbDocTypes
, "types");
117 m_pLbDocTypes
->set_height_request(m_pLbDocTypes
->GetTextHeight() * 5);
119 // Set HC bitmaps and disable display of bitmap names.
120 m_pBtCreate
->EnableTextDisplay (false);
124 SetExchangeSupport ();
127 m_pCbbPath
->SetBaseURL(SvtPathOptions().GetWorkPath());
130 m_pRbtEditNow
->Check();
132 m_pBtCreate
->SetClickHdl ( LINK ( this, SvxHyperlinkNewDocTp
, ClickNewHdl_Impl
) );
137 SvxHyperlinkNewDocTp::~SvxHyperlinkNewDocTp ()
142 void SvxHyperlinkNewDocTp::dispose()
146 for ( sal_Int32 n
=0; n
<m_pLbDocTypes
->GetEntryCount(); n
++ )
147 delete static_cast<DocumentTypeData
*>(m_pLbDocTypes
->GetEntryData ( n
));
148 m_pLbDocTypes
= nullptr;
150 m_pRbtEditNow
.clear();
151 m_pRbtEditLater
.clear();
154 m_pLbDocTypes
.clear();
155 SvxHyperlinkTabPageBase::dispose();
158 /*************************************************************************
160 |* Fill the all dialog-controls except controls in groupbox "more..."
162 |************************************************************************/
165 void SvxHyperlinkNewDocTp::FillDlgFields(const OUString
& /*rStrURL*/)
169 void SvxHyperlinkNewDocTp::FillDocumentList ()
173 uno::Sequence
< uno::Sequence
< beans::PropertyValue
> >
174 aDynamicMenuEntries( SvtDynamicMenuOptions().GetMenu( EDynamicMenuType::NewMenu
) );
176 sal_uInt32 i
, nCount
= aDynamicMenuEntries
.getLength();
177 for ( i
= 0; i
< nCount
; i
++ )
179 uno::Sequence
< beans::PropertyValue
>& rDynamicMenuEntry
= aDynamicMenuEntries
[ i
];
181 OUString aDocumentUrl
, aTitle
;
183 for ( int e
= 0; e
< rDynamicMenuEntry
.getLength(); e
++ )
185 if ( rDynamicMenuEntry
[ e
].Name
== DYNAMICMENU_PROPERTYNAME_URL
)
186 rDynamicMenuEntry
[ e
].Value
>>= aDocumentUrl
;
187 else if ( rDynamicMenuEntry
[e
].Name
== DYNAMICMENU_PROPERTYNAME_TITLE
)
188 rDynamicMenuEntry
[e
].Value
>>= aTitle
;
190 //#i96822# business cards, labels and database should not be inserted here
191 if( aDocumentUrl
== "private:factory/swriter?slot=21051" ||
192 aDocumentUrl
== "private:factory/swriter?slot=21052" ||
193 aDocumentUrl
== "private:factory/sdatabase?Interactive" )
196 // Insert into listbox
197 if ( !aDocumentUrl
.isEmpty() )
199 if ( aDocumentUrl
== "private:factory/simpress?slot=6686" ) // SJ: #106216# do not start
200 aDocumentUrl
= "private:factory/simpress"; // the AutoPilot for impress
202 // insert private-url and default-extension as user-data
203 std::shared_ptr
<const SfxFilter
> pFilter
= SfxFilter::GetDefaultFilterFromFactory( aDocumentUrl
);
206 // insert doc-name and image
207 OUString aTitleName
= aTitle
.replaceFirst( "~", "" );
209 sal_Int16 nPos
= m_pLbDocTypes
->InsertEntry ( aTitleName
);
210 OUString
aStrDefExt( pFilter
->GetDefaultExtension () );
211 DocumentTypeData
*pTypeData
= new DocumentTypeData ( aDocumentUrl
, aStrDefExt
.copy( 2 ) );
212 m_pLbDocTypes
->SetEntryData ( nPos
, pTypeData
);
216 m_pLbDocTypes
->SelectEntryPos ( 0 );
221 /*************************************************************************
223 |* retrieve and prepare data from dialog-fields
225 |************************************************************************/
227 void SvxHyperlinkNewDocTp::GetCurentItemData ( OUString
& rStrURL
, OUString
& aStrName
,
228 OUString
& aStrIntName
, OUString
& aStrFrame
,
229 SvxLinkInsertMode
& eMode
)
231 // get data from dialog-controls
232 rStrURL
= m_pCbbPath
->GetText();
234 if ( ImplGetURLObject( rStrURL
, m_pCbbPath
->GetBaseURL(), aURL
) )
236 rStrURL
= aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
239 GetDataFromCommonFields( aStrName
, aStrIntName
, aStrFrame
, eMode
);
242 /*************************************************************************
244 |* static method to create Tabpage
246 |************************************************************************/
248 VclPtr
<IconChoicePage
> SvxHyperlinkNewDocTp::Create( vcl::Window
* pWindow
, IconChoiceDialog
* pDlg
, const SfxItemSet
* pItemSet
)
250 return VclPtr
<SvxHyperlinkNewDocTp
>::Create( pWindow
, pDlg
, pItemSet
);
253 /*************************************************************************
257 |************************************************************************/
259 void SvxHyperlinkNewDocTp::SetInitFocus()
261 m_pCbbPath
->GrabFocus();
264 /*************************************************************************
266 |* Ask page whether an insert is possible
268 \************************************************************************/
270 bool SvxHyperlinkNewDocTp::AskApply()
272 INetURLObject aINetURLObject
;
273 bool bRet
= ImplGetURLObject( m_pCbbPath
->GetText(), m_pCbbPath
->GetBaseURL(), aINetURLObject
);
276 std::unique_ptr
<weld::MessageDialog
> xWarn(Application::CreateMessageDialog(GetFrameWeld(),
277 VclMessageType::Warning
, VclButtonsType::Ok
,
278 CuiResId(RID_SVXSTR_HYPDLG_NOVALIDFILENAME
)));
291 OUString aStrDocName
;
293 css::uno::Reference
<css::frame::XFrame
> xFrame
;
294 SfxDispatcher
* pDispatcher
;
298 IMPL_STATIC_LINK(SvxHyperlinkNewDocTp
, DispatchDocument
, void*, p
, void)
300 std::unique_ptr
<ExecuteInfo
> xExecuteInfo(static_cast<ExecuteInfo
*>(p
));
301 if (!xExecuteInfo
->xFrame
.is())
305 //if it throws dispatcher is invalid
306 css::uno::Reference
<css::awt::XTopWindow
>(xExecuteInfo
->xFrame
->getContainerWindow(), css::uno::UNO_QUERY_THROW
);
308 SfxViewFrame
*pViewFrame
= nullptr;
311 SfxStringItem
aName( SID_FILE_NAME
, xExecuteInfo
->aStrDocName
);
312 SfxStringItem
aReferer( SID_REFERER
, "private:user" );
313 SfxStringItem
aFrame( SID_TARGETNAME
, "_blank");
315 OUString
aStrFlags('S');
316 if (xExecuteInfo
->bRbtEditLater
)
320 SfxStringItem
aFlags (SID_OPTIONS
, aStrFlags
);
323 const SfxPoolItem
* pReturn
= xExecuteInfo
->pDispatcher
->ExecuteList(
324 SID_OPENDOC
, SfxCallMode::SYNCHRON
,
325 { &aName
, &aFlags
, &aFrame
, &aReferer
});
328 const SfxViewFrameItem
*pItem
= dynamic_cast<const SfxViewFrameItem
*>( pReturn
); // SJ: pReturn is NULL if the Hyperlink
329 if ( pItem
) // creation is cancelled #106216#
331 pViewFrame
= pItem
->GetFrame();
334 SfxStringItem
aNewName( SID_FILE_NAME
, xExecuteInfo
->aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
335 SfxUnoFrameItem
aDocFrame( SID_FILLFRAME
, pViewFrame
->GetFrame().GetFrameInterface() );
336 fprintf(stderr
, "is there a frame int %p\n", pViewFrame
->GetFrame().GetFrameInterface().get() );
337 pViewFrame
->GetDispatcher()->ExecuteList(
338 SID_SAVEASDOC
, SfxCallMode::SYNCHRON
,
339 { &aNewName
}, { &aDocFrame
});
343 if (xExecuteInfo
->bRbtEditNow
)
345 css::uno::Reference
<css::awt::XTopWindow
> xWindow(xExecuteInfo
->xFrame
->getContainerWindow(), css::uno::UNO_QUERY
);
346 if (xWindow
.is()) //will be false if the frame was exited while the document was loading (e.g. we waited for warning dialogs)
350 if (pViewFrame
&& xExecuteInfo
->bRbtEditLater
)
352 SfxObjectShell
* pObjShell
= pViewFrame
->GetObjectShell();
353 pObjShell
->DoClose();
361 /*************************************************************************
363 |* Any action to do after apply-button is pressed
365 \************************************************************************/
367 void SvxHyperlinkNewDocTp::DoApply ()
371 // get data from dialog-controls
372 OUString aStrNewName
= m_pCbbPath
->GetText();
374 if ( aStrNewName
.isEmpty() )
375 aStrNewName
= maStrInitURL
;
377 // create a real URL-String
379 if ( ImplGetURLObject( aStrNewName
, m_pCbbPath
->GetBaseURL(), aURL
) )
382 aStrNewName
= aURL
.GetURLPath( INetURLObject::DecodeMechanism::NONE
);
386 // check if file exists, warn before we overwrite it
387 std::unique_ptr
<SvStream
> pIStm
= ::utl::UcbStreamHelper::CreateStream( aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), StreamMode::READ
);
389 bool bOk
= pIStm
&& ( pIStm
->GetError() == ERRCODE_NONE
);
395 std::unique_ptr
<weld::MessageDialog
> xWarn(Application::CreateMessageDialog(GetFrameWeld(),
396 VclMessageType::Warning
, VclButtonsType::YesNo
,
397 CuiResId(RID_SVXSTR_HYPERDLG_QUERYOVERWRITE
)));
398 bCreate
= xWarn
->run() == RET_YES
;
401 catch (const uno::Exception
&)
405 if (bCreate
&& !aStrNewName
.isEmpty())
407 ExecuteInfo
* pExecuteInfo
= new ExecuteInfo
;
409 pExecuteInfo
->bRbtEditLater
= m_pRbtEditLater
->IsChecked();
410 pExecuteInfo
->bRbtEditNow
= m_pRbtEditNow
->IsChecked();
412 sal_Int32 nPos
= m_pLbDocTypes
->GetSelectedEntryPos();
413 if( nPos
== LISTBOX_ENTRY_NOTFOUND
)
415 pExecuteInfo
->aURL
= aURL
;
416 pExecuteInfo
->aStrDocName
= static_cast<DocumentTypeData
*>(
417 m_pLbDocTypes
->GetEntryData( nPos
))->aStrURL
;
420 pExecuteInfo
->xFrame
= GetDispatcher()->GetFrame()->GetFrame().GetFrameInterface();
421 pExecuteInfo
->pDispatcher
= GetDispatcher();
423 Application::PostUserEvent(LINK(nullptr, SvxHyperlinkNewDocTp
, DispatchDocument
), pExecuteInfo
);
430 /*************************************************************************
432 |* Click on imagebutton : new
434 |************************************************************************/
436 IMPL_LINK_NOARG(SvxHyperlinkNewDocTp
, ClickNewHdl_Impl
, Button
*, void)
438 uno::Reference
< XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
439 uno::Reference
< XFolderPicker2
> xFolderPicker
= FolderPicker::create(xContext
);
442 OUString
aTempStrURL( m_pCbbPath
->GetText() );
443 osl::FileBase::getFileURLFromSystemPath( aTempStrURL
, aStrURL
);
445 OUString aStrPath
= aStrURL
;
446 bool bZeroPath
= aStrPath
.isEmpty();
447 bool bHandleFileName
= bZeroPath
; // when path has length of 0, then the rest should always be handled
448 // as file name, otherwise we do not yet know
451 aStrPath
= SvtPathOptions().GetWorkPath();
452 else if( !::utl::UCBContentHelper::IsFolder( aStrURL
) )
453 bHandleFileName
= true;
455 xFolderPicker
->setDisplayDirectory( aStrPath
);
456 DisableClose( true );
457 sal_Int16 nResult
= xFolderPicker
->execute();
458 DisableClose( false );
459 if( ExecutableDialogResults::OK
== nResult
)
461 sal_Char
const sSlash
[] = "/";
463 INetURLObject
aURL( aStrURL
, INetProtocol::File
);
465 if( bHandleFileName
)
466 aStrName
= bZeroPath
? aTempStrURL
: aURL
.getName();
468 m_pCbbPath
->SetBaseURL( xFolderPicker
->getDirectory() );
469 OUString
aStrTmp( xFolderPicker
->getDirectory() );
471 if( aStrTmp
[ aStrTmp
.getLength() - 1 ] != sSlash
[0] )
474 // append old file name
475 if( bHandleFileName
)
478 INetURLObject
aNewURL( aStrTmp
);
480 if( !aStrName
.isEmpty() && !aNewURL
.getExtension().isEmpty() &&
481 m_pLbDocTypes
->GetSelectedEntryPos() != LISTBOX_ENTRY_NOTFOUND
)
484 const sal_Int32 nPos
= m_pLbDocTypes
->GetSelectedEntryPos();
485 aNewURL
.setExtension( static_cast<DocumentTypeData
*>(m_pLbDocTypes
->GetEntryData( nPos
))->aStrExt
);
488 if( aNewURL
.GetProtocol() == INetProtocol::File
)
490 osl::FileBase::getSystemPathFromFileURL(aNewURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), aStrTmp
);
494 aStrTmp
= aNewURL
.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous
);
497 m_pCbbPath
->SetText ( aStrTmp
);
501 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */