28#include <com/sun/star/beans/NamedValue.hpp>
29#include <com/sun/star/beans/XPropertySet.hpp>
30#include <com/sun/star/configuration/theDefaultProvider.hpp>
31#include <com/sun/star/container/XNameAccess.hpp>
32#include <com/sun/star/deployment/UpdateInformationProvider.hpp>
33#include <com/sun/star/deployment/ExtensionManager.hpp>
34#include <com/sun/star/deployment/XUpdateInformationProvider.hpp>
35#include <com/sun/star/frame/Desktop.hpp>
36#include <com/sun/star/frame/XDispatch.hpp>
37#include <com/sun/star/frame/XDispatchProvider.hpp>
38#include <com/sun/star/lang/IllegalArgumentException.hpp>
39#include <com/sun/star/task/InteractionHandler.hpp>
40#include <com/sun/star/ucb/CommandFailedException.hpp>
41#include <com/sun/star/ucb/XCommandEnvironment.hpp>
42#include <com/sun/star/uno/Any.hxx>
43#include <com/sun/star/uno/Exception.hpp>
44#include <com/sun/star/uno/Reference.hxx>
45#include <com/sun/star/uno/Sequence.hxx>
46#include <com/sun/star/util/URL.hpp>
47#include <com/sun/star/util/URLTransformer.hpp>
48#include <com/sun/star/util/XURLTransformer.hpp>
49#include <com/sun/star/xml/dom/XElement.hpp>
50#include <osl/diagnose.h>
52#include <rtl/ustrbuf.hxx>
53#include <rtl/ustring.hxx>
78 class XComponentContext;
89constexpr OUStringLiteral IGNORED_UPDATES =
u"/org.openoffice.Office.ExtensionManager/ExtensionUpdateData/IgnoredUpdates";
92enum Kind { ENABLED_UPDATE, DISABLED_UPDATE, SPECIFIC_ERROR };
94OUString confineToParagraph(OUString
const & text) {
99 return text.replace(
LF,
' ').replace(CR,
' ');
125 sExtensionID(
std::move( aExtensionID )),
126 sVersion(
std::move( aVersion ))
137 Index( Kind theKind, sal_uInt16 nIndex, OUString aName ) :
157 virtual void execute()
override;
164 dp_gui::UpdateData const & data, std::u16string_view version = std::u16string_view())
const;
167 css::uno::Reference< css::xml::dom::XNode >
const & updateInfo,
210 m_updateInformation->cancel();
215 if ( m_xInteractionHdl.is() )
228 deployment::ExtensionManager::get(m_context);
230 std::vector<std::pair<uno::Reference<deployment::XPackage>,
uno::Any > > errors;
235 for (
auto const& elem : errors)
236 handleSpecificError(elem.first, elem.second);
238 for (
auto const& updateInfo : updateInfoMap)
244 prepareUpdateData(info.
info, disableUpdate, updateData);
247 OUString sOnlineVersion;
250 OUString sVersionUser;
251 OUString sVersionShared;
252 OUString sVersionBundled;
255 extensions = extMgr->getExtensionsWithSameIdentifier(
258 }
catch (
const lang::IllegalArgumentException& ) {
261 }
catch (
const css::ucb::CommandFailedException& ) {
271 sVersionBundled =
extensions[2]->getVersion();
273 bool bSharedReadOnly = extMgr->isReadOnlyRepository(
"shared");
276 bSharedReadOnly, sVersionUser, sVersionShared, sVersionBundled, sOnlineVersion);
278 bSharedReadOnly, sVersionShared, sVersionBundled, sOnlineVersion);
292 if (!
update(disableUpdate, updateData))
304 if (!
update(disableUpdate, updateData))
312 m_dialog.checkingDone();
325 if (exception >>= e) {
330 m_dialog.addSpecificError(data);
343 b.append(m_dialog.m_version);
346 if (!version.empty())
357 b.append(m_dialog.m_browserbased);
360 return b.makeStringAndClear();
370 if (!updateInfo.is())
380 for (sal_Int32
i = 0;
i < ds.getLength(); ++
i) {
386 out_du.
name = getUpdateDisplayString(out_data, infoset.
getVersion());
392 if (updateWebsiteURL)
406 m_dialog.addEnabledUpdate(getUpdateDisplayString(data), data);
412 m_dialog.addDisabledUpdate(du);
420UpdateDialog::UpdateDialog(
423 std::vector< dp_gui::UpdateData > * updateData)
424 : GenericDialogController(parent,
"desktop/ui/updatedialog.ui",
"UpdateDialog")
426 , m_none(
DpResId(RID_DLG_UPDATE_NONE))
427 , m_noInstallable(
DpResId(RID_DLG_UPDATE_NOINSTALLABLE))
428 , m_failure(
DpResId(RID_DLG_UPDATE_FAILURE))
429 , m_unknownError(
DpResId(RID_DLG_UPDATE_UNKNOWNERROR))
430 , m_noDescription(
DpResId(RID_DLG_UPDATE_NODESCRIPTION))
431 , m_noInstall(
DpResId(RID_DLG_UPDATE_NOINSTALL))
432 , m_noDependency(
DpResId(RID_DLG_UPDATE_NODEPENDENCY))
433 , m_noDependencyCurVer(
DpResId(RID_DLG_UPDATE_NODEPENDENCY_CUR_VER))
434 , m_browserbased(
DpResId(RID_DLG_UPDATE_BROWSERBASED))
435 , m_version(
DpResId(RID_DLG_UPDATE_VERSION))
436 , m_ignoredUpdate(
DpResId(RID_DLG_UPDATE_IGNORED_UPDATE))
437 , m_updateData(*updateData)
439 , m_xChecking(m_xBuilder->weld_label(
"UPDATE_CHECKING"))
440 , m_xThrobber(m_xBuilder->weld_spinner(
"THROBBER"))
441 , m_xUpdate(m_xBuilder->weld_label(
"UPDATE_LABEL"))
442 , m_xUpdates(m_xBuilder->weld_tree_view(
"checklist"))
443 , m_xAll(m_xBuilder->weld_check_button(
"UPDATE_ALL"))
444 , m_xDescription(m_xBuilder->weld_label(
"DESCRIPTION_LABEL"))
445 , m_xPublisherLabel(m_xBuilder->weld_label(
"PUBLISHER_LABEL"))
446 , m_xPublisherLink(m_xBuilder->weld_link_button(
"PUBLISHER_LINK"))
447 , m_xReleaseNotesLabel(m_xBuilder->weld_label(
"RELEASE_NOTES_LABEL"))
448 , m_xReleaseNotesLink(m_xBuilder->weld_link_button(
"RELEASE_NOTES_LINK"))
449 , m_xDescriptions(m_xBuilder->weld_text_view(
"DESCRIPTIONS"))
450 , m_xOk(m_xBuilder->weld_button(
"ok"))
451 , m_xClose(m_xBuilder->weld_button(
"close"))
452 , m_xHelp(m_xBuilder->weld_button(
"help"))
454 auto nWidth = m_xDescriptions->get_approximate_digit_width() * 62;
455 auto nHeight = m_xDescriptions->get_height_rows(8);
456 m_xDescriptions->set_size_request(nWidth, nHeight);
457 m_xUpdates->set_size_request(nWidth, nHeight);
461 OSL_ASSERT(updateData !=
nullptr);
463 m_xExtensionManager = deployment::ExtensionManager::get( context );
471 m_xHelp->set_sensitive(
false);
477UpdateDialog::~UpdateDialog()
481short UpdateDialog::run() {
482 m_xThrobber->start();
484 short nRet = GenericDialogController::run();
492 const UpdateDialog::Index*
p = weld::fromId<UpdateDialog::Index const *>(m_xUpdates->get_id(rRowCol.first));
493 if (
p->m_eKind == SPECIFIC_ERROR)
501 int nEntry = m_xUpdates->n_children();
502 m_xUpdates->append();
504 m_xUpdates->set_text(nEntry, pEntry->
m_aName, 0);
505 m_xUpdates->set_id(nEntry,
weld::toId(pEntry));
510 m_xAll->set_sensitive(
true);
511 if (m_xAll->get_active())
513 insertItem(
index, bEnabledCheckBox);
514 m_xUpdate->set_sensitive(
true);
515 m_xUpdates->set_sensitive(
true);
516 m_xDescription->set_sensitive(
true);
517 m_xDescriptions->set_sensitive(
true);
521void UpdateDialog::addEnabledUpdate( OUString
const & name,
524 sal_uInt16
nIndex = sal::static_int_cast< sal_uInt16 >( m_enabledUpdates.size() );
527 m_enabledUpdates.push_back( data );
528 m_ListboxEntries.emplace_back( pEntry );
530 if (!isIgnoredUpdate(pEntry))
532 insertItem(pEntry,
true);
535 addAdditional(pEntry,
false);
537 m_xUpdate->set_sensitive(
true);
538 m_xUpdates->set_sensitive(
true);
539 m_xDescription->set_sensitive(
true);
540 m_xDescriptions->set_sensitive(
true);
545 sal_uInt16
nIndex = sal::static_int_cast< sal_uInt16 >( m_disabledUpdates.size() );
548 m_disabledUpdates.push_back( data );
549 m_ListboxEntries.emplace_back( pEntry );
551 isIgnoredUpdate( pEntry );
552 addAdditional(pEntry,
false);
557 sal_uInt16
nIndex = sal::static_int_cast< sal_uInt16 >( m_specificErrors.size() );
560 m_specificErrors.push_back( data );
561 m_ListboxEntries.emplace_back( pEntry );
563 addAdditional(pEntry,
false);
566void UpdateDialog::checkingDone() {
570 if (m_xUpdates->n_children() == 0)
573 m_xDescription->set_sensitive(
true);
574 m_xDescriptions->set_sensitive(
true);
576 if ( m_disabledUpdates.empty() && m_specificErrors.empty() && m_ignoredUpdates.empty() )
577 showDescription( m_none );
579 showDescription( m_noInstallable );
585void UpdateDialog::enableOk() {
586 if (!m_xChecking->get_visible()) {
592 m_xOk->set_sensitive(nChecked != 0);
597void UpdateDialog::createNotifyJob(
bool bPrepareOnly,
607 configuration::theDefaultProvider::get(
612 OUString(
"org.openoffice.Office.Addons/AddonUI/OfficeHelp/UpdateCheckJob"))) };
615 xConfigProvider->createInstanceWithArguments(
616 "com.sun.star.configuration.ConfigurationAccess", aArgumentList ),
617 uno::UNO_QUERY_THROW );
620 xNameAccess->getByName(
"URL") >>=
aURL.Complete;
625 xTransformer->parseStrict(
aURL);
629 uno::UNO_QUERY_THROW );
640 catch(
const uno::Exception& e )
643 + e.Message +
"\n thread terminated.\n\n");
648void UpdateDialog::notifyMenubar(
bool bPrepareOnly,
bool bRecheckOnly )
655 if ( ! bRecheckOnly )
658 for (sal_uInt16
i = 0, nItemCount = m_xUpdates->n_children();
i < nItemCount; ++
i)
663 if (
p->m_eKind == ENABLED_UPDATE )
673 aItemList.realloc(
nCount + 1 );
674 aItemList.getArray()[
nCount ] = aItem;
682 createNotifyJob( bPrepareOnly, aItemList );
687void UpdateDialog::initDescription()
689 m_xPublisherLabel->hide();
690 m_xPublisherLink->hide();
691 m_xReleaseNotesLabel->hide();
692 m_xReleaseNotesLink->hide();
695void UpdateDialog::clearDescription()
697 m_xPublisherLabel->hide();
698 m_xPublisherLink->hide();
699 m_xPublisherLink->set_label(
"");
700 m_xPublisherLink->set_uri(
"");
701 m_xReleaseNotesLabel->hide();
702 m_xReleaseNotesLink->hide();
703 m_xReleaseNotesLink->set_uri(
"" );
704 m_xDescriptions->set_text(
"");
710 return showDescription(infoset.getLocalizedPublisherNameAndURL(),
711 infoset.getLocalizedReleaseNotesURL());
716 OSL_ASSERT(aExtension.is());
717 beans::StringPair pubInfo = aExtension->getPublisherInfo();
718 return showDescription(std::make_pair(pubInfo.First, pubInfo.Second),
722bool UpdateDialog::showDescription(std::pair< OUString, OUString >
const & pairPublisher,
723 OUString
const & sReleaseNotes)
725 OUString sPub = pairPublisher.first;
726 OUString sURL = pairPublisher.second;
728 if ( sPub.isEmpty() && sURL.isEmpty() && sReleaseNotes.isEmpty() )
732 if ( !sPub.isEmpty() )
734 m_xPublisherLabel->show();
735 m_xPublisherLink->show();
736 m_xPublisherLink->set_label(sPub);
737 m_xPublisherLink->set_uri(sURL);
740 if ( !sReleaseNotes.isEmpty() )
742 m_xReleaseNotesLabel->show();
743 m_xReleaseNotesLink->show();
744 m_xReleaseNotesLink->set_uri( sReleaseNotes );
749bool UpdateDialog::showDescription(
const OUString& rDescription)
751 if ( rDescription.isEmpty() )
755 m_xDescriptions->set_text(rDescription);
759void UpdateDialog::getIgnoredUpdates()
762 configuration::theDefaultProvider::get(m_context));
763 beans::NamedValue aValue(
"nodepath",
uno::Any( OUString(IGNORED_UPDATES) ) );
769 for ( OUString
const & aIdentifier : aElementNames )
774 aPropValue >>= aVersion;
776 m_ignoredUpdates.emplace_back(
pData );
783 bool bIsIgnored =
false;
785 if (! m_ignoredUpdates.empty() )
787 OUString aExtensionID;
790 if (
index->m_eKind == ENABLED_UPDATE )
796 else if (
index->m_eKind == DISABLED_UPDATE )
806 for (
auto const& ignoredUpdate : m_ignoredUpdates)
808 if ( ignoredUpdate->sExtensionID == aExtensionID )
810 if ( ( !ignoredUpdate->sVersion.isEmpty() ) || ( ignoredUpdate->sVersion == aVersion ) )
813 index->m_bIgnored =
true;
827 int nSelectedPos = m_xUpdates->get_selected_index();
831 if (nSelectedPos != -1)
832 p = weld::fromId<UpdateDialog::Index const*>(m_xUpdates->get_id(nSelectedPos));
835 sal_uInt16
pos =
p->m_nIndex;
841 if ( m_enabledUpdates[
pos ].aUpdateSource.is() )
842 showDescription( m_enabledUpdates[
pos ].aUpdateSource );
844 showDescription( m_enabledUpdates[
pos ].aUpdateInfo );
847 b.append( m_ignoredUpdate );
851 case DISABLED_UPDATE:
853 if ( !m_disabledUpdates.empty() )
854 showDescription( m_disabledUpdates[
pos].aUpdateInfo );
857 b.append( m_ignoredUpdate );
859 if ( m_disabledUpdates.empty() )
866 OUString sVersion(
"%VERSION" );
867 OUString sProductName(
"%PRODUCTNAME" );
868 sal_Int32
nPos = m_noDependencyCurVer.indexOf( sVersion );
873 nPos = m_noDependencyCurVer.indexOf( sProductName );
878 nPos = m_noDependency.indexOf( sProductName );
884 b.append(m_noInstall);
886 b.append(m_noDependency);
887 for (sal_Int32
i = 0;
900 b.append(m_noDependencyCurVer);
909 b.append( data.
message.isEmpty() ? m_unknownError : data.
message );
919 b.append( m_noDescription );
921 showDescription( b.makeStringAndClear() );
926 if (m_xAll->get_active())
928 m_xUpdate->set_sensitive(
true);
929 m_xUpdates->set_sensitive(
true);
930 m_xDescription->set_sensitive(
true);
931 m_xDescriptions->set_sensitive(
true);
933 for (
auto const& listboxEntry : m_ListboxEntries)
935 if ( listboxEntry->m_bIgnored || ( listboxEntry->m_eKind != ENABLED_UPDATE ) )
936 insertItem(listboxEntry.get(),
false);
941 for (sal_uInt16
i = m_xUpdates->n_children();
i != 0 ;)
945 if (
p->m_bIgnored || (
p->m_eKind != ENABLED_UPDATE ) )
947 m_xUpdates->remove(
i);
951 if (m_xUpdates->n_children() == 0)
954 m_xUpdate->set_sensitive(
false);
955 m_xUpdates->set_sensitive(
false);
956 if (m_xChecking->get_visible())
957 m_xDescription->set_sensitive(
false);
959 showDescription(m_noInstallable);
968 for (
auto const& enableUpdate : m_enabledUpdates)
970 OSL_ASSERT(enableUpdate.aInstalledPackage.is());
976 for (sal_uInt16
i = 0,
nCount = m_xUpdates->n_children();
i <
nCount; ++
i)
979 weld::fromId<UpdateDialog::Index const*>(m_xUpdates->get_id(
i));
980 if (
p->m_eKind == ENABLED_UPDATE && m_xUpdates->get_toggle(
i) ==
TRISTATE_TRUE) {
981 m_updateData.push_back( m_enabledUpdates[
p->m_nIndex ] );
Reference< XExecutableDialog > m_xDialog
uno::Reference< deployment::XUpdateInformationProvider > m_updateInformation
uno::Reference< task::XInteractionHandler > m_xInteractionHdl
void handleSpecificError(uno::Reference< deployment::XPackage > const &package, uno::Any const &exception) const
virtual ~Thread() override
virtual void execute() override
uno::Reference< uno::XComponentContext > m_context
bool update(UpdateDialog::DisabledUpdate const &du, dp_gui::UpdateData const &data) const
std::vector< uno::Reference< deployment::XPackage > > m_vExtensionList
OUString getUpdateDisplayString(dp_gui::UpdateData const &data, std::u16string_view version=std::u16string_view()) const
void prepareUpdateData(css::uno::Reference< css::xml::dom::XNode > const &updateInfo, UpdateDialog::DisabledUpdate &out_du, dp_gui::UpdateData &out_data) const
out_data will only be filled if all dependencies are ok.
Thread(uno::Reference< uno::XComponentContext > const &context, UpdateDialog &dialog, std::vector< uno::Reference< deployment::XPackage > > &&vExtensionList)
The modal “Check for Updates” dialog.
Access to the content of an XML description element.
::std::optional< OUString > getLocalizedUpdateWebsiteURL() const
returns the download website URL from the update information.
::std::optional< OUString > getIdentifier() const
Return the identifier.
OUString getVersion() const
Return the textual version representation.
static OUString getAboutBoxProductVersion()
static OUString getProductName()
virtual Dialog * getDialog() override
std::pair< const TreeIter &, int > iter_col
virtual css::uno::Reference< css::awt::XWindow > GetXWindow()=0
Reference< XDispatch > xDispatch
std::vector< uno::Reference< deployment::XPackage > > m_vExtensionList
IMPL_LINK_NOARG(UpdateDialog, selectionHandler, weld::TreeView &, void)
IMPL_LINK(UpdateDialog, entryToggled, const weld::TreeView::iter_col &, rRowCol, void)
OUString DpResId(TranslateId aId)
static uno::Reference< css::uno::XComponentContext > xContext
#define LINK(Instance, Class, Member)
std::unique_ptr< sal_Int32[]> pData
Reference< XComponentContext > getProcessComponentContext()
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString getErrorText(css::uno::Reference< css::xml::dom::XElement > const &dependency)
Obtain the (human-readable) error message of a failed dependency.
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > check(dp_misc::DescriptionInfoset const &infoset)
Check for unsatisfied dependencies.
std::map< OUString, UpdateInfo > UpdateInfoMap
void TRACE(OUString const &sText)
print the text to the console in a debug build.
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC UPDATE_SOURCE isUpdateUserExtension(bool bReadOnlyShared, OUString const &userVersion, OUString const &sharedVersion, OUString const &bundledVersion, std::u16string_view onlineVersion)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC UPDATE_SOURCE isUpdateSharedExtension(bool bReadOnlyShared, OUString const &sharedVersion, OUString const &bundledVersion, std::u16string_view onlineVersion)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString getIdentifier(css::uno::Reference< css::deployment::XPackage > const &package)
Gets the identifier of a package.
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC UpdateInfoMap getOnlineUpdateInfos(css::uno::Reference< css::uno::XComponentContext > const &xContext, css::uno::Reference< css::deployment::XExtensionManager > const &xExtMgr, css::uno::Reference< css::deployment::XUpdateInformationProvider > const &updateInformation, std::vector< css::uno::Reference< css::deployment::XPackage > > const *extensionList, std::vector< std::pair< css::uno::Reference< css::deployment::XPackage >, css::uno::Any > > &out_errors)
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
OUString toId(const void *pValue)
uno::Sequence< OUString > unsatisfiedDependencies
css::uno::Reference< css::xml::dom::XNode > aUpdateInfo
IgnoredUpdate(OUString aExtensionID, OUString aVersion)
Index(Kind theKind, sal_uInt16 nIndex, OUString aName)
css::uno::Reference< css::xml::dom::XNode > aUpdateInfo
css::uno::Reference< css::deployment::XPackage > aInstalledPackage
css::uno::Reference< css::deployment::XPackage > aUpdateSource
css::uno::Reference< css::xml::dom::XNode > info
css::uno::Reference< css::deployment::XPackage > extension