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