1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_desktop.hxx" 30 31 #include "sal/config.h" 32 33 #include <cstddef> 34 #include <limits> 35 #include <map> 36 #include <memory> 37 #include <utility> 38 #include <vector> 39 40 41 #include "boost/optional.hpp" 42 #include "com/sun/star/awt/Rectangle.hpp" 43 #include "com/sun/star/awt/WindowAttribute.hpp" 44 #include "com/sun/star/awt/WindowClass.hpp" 45 #include "com/sun/star/awt/WindowDescriptor.hpp" 46 #include "com/sun/star/awt/XToolkit.hpp" 47 #include "com/sun/star/awt/XWindow.hpp" 48 #include "com/sun/star/awt/XWindowPeer.hpp" 49 #include "com/sun/star/beans/NamedValue.hpp" 50 #include "com/sun/star/beans/Optional.hpp" 51 #include "com/sun/star/beans/PropertyValue.hpp" 52 #include "com/sun/star/beans/XPropertySet.hpp" 53 #include "com/sun/star/container/XNameAccess.hpp" 54 #include "com/sun/star/container/XNameContainer.hpp" 55 #include "com/sun/star/deployment/DeploymentException.hpp" 56 #include "com/sun/star/deployment/UpdateInformationProvider.hpp" 57 #include "com/sun/star/deployment/XPackage.hpp" 58 #include "com/sun/star/deployment/XExtensionManager.hpp" 59 #include "com/sun/star/deployment/ExtensionManager.hpp" 60 #include "com/sun/star/deployment/XUpdateInformationProvider.hpp" 61 #include "com/sun/star/frame/XDesktop.hpp" 62 #include "com/sun/star/frame/XDispatch.hpp" 63 #include "com/sun/star/frame/XDispatchProvider.hpp" 64 #include "com/sun/star/lang/IllegalArgumentException.hpp" 65 #include "com/sun/star/lang/XMultiComponentFactory.hpp" 66 #include "com/sun/star/lang/XSingleServiceFactory.hpp" 67 #include "com/sun/star/system/SystemShellExecuteFlags.hpp" 68 #include "com/sun/star/system/XSystemShellExecute.hpp" 69 #include "com/sun/star/task/XAbortChannel.hpp" 70 #include "com/sun/star/task/XJob.hpp" 71 #include "com/sun/star/ucb/CommandAbortedException.hpp" 72 #include "com/sun/star/ucb/CommandFailedException.hpp" 73 #include "com/sun/star/ucb/XCommandEnvironment.hpp" 74 #include "com/sun/star/uno/Any.hxx" 75 #include "com/sun/star/uno/Exception.hpp" 76 #include "com/sun/star/uno/Reference.hxx" 77 #include "com/sun/star/uno/RuntimeException.hpp" 78 #include "com/sun/star/uno/Sequence.hxx" 79 #include "com/sun/star/uno/XInterface.hpp" 80 #include "com/sun/star/util/URL.hpp" 81 #include "com/sun/star/util/XChangesBatch.hpp" 82 #include "com/sun/star/util/XURLTransformer.hpp" 83 #include "com/sun/star/xml/dom/XElement.hpp" 84 #include "com/sun/star/xml/dom/XNode.hpp" 85 #include "osl/diagnose.h" 86 #include "rtl/bootstrap.hxx" 87 #include "rtl/ref.hxx" 88 #include "rtl/string.h" 89 #include "rtl/ustrbuf.hxx" 90 #include "rtl/ustring.h" 91 #include "rtl/ustring.hxx" 92 #include "sal/types.h" 93 #include "svtools/svlbitm.hxx" 94 #include "svtools/svlbox.hxx" 95 #include <svtools/controldims.hrc> 96 #include "svx/checklbx.hxx" 97 #include "tools/gen.hxx" 98 #include "tools/link.hxx" 99 #include "tools/resid.hxx" 100 #include "tools/resmgr.hxx" 101 #include "tools/solar.h" 102 #include "tools/string.hxx" 103 #include "vcl/button.hxx" 104 #include "vcl/dialog.hxx" 105 #include "vcl/fixed.hxx" 106 #include "vcl/image.hxx" 107 #include "vcl/msgbox.hxx" 108 #include "vcl/svapp.hxx" 109 #include "vos/mutex.hxx" 110 111 #include "comphelper/processfactory.hxx" 112 113 #include "dp_dependencies.hxx" 114 #include "dp_descriptioninfoset.hxx" 115 #include "dp_identifier.hxx" 116 #include "dp_version.hxx" 117 #include "dp_misc.h" 118 #include "dp_update.hxx" 119 120 #include "dp_gui.h" 121 #include "dp_gui.hrc" 122 #include "dp_gui_thread.hxx" 123 #include "dp_gui_updatedata.hxx" 124 #include "dp_gui_updatedialog.hxx" 125 #include "dp_gui_shared.hxx" 126 #include "dp_gui_system.hxx" 127 128 class KeyEvent; 129 class MouseEvent; 130 class Window; 131 namespace com { namespace sun { namespace star { namespace uno { 132 class XComponentContext; 133 } } } } 134 135 using namespace ::com::sun::star; 136 using dp_gui::UpdateDialog; 137 138 namespace { 139 140 static sal_Unicode const LF = 0x000A; 141 static sal_Unicode const CR = 0x000D; 142 static const sal_uInt16 CMD_ENABLE_UPDATE = 1; 143 static const sal_uInt16 CMD_IGNORE_UPDATE = 2; 144 static const sal_uInt16 CMD_IGNORE_ALL_UPDATES = 3; 145 146 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) 147 148 #define IGNORED_UPDATES OUSTR("/org.openoffice.Office.ExtensionManager/ExtensionUpdateData/IgnoredUpdates") 149 #define PROPERTY_VERSION OUSTR("Version") 150 151 enum Kind { ENABLED_UPDATE, DISABLED_UPDATE, SPECIFIC_ERROR }; 152 153 rtl::OUString confineToParagraph(rtl::OUString const & text) { 154 // Confine arbitrary text to a single paragraph in a dp_gui::AutoScrollEdit. 155 // This assumes that U+000A and U+000D are the only paragraph separators in 156 // a dp_gui::AutoScrollEdit, and that replacing them with a single space 157 // each is acceptable: 158 return text.replace(LF, ' ').replace(CR, ' '); 159 } 160 } 161 162 struct UpdateDialog::DisabledUpdate { 163 rtl::OUString name; 164 uno::Sequence< rtl::OUString > unsatisfiedDependencies; 165 // We also want to show release notes and publisher for disabled updates 166 ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > aUpdateInfo; 167 sal_uInt16 m_nID; 168 }; 169 170 struct UpdateDialog::SpecificError { 171 rtl::OUString name; 172 rtl::OUString message; 173 sal_uInt16 m_nID; 174 }; 175 176 //------------------------------------------------------------------------------ 177 struct UpdateDialog::IgnoredUpdate { 178 rtl::OUString sExtensionID; 179 rtl::OUString sVersion; 180 bool bRemoved; 181 182 IgnoredUpdate( const rtl::OUString &rExtensionID, const rtl::OUString &rVersion ); 183 }; 184 185 //------------------------------------------------------------------------------ 186 UpdateDialog::IgnoredUpdate::IgnoredUpdate( const rtl::OUString &rExtensionID, const rtl::OUString &rVersion ): 187 sExtensionID( rExtensionID ), 188 sVersion( rVersion ), 189 bRemoved( false ) 190 {} 191 192 //------------------------------------------------------------------------------ 193 struct UpdateDialog::Index 194 { 195 Kind m_eKind; 196 bool m_bIgnored; 197 sal_uInt16 m_nID; 198 sal_uInt16 m_nIndex; 199 rtl::OUString m_aName; 200 201 Index( Kind theKind, sal_uInt16 nID, sal_uInt16 nIndex, const rtl::OUString &rName ); 202 }; 203 204 //------------------------------------------------------------------------------ 205 UpdateDialog::Index::Index( Kind theKind, sal_uInt16 nID, sal_uInt16 nIndex, const rtl::OUString &rName ): 206 m_eKind( theKind ), 207 m_bIgnored( false ), 208 m_nID( nID ), 209 m_nIndex( nIndex ), 210 m_aName( rName ) 211 {} 212 213 //------------------------------------------------------------------------------ 214 //------------------------------------------------------------------------------ 215 //------------------------------------------------------------------------------ 216 class UpdateDialog::Thread: public dp_gui::Thread { 217 public: 218 Thread( 219 uno::Reference< uno::XComponentContext > const & context, 220 UpdateDialog & dialog, 221 const std::vector< uno::Reference< deployment::XPackage > > & vExtensionList); 222 223 void stop(); 224 225 private: 226 Thread(UpdateDialog::Thread &); // not defined 227 void operator =(UpdateDialog::Thread &); // not defined 228 229 struct Entry { 230 explicit Entry( 231 uno::Reference< deployment::XPackage > const & thePackage, 232 rtl::OUString const & theVersion); 233 234 uno::Reference< deployment::XPackage > package; 235 rtl::OUString version; 236 //Indicates that the extension provides its own update URLs. 237 //If this is true, then we must not use the default update 238 //URL to find the update information. 239 bool bProvidesOwnUpdate; 240 uno::Reference< xml::dom::XNode > info; 241 UpdateDialog::DisabledUpdate disableUpdate; 242 dp_gui::UpdateData updateData; 243 }; 244 245 // A multimap in case an extension is installed in "user", "shared" or "bundled" 246 typedef std::map< rtl::OUString, Entry > Map; 247 248 virtual ~Thread(); 249 250 virtual void execute(); 251 #if 0 252 void handleGeneralError(uno::Any const & exception) const; 253 #endif 254 void handleSpecificError( 255 uno::Reference< deployment::XPackage > const & package, 256 uno::Any const & exception) const; 257 258 uno::Sequence< uno::Reference< xml::dom::XElement > > 259 getUpdateInformation( 260 uno::Reference< deployment::XPackage > const & package, 261 uno::Sequence< rtl::OUString > const & urls, 262 rtl::OUString const & identifier) const; 263 264 void getOwnUpdateInformation( 265 uno::Reference< deployment::XPackage > const & package, 266 Map * map); 267 268 ::rtl::OUString getUpdateDisplayString( 269 dp_gui::UpdateData const & data, ::rtl::OUString const & version = ::rtl::OUString()) const; 270 271 void prepareUpdateData( 272 ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > const & updateInfo, 273 UpdateDialog::DisabledUpdate & out_du, 274 dp_gui::UpdateData & out_data) const; 275 276 bool update( 277 UpdateDialog::DisabledUpdate & du, 278 dp_gui::UpdateData & data) const; 279 280 uno::Reference< uno::XComponentContext > m_context; 281 UpdateDialog & m_dialog; 282 std::vector< uno::Reference< deployment::XPackage > > m_vExtensionList; 283 uno::Reference< deployment::XUpdateInformationProvider > m_updateInformation; 284 uno::Reference< task::XInteractionHandler > m_xInteractionHdl; 285 286 // guarded by Application::GetSolarMutex(): 287 uno::Reference< task::XAbortChannel > m_abort; 288 bool m_stop; 289 }; 290 291 UpdateDialog::Thread::Thread( 292 uno::Reference< uno::XComponentContext > const & context, 293 UpdateDialog & dialog, 294 const std::vector< uno::Reference< deployment::XPackage > > &vExtensionList): 295 m_context(context), 296 m_dialog(dialog), 297 m_vExtensionList(vExtensionList), 298 m_updateInformation( 299 deployment::UpdateInformationProvider::create(context)), 300 m_stop(false) 301 { 302 if( m_context.is() ) 303 { 304 uno::Reference< lang::XMultiComponentFactory > xServiceManager( m_context->getServiceManager() ); 305 306 if( xServiceManager.is() ) 307 { 308 m_xInteractionHdl = uno::Reference< task::XInteractionHandler > ( 309 xServiceManager->createInstanceWithContext( OUSTR( "com.sun.star.task.InteractionHandler" ), m_context), 310 uno::UNO_QUERY ); 311 if ( m_xInteractionHdl.is() ) 312 m_updateInformation->setInteractionHandler( m_xInteractionHdl ); 313 } 314 } 315 } 316 317 void UpdateDialog::Thread::stop() { 318 uno::Reference< task::XAbortChannel > abort; 319 { 320 vos::OGuard g(Application::GetSolarMutex()); 321 abort = m_abort; 322 m_stop = true; 323 } 324 if (abort.is()) { 325 abort->sendAbort(); 326 } 327 m_updateInformation->cancel(); 328 } 329 330 UpdateDialog::Thread::Entry::Entry( 331 uno::Reference< deployment::XPackage > const & thePackage, 332 rtl::OUString const & theVersion): 333 334 package(thePackage), 335 version(theVersion), 336 bProvidesOwnUpdate(false), 337 updateData(thePackage) 338 { 339 } 340 341 UpdateDialog::Thread::~Thread() 342 { 343 if ( m_xInteractionHdl.is() ) 344 m_updateInformation->setInteractionHandler( uno::Reference< task::XInteractionHandler > () ); 345 } 346 347 void UpdateDialog::Thread::execute() 348 { 349 { 350 vos::OGuard g( Application::GetSolarMutex() ); 351 if ( m_stop ) { 352 return; 353 } 354 } 355 uno::Reference<deployment::XExtensionManager> extMgr = 356 deployment::ExtensionManager::get(m_context); 357 358 std::vector<std::pair<uno::Reference<deployment::XPackage>, uno::Any > > errors; 359 360 dp_misc::UpdateInfoMap updateInfoMap = dp_misc::getOnlineUpdateInfos( 361 m_context, extMgr, m_updateInformation, &m_vExtensionList, errors); 362 363 typedef std::vector<std::pair<uno::Reference<deployment::XPackage>, 364 uno::Any> >::const_iterator ITERROR; 365 for (ITERROR ite = errors.begin(); ite != errors.end(); ite ++) 366 handleSpecificError(ite->first, ite->second); 367 368 for (dp_misc::UpdateInfoMap::iterator i(updateInfoMap.begin()); i != updateInfoMap.end(); i++) 369 { 370 dp_misc::UpdateInfo const & info = i->second; 371 UpdateData updateData(info.extension); 372 DisabledUpdate disableUpdate; 373 //determine if online updates meet the requirements 374 prepareUpdateData(info.info, disableUpdate, updateData); 375 376 //determine if the update is installed in the user or shared repository 377 rtl::OUString sOnlineVersion; 378 if (info.info.is()) 379 sOnlineVersion = info.version; 380 rtl::OUString sVersionUser; 381 rtl::OUString sVersionShared; 382 rtl::OUString sVersionBundled; 383 uno::Sequence< uno::Reference< deployment::XPackage> > extensions; 384 try { 385 extensions = extMgr->getExtensionsWithSameIdentifier( 386 dp_misc::getIdentifier(info.extension), info.extension->getName(), 387 uno::Reference<ucb::XCommandEnvironment>()); 388 } catch (lang::IllegalArgumentException& ) { 389 OSL_ASSERT(0); 390 continue; 391 } catch (css::ucb::CommandFailedException& ) { 392 OSL_ASSERT(0); 393 continue; 394 } 395 OSL_ASSERT(extensions.getLength() == 3); 396 if (extensions[0].is() ) 397 sVersionUser = extensions[0]->getVersion(); 398 if (extensions[1].is() ) 399 sVersionShared = extensions[1]->getVersion(); 400 if (extensions[2].is() ) 401 sVersionBundled = extensions[2]->getVersion(); 402 403 bool bSharedReadOnly = extMgr->isReadOnlyRepository(OUSTR("shared")); 404 405 dp_misc::UPDATE_SOURCE sourceUser = dp_misc::isUpdateUserExtension( 406 bSharedReadOnly, sVersionUser, sVersionShared, sVersionBundled, sOnlineVersion); 407 dp_misc::UPDATE_SOURCE sourceShared = dp_misc::isUpdateSharedExtension( 408 bSharedReadOnly, sVersionShared, sVersionBundled, sOnlineVersion); 409 410 uno::Reference<deployment::XPackage> updateSource; 411 if (sourceUser != dp_misc::UPDATE_SOURCE_NONE) 412 { 413 if (sourceUser == dp_misc::UPDATE_SOURCE_SHARED) 414 { 415 updateData.aUpdateSource = extensions[1]; 416 updateData.updateVersion = extensions[1]->getVersion(); 417 } 418 else if (sourceUser == dp_misc::UPDATE_SOURCE_BUNDLED) 419 { 420 updateData.aUpdateSource = extensions[2]; 421 updateData.updateVersion = extensions[2]->getVersion(); 422 } 423 if (!update(disableUpdate, updateData)) 424 return; 425 } 426 427 if (sourceShared != dp_misc::UPDATE_SOURCE_NONE) 428 { 429 if (sourceShared == dp_misc::UPDATE_SOURCE_BUNDLED) 430 { 431 updateData.aUpdateSource = extensions[2]; 432 updateData.updateVersion = extensions[2]->getVersion(); 433 } 434 updateData.bIsShared = true; 435 if (!update(disableUpdate, updateData)) 436 return; 437 } 438 } 439 440 441 vos::OGuard g(Application::GetSolarMutex()); 442 if (!m_stop) { 443 m_dialog.checkingDone(); 444 } 445 } 446 #if 0 447 void UpdateDialog::Thread::handleGeneralError(uno::Any const & exception) 448 const 449 { 450 rtl::OUString message; 451 uno::Exception e; 452 if (exception >>= e) { 453 message = e.Message; 454 } 455 vos::OGuard g(Application::GetSolarMutex()); 456 if (!m_stop) { 457 m_dialog.addGeneralError(message); 458 } 459 } 460 #endif 461 //Parameter package can be null 462 void UpdateDialog::Thread::handleSpecificError( 463 uno::Reference< deployment::XPackage > const & package, 464 uno::Any const & exception) const 465 { 466 UpdateDialog::SpecificError data; 467 if (package.is()) 468 data.name = package->getDisplayName(); 469 uno::Exception e; 470 if (exception >>= e) { 471 data.message = e.Message; 472 } 473 vos::OGuard g(Application::GetSolarMutex()); 474 if (!m_stop) { 475 m_dialog.addSpecificError(data); 476 } 477 } 478 479 ::rtl::OUString UpdateDialog::Thread::getUpdateDisplayString( 480 dp_gui::UpdateData const & data, ::rtl::OUString const & version) const 481 { 482 OSL_ASSERT(data.aInstalledPackage.is()); 483 rtl::OUStringBuffer b(data.aInstalledPackage->getDisplayName()); 484 b.append(static_cast< sal_Unicode >(' ')); 485 { 486 vos::OGuard g( Application::GetSolarMutex() ); 487 if(!m_stop) 488 b.append(m_dialog.m_version); 489 } 490 b.append(static_cast< sal_Unicode >(' ')); 491 if (version.getLength()) 492 b.append(version); 493 else 494 b.append(data.updateVersion); 495 496 if (data.sWebsiteURL.getLength()) 497 { 498 b.append(static_cast< sal_Unicode >(' ')); 499 { 500 vos::OGuard g( Application::GetSolarMutex() ); 501 if(!m_stop) 502 b.append(m_dialog.m_browserbased); 503 } 504 } 505 return b.makeStringAndClear(); 506 } 507 508 /** out_data will only be filled if all dependencies are ok. 509 */ 510 void UpdateDialog::Thread::prepareUpdateData( 511 uno::Reference< xml::dom::XNode > const & updateInfo, 512 UpdateDialog::DisabledUpdate & out_du, 513 dp_gui::UpdateData & out_data) const 514 { 515 if (!updateInfo.is()) 516 return; 517 dp_misc::DescriptionInfoset infoset(m_context, updateInfo); 518 OSL_ASSERT(infoset.getVersion().getLength() != 0); 519 uno::Sequence< uno::Reference< xml::dom::XElement > > ds( 520 dp_misc::Dependencies::check(infoset)); 521 522 out_du.aUpdateInfo = updateInfo; 523 out_du.unsatisfiedDependencies.realloc(ds.getLength()); 524 for (sal_Int32 i = 0; i < ds.getLength(); ++i) { 525 out_du.unsatisfiedDependencies[i] = dp_misc::Dependencies::getErrorText(ds[i]); 526 } 527 528 const ::boost::optional< ::rtl::OUString> updateWebsiteURL(infoset.getLocalizedUpdateWebsiteURL()); 529 530 out_du.name = getUpdateDisplayString(out_data, infoset.getVersion()); 531 532 if (out_du.unsatisfiedDependencies.getLength() == 0) 533 { 534 out_data.aUpdateInfo = updateInfo; 535 out_data.updateVersion = infoset.getVersion(); 536 if (updateWebsiteURL) 537 out_data.sWebsiteURL = *updateWebsiteURL; 538 } 539 } 540 541 bool UpdateDialog::Thread::update( 542 UpdateDialog::DisabledUpdate & du, 543 dp_gui::UpdateData & data) const 544 { 545 bool ret = false; 546 if (du.unsatisfiedDependencies.getLength() == 0) 547 { 548 vos::OGuard g(Application::GetSolarMutex()); 549 if (!m_stop) { 550 m_dialog.addEnabledUpdate(getUpdateDisplayString(data), data); 551 } 552 ret = !m_stop; 553 } else { 554 vos::OGuard g(Application::GetSolarMutex()); 555 if (!m_stop) { 556 m_dialog.addDisabledUpdate(du); 557 } 558 ret = !m_stop; 559 } 560 return ret; 561 } 562 563 // UpdateDialog ---------------------------------------------------------- 564 UpdateDialog::UpdateDialog( 565 uno::Reference< uno::XComponentContext > const & context, 566 Window * parent, 567 const std::vector<uno::Reference< deployment::XPackage > > &vExtensionList, 568 std::vector< dp_gui::UpdateData > * updateData): 569 ModalDialog(parent,DpGuiResId(RID_DLG_UPDATE)), 570 m_context(context), 571 m_checking(this, DpGuiResId(RID_DLG_UPDATE_CHECKING)), 572 m_throbber(this, DpGuiResId(RID_DLG_UPDATE_THROBBER)), 573 m_update(this, DpGuiResId(RID_DLG_UPDATE_UPDATE)), 574 m_updates( 575 *this, DpGuiResId(RID_DLG_UPDATE_UPDATES), 576 Image(DpGuiResId(RID_DLG_UPDATE_NORMALALERT)), 577 Image(DpGuiResId(RID_DLG_UPDATE_HIGHCONTRASTALERT))), 578 m_all(this, DpGuiResId(RID_DLG_UPDATE_ALL)), 579 m_description(this, DpGuiResId(RID_DLG_UPDATE_DESCRIPTION)), 580 m_PublisherLabel(this, DpGuiResId(RID_DLG_UPDATE_PUBLISHER_LABEL)), 581 m_PublisherLink(this, DpGuiResId(RID_DLG_UPDATE_PUBLISHER_LINK)), 582 m_ReleaseNotesLabel(this, DpGuiResId(RID_DLG_UPDATE_RELEASENOTES_LABEL)), 583 m_ReleaseNotesLink(this, DpGuiResId(RID_DLG_UPDATE_RELEASENOTES_LINK)), 584 m_descriptions(this, DpGuiResId(RID_DLG_UPDATE_DESCRIPTIONS)), 585 m_line(this, DpGuiResId(RID_DLG_UPDATE_LINE)), 586 m_help(this, DpGuiResId(RID_DLG_UPDATE_HELP)), 587 m_ok(this, DpGuiResId(RID_DLG_UPDATE_OK)), 588 m_close(this, DpGuiResId(RID_DLG_UPDATE_CLOSE)), 589 m_error(String(DpGuiResId(RID_DLG_UPDATE_ERROR))), 590 m_none(String(DpGuiResId(RID_DLG_UPDATE_NONE))), 591 m_noInstallable(String(DpGuiResId(RID_DLG_UPDATE_NOINSTALLABLE))), 592 m_failure(String(DpGuiResId(RID_DLG_UPDATE_FAILURE))), 593 m_unknownError(String(DpGuiResId(RID_DLG_UPDATE_UNKNOWNERROR))), 594 m_noDescription(String(DpGuiResId(RID_DLG_UPDATE_NODESCRIPTION))), 595 m_noInstall(String(DpGuiResId(RID_DLG_UPDATE_NOINSTALL))), 596 m_noDependency(String(DpGuiResId(RID_DLG_UPDATE_NODEPENDENCY))), 597 m_noDependencyCurVer(String(DpGuiResId(RID_DLG_UPDATE_NODEPENDENCY_CUR_VER))), 598 m_browserbased(String(DpGuiResId(RID_DLG_UPDATE_BROWSERBASED))), 599 m_version(String(DpGuiResId(RID_DLG_UPDATE_VERSION))), 600 m_ignoredUpdate(String(DpGuiResId(RID_DLG_UPDATE_IGNORED_UPDATE))), 601 m_updateData(*updateData), 602 m_thread( 603 new UpdateDialog::Thread( 604 context, *this, vExtensionList)), 605 m_nFirstLineDelta(0), 606 m_nOneLineMissing(0), 607 m_nLastID(1), 608 m_bModified( false ) 609 // TODO: check! 610 // , 611 // m_extensionManagerDialog(extensionManagerDialog) 612 { 613 OSL_ASSERT(updateData != NULL); 614 615 m_xExtensionManager = deployment::ExtensionManager::get( context ); 616 617 uno::Reference< awt::XToolkit > toolkit; 618 try { 619 toolkit = uno::Reference< awt::XToolkit >( 620 (uno::Reference< lang::XMultiComponentFactory >( 621 m_context->getServiceManager(), 622 uno::UNO_QUERY_THROW)-> 623 createInstanceWithContext( 624 rtl::OUString( 625 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.Toolkit")), 626 m_context)), 627 uno::UNO_QUERY_THROW); 628 } catch (uno::RuntimeException &) { 629 throw; 630 } catch (uno::Exception & e) { 631 throw uno::RuntimeException(e.Message, e.Context); 632 } 633 m_updates.SetSelectHdl(LINK(this, UpdateDialog, selectionHandler)); 634 m_all.SetToggleHdl(LINK(this, UpdateDialog, allHandler)); 635 m_ok.SetClickHdl(LINK(this, UpdateDialog, okHandler)); 636 m_close.SetClickHdl(LINK(this, UpdateDialog, closeHandler)); 637 if ( ! dp_misc::office_is_running()) 638 m_help.Disable(); 639 FreeResource(); 640 641 initDescription(); 642 getIgnoredUpdates(); 643 } 644 645 //------------------------------------------------------------------------------ 646 UpdateDialog::~UpdateDialog() 647 { 648 storeIgnoredUpdates(); 649 650 for ( std::vector< UpdateDialog::Index* >::iterator i( m_ListboxEntries.begin() ); i != m_ListboxEntries.end(); ++i ) 651 { 652 delete (*i); 653 } 654 for ( std::vector< UpdateDialog::IgnoredUpdate* >::iterator i( m_ignoredUpdates.begin() ); i != m_ignoredUpdates.end(); ++i ) 655 { 656 delete (*i); 657 } 658 } 659 660 //------------------------------------------------------------------------------ 661 sal_Bool UpdateDialog::Close() { 662 m_thread->stop(); 663 return ModalDialog::Close(); 664 } 665 666 short UpdateDialog::Execute() { 667 m_throbber.start(); 668 m_thread->launch(); 669 return ModalDialog::Execute(); 670 } 671 672 //------------------------------------------------------------------------------ 673 //------------------------------------------------------------------------------ 674 //------------------------------------------------------------------------------ 675 UpdateDialog::CheckListBox::CheckListBox( UpdateDialog & dialog, ResId const & resource, 676 Image const & normalStaticImage, 677 Image const & highContrastStaticImage ): 678 SvxCheckListBox( &dialog, resource, normalStaticImage, highContrastStaticImage ), 679 m_ignoreUpdate( String( DpGuiResId( RID_DLG_UPDATE_IGNORE ) ) ), 680 m_ignoreAllUpdates( String( DpGuiResId( RID_DLG_UPDATE_IGNORE_ALL ) ) ), 681 m_enableUpdate( String( DpGuiResId( RID_DLG_UPDATE_ENABLE ) ) ), 682 m_dialog(dialog) 683 {} 684 685 //------------------------------------------------------------------------------ 686 UpdateDialog::CheckListBox::~CheckListBox() {} 687 688 //------------------------------------------------------------------------------ 689 sal_uInt16 UpdateDialog::CheckListBox::getItemCount() const { 690 sal_uLong i = GetEntryCount(); 691 OSL_ASSERT(i <= std::numeric_limits< sal_uInt16 >::max()); 692 return sal::static_int_cast< sal_uInt16 >(i); 693 } 694 695 //------------------------------------------------------------------------------ 696 void UpdateDialog::CheckListBox::MouseButtonDown( MouseEvent const & event ) 697 { 698 // When clicking on a selected entry in an SvxCheckListBox, the entry's 699 // checkbox is toggled on mouse button down: 700 SvxCheckListBox::MouseButtonDown( event ); 701 702 if ( event.IsRight() ) 703 { 704 handlePopupMenu( event.GetPosPixel() ); 705 } 706 707 m_dialog.enableOk(); 708 } 709 710 //------------------------------------------------------------------------------ 711 void UpdateDialog::CheckListBox::MouseButtonUp(MouseEvent const & event) { 712 // When clicking on an entry's checkbox in an SvxCheckListBox, the entry's 713 // checkbox is toggled on mouse button up: 714 SvxCheckListBox::MouseButtonUp(event); 715 m_dialog.enableOk(); 716 } 717 718 void UpdateDialog::CheckListBox::KeyInput(KeyEvent const & event) { 719 SvxCheckListBox::KeyInput(event); 720 m_dialog.enableOk(); 721 } 722 723 //------------------------------------------------------------------------------ 724 void UpdateDialog::CheckListBox::handlePopupMenu( const Point &rPos ) 725 { 726 SvListEntry *pData = GetEntry( rPos ); 727 728 if ( pData ) 729 { 730 sal_uInt16 nEntryPos = GetSelectEntryPos(); 731 UpdateDialog::Index * p = static_cast< UpdateDialog::Index * >( GetEntryData( nEntryPos ) ); 732 733 if ( ( p->m_eKind == ENABLED_UPDATE ) || ( p->m_eKind == DISABLED_UPDATE ) ) 734 { 735 PopupMenu aPopup; 736 737 if ( p->m_bIgnored ) 738 aPopup.InsertItem( CMD_ENABLE_UPDATE, m_enableUpdate ); 739 else 740 { 741 aPopup.InsertItem( CMD_IGNORE_UPDATE, m_ignoreUpdate ); 742 aPopup.InsertItem( CMD_IGNORE_ALL_UPDATES, m_ignoreAllUpdates ); 743 } 744 745 sal_uInt16 aCmd = aPopup.Execute( this, rPos ); 746 if ( ( aCmd == CMD_IGNORE_UPDATE ) || ( aCmd == CMD_IGNORE_ALL_UPDATES ) ) 747 { 748 p->m_bIgnored = true; 749 if ( p->m_eKind == ENABLED_UPDATE ) 750 { 751 RemoveEntry( nEntryPos ); 752 m_dialog.addAdditional( p, SvLBoxButtonKind_disabledCheckbox ); 753 } 754 if ( aCmd == CMD_IGNORE_UPDATE ) 755 m_dialog.setIgnoredUpdate( p, true, false ); 756 else 757 m_dialog.setIgnoredUpdate( p, true, true ); 758 // TODO: reselect entry to display new description! 759 } 760 else if ( aCmd == CMD_ENABLE_UPDATE ) 761 { 762 p->m_bIgnored = false; 763 if ( p->m_eKind == ENABLED_UPDATE ) 764 { 765 RemoveEntry( nEntryPos ); 766 m_dialog.insertItem( p, SvLBoxButtonKind_enabledCheckbox ); 767 } 768 m_dialog.setIgnoredUpdate( p, false, false ); 769 } 770 } 771 } 772 } 773 774 //------------------------------------------------------------------------------ 775 //------------------------------------------------------------------------------ 776 //------------------------------------------------------------------------------ 777 sal_uInt16 UpdateDialog::insertItem( UpdateDialog::Index *pEntry, SvLBoxButtonKind kind ) 778 { 779 m_updates.InsertEntry( pEntry->m_aName, LISTBOX_APPEND, static_cast< void * >( pEntry ), kind ); 780 781 for ( sal_uInt16 i = m_updates.getItemCount(); i != 0 ; ) 782 { 783 i -= 1; 784 UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >( m_updates.GetEntryData( i ) ); 785 if ( p == pEntry ) 786 return i; 787 } 788 OSL_ASSERT(0); 789 return 0; 790 } 791 792 //------------------------------------------------------------------------------ 793 void UpdateDialog::addAdditional( UpdateDialog::Index * index, SvLBoxButtonKind kind ) 794 { 795 m_all.Enable(); 796 if (m_all.IsChecked()) 797 { 798 insertItem( index, kind ); 799 m_update.Enable(); 800 m_updates.Enable(); 801 m_description.Enable(); 802 m_descriptions.Enable(); 803 } 804 } 805 806 //------------------------------------------------------------------------------ 807 void UpdateDialog::addEnabledUpdate( rtl::OUString const & name, 808 dp_gui::UpdateData & data ) 809 { 810 sal_uInt16 nIndex = sal::static_int_cast< sal_uInt16 >( m_enabledUpdates.size() ); 811 UpdateDialog::Index *pEntry = new UpdateDialog::Index( ENABLED_UPDATE, m_nLastID, nIndex, name ); 812 813 data.m_nID = m_nLastID; 814 m_nLastID += 1; 815 816 m_enabledUpdates.push_back( data ); 817 m_ListboxEntries.push_back( pEntry ); 818 819 if ( ! isIgnoredUpdate( pEntry ) ) 820 { 821 sal_uInt16 nPos = insertItem( pEntry, SvLBoxButtonKind_enabledCheckbox ); 822 m_updates.CheckEntryPos( nPos ); 823 } 824 else 825 addAdditional( pEntry, SvLBoxButtonKind_disabledCheckbox ); 826 827 m_update.Enable(); 828 m_updates.Enable(); 829 m_description.Enable(); 830 m_descriptions.Enable(); 831 } 832 833 //------------------------------------------------------------------------------ 834 void UpdateDialog::addDisabledUpdate( UpdateDialog::DisabledUpdate & data ) 835 { 836 sal_uInt16 nIndex = sal::static_int_cast< sal_uInt16 >( m_disabledUpdates.size() ); 837 UpdateDialog::Index *pEntry = new UpdateDialog::Index( DISABLED_UPDATE, m_nLastID, nIndex, data.name ); 838 839 data.m_nID = m_nLastID; 840 m_nLastID += 1; 841 842 m_disabledUpdates.push_back( data ); 843 m_ListboxEntries.push_back( pEntry ); 844 845 isIgnoredUpdate( pEntry ); 846 addAdditional( pEntry, SvLBoxButtonKind_disabledCheckbox ); 847 } 848 849 //------------------------------------------------------------------------------ 850 void UpdateDialog::addSpecificError( UpdateDialog::SpecificError & data ) 851 { 852 sal_uInt16 nIndex = sal::static_int_cast< sal_uInt16 >( m_specificErrors.size() ); 853 UpdateDialog::Index *pEntry = new UpdateDialog::Index( DISABLED_UPDATE, m_nLastID, nIndex, data.name ); 854 855 data.m_nID = m_nLastID; 856 m_nLastID += 1; 857 858 m_specificErrors.push_back( data ); 859 m_ListboxEntries.push_back( pEntry ); 860 861 addAdditional( pEntry, SvLBoxButtonKind_staticImage); 862 } 863 864 void UpdateDialog::checkingDone() { 865 m_checking.Hide(); 866 m_throbber.stop(); 867 m_throbber.Hide(); 868 if (m_updates.getItemCount() == 0) 869 { 870 clearDescription(); 871 m_description.Enable(); 872 m_descriptions.Enable(); 873 874 if ( m_disabledUpdates.empty() && m_specificErrors.empty() && m_ignoredUpdates.empty() ) 875 showDescription( m_none, false ); 876 else 877 showDescription( m_noInstallable, false ); 878 } 879 880 enableOk(); 881 } 882 883 void UpdateDialog::enableOk() { 884 if (!m_checking.IsVisible()) { 885 m_ok.Enable(m_updates.GetCheckedEntryCount() != 0); 886 } 887 } 888 889 // ********************************************************************************* 890 void UpdateDialog::createNotifyJob( bool bPrepareOnly, 891 uno::Sequence< uno::Sequence< rtl::OUString > > &rItemList ) 892 { 893 if ( !dp_misc::office_is_running() ) 894 return; 895 896 // notify update check job 897 try 898 { 899 uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); 900 uno::Reference< lang::XMultiServiceFactory > xConfigProvider( 901 xFactory->createInstance( OUSTR( "com.sun.star.configuration.ConfigurationProvider" )), 902 uno::UNO_QUERY_THROW); 903 904 beans::PropertyValue aProperty; 905 aProperty.Name = OUSTR( "nodepath" ); 906 aProperty.Value = uno::makeAny( OUSTR("org.openoffice.Office.Addons/AddonUI/OfficeHelp/UpdateCheckJob") ); 907 908 uno::Sequence< uno::Any > aArgumentList( 1 ); 909 aArgumentList[0] = uno::makeAny( aProperty ); 910 911 uno::Reference< container::XNameAccess > xNameAccess( 912 xConfigProvider->createInstanceWithArguments( 913 OUSTR("com.sun.star.configuration.ConfigurationAccess"), aArgumentList ), 914 uno::UNO_QUERY_THROW ); 915 916 util::URL aURL; 917 xNameAccess->getByName(OUSTR("URL")) >>= aURL.Complete; 918 919 uno::Reference < util::XURLTransformer > xTransformer( xFactory->createInstance( OUSTR( "com.sun.star.util.URLTransformer" ) ), 920 uno::UNO_QUERY_THROW ); 921 922 xTransformer->parseStrict(aURL); 923 924 uno::Reference < frame::XDesktop > xDesktop( xFactory->createInstance( OUSTR( "com.sun.star.frame.Desktop" ) ), 925 uno::UNO_QUERY_THROW ); 926 uno::Reference< frame::XDispatchProvider > xDispatchProvider( xDesktop->getCurrentFrame(), 927 uno::UNO_QUERY_THROW ); 928 uno::Reference< frame::XDispatch > xDispatch = xDispatchProvider->queryDispatch(aURL, rtl::OUString(), 0); 929 930 if( xDispatch.is() ) 931 { 932 uno::Sequence< beans::PropertyValue > aPropList(2); 933 aProperty.Name = OUSTR( "updateList" ); 934 aProperty.Value = uno::makeAny( rItemList ); 935 aPropList[0] = aProperty; 936 aProperty.Name = OUSTR( "prepareOnly" ); 937 aProperty.Value = uno::makeAny( bPrepareOnly ); 938 aPropList[1] = aProperty; 939 940 xDispatch->dispatch(aURL, aPropList ); 941 } 942 } 943 catch( const uno::Exception& e ) 944 { 945 dp_misc::TRACE( OUSTR("Caught exception: ") 946 + e.Message + OUSTR("\n thread terminated.\n\n")); 947 } 948 } 949 950 // ********************************************************************************* 951 void UpdateDialog::notifyMenubar( bool bPrepareOnly, bool bRecheckOnly ) 952 { 953 if ( !dp_misc::office_is_running() ) 954 return; 955 956 uno::Sequence< uno::Sequence< rtl::OUString > > aItemList; 957 sal_Int32 nCount = 0; 958 959 if ( ! bRecheckOnly ) 960 { 961 for ( sal_Int16 i = 0; i < m_updates.getItemCount(); ++i ) 962 { 963 uno::Sequence< rtl::OUString > aItem(2); 964 965 UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >(m_updates.GetEntryData(i)); 966 967 if ( p->m_eKind == ENABLED_UPDATE ) 968 { 969 dp_gui::UpdateData aUpdData = m_enabledUpdates[ p->m_nIndex ]; 970 aItem[0] = dp_misc::getIdentifier( aUpdData.aInstalledPackage ); 971 972 dp_misc::DescriptionInfoset aInfoset( m_context, aUpdData.aUpdateInfo ); 973 aItem[1] = aInfoset.getVersion(); 974 } 975 else if ( p->m_eKind == DISABLED_UPDATE ) 976 continue; 977 else 978 continue; 979 980 aItemList.realloc( nCount + 1 ); 981 aItemList[ nCount ] = aItem; 982 nCount += 1; 983 } 984 } 985 986 storeIgnoredUpdates(); 987 createNotifyJob( bPrepareOnly, aItemList ); 988 } 989 990 // ********************************************************************************* 991 992 void UpdateDialog::initDescription() 993 { 994 m_PublisherLabel.Hide(); 995 m_PublisherLink.Hide(); 996 m_ReleaseNotesLabel.Hide(); 997 m_ReleaseNotesLink.Hide(); 998 m_descriptions.Hide(); 999 1000 Link aLink = LINK( this, UpdateDialog, hyperlink_clicked ); 1001 m_PublisherLink.SetClickHdl( aLink ); 1002 m_ReleaseNotesLink.SetClickHdl( aLink ); 1003 1004 long nTextWidth = m_PublisherLabel.GetCtrlTextWidth( m_PublisherLabel.GetText() ); 1005 long nTemp = m_ReleaseNotesLabel.GetTextWidth( m_ReleaseNotesLabel.GetText() ); 1006 if ( nTemp > nTextWidth ) 1007 nTextWidth = nTemp; 1008 nTextWidth = nTextWidth * 110 / 100; 1009 1010 Size aNewSize = m_PublisherLabel.GetSizePixel(); 1011 if ( nTextWidth > aNewSize.Width() ) 1012 { 1013 long nDelta = nTextWidth - aNewSize.Width(); 1014 aNewSize.Width() = nTextWidth; 1015 m_PublisherLabel.SetSizePixel( aNewSize ); 1016 m_ReleaseNotesLabel.SetSizePixel( aNewSize ); 1017 1018 aNewSize = m_PublisherLink.GetSizePixel(); 1019 aNewSize.Width() = aNewSize.Width() - nDelta; 1020 Point aNewPos = m_PublisherLink.GetPosPixel(); 1021 aNewPos.X() = aNewPos.X() + nDelta; 1022 m_PublisherLink.SetPosSizePixel( aNewPos, aNewSize ); 1023 aNewPos.Y() = m_ReleaseNotesLink.GetPosPixel().Y(); 1024 m_ReleaseNotesLink.SetPosSizePixel( aNewPos, aNewSize ); 1025 } 1026 1027 m_aFirstLinePos = m_descriptions.GetPosPixel(); 1028 m_aFirstLineSize = m_descriptions.GetSizePixel(); 1029 Size aMarginSize = LogicToPixel( Size( RSC_SP_CTRL_GROUP_X, RSC_SP_CTRL_GROUP_Y ), MAP_APPFONT ); 1030 Point aThirdLinePos = m_ReleaseNotesLabel.GetPosPixel(); 1031 aThirdLinePos.Y() = aThirdLinePos.Y() + m_ReleaseNotesLabel.GetSizePixel().Height() + aMarginSize.Height(); 1032 m_nFirstLineDelta = aThirdLinePos.Y() - m_aFirstLinePos.Y(); 1033 m_nOneLineMissing = m_ReleaseNotesLabel.GetPosPixel().Y() - m_PublisherLabel.GetPosPixel().Y(); 1034 } 1035 1036 void UpdateDialog::clearDescription() 1037 { 1038 String sEmpty; 1039 m_PublisherLabel.Hide(); 1040 m_PublisherLink.Hide(); 1041 m_PublisherLink.SetDescription( sEmpty ); 1042 m_PublisherLink.SetURL( sEmpty ); 1043 m_ReleaseNotesLabel.Hide(); 1044 m_ReleaseNotesLink.Hide(); 1045 m_ReleaseNotesLink.SetURL( sEmpty ); 1046 if ( m_PublisherLabel.GetPosPixel().Y() == m_ReleaseNotesLabel.GetPosPixel().Y() ) 1047 { 1048 Point aNewPos = m_ReleaseNotesLabel.GetPosPixel(); 1049 aNewPos.Y() += m_nOneLineMissing; 1050 m_ReleaseNotesLabel.SetPosPixel( aNewPos ); 1051 aNewPos = m_ReleaseNotesLink.GetPosPixel(); 1052 aNewPos.Y() += m_nOneLineMissing; 1053 m_ReleaseNotesLink.SetPosPixel( aNewPos ); 1054 } 1055 m_descriptions.Hide(); 1056 m_descriptions.Clear(); 1057 m_descriptions.SetPosSizePixel( m_aFirstLinePos, m_aFirstLineSize ); 1058 } 1059 1060 bool UpdateDialog::showDescription(uno::Reference< xml::dom::XNode > const & aUpdateInfo) 1061 { 1062 dp_misc::DescriptionInfoset infoset(m_context, aUpdateInfo); 1063 return showDescription(infoset.getLocalizedPublisherNameAndURL(), 1064 infoset.getLocalizedReleaseNotesURL()); 1065 } 1066 1067 bool UpdateDialog::showDescription(uno::Reference< deployment::XPackage > const & aExtension) 1068 { 1069 OSL_ASSERT(aExtension.is()); 1070 beans::StringPair pubInfo = aExtension->getPublisherInfo(); 1071 return showDescription(std::make_pair(pubInfo.First, pubInfo.Second), 1072 OUSTR("")); 1073 } 1074 1075 bool UpdateDialog::showDescription(std::pair< rtl::OUString, rtl::OUString > const & pairPublisher, 1076 rtl::OUString const & sReleaseNotes) 1077 { 1078 rtl::OUString sPub = pairPublisher.first; 1079 rtl::OUString sURL = pairPublisher.second; 1080 1081 if ( sPub.getLength() == 0 && sURL.getLength() == 0 && sReleaseNotes.getLength() == 0 ) 1082 // nothing to show 1083 return false; 1084 1085 bool bPublisher = false; 1086 if ( sPub.getLength() > 0 ) 1087 { 1088 m_PublisherLabel.Show(); 1089 m_PublisherLink.Show(); 1090 m_PublisherLink.SetDescription( sPub ); 1091 m_PublisherLink.SetURL( sURL ); 1092 bPublisher = true; 1093 } 1094 1095 if ( sReleaseNotes.getLength() > 0 ) 1096 { 1097 if ( !bPublisher ) 1098 { 1099 m_ReleaseNotesLabel.SetPosPixel( m_PublisherLabel.GetPosPixel() ); 1100 m_ReleaseNotesLink.SetPosPixel( m_PublisherLink.GetPosPixel() ); 1101 } 1102 m_ReleaseNotesLabel.Show(); 1103 m_ReleaseNotesLink.Show(); 1104 m_ReleaseNotesLink.SetURL( sReleaseNotes ); 1105 } 1106 return true; 1107 } 1108 1109 bool UpdateDialog::showDescription( const String& rDescription, bool bWithPublisher ) 1110 { 1111 if ( rDescription.Len() == 0 ) 1112 // nothing to show 1113 return false; 1114 1115 if ( bWithPublisher ) 1116 { 1117 bool bOneLineMissing = !m_ReleaseNotesLabel.IsVisible() || !m_PublisherLabel.IsVisible(); 1118 Point aNewPos = m_aFirstLinePos; 1119 aNewPos.Y() += m_nFirstLineDelta; 1120 if ( bOneLineMissing ) 1121 aNewPos.Y() -= m_nOneLineMissing; 1122 Size aNewSize = m_aFirstLineSize; 1123 aNewSize.Height() -= m_nFirstLineDelta; 1124 if ( bOneLineMissing ) 1125 aNewSize.Height() += m_nOneLineMissing; 1126 m_descriptions.SetPosSizePixel( aNewPos, aNewSize ); 1127 } 1128 m_descriptions.Show(); 1129 m_descriptions.SetDescription( rDescription ); 1130 return true; 1131 } 1132 1133 bool UpdateDialog::isReadOnly( const uno::Reference< deployment::XPackage > &xPackage ) const 1134 { 1135 if ( m_xExtensionManager.is() && xPackage.is() ) 1136 { 1137 return m_xExtensionManager->isReadOnlyRepository( xPackage->getRepositoryName() ); 1138 } 1139 else 1140 return true; 1141 } 1142 1143 //------------------------------------------------------------------------------ 1144 void UpdateDialog::getIgnoredUpdates() 1145 { 1146 uno::Reference< lang::XMultiServiceFactory > xConfig( m_context->getServiceManager()->createInstanceWithContext( 1147 OUSTR("com.sun.star.configuration.ConfigurationProvider"), m_context ), uno::UNO_QUERY_THROW); 1148 beans::NamedValue aValue( OUSTR("nodepath"), uno::Any( IGNORED_UPDATES ) ); 1149 uno::Sequence< uno::Any > args(1); 1150 args[0] <<= aValue; 1151 1152 uno::Reference< container::XNameAccess > xNameAccess( xConfig->createInstanceWithArguments( OUSTR("com.sun.star.configuration.ConfigurationAccess"), args), uno::UNO_QUERY_THROW ); 1153 uno::Sequence< rtl::OUString > aElementNames = xNameAccess->getElementNames(); 1154 1155 for ( sal_Int32 i = 0; i < aElementNames.getLength(); i++ ) 1156 { 1157 ::rtl::OUString aIdentifier = aElementNames[i]; 1158 ::rtl::OUString aVersion; 1159 1160 uno::Any aPropValue( uno::Reference< beans::XPropertySet >( xNameAccess->getByName( aIdentifier ), uno::UNO_QUERY_THROW )->getPropertyValue( PROPERTY_VERSION ) ); 1161 aPropValue >>= aVersion; 1162 IgnoredUpdate *pData = new IgnoredUpdate( aIdentifier, aVersion ); 1163 m_ignoredUpdates.push_back( pData ); 1164 } 1165 } 1166 1167 //------------------------------------------------------------------------------ 1168 void UpdateDialog::storeIgnoredUpdates() 1169 { 1170 if ( m_bModified && ( m_ignoredUpdates.size() != 0 ) ) 1171 { 1172 uno::Reference< lang::XMultiServiceFactory > xConfig( m_context->getServiceManager()->createInstanceWithContext( 1173 OUSTR("com.sun.star.configuration.ConfigurationProvider"), m_context ), uno::UNO_QUERY_THROW ); 1174 beans::NamedValue aValue( OUSTR("nodepath"), uno::Any( IGNORED_UPDATES ) ); 1175 uno::Sequence< uno::Any > args(1); 1176 args[0] <<= aValue; 1177 1178 uno::Reference< container::XNameContainer > xNameContainer( xConfig->createInstanceWithArguments( 1179 OUSTR("com.sun.star.configuration.ConfigurationUpdateAccess"), args ), uno::UNO_QUERY_THROW ); 1180 1181 for ( std::vector< UpdateDialog::IgnoredUpdate* >::iterator i( m_ignoredUpdates.begin() ); i != m_ignoredUpdates.end(); ++i ) 1182 { 1183 if ( xNameContainer->hasByName( (*i)->sExtensionID ) ) 1184 { 1185 if ( (*i)->bRemoved ) 1186 xNameContainer->removeByName( (*i)->sExtensionID ); 1187 else 1188 uno::Reference< beans::XPropertySet >( xNameContainer->getByName( (*i)->sExtensionID ), uno::UNO_QUERY_THROW )->setPropertyValue( PROPERTY_VERSION, uno::Any( (*i)->sVersion ) ); 1189 } 1190 else if ( ! (*i)->bRemoved ) 1191 { 1192 uno::Reference< beans::XPropertySet > elem( uno::Reference< lang::XSingleServiceFactory >( xNameContainer, uno::UNO_QUERY_THROW )->createInstance(), uno::UNO_QUERY_THROW ); 1193 elem->setPropertyValue( PROPERTY_VERSION, uno::Any( (*i)->sVersion ) ); 1194 xNameContainer->insertByName( (*i)->sExtensionID, uno::Any( elem ) ); 1195 } 1196 } 1197 1198 uno::Reference< util::XChangesBatch > xChangesBatch( xNameContainer, uno::UNO_QUERY ); 1199 if ( xChangesBatch.is() && xChangesBatch->hasPendingChanges() ) 1200 xChangesBatch->commitChanges(); 1201 } 1202 1203 m_bModified = false; 1204 } 1205 1206 //------------------------------------------------------------------------------ 1207 bool UpdateDialog::isIgnoredUpdate( UpdateDialog::Index * index ) 1208 { 1209 bool bIsIgnored = false; 1210 1211 if ( m_ignoredUpdates.size() != 0 ) 1212 { 1213 rtl::OUString aExtensionID; 1214 rtl::OUString aVersion; 1215 1216 if ( index->m_eKind == ENABLED_UPDATE ) 1217 { 1218 dp_gui::UpdateData aUpdData = m_enabledUpdates[ index->m_nIndex ]; 1219 aExtensionID = dp_misc::getIdentifier( aUpdData.aInstalledPackage ); 1220 aVersion = aUpdData.updateVersion; 1221 } 1222 else if ( index->m_eKind == DISABLED_UPDATE ) 1223 { 1224 DisabledUpdate &rData = m_disabledUpdates[ index->m_nIndex ]; 1225 dp_misc::DescriptionInfoset aInfoset( m_context, rData.aUpdateInfo ); 1226 ::boost::optional< ::rtl::OUString > aID( aInfoset.getIdentifier() ); 1227 if ( aID ) 1228 aExtensionID = *aID; 1229 aVersion = aInfoset.getVersion(); 1230 } 1231 1232 for ( std::vector< UpdateDialog::IgnoredUpdate* >::iterator i( m_ignoredUpdates.begin() ); i != m_ignoredUpdates.end(); ++i ) 1233 { 1234 if ( (*i)->sExtensionID == aExtensionID ) 1235 { 1236 if ( ( (*i)->sVersion.getLength() == 0 ) || ( (*i)->sVersion == aVersion ) ) 1237 { 1238 bIsIgnored = true; 1239 index->m_bIgnored = true; 1240 } 1241 else // when we find another update of an ignored version, we will remove the old one to keep the ignored list small 1242 (*i)->bRemoved = true; 1243 break; 1244 } 1245 } 1246 } 1247 1248 return bIsIgnored; 1249 } 1250 1251 //------------------------------------------------------------------------------ 1252 void UpdateDialog::setIgnoredUpdate( UpdateDialog::Index *pIndex, bool bIgnore, bool bIgnoreAll ) 1253 { 1254 rtl::OUString aExtensionID; 1255 rtl::OUString aVersion; 1256 1257 m_bModified = true; 1258 1259 if ( pIndex->m_eKind == ENABLED_UPDATE ) 1260 { 1261 dp_gui::UpdateData aUpdData = m_enabledUpdates[ pIndex->m_nIndex ]; 1262 aExtensionID = dp_misc::getIdentifier( aUpdData.aInstalledPackage ); 1263 if ( !bIgnoreAll ) 1264 aVersion = aUpdData.updateVersion; 1265 } 1266 else if ( pIndex->m_eKind == DISABLED_UPDATE ) 1267 { 1268 DisabledUpdate &rData = m_disabledUpdates[ pIndex->m_nIndex ]; 1269 dp_misc::DescriptionInfoset aInfoset( m_context, rData.aUpdateInfo ); 1270 ::boost::optional< ::rtl::OUString > aID( aInfoset.getIdentifier() ); 1271 if ( aID ) 1272 aExtensionID = *aID; 1273 if ( !bIgnoreAll ) 1274 aVersion = aInfoset.getVersion(); 1275 } 1276 1277 if ( aExtensionID.getLength() ) 1278 { 1279 bool bFound = false; 1280 for ( std::vector< UpdateDialog::IgnoredUpdate* >::iterator i( m_ignoredUpdates.begin() ); i != m_ignoredUpdates.end(); ++i ) 1281 { 1282 if ( (*i)->sExtensionID == aExtensionID ) 1283 { 1284 (*i)->sVersion = aVersion; 1285 (*i)->bRemoved = !bIgnore; 1286 bFound = true; 1287 break; 1288 } 1289 } 1290 if ( bIgnore && !bFound ) 1291 { 1292 IgnoredUpdate *pData = new IgnoredUpdate( aExtensionID, aVersion ); 1293 m_ignoredUpdates.push_back( pData ); 1294 } 1295 } 1296 } 1297 1298 //------------------------------------------------------------------------------ 1299 IMPL_LINK(UpdateDialog, selectionHandler, void *, EMPTYARG) 1300 { 1301 rtl::OUStringBuffer b; 1302 bool bInserted = false; 1303 UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >( 1304 m_updates.GetEntryData(m_updates.GetSelectEntryPos())); 1305 clearDescription(); 1306 1307 if ( p != NULL ) 1308 { 1309 sal_uInt16 pos = p->m_nIndex; 1310 1311 switch (p->m_eKind) 1312 { 1313 case ENABLED_UPDATE: 1314 { 1315 if ( m_enabledUpdates[ pos ].aUpdateSource.is() ) 1316 bInserted = showDescription( m_enabledUpdates[ pos ].aUpdateSource ); 1317 else 1318 bInserted = showDescription( m_enabledUpdates[ pos ].aUpdateInfo ); 1319 1320 if ( p->m_bIgnored ) 1321 b.append( m_ignoredUpdate ); 1322 1323 break; 1324 } 1325 case DISABLED_UPDATE: 1326 { 1327 bInserted = showDescription( m_disabledUpdates[pos].aUpdateInfo ); 1328 1329 if ( p->m_bIgnored ) 1330 b.append( m_ignoredUpdate ); 1331 1332 UpdateDialog::DisabledUpdate & data = m_disabledUpdates[ pos ]; 1333 if (data.unsatisfiedDependencies.getLength() != 0) 1334 { 1335 // create error string for version mismatch 1336 ::rtl::OUString sVersion( RTL_CONSTASCII_USTRINGPARAM("%VERSION") ); 1337 sal_Int32 nPos = m_noDependencyCurVer.indexOf( sVersion ); 1338 if ( nPos >= 0 ) 1339 { 1340 ::rtl::OUString sCurVersion( RTL_CONSTASCII_USTRINGPARAM( "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":Version:OOOPackageVersion}")); 1341 ::rtl::Bootstrap::expandMacros(sCurVersion); 1342 m_noDependencyCurVer = m_noDependencyCurVer.replaceAt( nPos, sVersion.getLength(), sCurVersion ); 1343 } 1344 1345 b.append(m_noInstall); 1346 b.append(LF); 1347 b.append(m_noDependency); 1348 for (sal_Int32 i = 0; 1349 i < data.unsatisfiedDependencies.getLength(); ++i) 1350 { 1351 b.append(LF); 1352 b.appendAscii(RTL_CONSTASCII_STRINGPARAM(" ")); 1353 // U+2003 EM SPACE would be better than two spaces, 1354 // but some fonts do not contain it 1355 b.append( 1356 confineToParagraph( 1357 data.unsatisfiedDependencies[i])); 1358 } 1359 b.append(LF); 1360 b.appendAscii(RTL_CONSTASCII_STRINGPARAM(" ")); 1361 b.append(m_noDependencyCurVer); 1362 } 1363 break; 1364 } 1365 case SPECIFIC_ERROR: 1366 { 1367 UpdateDialog::SpecificError & data = m_specificErrors[ pos ]; 1368 b.append(m_failure); 1369 b.append(LF); 1370 b.append( data.message.getLength() == 0 ? m_unknownError : data.message ); 1371 break; 1372 } 1373 default: 1374 OSL_ASSERT(false); 1375 break; 1376 } 1377 } 1378 1379 if ( b.getLength() == 0 ) 1380 b.append( m_noDescription ); 1381 1382 showDescription( b.makeStringAndClear(), bInserted ); 1383 return 0; 1384 } 1385 1386 IMPL_LINK(UpdateDialog, allHandler, void *, EMPTYARG) 1387 { 1388 if (m_all.IsChecked()) 1389 { 1390 m_update.Enable(); 1391 m_updates.Enable(); 1392 m_description.Enable(); 1393 m_descriptions.Enable(); 1394 1395 for (std::vector< UpdateDialog::Index* >::iterator i( m_ListboxEntries.begin() ); 1396 i != m_ListboxEntries.end(); ++i ) 1397 { 1398 if ( (*i)->m_bIgnored || ( (*i)->m_eKind != ENABLED_UPDATE ) ) 1399 insertItem( (*i), SvLBoxButtonKind_disabledCheckbox ); 1400 } 1401 } 1402 else 1403 { 1404 for ( sal_uInt16 i = 0; i < m_updates.getItemCount(); ) 1405 { 1406 UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >( m_updates.GetEntryData(i) ); 1407 if ( p->m_bIgnored || ( p->m_eKind != ENABLED_UPDATE ) ) 1408 { 1409 m_updates.RemoveEntry(i); 1410 } else { 1411 ++i; 1412 } 1413 } 1414 1415 if (m_updates.getItemCount() == 0) 1416 { 1417 clearDescription(); 1418 m_update.Disable(); 1419 m_updates.Disable(); 1420 if (m_checking.IsVisible()) 1421 m_description.Disable(); 1422 else 1423 showDescription(m_noInstallable,false); 1424 } 1425 } 1426 return 0; 1427 } 1428 1429 IMPL_LINK(UpdateDialog, okHandler, void *, EMPTYARG) 1430 { 1431 //If users are going to update a shared extension then we need 1432 //to warn them 1433 typedef ::std::vector<UpdateData>::const_iterator CIT; 1434 for (CIT i = m_enabledUpdates.begin(); i < m_enabledUpdates.end(); i++) 1435 { 1436 OSL_ASSERT(i->aInstalledPackage.is()); 1437 //If the user has no write access to the shared folder then the update 1438 //for a shared extension is disable, that is it cannot be in m_enabledUpdates 1439 // OSL_ASSERT(isReadOnly(i->aInstalledPackage) == sal_False); 1440 #if 0 1441 // TODO: check! 1442 OSL_ASSERT(m_extensionManagerDialog.get()); 1443 if (RET_CANCEL == m_extensionManagerDialog->continueUpdateForSharedExtension( 1444 this, i->aPackageManager)) 1445 { 1446 EndDialog(RET_CANCEL); 1447 } 1448 #endif 1449 } 1450 1451 1452 for (sal_uInt16 i = 0; i < m_updates.getItemCount(); ++i) { 1453 UpdateDialog::Index const * p = 1454 static_cast< UpdateDialog::Index const * >( 1455 m_updates.GetEntryData(i)); 1456 if (p->m_eKind == ENABLED_UPDATE && m_updates.IsChecked(i)) { 1457 m_updateData.push_back( m_enabledUpdates[ p->m_nIndex ] ); 1458 } 1459 } 1460 1461 EndDialog(RET_OK); 1462 return 0; 1463 } 1464 1465 IMPL_LINK(UpdateDialog, closeHandler, void *, EMPTYARG) { 1466 m_thread->stop(); 1467 EndDialog(RET_CANCEL); 1468 return 0; 1469 } 1470 1471 IMPL_LINK( UpdateDialog, hyperlink_clicked, svt::FixedHyperlink*, pHyperlink ) 1472 { 1473 ::rtl::OUString sURL; 1474 if ( pHyperlink ) 1475 sURL = ::rtl::OUString( pHyperlink->GetURL() ); 1476 if ( sURL.getLength() == 0 ) 1477 return 0; 1478 1479 try 1480 { 1481 uno::Reference< com::sun::star::system::XSystemShellExecute > xSystemShellExecute( 1482 m_context->getServiceManager()->createInstanceWithContext( 1483 OUSTR( "com.sun.star.system.SystemShellExecute" ), 1484 m_context), uno::UNO_QUERY_THROW); 1485 //throws lang::IllegalArgumentException, system::SystemShellExecuteException 1486 xSystemShellExecute->execute( 1487 sURL, ::rtl::OUString(), com::sun::star::system::SystemShellExecuteFlags::DEFAULTS); 1488 } 1489 catch (uno::Exception& ) 1490 { 1491 } 1492 1493 return 1; 1494 } 1495