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