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 .
21 #include <sal/config.h>
30 #include <boost/optional.hpp>
31 #include <com/sun/star/awt/Rectangle.hpp>
32 #include <com/sun/star/awt/WindowAttribute.hpp>
33 #include <com/sun/star/awt/WindowClass.hpp>
34 #include <com/sun/star/awt/WindowDescriptor.hpp>
35 #include <com/sun/star/awt/XWindow.hpp>
36 #include <com/sun/star/awt/XWindowPeer.hpp>
37 #include <com/sun/star/beans/NamedValue.hpp>
38 #include <com/sun/star/beans/Optional.hpp>
39 #include <com/sun/star/beans/PropertyValue.hpp>
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <com/sun/star/configuration/theDefaultProvider.hpp>
42 #include <com/sun/star/container/XNameAccess.hpp>
43 #include <com/sun/star/container/XNameContainer.hpp>
44 #include <com/sun/star/deployment/DeploymentException.hpp>
45 #include <com/sun/star/deployment/UpdateInformationProvider.hpp>
46 #include <com/sun/star/deployment/XPackage.hpp>
47 #include <com/sun/star/deployment/XExtensionManager.hpp>
48 #include <com/sun/star/deployment/ExtensionManager.hpp>
49 #include <com/sun/star/deployment/XUpdateInformationProvider.hpp>
50 #include <com/sun/star/frame/Desktop.hpp>
51 #include <com/sun/star/frame/XDispatch.hpp>
52 #include <com/sun/star/frame/XDispatchProvider.hpp>
53 #include <com/sun/star/lang/IllegalArgumentException.hpp>
54 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
55 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
56 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
57 #include <com/sun/star/task/InteractionHandler.hpp>
58 #include <com/sun/star/task/XAbortChannel.hpp>
59 #include <com/sun/star/task/XJob.hpp>
60 #include <com/sun/star/ucb/CommandAbortedException.hpp>
61 #include <com/sun/star/ucb/CommandFailedException.hpp>
62 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
63 #include <com/sun/star/uno/Any.hxx>
64 #include <com/sun/star/uno/Exception.hpp>
65 #include <com/sun/star/uno/Reference.hxx>
66 #include <com/sun/star/uno/RuntimeException.hpp>
67 #include <com/sun/star/uno/Sequence.hxx>
68 #include <com/sun/star/uno/XInterface.hpp>
69 #include <com/sun/star/util/URL.hpp>
70 #include <com/sun/star/util/XChangesBatch.hpp>
71 #include <com/sun/star/util/URLTransformer.hpp>
72 #include <com/sun/star/util/XURLTransformer.hpp>
73 #include <com/sun/star/xml/dom/XElement.hpp>
74 #include <com/sun/star/xml/dom/XNode.hpp>
75 #include <osl/diagnose.h>
76 #include <rtl/ref.hxx>
77 #include <rtl/string.h>
78 #include <rtl/ustrbuf.hxx>
79 #include <rtl/ustring.h>
80 #include <rtl/ustring.hxx>
81 #include <sal/types.h>
82 #include <salhelper/thread.hxx>
83 #include <svtools/controldims.hxx>
84 #include <tools/gen.hxx>
85 #include <tools/link.hxx>
86 #include <tools/solar.h>
87 #include <unotools/configmgr.hxx>
88 #include <vcl/svapp.hxx>
90 #include <comphelper/processfactory.hxx>
91 #include <cppuhelper/exc_hlp.hxx>
93 #include <dp_dependencies.hxx>
94 #include <dp_descriptioninfoset.hxx>
95 #include <dp_identifier.hxx>
96 #include <dp_version.hxx>
98 #include <dp_update.hxx>
101 #include <strings.hrc>
102 #include <bitmaps.hlst>
103 #include "dp_gui_updatedata.hxx"
104 #include "dp_gui_updatedialog.hxx"
105 #include <dp_shared.hxx>
109 namespace com
{ namespace sun
{ namespace star
{ namespace uno
{
110 class XComponentContext
;
113 using namespace ::com::sun::star
;
114 using dp_gui::UpdateDialog
;
118 static sal_Unicode
const LF
= 0x000A;
119 static sal_Unicode
const CR
= 0x000D;
121 #define IGNORED_UPDATES OUString("/org.openoffice.Office.ExtensionManager/ExtensionUpdateData/IgnoredUpdates")
122 #define PROPERTY_VERSION "Version"
124 enum Kind
{ ENABLED_UPDATE
, DISABLED_UPDATE
, SPECIFIC_ERROR
};
126 OUString
confineToParagraph(OUString
const & text
) {
127 // Confine arbitrary text to a single paragraph in a VclMultiLineEdit
128 // This assumes that U+000A and U+000D are the only paragraph separators in
129 // a VclMultiLineEdit, and that replacing them with a single space
130 // each is acceptable:
131 return text
.replace(LF
, ' ').replace(CR
, ' ');
135 struct UpdateDialog::DisabledUpdate
{
137 uno::Sequence
< OUString
> unsatisfiedDependencies
;
138 // We also want to show release notes and publisher for disabled updates
139 css::uno::Reference
< css::xml::dom::XNode
> aUpdateInfo
;
142 struct UpdateDialog::SpecificError
{
148 struct UpdateDialog::IgnoredUpdate
{
149 OUString sExtensionID
;
152 IgnoredUpdate( const OUString
&rExtensionID
, const OUString
&rVersion
);
156 UpdateDialog::IgnoredUpdate::IgnoredUpdate( const OUString
&rExtensionID
, const OUString
&rVersion
):
157 sExtensionID( rExtensionID
),
162 struct UpdateDialog::Index
169 Index( Kind theKind
, sal_uInt16 nIndex
, const OUString
&rName
) :
177 class UpdateDialog::Thread
: public salhelper::Thread
{
180 uno::Reference
< uno::XComponentContext
> const & context
,
181 UpdateDialog
& dialog
,
182 const std::vector
< uno::Reference
< deployment::XPackage
> > & vExtensionList
);
187 virtual ~Thread() override
;
189 virtual void execute() override
;
191 void handleSpecificError(
192 uno::Reference
< deployment::XPackage
> const & package
,
193 uno::Any
const & exception
) const;
195 OUString
getUpdateDisplayString(
196 dp_gui::UpdateData
const & data
, OUString
const & version
= OUString()) const;
198 void prepareUpdateData(
199 css::uno::Reference
< css::xml::dom::XNode
> const & updateInfo
,
200 UpdateDialog::DisabledUpdate
& out_du
,
201 dp_gui::UpdateData
& out_data
) const;
204 UpdateDialog::DisabledUpdate
const & du
,
205 dp_gui::UpdateData
const & data
) const;
207 uno::Reference
< uno::XComponentContext
> m_context
;
208 UpdateDialog
& m_dialog
;
209 std::vector
< uno::Reference
< deployment::XPackage
> > m_vExtensionList
;
210 uno::Reference
< deployment::XUpdateInformationProvider
> m_updateInformation
;
211 uno::Reference
< task::XInteractionHandler
> m_xInteractionHdl
;
213 // guarded by Application::GetSolarMutex():
217 UpdateDialog::Thread::Thread(
218 uno::Reference
< uno::XComponentContext
> const & context
,
219 UpdateDialog
& dialog
,
220 const std::vector
< uno::Reference
< deployment::XPackage
> > &vExtensionList
):
221 salhelper::Thread("dp_gui_updatedialog"),
224 m_vExtensionList(vExtensionList
),
226 deployment::UpdateInformationProvider::create(context
)),
232 task::InteractionHandler::createWithParent(m_context
, dialog
.getDialog()->GetXWindow());
233 m_updateInformation
->setInteractionHandler( m_xInteractionHdl
);
237 void UpdateDialog::Thread::stop() {
242 m_updateInformation
->cancel();
245 UpdateDialog::Thread::~Thread()
247 if ( m_xInteractionHdl
.is() )
248 m_updateInformation
->setInteractionHandler( uno::Reference
< task::XInteractionHandler
> () );
251 void UpdateDialog::Thread::execute()
259 uno::Reference
<deployment::XExtensionManager
> extMgr
=
260 deployment::ExtensionManager::get(m_context
);
262 std::vector
<std::pair
<uno::Reference
<deployment::XPackage
>, uno::Any
> > errors
;
264 dp_misc::UpdateInfoMap updateInfoMap
= dp_misc::getOnlineUpdateInfos(
265 m_context
, extMgr
, m_updateInformation
, &m_vExtensionList
, errors
);
267 for (auto const& elem
: errors
)
268 handleSpecificError(elem
.first
, elem
.second
);
270 for (auto const& updateInfo
: updateInfoMap
)
272 dp_misc::UpdateInfo
const & info
= updateInfo
.second
;
273 UpdateData
updateData(info
.extension
);
274 DisabledUpdate disableUpdate
;
275 //determine if online updates meet the requirements
276 prepareUpdateData(info
.info
, disableUpdate
, updateData
);
278 //determine if the update is installed in the user or shared repository
279 OUString sOnlineVersion
;
281 sOnlineVersion
= info
.version
;
282 OUString sVersionUser
;
283 OUString sVersionShared
;
284 OUString sVersionBundled
;
285 uno::Sequence
< uno::Reference
< deployment::XPackage
> > extensions
;
287 extensions
= extMgr
->getExtensionsWithSameIdentifier(
288 dp_misc::getIdentifier(info
.extension
), info
.extension
->getName(),
289 uno::Reference
<ucb::XCommandEnvironment
>());
290 } catch ( const lang::IllegalArgumentException
& ) {
293 } catch ( const css::ucb::CommandFailedException
& ) {
297 OSL_ASSERT(extensions
.getLength() == 3);
298 if (extensions
[0].is() )
299 sVersionUser
= extensions
[0]->getVersion();
300 if (extensions
[1].is() )
301 sVersionShared
= extensions
[1]->getVersion();
302 if (extensions
[2].is() )
303 sVersionBundled
= extensions
[2]->getVersion();
305 bool bSharedReadOnly
= extMgr
->isReadOnlyRepository("shared");
307 dp_misc::UPDATE_SOURCE sourceUser
= dp_misc::isUpdateUserExtension(
308 bSharedReadOnly
, sVersionUser
, sVersionShared
, sVersionBundled
, sOnlineVersion
);
309 dp_misc::UPDATE_SOURCE sourceShared
= dp_misc::isUpdateSharedExtension(
310 bSharedReadOnly
, sVersionShared
, sVersionBundled
, sOnlineVersion
);
312 if (sourceUser
!= dp_misc::UPDATE_SOURCE_NONE
)
314 if (sourceUser
== dp_misc::UPDATE_SOURCE_SHARED
)
316 updateData
.aUpdateSource
= extensions
[1];
317 updateData
.updateVersion
= extensions
[1]->getVersion();
319 else if (sourceUser
== dp_misc::UPDATE_SOURCE_BUNDLED
)
321 updateData
.aUpdateSource
= extensions
[2];
322 updateData
.updateVersion
= extensions
[2]->getVersion();
324 if (!update(disableUpdate
, updateData
))
328 if (sourceShared
!= dp_misc::UPDATE_SOURCE_NONE
)
330 if (sourceShared
== dp_misc::UPDATE_SOURCE_BUNDLED
)
332 updateData
.aUpdateSource
= extensions
[2];
333 updateData
.updateVersion
= extensions
[2]->getVersion();
335 updateData
.bIsShared
= true;
336 if (!update(disableUpdate
, updateData
))
344 m_dialog
.checkingDone();
348 //Parameter package can be null
349 void UpdateDialog::Thread::handleSpecificError(
350 uno::Reference
< deployment::XPackage
> const & package
,
351 uno::Any
const & exception
) const
353 UpdateDialog::SpecificError data
;
355 data
.name
= package
->getDisplayName();
357 if (exception
>>= e
) {
358 data
.message
= e
.Message
;
362 m_dialog
.addSpecificError(data
);
366 OUString
UpdateDialog::Thread::getUpdateDisplayString(
367 dp_gui::UpdateData
const & data
, OUString
const & version
) const
369 OSL_ASSERT(data
.aInstalledPackage
.is());
370 OUStringBuffer
b(data
.aInstalledPackage
->getDisplayName());
375 b
.append(m_dialog
.m_version
);
378 if (!version
.isEmpty())
381 b
.append(data
.updateVersion
);
383 if (!data
.sWebsiteURL
.isEmpty())
389 b
.append(m_dialog
.m_browserbased
);
392 return b
.makeStringAndClear();
395 /** out_data will only be filled if all dependencies are ok.
397 void UpdateDialog::Thread::prepareUpdateData(
398 uno::Reference
< xml::dom::XNode
> const & updateInfo
,
399 UpdateDialog::DisabledUpdate
& out_du
,
400 dp_gui::UpdateData
& out_data
) const
402 if (!updateInfo
.is())
404 dp_misc::DescriptionInfoset
infoset(m_context
, updateInfo
);
405 OSL_ASSERT(!infoset
.getVersion().isEmpty());
406 uno::Sequence
< uno::Reference
< xml::dom::XElement
> > ds(
407 dp_misc::Dependencies::check(infoset
));
409 out_du
.aUpdateInfo
= updateInfo
;
410 out_du
.unsatisfiedDependencies
.realloc(ds
.getLength());
411 for (sal_Int32 i
= 0; i
< ds
.getLength(); ++i
) {
412 out_du
.unsatisfiedDependencies
[i
] = dp_misc::Dependencies::getErrorText(ds
[i
]);
415 const ::boost::optional
< OUString
> updateWebsiteURL(infoset
.getLocalizedUpdateWebsiteURL());
417 out_du
.name
= getUpdateDisplayString(out_data
, infoset
.getVersion());
419 if (!out_du
.unsatisfiedDependencies
.hasElements())
421 out_data
.aUpdateInfo
= updateInfo
;
422 out_data
.updateVersion
= infoset
.getVersion();
423 if (updateWebsiteURL
)
424 out_data
.sWebsiteURL
= *updateWebsiteURL
;
428 bool UpdateDialog::Thread::update(
429 UpdateDialog::DisabledUpdate
const & du
,
430 dp_gui::UpdateData
const & data
) const
433 if (!du
.unsatisfiedDependencies
.hasElements())
437 m_dialog
.addEnabledUpdate(getUpdateDisplayString(data
), data
);
443 m_dialog
.addDisabledUpdate(du
);
450 // UpdateDialog ----------------------------------------------------------
451 UpdateDialog::UpdateDialog(
452 uno::Reference
< uno::XComponentContext
> const & context
,
453 weld::Window
* parent
, const std::vector
<uno::Reference
< deployment::XPackage
> > &vExtensionList
,
454 std::vector
< dp_gui::UpdateData
> * updateData
)
455 : GenericDialogController(parent
, "desktop/ui/updatedialog.ui", "UpdateDialog")
457 , m_none(DpResId(RID_DLG_UPDATE_NONE
))
458 , m_noInstallable(DpResId(RID_DLG_UPDATE_NOINSTALLABLE
))
459 , m_failure(DpResId(RID_DLG_UPDATE_FAILURE
))
460 , m_unknownError(DpResId(RID_DLG_UPDATE_UNKNOWNERROR
))
461 , m_noDescription(DpResId(RID_DLG_UPDATE_NODESCRIPTION
))
462 , m_noInstall(DpResId(RID_DLG_UPDATE_NOINSTALL
))
463 , m_noDependency(DpResId(RID_DLG_UPDATE_NODEPENDENCY
))
464 , m_noDependencyCurVer(DpResId(RID_DLG_UPDATE_NODEPENDENCY_CUR_VER
))
465 , m_browserbased(DpResId(RID_DLG_UPDATE_BROWSERBASED
))
466 , m_version(DpResId(RID_DLG_UPDATE_VERSION
))
467 , m_ignoredUpdate(DpResId(RID_DLG_UPDATE_IGNORED_UPDATE
))
468 , m_updateData(*updateData
)
469 , m_thread(new UpdateDialog::Thread(context
, *this, vExtensionList
))
470 , m_xChecking(m_xBuilder
->weld_label("UPDATE_CHECKING"))
471 , m_xThrobber(m_xBuilder
->weld_spinner("THROBBER"))
472 , m_xUpdate(m_xBuilder
->weld_label("UPDATE_LABEL"))
473 , m_xUpdates(m_xBuilder
->weld_tree_view("checklist"))
474 , m_xAll(m_xBuilder
->weld_check_button("UPDATE_ALL"))
475 , m_xDescription(m_xBuilder
->weld_label("DESCRIPTION_LABEL"))
476 , m_xPublisherLabel(m_xBuilder
->weld_label("PUBLISHER_LABEL"))
477 , m_xPublisherLink(m_xBuilder
->weld_link_button("PUBLISHER_LINK"))
478 , m_xReleaseNotesLabel(m_xBuilder
->weld_label("RELEASE_NOTES_LABEL"))
479 , m_xReleaseNotesLink(m_xBuilder
->weld_link_button("RELEASE_NOTES_LINK"))
480 , m_xDescriptions(m_xBuilder
->weld_text_view("DESCRIPTIONS"))
481 , m_xOk(m_xBuilder
->weld_button("ok"))
482 , m_xClose(m_xBuilder
->weld_button("close"))
483 , m_xHelp(m_xBuilder
->weld_button("help"))
485 auto nWidth
= m_xDescriptions
->get_approximate_digit_width() * 62;
486 auto nHeight
= m_xDescriptions
->get_height_rows(8);
487 m_xDescriptions
->set_size_request(nWidth
, nHeight
);
488 m_xUpdates
->set_size_request(nWidth
, nHeight
);
490 std::vector
<int> aWidths
;
491 aWidths
.push_back(m_xUpdates
->get_checkbox_column_width());
492 m_xUpdates
->set_column_fixed_widths(aWidths
);
494 OSL_ASSERT(updateData
!= nullptr);
496 m_xExtensionManager
= deployment::ExtensionManager::get( context
);
498 m_xUpdates
->connect_changed(LINK(this, UpdateDialog
, selectionHandler
));
499 m_xUpdates
->connect_toggled(LINK(this, UpdateDialog
, entryToggled
));
500 m_xAll
->connect_toggled(LINK(this, UpdateDialog
, allHandler
));
501 m_xOk
->connect_clicked(LINK(this, UpdateDialog
, okHandler
));
502 m_xClose
->connect_clicked(LINK(this, UpdateDialog
, closeHandler
));
503 if (!dp_misc::office_is_running())
504 m_xHelp
->set_sensitive(false);
510 UpdateDialog::~UpdateDialog()
514 short UpdateDialog::run() {
515 m_xThrobber
->start();
517 short nRet
= GenericDialogController::run();
522 IMPL_LINK(UpdateDialog
, entryToggled
, const row_col
&, rRowCol
, void)
524 int nRow
= rRowCol
.first
;
526 // error's can't be enabled
527 const UpdateDialog::Index
* p
= reinterpret_cast<UpdateDialog::Index
const *>(m_xUpdates
->get_id(rRowCol
.first
).toInt64());
528 if (p
->m_eKind
== SPECIFIC_ERROR
)
529 m_xUpdates
->set_toggle(nRow
, TRISTATE_FALSE
, 0);
534 void UpdateDialog::insertItem(UpdateDialog::Index
*pEntry
, bool bEnabledCheckBox
)
536 int nEntry
= m_xUpdates
->n_children();
537 m_xUpdates
->append();
538 m_xUpdates
->set_toggle(nEntry
, bEnabledCheckBox
? TRISTATE_TRUE
: TRISTATE_FALSE
, 0);
539 m_xUpdates
->set_text(nEntry
, pEntry
->m_aName
, 1);
540 m_xUpdates
->set_id(nEntry
, OUString::number(reinterpret_cast<sal_Int64
>(pEntry
)));
543 void UpdateDialog::addAdditional(UpdateDialog::Index
* index
, bool bEnabledCheckBox
)
545 m_xAll
->set_sensitive(true);
546 if (m_xAll
->get_active())
548 insertItem(index
, bEnabledCheckBox
);
549 m_xUpdate
->set_sensitive(true);
550 m_xUpdates
->set_sensitive(true);
551 m_xDescription
->set_sensitive(true);
552 m_xDescriptions
->set_sensitive(true);
556 void UpdateDialog::addEnabledUpdate( OUString
const & name
,
557 dp_gui::UpdateData
const & data
)
559 sal_uInt16 nIndex
= sal::static_int_cast
< sal_uInt16
>( m_enabledUpdates
.size() );
560 UpdateDialog::Index
*pEntry
= new UpdateDialog::Index( ENABLED_UPDATE
, nIndex
, name
);
562 m_enabledUpdates
.push_back( data
);
563 m_ListboxEntries
.emplace_back( pEntry
);
565 if (!isIgnoredUpdate(pEntry
))
567 insertItem(pEntry
, true);
570 addAdditional(pEntry
, false);
572 m_xUpdate
->set_sensitive(true);
573 m_xUpdates
->set_sensitive(true);
574 m_xDescription
->set_sensitive(true);
575 m_xDescriptions
->set_sensitive(true);
578 void UpdateDialog::addDisabledUpdate( UpdateDialog::DisabledUpdate
const & data
)
580 sal_uInt16 nIndex
= sal::static_int_cast
< sal_uInt16
>( m_disabledUpdates
.size() );
581 UpdateDialog::Index
*pEntry
= new UpdateDialog::Index( DISABLED_UPDATE
, nIndex
, data
.name
);
583 m_disabledUpdates
.push_back( data
);
584 m_ListboxEntries
.emplace_back( pEntry
);
586 isIgnoredUpdate( pEntry
);
587 addAdditional(pEntry
, false);
590 void UpdateDialog::addSpecificError( UpdateDialog::SpecificError
const & data
)
592 sal_uInt16 nIndex
= sal::static_int_cast
< sal_uInt16
>( m_specificErrors
.size() );
593 UpdateDialog::Index
*pEntry
= new UpdateDialog::Index( SPECIFIC_ERROR
, nIndex
, data
.name
);
595 m_specificErrors
.push_back( data
);
596 m_ListboxEntries
.emplace_back( pEntry
);
598 addAdditional(pEntry
, false);
601 void UpdateDialog::checkingDone() {
605 if (m_xUpdates
->n_children() == 0)
608 m_xDescription
->set_sensitive(true);
609 m_xDescriptions
->set_sensitive(true);
611 if ( m_disabledUpdates
.empty() && m_specificErrors
.empty() && m_ignoredUpdates
.empty() )
612 showDescription( m_none
);
614 showDescription( m_noInstallable
);
620 void UpdateDialog::enableOk() {
621 if (!m_xChecking
->get_visible()) {
623 for (int i
= 0, nCount
= m_xUpdates
->n_children(); i
< nCount
; ++i
) {
624 if (m_xUpdates
->get_toggle(i
, 0) == TRISTATE_TRUE
)
627 m_xOk
->set_sensitive(nChecked
!= 0);
631 // *********************************************************************************
632 void UpdateDialog::createNotifyJob( bool bPrepareOnly
,
633 uno::Sequence
< uno::Sequence
< OUString
> > const &rItemList
)
635 if ( !dp_misc::office_is_running() )
638 // notify update check job
641 uno::Reference
< lang::XMultiServiceFactory
> xConfigProvider(
642 configuration::theDefaultProvider::get(
643 comphelper::getProcessComponentContext()));
645 beans::PropertyValue aProperty
;
646 aProperty
.Name
= "nodepath";
647 aProperty
.Value
<<= OUString("org.openoffice.Office.Addons/AddonUI/OfficeHelp/UpdateCheckJob");
649 uno::Sequence
< uno::Any
> aArgumentList( 1 );
650 aArgumentList
[0] <<= aProperty
;
652 uno::Reference
< container::XNameAccess
> xNameAccess(
653 xConfigProvider
->createInstanceWithArguments(
654 "com.sun.star.configuration.ConfigurationAccess", aArgumentList
),
655 uno::UNO_QUERY_THROW
);
658 xNameAccess
->getByName("URL") >>= aURL
.Complete
;
660 uno::Reference
< uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
661 uno::Reference
< util::XURLTransformer
> xTransformer
= util::URLTransformer::create(xContext
);
663 xTransformer
->parseStrict(aURL
);
665 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create( xContext
);
666 uno::Reference
< frame::XDispatchProvider
> xDispatchProvider( xDesktop
->getCurrentFrame(),
667 uno::UNO_QUERY_THROW
);
668 uno::Reference
< frame::XDispatch
> xDispatch
= xDispatchProvider
->queryDispatch(aURL
, OUString(), 0);
672 uno::Sequence
< beans::PropertyValue
> aPropList(2);
673 aProperty
.Name
= "updateList";
674 aProperty
.Value
<<= rItemList
;
675 aPropList
[0] = aProperty
;
676 aProperty
.Name
= "prepareOnly";
677 aProperty
.Value
<<= bPrepareOnly
;
678 aPropList
[1] = aProperty
;
680 xDispatch
->dispatch(aURL
, aPropList
);
683 catch( const uno::Exception
& e
)
685 dp_misc::TRACE( "Caught exception: "
686 + e
.Message
+ "\n thread terminated.\n\n");
690 // *********************************************************************************
691 void UpdateDialog::notifyMenubar( bool bPrepareOnly
, bool bRecheckOnly
)
693 if ( !dp_misc::office_is_running() )
696 uno::Sequence
< uno::Sequence
< OUString
> > aItemList
;
698 if ( ! bRecheckOnly
)
700 sal_Int32 nCount
= 0;
701 for (sal_uInt16 i
= 0, nItemCount
= m_xUpdates
->n_children(); i
< nItemCount
; ++i
)
703 uno::Sequence
< OUString
> aItem(2);
705 UpdateDialog::Index
const * p
= reinterpret_cast< UpdateDialog::Index
const * >(m_xUpdates
->get_id(i
).toInt64());
707 if ( p
->m_eKind
== ENABLED_UPDATE
)
709 dp_gui::UpdateData aUpdData
= m_enabledUpdates
[ p
->m_nIndex
];
710 aItem
[0] = dp_misc::getIdentifier( aUpdData
.aInstalledPackage
);
712 dp_misc::DescriptionInfoset
aInfoset( m_context
, aUpdData
.aUpdateInfo
);
713 aItem
[1] = aInfoset
.getVersion();
718 aItemList
.realloc( nCount
+ 1 );
719 aItemList
[ nCount
] = aItem
;
724 createNotifyJob( bPrepareOnly
, aItemList
);
727 // *********************************************************************************
729 void UpdateDialog::initDescription()
731 m_xPublisherLabel
->hide();
732 m_xPublisherLink
->hide();
733 m_xReleaseNotesLabel
->hide();
734 m_xReleaseNotesLink
->hide();
737 void UpdateDialog::clearDescription()
739 m_xPublisherLabel
->hide();
740 m_xPublisherLink
->hide();
741 m_xPublisherLink
->set_label("");
742 m_xPublisherLink
->set_uri("");
743 m_xReleaseNotesLabel
->hide();
744 m_xReleaseNotesLink
->hide();
745 m_xReleaseNotesLink
->set_uri( "" );
746 m_xDescriptions
->set_text("");
749 bool UpdateDialog::showDescription(uno::Reference
< xml::dom::XNode
> const & aUpdateInfo
)
751 dp_misc::DescriptionInfoset
infoset(m_context
, aUpdateInfo
);
752 return showDescription(infoset
.getLocalizedPublisherNameAndURL(),
753 infoset
.getLocalizedReleaseNotesURL());
756 bool UpdateDialog::showDescription(uno::Reference
< deployment::XPackage
> const & aExtension
)
758 OSL_ASSERT(aExtension
.is());
759 beans::StringPair pubInfo
= aExtension
->getPublisherInfo();
760 return showDescription(std::make_pair(pubInfo
.First
, pubInfo
.Second
),
764 bool UpdateDialog::showDescription(std::pair
< OUString
, OUString
> const & pairPublisher
,
765 OUString
const & sReleaseNotes
)
767 OUString sPub
= pairPublisher
.first
;
768 OUString sURL
= pairPublisher
.second
;
770 if ( sPub
.isEmpty() && sURL
.isEmpty() && sReleaseNotes
.isEmpty() )
774 if ( !sPub
.isEmpty() )
776 m_xPublisherLabel
->show();
777 m_xPublisherLink
->show();
778 m_xPublisherLink
->set_label(sPub
);
779 m_xPublisherLink
->set_uri(sURL
);
782 if ( !sReleaseNotes
.isEmpty() )
784 m_xReleaseNotesLabel
->show();
785 m_xReleaseNotesLink
->show();
786 m_xReleaseNotesLink
->set_uri( sReleaseNotes
);
791 bool UpdateDialog::showDescription( const OUString
& rDescription
)
793 if ( rDescription
.isEmpty() )
797 m_xDescriptions
->set_text(rDescription
);
801 void UpdateDialog::getIgnoredUpdates()
803 uno::Reference
< lang::XMultiServiceFactory
> xConfig(
804 configuration::theDefaultProvider::get(m_context
));
805 beans::NamedValue
aValue( "nodepath", uno::Any( IGNORED_UPDATES
) );
806 uno::Sequence
< uno::Any
> args(1);
809 uno::Reference
< container::XNameAccess
> xNameAccess( xConfig
->createInstanceWithArguments( "com.sun.star.configuration.ConfigurationAccess", args
), uno::UNO_QUERY_THROW
);
810 uno::Sequence
< OUString
> aElementNames
= xNameAccess
->getElementNames();
812 for ( sal_Int32 i
= 0; i
< aElementNames
.getLength(); i
++ )
814 OUString aIdentifier
= aElementNames
[i
];
817 uno::Any
aPropValue( uno::Reference
< beans::XPropertySet
>( xNameAccess
->getByName( aIdentifier
), uno::UNO_QUERY_THROW
)->getPropertyValue( PROPERTY_VERSION
) );
818 aPropValue
>>= aVersion
;
819 IgnoredUpdate
*pData
= new IgnoredUpdate( aIdentifier
, aVersion
);
820 m_ignoredUpdates
.emplace_back( pData
);
825 bool UpdateDialog::isIgnoredUpdate( UpdateDialog::Index
* index
)
827 bool bIsIgnored
= false;
829 if (! m_ignoredUpdates
.empty() )
831 OUString aExtensionID
;
834 if ( index
->m_eKind
== ENABLED_UPDATE
)
836 dp_gui::UpdateData aUpdData
= m_enabledUpdates
[ index
->m_nIndex
];
837 aExtensionID
= dp_misc::getIdentifier( aUpdData
.aInstalledPackage
);
838 aVersion
= aUpdData
.updateVersion
;
840 else if ( index
->m_eKind
== DISABLED_UPDATE
)
842 DisabledUpdate
&rData
= m_disabledUpdates
[ index
->m_nIndex
];
843 dp_misc::DescriptionInfoset
aInfoset( m_context
, rData
.aUpdateInfo
);
844 ::boost::optional
< OUString
> aID( aInfoset
.getIdentifier() );
847 aVersion
= aInfoset
.getVersion();
850 for (auto const& ignoredUpdate
: m_ignoredUpdates
)
852 if ( ignoredUpdate
->sExtensionID
== aExtensionID
)
854 if ( ( !ignoredUpdate
->sVersion
.isEmpty() ) || ( ignoredUpdate
->sVersion
== aVersion
) )
857 index
->m_bIgnored
= true;
868 IMPL_LINK_NOARG(UpdateDialog
, selectionHandler
, weld::TreeView
&, void)
871 int nSelectedPos
= m_xUpdates
->get_selected_index();
874 const UpdateDialog::Index
* p
= nullptr;
875 if (nSelectedPos
!= -1)
876 p
= reinterpret_cast<UpdateDialog::Index
const *>(m_xUpdates
->get_id(nSelectedPos
).toInt64());
879 sal_uInt16 pos
= p
->m_nIndex
;
885 if ( m_enabledUpdates
[ pos
].aUpdateSource
.is() )
886 showDescription( m_enabledUpdates
[ pos
].aUpdateSource
);
888 showDescription( m_enabledUpdates
[ pos
].aUpdateInfo
);
891 b
.append( m_ignoredUpdate
);
895 case DISABLED_UPDATE
:
897 if ( !m_disabledUpdates
.empty() )
898 showDescription( m_disabledUpdates
[pos
].aUpdateInfo
);
901 b
.append( m_ignoredUpdate
);
903 if ( m_disabledUpdates
.empty() )
906 UpdateDialog::DisabledUpdate
& data
= m_disabledUpdates
[ pos
];
907 if (data
.unsatisfiedDependencies
.hasElements())
909 // create error string for version mismatch
910 OUString
sVersion( "%VERSION" );
911 OUString
sProductName( "%PRODUCTNAME" );
912 sal_Int32 nPos
= m_noDependencyCurVer
.indexOf( sVersion
);
915 m_noDependencyCurVer
= m_noDependencyCurVer
.replaceAt( nPos
, sVersion
.getLength(), utl::ConfigManager::getAboutBoxProductVersion() );
917 nPos
= m_noDependencyCurVer
.indexOf( sProductName
);
920 m_noDependencyCurVer
= m_noDependencyCurVer
.replaceAt( nPos
, sProductName
.getLength(), utl::ConfigManager::getProductName() );
922 nPos
= m_noDependency
.indexOf( sProductName
);
925 m_noDependency
= m_noDependency
.replaceAt( nPos
, sProductName
.getLength(), utl::ConfigManager::getProductName() );
928 b
.append(m_noInstall
);
930 b
.append(m_noDependency
);
931 for (sal_Int32 i
= 0;
932 i
< data
.unsatisfiedDependencies
.getLength(); ++i
)
936 // U+2003 EM SPACE would be better than two spaces,
937 // but some fonts do not contain it
940 data
.unsatisfiedDependencies
[i
]));
944 b
.append(m_noDependencyCurVer
);
950 UpdateDialog::SpecificError
& data
= m_specificErrors
[ pos
];
953 b
.append( data
.message
.isEmpty() ? m_unknownError
: data
.message
);
963 b
.append( m_noDescription
);
965 showDescription( b
.makeStringAndClear() );
968 IMPL_LINK_NOARG(UpdateDialog
, allHandler
, weld::ToggleButton
&, void)
970 if (m_xAll
->get_active())
972 m_xUpdate
->set_sensitive(true);
973 m_xUpdates
->set_sensitive(true);
974 m_xDescription
->set_sensitive(true);
975 m_xDescriptions
->set_sensitive(true);
977 for (auto const& listboxEntry
: m_ListboxEntries
)
979 if ( listboxEntry
->m_bIgnored
|| ( listboxEntry
->m_eKind
!= ENABLED_UPDATE
) )
980 insertItem(listboxEntry
.get(), false);
985 for (sal_uInt16 i
= m_xUpdates
->n_children(); i
!= 0 ;)
988 UpdateDialog::Index
const * p
= reinterpret_cast< UpdateDialog::Index
const * >( m_xUpdates
->get_id(i
).toInt64() );
989 if ( p
->m_bIgnored
|| ( p
->m_eKind
!= ENABLED_UPDATE
) )
991 m_xUpdates
->remove(i
);
995 if (m_xUpdates
->n_children() == 0)
998 m_xUpdate
->set_sensitive(false);
999 m_xUpdates
->set_sensitive(false);
1000 if (m_xChecking
->get_visible())
1001 m_xDescription
->set_sensitive(false);
1003 showDescription(m_noInstallable
);
1008 IMPL_LINK_NOARG(UpdateDialog
, okHandler
, weld::Button
&, void)
1010 //If users are going to update a shared extension then we need
1012 for (auto const& enableUpdate
: m_enabledUpdates
)
1014 OSL_ASSERT(enableUpdate
.aInstalledPackage
.is());
1015 //If the user has no write access to the shared folder then the update
1016 //for a shared extension is disable, that is it cannot be in m_enabledUpdates
1020 for (sal_uInt16 i
= 0, nCount
= m_xUpdates
->n_children(); i
< nCount
; ++i
)
1022 UpdateDialog::Index
const * p
=
1023 reinterpret_cast< UpdateDialog::Index
const * >(
1024 m_xUpdates
->get_id(i
).toInt64());
1025 if (p
->m_eKind
== ENABLED_UPDATE
&& m_xUpdates
->get_toggle(i
, 0) == TRISTATE_TRUE
) {
1026 m_updateData
.push_back( m_enabledUpdates
[ p
->m_nIndex
] );
1030 m_xDialog
->response(RET_OK
);
1033 IMPL_LINK_NOARG(UpdateDialog
, closeHandler
, weld::Button
&, void)
1036 m_xDialog
->response(RET_CANCEL
);
1039 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */