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 #include <basic/basmgr.hxx> 21 #include <basic/sbmod.hxx> 22 #include <bastype2.hxx> 23 #include <bitmaps.hlst> 24 #include <bastypes.hxx> 25 #include <com/sun/star/script/XLibraryContainer.hpp> 26 #include <com/sun/star/script/XLibraryContainerPassword.hpp> 27 #include <deque> 28 #include <sfx2/docfac.hxx> 29 #include <svtools/treelistentry.hxx> 30 31 namespace basctl 32 { 33 34 using namespace ::com::sun::star::uno; 35 using namespace ::com::sun::star; 36 37 38 typedef std::deque< SvTreeListEntry* > EntryArray; 39 40 41 void TreeListBox::RequestingChildren( SvTreeListEntry* pEntry ) 42 { 43 EntryDescriptor aDesc = GetEntryDescriptor(pEntry); 44 const ScriptDocument& aDocument = aDesc.GetDocument(); 45 OSL_ENSURE( aDocument.isAlive(), "basctl::TreeListBox::RequestingChildren: invalid document!" ); 46 if ( !aDocument.isAlive() ) 47 return; 48 49 LibraryLocation eLocation = aDesc.GetLocation(); 50 EntryType eType = aDesc.GetType(); 51 52 if ( eType == OBJ_TYPE_DOCUMENT ) 53 { 54 ImpCreateLibEntries( pEntry, aDocument, eLocation ); 55 } 56 else if ( eType == OBJ_TYPE_LIBRARY ) 57 { 58 const OUString& aOULibName( aDesc.GetLibName() ); 59 60 // check password 61 bool bOK = true; 62 Reference< script::XLibraryContainer > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ) ); 63 if ( xModLibContainer.is() && xModLibContainer->hasByName( aOULibName ) ) 64 { 65 Reference< script::XLibraryContainerPassword > xPasswd( xModLibContainer, UNO_QUERY ); 66 if ( xPasswd.is() && xPasswd->isLibraryPasswordProtected( aOULibName ) && !xPasswd->isLibraryPasswordVerified( aOULibName ) ) 67 { 68 OUString aPassword; 69 bOK = QueryPassword( xModLibContainer, aOULibName, aPassword ); 70 } 71 } 72 73 if ( bOK ) 74 { 75 // load module library 76 bool bModLibLoaded = false; 77 if ( xModLibContainer.is() && xModLibContainer->hasByName( aOULibName ) ) 78 { 79 if ( !xModLibContainer->isLibraryLoaded( aOULibName ) ) 80 { 81 EnterWait(); 82 xModLibContainer->loadLibrary( aOULibName ); 83 LeaveWait(); 84 } 85 bModLibLoaded = xModLibContainer->isLibraryLoaded( aOULibName ); 86 } 87 88 // load dialog library 89 bool bDlgLibLoaded = false; 90 Reference< script::XLibraryContainer > xDlgLibContainer( aDocument.getLibraryContainer( E_DIALOGS ), UNO_QUERY ); 91 if ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aOULibName ) ) 92 { 93 if ( !xDlgLibContainer->isLibraryLoaded( aOULibName ) ) 94 { 95 EnterWait(); 96 xDlgLibContainer->loadLibrary( aOULibName ); 97 LeaveWait(); 98 } 99 bDlgLibLoaded = xDlgLibContainer->isLibraryLoaded( aOULibName ); 100 } 101 102 if ( bModLibLoaded || bDlgLibLoaded ) 103 { 104 // create the sub entries 105 ImpCreateLibSubEntries( pEntry, aDocument, aOULibName ); 106 107 // exchange image 108 const bool bDlgMode = (nMode & BrowseMode::Dialogs) && !(nMode & BrowseMode::Modules); 109 Image aImage(BitmapEx(bDlgMode ? OUStringLiteral(RID_BMP_DLGLIB) : OUStringLiteral(RID_BMP_MODLIB))); 110 SetEntryBitmaps( pEntry, aImage ); 111 } 112 else 113 { 114 OSL_FAIL( "basctl::TreeListBox::RequestingChildren: Error loading library!" ); 115 } 116 } 117 } 118 else if ( eType == OBJ_TYPE_DOCUMENT_OBJECTS 119 || eType == OBJ_TYPE_USERFORMS 120 || eType == OBJ_TYPE_NORMAL_MODULES 121 || eType == OBJ_TYPE_CLASS_MODULES ) 122 { 123 const OUString& aLibName( aDesc.GetLibName() ); 124 ImpCreateLibSubSubEntriesInVBAMode( pEntry, aDocument, aLibName ); 125 } 126 else { 127 OSL_FAIL( "basctl::TreeListBox::RequestingChildren: Unknown Type!" ); 128 } 129 } 130 131 void TreeListBox::ExpandedHdl() 132 { 133 SvTreeListEntry* pEntry = GetHdlEntry(); 134 assert(pEntry && "What was collapsed?"); 135 if ( !IsExpanded( pEntry ) && pEntry->HasChildrenOnDemand() ) 136 { 137 SvTreeListEntry* pChild = FirstChild( pEntry ); 138 while ( pChild ) 139 { 140 GetModel()->Remove( pChild ); // does also call the DTOR 141 pChild = FirstChild( pEntry ); 142 } 143 } 144 } 145 146 void TreeListBox::ScanAllEntries() 147 { 148 ScanEntry( ScriptDocument::getApplicationScriptDocument(), LIBRARY_LOCATION_USER ); 149 ScanEntry( ScriptDocument::getApplicationScriptDocument(), LIBRARY_LOCATION_SHARE ); 150 151 ScriptDocuments aDocuments( ScriptDocument::getAllScriptDocuments( ScriptDocument::DocumentsSorted ) ); 152 for (auto const& doc : aDocuments) 153 { 154 if ( doc.isAlive() ) 155 ScanEntry(doc, LIBRARY_LOCATION_DOCUMENT); 156 } 157 } 158 159 SbxVariable* TreeListBox::FindVariable( SvTreeListEntry* pEntry ) 160 { 161 if ( !pEntry ) 162 return nullptr; 163 164 ScriptDocument aDocument( ScriptDocument::getApplicationScriptDocument() ); 165 EntryArray aEntries; 166 167 while ( pEntry ) 168 { 169 sal_uInt16 nDepth = GetModel()->GetDepth( pEntry ); 170 switch ( nDepth ) 171 { 172 case 4: 173 case 3: 174 case 2: 175 case 1: 176 { 177 aEntries.push_front( pEntry ); 178 } 179 break; 180 case 0: 181 { 182 aDocument = static_cast<DocumentEntry*>(pEntry->GetUserData())->GetDocument(); 183 } 184 break; 185 } 186 pEntry = GetParent( pEntry ); 187 } 188 189 SbxVariable* pVar = nullptr; 190 if ( !aEntries.empty() ) 191 { 192 bool bDocumentObjects = false; 193 for (SvTreeListEntry* pLE : aEntries) 194 { 195 assert(pLE && "Can not find entry in array"); 196 Entry* pBE = static_cast<Entry*>(pLE->GetUserData()); 197 assert(pBE && "The data in the entry not found!"); 198 OUString aName( GetEntryText( pLE ) ); 199 200 switch ( pBE->GetType() ) 201 { 202 case OBJ_TYPE_LIBRARY: 203 if (BasicManager* pBasMgr = aDocument.getBasicManager()) 204 pVar = pBasMgr->GetLib( aName ); 205 break; 206 case OBJ_TYPE_MODULE: 207 DBG_ASSERT(dynamic_cast<StarBASIC*>(pVar), "FindVariable: invalid Basic"); 208 if(!pVar) 209 { 210 break; 211 } 212 // extract the module name from the string like "Sheet1 (Example1)" 213 if( bDocumentObjects ) 214 { 215 sal_Int32 nIndex = 0; 216 aName = aName.getToken( 0, ' ', nIndex ); 217 } 218 pVar = static_cast<StarBASIC*>(pVar)->FindModule( aName ); 219 break; 220 case OBJ_TYPE_METHOD: 221 DBG_ASSERT(dynamic_cast<SbxObject*>(pVar), "FindVariable: invalid module/object"); 222 if(!pVar) 223 { 224 break; 225 } 226 pVar = static_cast<SbxObject*>(pVar)->GetMethods()->Find(aName, SbxClassType::Method); 227 break; 228 case OBJ_TYPE_DIALOG: 229 // sbx dialogs removed 230 break; 231 case OBJ_TYPE_DOCUMENT_OBJECTS: 232 bDocumentObjects = true; 233 SAL_FALLTHROUGH; 234 case OBJ_TYPE_USERFORMS: 235 case OBJ_TYPE_NORMAL_MODULES: 236 case OBJ_TYPE_CLASS_MODULES: 237 // skip, to find the child entry. 238 continue; 239 default: 240 OSL_FAIL( "FindVariable: unknown type" ); 241 pVar = nullptr; 242 break; 243 } 244 if ( !pVar ) 245 break; 246 } 247 } 248 249 return pVar; 250 } 251 252 EntryDescriptor TreeListBox::GetEntryDescriptor( SvTreeListEntry* pEntry ) 253 { 254 ScriptDocument aDocument( ScriptDocument::getApplicationScriptDocument() ); 255 LibraryLocation eLocation = LIBRARY_LOCATION_UNKNOWN; 256 OUString aLibName; 257 OUString aLibSubName; 258 OUString aName; 259 OUString aMethodName; 260 EntryType eType = OBJ_TYPE_UNKNOWN; 261 262 if ( !pEntry ) 263 return EntryDescriptor( aDocument, eLocation, aLibName, aLibSubName, aName, aMethodName, eType ); 264 265 EntryArray aEntries; 266 267 while ( pEntry ) 268 { 269 sal_uInt16 nDepth = GetModel()->GetDepth( pEntry ); 270 switch ( nDepth ) 271 { 272 case 4: 273 case 3: 274 case 2: 275 case 1: 276 { 277 aEntries.push_front( pEntry ); 278 } 279 break; 280 case 0: 281 { 282 if (DocumentEntry* pDocumentEntry = static_cast<DocumentEntry*>(pEntry->GetUserData())) 283 { 284 aDocument = pDocumentEntry->GetDocument(); 285 eLocation = pDocumentEntry->GetLocation(); 286 eType = OBJ_TYPE_DOCUMENT; 287 } 288 } 289 break; 290 } 291 pEntry = GetParent( pEntry ); 292 } 293 294 if ( !aEntries.empty() ) 295 { 296 for (SvTreeListEntry* pLE : aEntries) 297 { 298 assert(pLE && "Entry not found in array"); 299 Entry* pBE = static_cast<Entry*>(pLE->GetUserData()); 300 assert(pBE && "No data found in entry!"); 301 302 switch ( pBE->GetType() ) 303 { 304 case OBJ_TYPE_LIBRARY: 305 { 306 aLibName = GetEntryText( pLE ); 307 eType = pBE->GetType(); 308 } 309 break; 310 case OBJ_TYPE_MODULE: 311 { 312 aName = GetEntryText( pLE ); 313 eType = pBE->GetType(); 314 } 315 break; 316 case OBJ_TYPE_METHOD: 317 { 318 aMethodName = GetEntryText( pLE ); 319 eType = pBE->GetType(); 320 } 321 break; 322 case OBJ_TYPE_DIALOG: 323 { 324 aName = GetEntryText( pLE ); 325 eType = pBE->GetType(); 326 } 327 break; 328 case OBJ_TYPE_DOCUMENT_OBJECTS: 329 case OBJ_TYPE_USERFORMS: 330 case OBJ_TYPE_NORMAL_MODULES: 331 case OBJ_TYPE_CLASS_MODULES: 332 { 333 aLibSubName = GetEntryText( pLE ); 334 eType = pBE->GetType(); 335 } 336 break; 337 default: 338 { 339 OSL_FAIL( "GetEntryDescriptor: unknown type" ); 340 eType = OBJ_TYPE_UNKNOWN; 341 } 342 break; 343 } 344 345 if ( eType == OBJ_TYPE_UNKNOWN ) 346 break; 347 } 348 } 349 350 return EntryDescriptor( aDocument, eLocation, aLibName, aLibSubName, aName, aMethodName, eType ); 351 } 352 353 ItemType TreeListBox::ConvertType (EntryType eType) 354 { 355 switch (eType) 356 { 357 case OBJ_TYPE_DOCUMENT: return TYPE_SHELL; 358 case OBJ_TYPE_LIBRARY: return TYPE_LIBRARY; 359 case OBJ_TYPE_MODULE: return TYPE_MODULE; 360 case OBJ_TYPE_DIALOG: return TYPE_DIALOG; 361 case OBJ_TYPE_METHOD: return TYPE_METHOD; 362 default: 363 return static_cast<ItemType>(OBJ_TYPE_UNKNOWN); 364 } 365 } 366 367 bool TreeListBox::IsValidEntry( SvTreeListEntry* pEntry ) 368 { 369 bool bIsValid = false; 370 371 EntryDescriptor aDesc( GetEntryDescriptor( pEntry ) ); 372 const ScriptDocument& aDocument( aDesc.GetDocument() ); 373 LibraryLocation eLocation( aDesc.GetLocation() ); 374 const OUString& aLibName( aDesc.GetLibName() ); 375 const OUString& aName( aDesc.GetName() ); 376 const OUString& aMethodName( aDesc.GetMethodName() ); 377 EntryType eType( aDesc.GetType() ); 378 379 switch ( eType ) 380 { 381 case OBJ_TYPE_DOCUMENT: 382 { 383 bIsValid = aDocument.isAlive() 384 && (aDocument.isApplication() 385 || GetRootEntryName(aDocument, eLocation) == GetEntryText(pEntry)); 386 } 387 break; 388 case OBJ_TYPE_LIBRARY: 389 { 390 bIsValid = aDocument.hasLibrary( E_SCRIPTS, aLibName ) || aDocument.hasLibrary( E_DIALOGS, aLibName ); 391 } 392 break; 393 case OBJ_TYPE_MODULE: 394 { 395 bIsValid = aDocument.hasModule( aLibName, aName ); 396 } 397 break; 398 case OBJ_TYPE_DIALOG: 399 { 400 bIsValid = aDocument.hasDialog( aLibName, aName ); 401 } 402 break; 403 case OBJ_TYPE_METHOD: 404 { 405 bIsValid = HasMethod( aDocument, aLibName, aName, aMethodName ); 406 } 407 break; 408 case OBJ_TYPE_DOCUMENT_OBJECTS: 409 case OBJ_TYPE_USERFORMS: 410 case OBJ_TYPE_NORMAL_MODULES: 411 case OBJ_TYPE_CLASS_MODULES: 412 { 413 bIsValid = true; 414 } 415 break; 416 default: ; 417 } 418 419 return bIsValid; 420 } 421 422 SbModule* TreeListBox::FindModule( SvTreeListEntry* pEntry ) 423 { 424 return dynamic_cast<SbModule*>(FindVariable(pEntry)); 425 } 426 427 SvTreeListEntry* TreeListBox::FindRootEntry( const ScriptDocument& rDocument, LibraryLocation eLocation ) 428 { 429 OSL_ENSURE( rDocument.isValid(), "basctl::TreeListBox::FindRootEntry: invalid document!" ); 430 sal_uLong nRootPos = 0; 431 SvTreeListEntry* pRootEntry = GetEntry( nRootPos ); 432 while ( pRootEntry ) 433 { 434 DBG_ASSERT( static_cast<Entry*>(pRootEntry->GetUserData())->GetType() == OBJ_TYPE_DOCUMENT, "No shell entry?" ); 435 DocumentEntry* pBDEntry = static_cast<DocumentEntry*>(pRootEntry->GetUserData()); 436 if (pBDEntry && pBDEntry->GetDocument() == rDocument && pBDEntry->GetLocation() == eLocation) 437 return pRootEntry; 438 pRootEntry = GetEntry( ++nRootPos ); 439 } 440 return nullptr; 441 } 442 443 OUString CreateMgrAndLibStr( const OUString& rMgrName, const OUString& rLibName ) 444 { 445 return "[" + rMgrName + "]." + rLibName; 446 } 447 448 449 } // namespace basctl 450 451 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 452
