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