xref: /core/basctl/source/basicide/bastype3.cxx (revision 44688e49)
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