1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include <memory> 29 30 #include "vos/mutex.hxx" 31 #include "vcl/svapp.hxx" 32 #include "vcl/msgbox.hxx" 33 34 #include "com/sun/star/task/XInteractionAbort.hpp" 35 #include "com/sun/star/task/XInteractionApprove.hpp" 36 #include "com/sun/star/task/XInteractionDisapprove.hpp" 37 #include "com/sun/star/task/XInteractionRetry.hpp" 38 39 #include "tools/errinf.hxx" // ErrorHandler, ErrorContext, ... 40 #include "svtools/svtools.hrc" // RID_ERRHDL 41 42 #include "ids.hrc" 43 #include "getcontinuations.hxx" 44 45 #include "iahndl.hxx" 46 47 using namespace com::sun::star; 48 49 namespace { 50 51 sal_uInt16 52 executeErrorDialog( 53 Window * pParent, 54 task::InteractionClassification eClassification, 55 rtl::OUString const & rContext, 56 rtl::OUString const & rMessage, 57 WinBits nButtonMask) 58 SAL_THROW((uno::RuntimeException)) 59 { 60 vos::OGuard aGuard(Application::GetSolarMutex()); 61 62 rtl::OUStringBuffer aText(rContext); 63 if (rContext.getLength() != 0 && rMessage.getLength() != 0) 64 aText.appendAscii(RTL_CONSTASCII_STRINGPARAM(":\n")); 65 //TODO! must be internationalized 66 aText.append(rMessage); 67 68 std::auto_ptr< MessBox > xBox; 69 try 70 { 71 switch (eClassification) 72 { 73 case task::InteractionClassification_ERROR: 74 xBox.reset(new ErrorBox(pParent, 75 nButtonMask, 76 aText.makeStringAndClear())); 77 break; 78 79 case task::InteractionClassification_WARNING: 80 xBox.reset(new WarningBox(pParent, 81 nButtonMask, 82 aText.makeStringAndClear())); 83 break; 84 85 case task::InteractionClassification_INFO: 86 if ((nButtonMask & 0x01F00000) == WB_DEF_OK) 87 //TODO! missing win bit button mask define (want to ignore 88 // any default button settings)... 89 xBox.reset(new InfoBox(pParent, 90 aText.makeStringAndClear())); 91 else 92 xBox.reset(new ErrorBox(pParent, 93 nButtonMask, 94 aText.makeStringAndClear())); 95 break; 96 97 case task::InteractionClassification_QUERY: 98 xBox.reset(new QueryBox(pParent, 99 nButtonMask, 100 aText.makeStringAndClear())); 101 break; 102 103 default: 104 OSL_ASSERT(false); 105 break; 106 } 107 } 108 catch (std::bad_alloc const &) 109 { 110 throw uno::RuntimeException( 111 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("out of memory")), 112 uno::Reference< uno::XInterface >()); 113 } 114 115 sal_uInt16 aResult = xBox->Execute(); 116 switch( aResult ) 117 { 118 case BUTTONID_OK: 119 aResult = ERRCODE_BUTTON_OK; 120 break; 121 case BUTTONID_CANCEL: 122 aResult = ERRCODE_BUTTON_CANCEL; 123 break; 124 case BUTTONID_YES: 125 aResult = ERRCODE_BUTTON_YES; 126 break; 127 case BUTTONID_NO: 128 aResult = ERRCODE_BUTTON_NO; 129 break; 130 case BUTTONID_RETRY: 131 aResult = ERRCODE_BUTTON_RETRY; 132 break; 133 } 134 135 return aResult; 136 } 137 138 } 139 140 void 141 UUIInteractionHelper::handleErrorHandlerRequest( 142 task::InteractionClassification eClassification, 143 ErrCode nErrorCode, 144 std::vector< rtl::OUString > const & rArguments, 145 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & 146 rContinuations, 147 bool bObtainErrorStringOnly, 148 bool & bHasErrorString, 149 rtl::OUString & rErrorString) 150 SAL_THROW((uno::RuntimeException)) 151 { 152 if (bObtainErrorStringOnly) 153 { 154 bHasErrorString = isInformationalErrorMessageRequest(rContinuations); 155 if (!bHasErrorString) 156 return; 157 } 158 159 rtl::OUString aMessage; 160 { 161 enum Source { SOURCE_DEFAULT, SOURCE_CNT, SOURCE_SVX, SOURCE_UUI }; 162 static char const * const aManager[4] 163 = { CREATEVERSIONRESMGR_NAME(ofa), 164 CREATEVERSIONRESMGR_NAME(cnt), 165 CREATEVERSIONRESMGR_NAME(svx), 166 CREATEVERSIONRESMGR_NAME(uui) }; 167 static sal_uInt16 const aId[4] 168 = { RID_ERRHDL, 169 RID_CHAOS_START + 12, 170 // cf. chaos/source/inc/cntrids.hrc, where 171 // #define RID_CHAOS_ERRHDL (RID_CHAOS_START + 12) 172 RID_SVX_START + 350, // RID_SVXERRCODE 173 RID_UUI_ERRHDL }; 174 ErrCode nErrorId = nErrorCode & ~ERRCODE_WARNING_MASK; 175 Source eSource = nErrorId < ERRCODE_AREA_LIB1 ? 176 SOURCE_DEFAULT : 177 nErrorId >= ERRCODE_AREA_CHAOS 178 && nErrorId < ERRCODE_AREA_CHAOS_END ? 179 SOURCE_CNT : 180 nErrorId >= ERRCODE_AREA_SVX 181 && nErrorId <= ERRCODE_AREA_SVX_END ? 182 SOURCE_SVX : 183 SOURCE_UUI; 184 185 vos::OGuard aGuard(Application::GetSolarMutex()); 186 std::auto_ptr< ResMgr > xManager; 187 xManager.reset(ResMgr::CreateResMgr(aManager[eSource])); 188 if (!xManager.get()) 189 return; 190 ResId aResId(aId[eSource], *xManager.get()); 191 if (!ErrorResource(aResId).getString(nErrorCode, &aMessage)) 192 return; 193 } 194 195 aMessage = replaceMessageWithArguments( aMessage, rArguments ); 196 197 if (bObtainErrorStringOnly) 198 { 199 rErrorString = aMessage; 200 return; 201 } 202 else 203 { 204 //TODO! It can happen that the buttons calculated below do not match 205 // the error text from the resource (e.g., some text that is not a 206 // question, but YES and NO buttons). Some error texts have 207 // ExtraData that specifies a set of buttons, but that data is not 208 // really useful, because a single error text may well make sense 209 // both with only an OK button and with RETRY and CANCEL buttons. 210 211 uno::Reference< task::XInteractionApprove > xApprove; 212 uno::Reference< task::XInteractionDisapprove > xDisapprove; 213 uno::Reference< task::XInteractionRetry > xRetry; 214 uno::Reference< task::XInteractionAbort > xAbort; 215 getContinuations( 216 rContinuations, &xApprove, &xDisapprove, &xRetry, &xAbort); 217 218 // The following mapping uses the bit mask 219 // Approve = 8, 220 // Disapprove = 4, 221 // Retry = 2, 222 // Abort = 1 223 // 224 // The mapping has five properties on which the code to select the 225 // correct continuation relies: 226 // 1 The OK button is mapped to Approve if that is available, 227 // otherwise to Abort if that is available, otherwise to none. 228 // 2 The CANCEL button is always mapped to Abort. 229 // 3 The RETRY button is always mapped to Retry. 230 // 4 The NO button is always mapped to Disapprove. 231 // 5 The YES button is always mapped to Approve. 232 // 233 // Because the WinBits button combinations are quite restricted, not 234 // every request can be served here. 235 // 236 // Finally, it seems to be better to leave default button 237 // determination to VCL (the favouring of CANCEL as default button 238 // seems to not always be what the user wants)... 239 WinBits const aButtonMask[16] 240 = { 0, 241 WB_OK /*| WB_DEF_OK*/, // Abort 242 0, 243 WB_RETRY_CANCEL /*| WB_DEF_CANCEL*/, // Retry, Abort 244 0, 245 0, 246 0, 247 0, 248 WB_OK /*| WB_DEF_OK*/, // Approve 249 WB_OK_CANCEL /*| WB_DEF_CANCEL*/, // Approve, Abort 250 0, 251 0, 252 WB_YES_NO /*| WB_DEF_NO*/, // Approve, Disapprove 253 WB_YES_NO_CANCEL /*| WB_DEF_CANCEL*/, 254 // Approve, Disapprove, Abort 255 0, 256 0 }; 257 258 WinBits nButtonMask = aButtonMask[(xApprove.is() ? 8 : 0) 259 | (xDisapprove.is() ? 4 : 0) 260 | (xRetry.is() ? 2 : 0) 261 | (xAbort.is() ? 1 : 0)]; 262 if (nButtonMask == 0) 263 return; 264 265 //TODO! remove this backwards compatibility? 266 rtl::OUString aContext(getContextProperty()); 267 if (aContext.getLength() == 0 && nErrorCode != 0) 268 { 269 vos::OGuard aGuard(Application::GetSolarMutex()); 270 ErrorContext * pContext = ErrorContext::GetContext(); 271 if (pContext) 272 { 273 UniString aContextString; 274 if (pContext->GetString(nErrorCode, aContextString)) 275 aContext = aContextString; 276 } 277 } 278 279 sal_uInt16 nResult = executeErrorDialog( 280 getParentProperty(), eClassification, aContext, aMessage, nButtonMask ); 281 282 switch (nResult) 283 { 284 case ERRCODE_BUTTON_OK: 285 OSL_ENSURE(xApprove.is() || xAbort.is(), "unexpected situation"); 286 if (xApprove.is()) 287 xApprove->select(); 288 else if (xAbort.is()) 289 xAbort->select(); 290 break; 291 292 case ERRCODE_BUTTON_CANCEL: 293 OSL_ENSURE(xAbort.is(), "unexpected situation"); 294 if (xAbort.is()) 295 xAbort->select(); 296 break; 297 298 case ERRCODE_BUTTON_RETRY: 299 OSL_ENSURE(xRetry.is(), "unexpected situation"); 300 if (xRetry.is()) 301 xRetry->select(); 302 break; 303 304 case ERRCODE_BUTTON_NO: 305 OSL_ENSURE(xDisapprove.is(), "unexpected situation"); 306 if (xDisapprove.is()) 307 xDisapprove->select(); 308 break; 309 310 case ERRCODE_BUTTON_YES: 311 OSL_ENSURE(xApprove.is(), "unexpected situation"); 312 if (xApprove.is()) 313 xApprove->select(); 314 break; 315 } 316 317 } 318 } 319