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 = new UpdateDialog::CheckListBox(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 : storeIgnoredUpdates();
568 :
569 0 : for ( std::vector< UpdateDialog::Index* >::iterator i( m_ListboxEntries.begin() ); i != m_ListboxEntries.end(); ++i )
570 : {
571 0 : delete (*i);
572 : }
573 0 : for ( std::vector< UpdateDialog::IgnoredUpdate* >::iterator i( m_ignoredUpdates.begin() ); i != m_ignoredUpdates.end(); ++i )
574 : {
575 0 : delete (*i);
576 : }
577 0 : delete m_pUpdates;
578 0 : }
579 :
580 :
581 0 : bool UpdateDialog::Close() {
582 0 : m_thread->stop();
583 0 : return ModalDialog::Close();
584 : }
585 :
586 0 : short UpdateDialog::Execute() {
587 0 : m_pthrobber->start();
588 0 : m_thread->launch();
589 0 : return ModalDialog::Execute();
590 : }
591 :
592 0 : UpdateDialog::CheckListBox::CheckListBox( vcl::Window* pParent, UpdateDialog & dialog):
593 : SvxCheckListBox( pParent, WinBits(WB_BORDER) ),
594 : m_ignoreUpdate( DPGUI_RESSTR( RID_DLG_UPDATE_IGNORE ) ),
595 : m_ignoreAllUpdates( DPGUI_RESSTR( RID_DLG_UPDATE_IGNORE_ALL ) ),
596 : m_enableUpdate( DPGUI_RESSTR( RID_DLG_UPDATE_ENABLE ) ),
597 0 : m_dialog(dialog)
598 : {
599 0 : SetNormalStaticImage(Image(DpGuiResId(RID_DLG_UPDATE_NORMALALERT)));
600 0 : }
601 :
602 0 : UpdateDialog::CheckListBox::~CheckListBox() {}
603 :
604 :
605 0 : sal_uInt16 UpdateDialog::CheckListBox::getItemCount() const {
606 0 : sal_uLong i = GetEntryCount();
607 : OSL_ASSERT(i <= std::numeric_limits< sal_uInt16 >::max());
608 0 : return sal::static_int_cast< sal_uInt16 >(i);
609 : }
610 :
611 :
612 0 : void UpdateDialog::CheckListBox::MouseButtonDown( MouseEvent const & event )
613 : {
614 : // When clicking on a selected entry in an SvxCheckListBox, the entry's
615 : // checkbox is toggled on mouse button down:
616 0 : SvxCheckListBox::MouseButtonDown( event );
617 :
618 0 : if ( event.IsRight() )
619 : {
620 0 : handlePopupMenu( event.GetPosPixel() );
621 : }
622 :
623 0 : m_dialog.enableOk();
624 0 : }
625 :
626 :
627 0 : void UpdateDialog::CheckListBox::MouseButtonUp(MouseEvent const & event) {
628 : // When clicking on an entry's checkbox in an SvxCheckListBox, the entry's
629 : // checkbox is toggled on mouse button up:
630 0 : SvxCheckListBox::MouseButtonUp(event);
631 0 : m_dialog.enableOk();
632 0 : }
633 :
634 0 : void UpdateDialog::CheckListBox::KeyInput(KeyEvent const & event) {
635 0 : SvxCheckListBox::KeyInput(event);
636 0 : m_dialog.enableOk();
637 0 : }
638 :
639 :
640 0 : void UpdateDialog::CheckListBox::handlePopupMenu( const Point &rPos )
641 : {
642 0 : SvTreeListEntry *pData = GetEntry( rPos );
643 :
644 0 : if ( pData )
645 : {
646 0 : sal_uLong nEntryPos = GetSelectEntryPos();
647 0 : UpdateDialog::Index * p = static_cast< UpdateDialog::Index * >( GetEntryData( nEntryPos ) );
648 :
649 0 : if ( ( p->m_eKind == ENABLED_UPDATE ) || ( p->m_eKind == DISABLED_UPDATE ) )
650 : {
651 0 : PopupMenu aPopup;
652 :
653 0 : if ( p->m_bIgnored )
654 0 : aPopup.InsertItem( CMD_ENABLE_UPDATE, m_enableUpdate );
655 : else
656 : {
657 0 : aPopup.InsertItem( CMD_IGNORE_UPDATE, m_ignoreUpdate );
658 0 : aPopup.InsertItem( CMD_IGNORE_ALL_UPDATES, m_ignoreAllUpdates );
659 : }
660 :
661 0 : sal_uInt16 aCmd = aPopup.Execute( this, rPos );
662 0 : if ( ( aCmd == CMD_IGNORE_UPDATE ) || ( aCmd == CMD_IGNORE_ALL_UPDATES ) )
663 : {
664 0 : p->m_bIgnored = true;
665 0 : if ( p->m_eKind == ENABLED_UPDATE )
666 : {
667 0 : RemoveEntry( nEntryPos );
668 0 : m_dialog.addAdditional( p, SvLBoxButtonKind_disabledCheckbox );
669 : }
670 0 : if ( aCmd == CMD_IGNORE_UPDATE )
671 0 : m_dialog.setIgnoredUpdate( p, true, false );
672 : else
673 0 : m_dialog.setIgnoredUpdate( p, true, true );
674 : // TODO: reselect entry to display new description!
675 : }
676 0 : else if ( aCmd == CMD_ENABLE_UPDATE )
677 : {
678 0 : p->m_bIgnored = false;
679 0 : if ( p->m_eKind == ENABLED_UPDATE )
680 : {
681 0 : RemoveEntry( nEntryPos );
682 0 : m_dialog.insertItem( p, SvLBoxButtonKind_enabledCheckbox );
683 : }
684 0 : m_dialog.setIgnoredUpdate( p, false, false );
685 0 : }
686 : }
687 : }
688 0 : }
689 :
690 :
691 :
692 :
693 0 : sal_uInt16 UpdateDialog::insertItem( UpdateDialog::Index *pEntry, SvLBoxButtonKind kind )
694 : {
695 0 : m_pUpdates->InsertEntry( pEntry->m_aName, TREELIST_APPEND, static_cast< void * >( pEntry ), kind );
696 :
697 0 : for ( sal_uInt16 i = m_pUpdates->getItemCount(); i != 0 ; )
698 : {
699 0 : i -= 1;
700 0 : UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >( m_pUpdates->GetEntryData( i ) );
701 0 : if ( p == pEntry )
702 0 : return i;
703 : }
704 : OSL_ASSERT(false);
705 0 : return 0;
706 : }
707 :
708 :
709 0 : void UpdateDialog::addAdditional( UpdateDialog::Index * index, SvLBoxButtonKind kind )
710 : {
711 0 : m_pAll->Enable();
712 0 : if (m_pAll->IsChecked())
713 : {
714 0 : insertItem( index, kind );
715 0 : m_pUpdate->Enable();
716 0 : m_pUpdates->Enable();
717 0 : m_pDescription->Enable();
718 0 : m_pDescriptions->Enable();
719 : }
720 0 : }
721 :
722 :
723 0 : void UpdateDialog::addEnabledUpdate( OUString const & name,
724 : dp_gui::UpdateData & data )
725 : {
726 0 : sal_uInt16 nIndex = sal::static_int_cast< sal_uInt16 >( m_enabledUpdates.size() );
727 0 : UpdateDialog::Index *pEntry = new UpdateDialog::Index( ENABLED_UPDATE, m_nLastID, nIndex, name );
728 :
729 0 : data.m_nID = m_nLastID;
730 0 : m_nLastID += 1;
731 :
732 0 : m_enabledUpdates.push_back( data );
733 0 : m_ListboxEntries.push_back( pEntry );
734 :
735 0 : if ( ! isIgnoredUpdate( pEntry ) )
736 : {
737 0 : sal_uInt16 nPos = insertItem( pEntry, SvLBoxButtonKind_enabledCheckbox );
738 0 : m_pUpdates->CheckEntryPos( nPos );
739 : }
740 : else
741 0 : addAdditional( pEntry, SvLBoxButtonKind_disabledCheckbox );
742 :
743 0 : m_pUpdate->Enable();
744 0 : m_pUpdates->Enable();
745 0 : m_pDescription->Enable();
746 0 : m_pDescriptions->Enable();
747 0 : }
748 :
749 :
750 0 : void UpdateDialog::addDisabledUpdate( UpdateDialog::DisabledUpdate & data )
751 : {
752 0 : sal_uInt16 nIndex = sal::static_int_cast< sal_uInt16 >( m_disabledUpdates.size() );
753 0 : UpdateDialog::Index *pEntry = new UpdateDialog::Index( DISABLED_UPDATE, m_nLastID, nIndex, data.name );
754 :
755 0 : data.m_nID = m_nLastID;
756 0 : m_nLastID += 1;
757 :
758 0 : m_disabledUpdates.push_back( data );
759 0 : m_ListboxEntries.push_back( pEntry );
760 :
761 0 : isIgnoredUpdate( pEntry );
762 0 : addAdditional( pEntry, SvLBoxButtonKind_disabledCheckbox );
763 0 : }
764 :
765 :
766 0 : void UpdateDialog::addSpecificError( UpdateDialog::SpecificError & data )
767 : {
768 0 : sal_uInt16 nIndex = sal::static_int_cast< sal_uInt16 >( m_specificErrors.size() );
769 0 : UpdateDialog::Index *pEntry = new UpdateDialog::Index( SPECIFIC_ERROR, m_nLastID, nIndex, data.name );
770 :
771 0 : data.m_nID = m_nLastID;
772 0 : m_nLastID += 1;
773 :
774 0 : m_specificErrors.push_back( data );
775 0 : m_ListboxEntries.push_back( pEntry );
776 :
777 0 : addAdditional( pEntry, SvLBoxButtonKind_staticImage);
778 0 : }
779 :
780 0 : void UpdateDialog::checkingDone() {
781 0 : m_pchecking->Hide();
782 0 : m_pthrobber->stop();
783 0 : m_pthrobber->Hide();
784 0 : if (m_pUpdates->getItemCount() == 0)
785 : {
786 0 : clearDescription();
787 0 : m_pDescription->Enable();
788 0 : m_pDescriptions->Enable();
789 :
790 0 : if ( m_disabledUpdates.empty() && m_specificErrors.empty() && m_ignoredUpdates.empty() )
791 0 : showDescription( m_none );
792 : else
793 0 : showDescription( m_noInstallable );
794 : }
795 :
796 0 : enableOk();
797 0 : }
798 :
799 0 : void UpdateDialog::enableOk() {
800 0 : if (!m_pchecking->IsVisible()) {
801 0 : m_pOk->Enable(m_pUpdates->GetCheckedEntryCount() != 0);
802 : }
803 0 : }
804 :
805 : // *********************************************************************************
806 0 : void UpdateDialog::createNotifyJob( bool bPrepareOnly,
807 : uno::Sequence< uno::Sequence< OUString > > &rItemList )
808 : {
809 0 : if ( !dp_misc::office_is_running() )
810 0 : return;
811 :
812 : // notify update check job
813 : try
814 : {
815 : uno::Reference< lang::XMultiServiceFactory > xConfigProvider(
816 : configuration::theDefaultProvider::get(
817 0 : comphelper::getProcessComponentContext()));
818 :
819 0 : beans::PropertyValue aProperty;
820 0 : aProperty.Name = "nodepath";
821 0 : aProperty.Value = uno::makeAny( OUString("org.openoffice.Office.Addons/AddonUI/OfficeHelp/UpdateCheckJob") );
822 :
823 0 : uno::Sequence< uno::Any > aArgumentList( 1 );
824 0 : aArgumentList[0] = uno::makeAny( aProperty );
825 :
826 : uno::Reference< container::XNameAccess > xNameAccess(
827 0 : xConfigProvider->createInstanceWithArguments(
828 0 : "com.sun.star.configuration.ConfigurationAccess", aArgumentList ),
829 0 : uno::UNO_QUERY_THROW );
830 :
831 0 : util::URL aURL;
832 0 : xNameAccess->getByName("URL") >>= aURL.Complete;
833 :
834 0 : uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
835 0 : uno::Reference < util::XURLTransformer > xTransformer = util::URLTransformer::create(xContext);
836 :
837 0 : xTransformer->parseStrict(aURL);
838 :
839 0 : uno::Reference < frame::XDesktop2 > xDesktop = frame::Desktop::create( xContext );
840 0 : uno::Reference< frame::XDispatchProvider > xDispatchProvider( xDesktop->getCurrentFrame(),
841 0 : uno::UNO_QUERY_THROW );
842 0 : uno::Reference< frame::XDispatch > xDispatch = xDispatchProvider->queryDispatch(aURL, OUString(), 0);
843 :
844 0 : if( xDispatch.is() )
845 : {
846 0 : uno::Sequence< beans::PropertyValue > aPropList(2);
847 0 : aProperty.Name = "updateList";
848 0 : aProperty.Value = uno::makeAny( rItemList );
849 0 : aPropList[0] = aProperty;
850 0 : aProperty.Name = "prepareOnly";
851 0 : aProperty.Value = uno::makeAny( bPrepareOnly );
852 0 : aPropList[1] = aProperty;
853 :
854 0 : xDispatch->dispatch(aURL, aPropList );
855 0 : }
856 : }
857 0 : catch( const uno::Exception& e )
858 : {
859 : dp_misc::TRACE( "Caught exception: "
860 0 : + e.Message + "\n thread terminated.\n\n");
861 : }
862 : }
863 :
864 : // *********************************************************************************
865 0 : void UpdateDialog::notifyMenubar( bool bPrepareOnly, bool bRecheckOnly )
866 : {
867 0 : if ( !dp_misc::office_is_running() )
868 0 : return;
869 :
870 0 : uno::Sequence< uno::Sequence< OUString > > aItemList;
871 :
872 0 : if ( ! bRecheckOnly )
873 : {
874 0 : sal_Int32 nCount = 0;
875 0 : for ( sal_Int16 i = 0; i < m_pUpdates->getItemCount(); ++i )
876 : {
877 0 : uno::Sequence< OUString > aItem(2);
878 :
879 0 : UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >(m_pUpdates->GetEntryData(i));
880 :
881 0 : if ( p->m_eKind == ENABLED_UPDATE )
882 : {
883 0 : dp_gui::UpdateData aUpdData = m_enabledUpdates[ p->m_nIndex ];
884 0 : aItem[0] = dp_misc::getIdentifier( aUpdData.aInstalledPackage );
885 :
886 0 : dp_misc::DescriptionInfoset aInfoset( m_context, aUpdData.aUpdateInfo );
887 0 : aItem[1] = aInfoset.getVersion();
888 : }
889 : else
890 0 : continue;
891 :
892 0 : aItemList.realloc( nCount + 1 );
893 0 : aItemList[ nCount ] = aItem;
894 0 : nCount += 1;
895 0 : }
896 : }
897 :
898 0 : storeIgnoredUpdates();
899 0 : createNotifyJob( bPrepareOnly, aItemList );
900 : }
901 :
902 : // *********************************************************************************
903 :
904 0 : void UpdateDialog::initDescription()
905 : {
906 0 : m_pPublisherLabel->Hide();
907 0 : m_pPublisherLink->Hide();
908 0 : m_pReleaseNotesLabel->Hide();
909 0 : m_pReleaseNotesLink->Hide();
910 :
911 0 : Link aLink = LINK( this, UpdateDialog, hyperlink_clicked );
912 0 : m_pPublisherLink->SetClickHdl( aLink );
913 0 : m_pReleaseNotesLink->SetClickHdl( aLink );
914 0 : }
915 :
916 0 : void UpdateDialog::clearDescription()
917 : {
918 0 : OUString sEmpty;
919 0 : m_pPublisherLabel->Hide();
920 0 : m_pPublisherLink->Hide();
921 0 : m_pPublisherLink->SetText( sEmpty );
922 0 : m_pPublisherLink->SetURL( sEmpty );
923 0 : m_pReleaseNotesLabel->Hide();
924 0 : m_pReleaseNotesLink->Hide();
925 0 : m_pReleaseNotesLink->SetURL( sEmpty );
926 0 : m_pDescriptions->SetText("");
927 0 : }
928 :
929 0 : bool UpdateDialog::showDescription(uno::Reference< xml::dom::XNode > const & aUpdateInfo)
930 : {
931 0 : dp_misc::DescriptionInfoset infoset(m_context, aUpdateInfo);
932 : return showDescription(infoset.getLocalizedPublisherNameAndURL(),
933 0 : infoset.getLocalizedReleaseNotesURL());
934 : }
935 :
936 0 : bool UpdateDialog::showDescription(uno::Reference< deployment::XPackage > const & aExtension)
937 : {
938 : OSL_ASSERT(aExtension.is());
939 0 : beans::StringPair pubInfo = aExtension->getPublisherInfo();
940 : return showDescription(std::make_pair(pubInfo.First, pubInfo.Second),
941 0 : "");
942 : }
943 :
944 0 : bool UpdateDialog::showDescription(std::pair< OUString, OUString > const & pairPublisher,
945 : OUString const & sReleaseNotes)
946 : {
947 0 : OUString sPub = pairPublisher.first;
948 0 : OUString sURL = pairPublisher.second;
949 :
950 0 : if ( sPub.isEmpty() && sURL.isEmpty() && sReleaseNotes.isEmpty() )
951 : // nothing to show
952 0 : return false;
953 :
954 0 : if ( !sPub.isEmpty() )
955 : {
956 0 : m_pPublisherLabel->Show();
957 0 : m_pPublisherLink->Show();
958 0 : m_pPublisherLink->SetText( sPub );
959 0 : m_pPublisherLink->SetURL( sURL );
960 : }
961 :
962 0 : if ( !sReleaseNotes.isEmpty() )
963 : {
964 0 : m_pReleaseNotesLabel->Show();
965 0 : m_pReleaseNotesLink->Show();
966 0 : m_pReleaseNotesLink->SetURL( sReleaseNotes );
967 : }
968 0 : return true;
969 : }
970 :
971 0 : bool UpdateDialog::showDescription( const OUString& rDescription)
972 : {
973 0 : if ( rDescription.isEmpty() )
974 : // nothing to show
975 0 : return false;
976 :
977 0 : m_pDescriptions->SetText( rDescription );
978 0 : return true;
979 : }
980 :
981 :
982 0 : void UpdateDialog::getIgnoredUpdates()
983 : {
984 : uno::Reference< lang::XMultiServiceFactory > xConfig(
985 0 : configuration::theDefaultProvider::get(m_context));
986 0 : beans::NamedValue aValue( "nodepath", uno::Any( IGNORED_UPDATES ) );
987 0 : uno::Sequence< uno::Any > args(1);
988 0 : args[0] <<= aValue;
989 :
990 0 : uno::Reference< container::XNameAccess > xNameAccess( xConfig->createInstanceWithArguments( "com.sun.star.configuration.ConfigurationAccess", args), uno::UNO_QUERY_THROW );
991 0 : uno::Sequence< OUString > aElementNames = xNameAccess->getElementNames();
992 :
993 0 : for ( sal_Int32 i = 0; i < aElementNames.getLength(); i++ )
994 : {
995 0 : OUString aIdentifier = aElementNames[i];
996 0 : OUString aVersion;
997 :
998 0 : uno::Any aPropValue( uno::Reference< beans::XPropertySet >( xNameAccess->getByName( aIdentifier ), uno::UNO_QUERY_THROW )->getPropertyValue( PROPERTY_VERSION ) );
999 0 : aPropValue >>= aVersion;
1000 0 : IgnoredUpdate *pData = new IgnoredUpdate( aIdentifier, aVersion );
1001 0 : m_ignoredUpdates.push_back( pData );
1002 0 : }
1003 0 : }
1004 :
1005 :
1006 0 : void UpdateDialog::storeIgnoredUpdates()
1007 : {
1008 0 : if ( m_bModified && ( !m_ignoredUpdates.empty() ) )
1009 : {
1010 : uno::Reference< lang::XMultiServiceFactory > xConfig(
1011 0 : configuration::theDefaultProvider::get(m_context));
1012 0 : beans::NamedValue aValue( "nodepath", uno::Any( IGNORED_UPDATES ) );
1013 0 : uno::Sequence< uno::Any > args(1);
1014 0 : args[0] <<= aValue;
1015 :
1016 0 : uno::Reference< container::XNameContainer > xNameContainer( xConfig->createInstanceWithArguments(
1017 0 : "com.sun.star.configuration.ConfigurationUpdateAccess", args ), uno::UNO_QUERY_THROW );
1018 :
1019 0 : for ( std::vector< UpdateDialog::IgnoredUpdate* >::iterator i( m_ignoredUpdates.begin() ); i != m_ignoredUpdates.end(); ++i )
1020 : {
1021 0 : if ( xNameContainer->hasByName( (*i)->sExtensionID ) )
1022 : {
1023 0 : if ( (*i)->bRemoved )
1024 0 : xNameContainer->removeByName( (*i)->sExtensionID );
1025 : else
1026 0 : uno::Reference< beans::XPropertySet >( xNameContainer->getByName( (*i)->sExtensionID ), uno::UNO_QUERY_THROW )->setPropertyValue( PROPERTY_VERSION, uno::Any( (*i)->sVersion ) );
1027 : }
1028 0 : else if ( ! (*i)->bRemoved )
1029 : {
1030 0 : uno::Reference< beans::XPropertySet > elem( uno::Reference< lang::XSingleServiceFactory >( xNameContainer, uno::UNO_QUERY_THROW )->createInstance(), uno::UNO_QUERY_THROW );
1031 0 : elem->setPropertyValue( PROPERTY_VERSION, uno::Any( (*i)->sVersion ) );
1032 0 : xNameContainer->insertByName( (*i)->sExtensionID, uno::Any( elem ) );
1033 : }
1034 : }
1035 :
1036 0 : uno::Reference< util::XChangesBatch > xChangesBatch( xNameContainer, uno::UNO_QUERY );
1037 0 : if ( xChangesBatch.is() && xChangesBatch->hasPendingChanges() )
1038 0 : xChangesBatch->commitChanges();
1039 : }
1040 :
1041 0 : m_bModified = false;
1042 0 : }
1043 :
1044 :
1045 0 : bool UpdateDialog::isIgnoredUpdate( UpdateDialog::Index * index )
1046 : {
1047 0 : bool bIsIgnored = false;
1048 :
1049 0 : if (! m_ignoredUpdates.empty() )
1050 : {
1051 0 : OUString aExtensionID;
1052 0 : OUString aVersion;
1053 :
1054 0 : if ( index->m_eKind == ENABLED_UPDATE )
1055 : {
1056 0 : dp_gui::UpdateData aUpdData = m_enabledUpdates[ index->m_nIndex ];
1057 0 : aExtensionID = dp_misc::getIdentifier( aUpdData.aInstalledPackage );
1058 0 : aVersion = aUpdData.updateVersion;
1059 : }
1060 0 : else if ( index->m_eKind == DISABLED_UPDATE )
1061 : {
1062 0 : DisabledUpdate &rData = m_disabledUpdates[ index->m_nIndex ];
1063 0 : dp_misc::DescriptionInfoset aInfoset( m_context, rData.aUpdateInfo );
1064 0 : ::boost::optional< OUString > aID( aInfoset.getIdentifier() );
1065 0 : if ( aID )
1066 0 : aExtensionID = *aID;
1067 0 : aVersion = aInfoset.getVersion();
1068 : }
1069 :
1070 0 : for ( std::vector< UpdateDialog::IgnoredUpdate* >::iterator i( m_ignoredUpdates.begin() ); i != m_ignoredUpdates.end(); ++i )
1071 : {
1072 0 : if ( (*i)->sExtensionID == aExtensionID )
1073 : {
1074 0 : if ( ( !(*i)->sVersion.isEmpty() ) || ( (*i)->sVersion == aVersion ) )
1075 : {
1076 0 : bIsIgnored = true;
1077 0 : index->m_bIgnored = true;
1078 : }
1079 : else // when we find another update of an ignored version, we will remove the old one to keep the ignored list small
1080 0 : (*i)->bRemoved = true;
1081 0 : break;
1082 : }
1083 0 : }
1084 : }
1085 :
1086 0 : return bIsIgnored;
1087 : }
1088 :
1089 :
1090 0 : void UpdateDialog::setIgnoredUpdate( UpdateDialog::Index *pIndex, bool bIgnore, bool bIgnoreAll )
1091 : {
1092 0 : OUString aExtensionID;
1093 0 : OUString aVersion;
1094 :
1095 0 : m_bModified = true;
1096 :
1097 0 : if ( pIndex->m_eKind == ENABLED_UPDATE )
1098 : {
1099 0 : dp_gui::UpdateData aUpdData = m_enabledUpdates[ pIndex->m_nIndex ];
1100 0 : aExtensionID = dp_misc::getIdentifier( aUpdData.aInstalledPackage );
1101 0 : if ( !bIgnoreAll )
1102 0 : aVersion = aUpdData.updateVersion;
1103 : }
1104 0 : else if ( pIndex->m_eKind == DISABLED_UPDATE )
1105 : {
1106 0 : DisabledUpdate &rData = m_disabledUpdates[ pIndex->m_nIndex ];
1107 0 : dp_misc::DescriptionInfoset aInfoset( m_context, rData.aUpdateInfo );
1108 0 : ::boost::optional< OUString > aID( aInfoset.getIdentifier() );
1109 0 : if ( aID )
1110 0 : aExtensionID = *aID;
1111 0 : if ( !bIgnoreAll )
1112 0 : aVersion = aInfoset.getVersion();
1113 : }
1114 :
1115 0 : if ( !aExtensionID.isEmpty() )
1116 : {
1117 0 : bool bFound = false;
1118 0 : for ( std::vector< UpdateDialog::IgnoredUpdate* >::iterator i( m_ignoredUpdates.begin() ); i != m_ignoredUpdates.end(); ++i )
1119 : {
1120 0 : if ( (*i)->sExtensionID == aExtensionID )
1121 : {
1122 0 : (*i)->sVersion = aVersion;
1123 0 : (*i)->bRemoved = !bIgnore;
1124 0 : bFound = true;
1125 0 : break;
1126 : }
1127 : }
1128 0 : if ( bIgnore && !bFound )
1129 : {
1130 0 : IgnoredUpdate *pData = new IgnoredUpdate( aExtensionID, aVersion );
1131 0 : m_ignoredUpdates.push_back( pData );
1132 : }
1133 0 : }
1134 0 : }
1135 :
1136 :
1137 :
1138 0 : IMPL_LINK_NOARG(UpdateDialog, selectionHandler)
1139 : {
1140 0 : OUStringBuffer b;
1141 : UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >(
1142 0 : m_pUpdates->GetEntryData(m_pUpdates->GetSelectEntryPos()));
1143 0 : clearDescription();
1144 :
1145 0 : if ( p != NULL )
1146 : {
1147 0 : sal_uInt16 pos = p->m_nIndex;
1148 :
1149 0 : switch (p->m_eKind)
1150 : {
1151 : case ENABLED_UPDATE:
1152 : {
1153 0 : if ( m_enabledUpdates[ pos ].aUpdateSource.is() )
1154 0 : showDescription( m_enabledUpdates[ pos ].aUpdateSource );
1155 : else
1156 0 : showDescription( m_enabledUpdates[ pos ].aUpdateInfo );
1157 :
1158 0 : if ( p->m_bIgnored )
1159 0 : b.append( m_ignoredUpdate );
1160 :
1161 0 : break;
1162 : }
1163 : case DISABLED_UPDATE:
1164 : {
1165 0 : if ( !m_disabledUpdates.empty() )
1166 0 : showDescription( m_disabledUpdates[pos].aUpdateInfo );
1167 :
1168 0 : if ( p->m_bIgnored )
1169 0 : b.append( m_ignoredUpdate );
1170 :
1171 0 : if ( m_disabledUpdates.empty() )
1172 0 : break;
1173 :
1174 0 : UpdateDialog::DisabledUpdate & data = m_disabledUpdates[ pos ];
1175 0 : if (data.unsatisfiedDependencies.getLength() != 0)
1176 : {
1177 : // create error string for version mismatch
1178 0 : OUString sVersion( "%VERSION" );
1179 0 : OUString sProductName( "%PRODUCTNAME" );
1180 0 : sal_Int32 nPos = m_noDependencyCurVer.indexOf( sVersion );
1181 0 : if ( nPos >= 0 )
1182 : {
1183 0 : m_noDependencyCurVer = m_noDependencyCurVer.replaceAt( nPos, sVersion.getLength(), utl::ConfigManager::getAboutBoxProductVersion() );
1184 : }
1185 0 : nPos = m_noDependencyCurVer.indexOf( sProductName );
1186 0 : if ( nPos >= 0 )
1187 : {
1188 0 : m_noDependencyCurVer = m_noDependencyCurVer.replaceAt( nPos, sProductName.getLength(), utl::ConfigManager::getProductName() );
1189 : }
1190 0 : nPos = m_noDependency.indexOf( sProductName );
1191 0 : if ( nPos >= 0 )
1192 : {
1193 0 : m_noDependency = m_noDependency.replaceAt( nPos, sProductName.getLength(), utl::ConfigManager::getProductName() );
1194 : }
1195 :
1196 0 : b.append(m_noInstall);
1197 0 : b.append(LF);
1198 0 : b.append(m_noDependency);
1199 0 : for (sal_Int32 i = 0;
1200 0 : i < data.unsatisfiedDependencies.getLength(); ++i)
1201 : {
1202 0 : b.append(LF);
1203 0 : b.appendAscii(" ");
1204 : // U+2003 EM SPACE would be better than two spaces,
1205 : // but some fonts do not contain it
1206 : b.append(
1207 : confineToParagraph(
1208 0 : data.unsatisfiedDependencies[i]));
1209 : }
1210 0 : b.append(LF);
1211 0 : b.appendAscii(" ");
1212 0 : b.append(m_noDependencyCurVer);
1213 : }
1214 0 : break;
1215 : }
1216 : case SPECIFIC_ERROR:
1217 : {
1218 0 : UpdateDialog::SpecificError & data = m_specificErrors[ pos ];
1219 0 : b.append(m_failure);
1220 0 : b.append(LF);
1221 0 : b.append( data.message.isEmpty() ? m_unknownError : data.message );
1222 0 : break;
1223 : }
1224 : default:
1225 : OSL_ASSERT(false);
1226 0 : break;
1227 : }
1228 : }
1229 :
1230 0 : if ( b.isEmpty() )
1231 0 : b.append( m_noDescription );
1232 :
1233 0 : showDescription( b.makeStringAndClear() );
1234 0 : return 0;
1235 : }
1236 :
1237 0 : IMPL_LINK_NOARG(UpdateDialog, allHandler)
1238 : {
1239 0 : if (m_pAll->IsChecked())
1240 : {
1241 0 : m_pUpdate->Enable();
1242 0 : m_pUpdates->Enable();
1243 0 : m_pDescription->Enable();
1244 0 : m_pDescriptions->Enable();
1245 :
1246 0 : for (std::vector< UpdateDialog::Index* >::iterator i( m_ListboxEntries.begin() );
1247 0 : i != m_ListboxEntries.end(); ++i )
1248 : {
1249 0 : if ( (*i)->m_bIgnored || ( (*i)->m_eKind != ENABLED_UPDATE ) )
1250 0 : insertItem( (*i), SvLBoxButtonKind_disabledCheckbox );
1251 : }
1252 : }
1253 : else
1254 : {
1255 0 : for ( sal_uInt16 i = 0; i < m_pUpdates->getItemCount(); )
1256 : {
1257 0 : UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >( m_pUpdates->GetEntryData(i) );
1258 0 : if ( p->m_bIgnored || ( p->m_eKind != ENABLED_UPDATE ) )
1259 : {
1260 0 : m_pUpdates->RemoveEntry(i);
1261 : } else {
1262 0 : ++i;
1263 : }
1264 : }
1265 :
1266 0 : if (m_pUpdates->getItemCount() == 0)
1267 : {
1268 0 : clearDescription();
1269 0 : m_pUpdate->Disable();
1270 0 : m_pUpdates->Disable();
1271 0 : if (m_pchecking->IsVisible())
1272 0 : m_pDescription->Disable();
1273 : else
1274 0 : showDescription(m_noInstallable);
1275 : }
1276 : }
1277 0 : return 0;
1278 : }
1279 :
1280 0 : IMPL_LINK_NOARG(UpdateDialog, okHandler)
1281 : {
1282 : //If users are going to update a shared extension then we need
1283 : //to warn them
1284 : typedef ::std::vector<UpdateData>::const_iterator CIT;
1285 0 : for (CIT i = m_enabledUpdates.begin(); i < m_enabledUpdates.end(); ++i)
1286 : {
1287 : OSL_ASSERT(i->aInstalledPackage.is());
1288 : //If the user has no write access to the shared folder then the update
1289 : //for a shared extension is disable, that is it cannot be in m_enabledUpdates
1290 : }
1291 :
1292 :
1293 0 : for (sal_uInt16 i = 0; i < m_pUpdates->getItemCount(); ++i) {
1294 : UpdateDialog::Index const * p =
1295 : static_cast< UpdateDialog::Index const * >(
1296 0 : m_pUpdates->GetEntryData(i));
1297 0 : if (p->m_eKind == ENABLED_UPDATE && m_pUpdates->IsChecked(i)) {
1298 0 : m_updateData.push_back( m_enabledUpdates[ p->m_nIndex ] );
1299 : }
1300 : }
1301 :
1302 0 : EndDialog(RET_OK);
1303 0 : return 0;
1304 : }
1305 :
1306 0 : IMPL_LINK_NOARG(UpdateDialog, closeHandler) {
1307 0 : m_thread->stop();
1308 0 : EndDialog(RET_CANCEL);
1309 0 : return 0;
1310 : }
1311 :
1312 0 : IMPL_LINK( UpdateDialog, hyperlink_clicked, FixedHyperlink*, pHyperlink )
1313 : {
1314 0 : OUString sURL;
1315 0 : if ( pHyperlink )
1316 0 : sURL = OUString( pHyperlink->GetURL() );
1317 0 : if ( sURL.isEmpty() )
1318 0 : return 0;
1319 :
1320 : try
1321 : {
1322 : uno::Reference< com::sun::star::system::XSystemShellExecute > xSystemShellExecute(
1323 0 : com::sun::star::system::SystemShellExecute::create(m_context) );
1324 : //throws lang::IllegalArgumentException, system::SystemShellExecuteException
1325 0 : xSystemShellExecute->execute( sURL, OUString(), com::sun::star::system::SystemShellExecuteFlags::URIS_ONLY);
1326 : }
1327 0 : catch ( const uno::Exception& )
1328 : {
1329 : }
1330 :
1331 0 : return 1;
1332 6 : }
1333 :
1334 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|