Logo ROOT  
Reference Guide
RBrowserData.cxx
Go to the documentation of this file.
1// Author: Sergey Linev <S.Linev@gsi.de>
2// Date: 2019-10-14
3// Warning: This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
4
5/*************************************************************************
6 * Copyright (C) 1995-2020, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13#include <ROOT/RBrowserData.hxx>
14
21
22#include <ROOT/RLogger.hxx>
23
24#include "TFolder.h"
25#include "TROOT.h"
26#include "TBufferJSON.h"
27
28#include <algorithm>
29#include <regex>
30
31using namespace ROOT::Experimental;
32using namespace std::string_literals;
33
35 static RLogChannel sLog("ROOT.Browser");
36 return sLog;
37}
38
39
40/** \class ROOT::Experimental::RBrowserData
41\ingroup rbrowser
42\brief Way to browse (hopefully) everything in %ROOT
43*/
44
45/////////////////////////////////////////////////////////////////////
46/// set top element for browsing
47
48void RBrowserData::SetTopElement(std::shared_ptr<Browsable::RElement> elem)
49{
50 fTopElement = elem;
51
53}
54
55/////////////////////////////////////////////////////////////////////
56/// set working directory relative to top element
57
59{
60 fWorkingPath = path;
61
63}
64
65/////////////////////////////////////////////////////////////////////
66/// Create default elements shown in the RBrowser
67
69{
70 auto comp = std::make_shared<Browsable::RGroup>("top","Root browser");
71
73
74 std::unique_ptr<Browsable::RHolder> rootfold = std::make_unique<Browsable::TObjectHolder>(gROOT->GetRootFolder(), kFALSE);
75 auto elem_root = Browsable::RProvider::Browse(rootfold);
76 if (elem_root)
77 comp->Add(std::make_shared<Browsable::RWrapper>("root", elem_root));
78
79 std::unique_ptr<Browsable::RHolder> rootfiles = std::make_unique<Browsable::TObjectHolder>(gROOT->GetListOfFiles(), kFALSE);
80 auto elem_files = Browsable::RProvider::Browse(rootfiles);
81 if (elem_files) {
82 auto files = std::make_shared<Browsable::RWrapper>("ROOT Files", elem_files);
83 files->SetExpandByDefault(true);
84 comp->Add(files);
85 // if there are any open files, make them visible by default
86 if (elem_files->GetNumChilds() > 0)
87 seldir = {};
88 }
89
90 SetTopElement(comp);
91
92 SetWorkingPath(seldir);
93}
94
95/////////////////////////////////////////////////////////////////////
96/// Reset all data correspondent to last request
97
99{
100 fLastAllChilds = false;
101 fLastSortedItems.clear();
102 fLastSortMethod.clear();
103 fLastItems.clear();
104 if (with_element) {
105 fLastPath.clear();
106 fLastElement.reset();
107 }
108}
109
110/////////////////////////////////////////////////////////////////////////
111/// Decompose path to elements
112/// Returns array of names for each element in the path, first element either "/" or "."
113/// If returned array empty - it is error
114
115Browsable::RElementPath_t RBrowserData::DecomposePath(const std::string &strpath, bool relative_to_work_element)
116{
118 if (relative_to_work_element) arr = fWorkingPath;
119
120 if (strpath.empty())
121 return arr;
122
123 auto arr2 = Browsable::RElement::ParsePath(strpath);
124 arr.insert(arr.end(), arr2.begin(), arr2.end());
125 return arr;
126}
127
128/////////////////////////////////////////////////////////////////////////
129/// Process browser request
130
132{
133 auto path = fWorkingPath;
134 path.insert(path.end(), request.path.begin(), request.path.end());
135
136 if ((path != fLastPath) || !fLastElement) {
137
138 auto elem = GetSubElement(path);
139 if (!elem) return false;
140
142
143 fLastPath = path;
144 fLastElement = std::move(elem);
145
146 fLastElement->cd(); // set element active
147 } else if (request.reload) {
148 // only reload items from element, not need to reset element itself
150 }
151
152 // when request childs, always try to make elements
153 if (fLastItems.empty()) {
154
155 auto iter = fLastElement->GetChildsIter();
156
157 if (!iter) return false;
158 int id = 0;
159 fLastAllChilds = true;
160
161 while (iter->Next() && fLastAllChilds) {
162 fLastItems.emplace_back(iter->CreateItem());
163 if (id++ > 10000)
164 fLastAllChilds = false;
165 }
166
167 fLastSortedItems.clear();
168 fLastSortMethod.clear();
169 }
170
171 // create sorted array
172 if ((fLastSortedItems.size() != fLastItems.size()) ||
173 (fLastSortMethod != request.sort) ||
174 (fLastSortReverse != request.reverse)) {
175 fLastSortedItems.resize(fLastItems.size(), nullptr);
176 int id = 0;
177 if (request.sort.empty()) {
178 // no sorting, just move all folders up
179 for (auto &item : fLastItems)
180 if (item->IsFolder())
181 fLastSortedItems[id++] = item.get();
182 for (auto &item : fLastItems)
183 if (!item->IsFolder())
184 fLastSortedItems[id++] = item.get();
185 } else {
186 // copy items
187 for (auto &item : fLastItems)
188 fLastSortedItems[id++] = item.get();
189
190 if (request.sort != "unsorted")
191 std::sort(fLastSortedItems.begin(), fLastSortedItems.end(),
192 [request](const Browsable::RItem *a, const Browsable::RItem *b) { return a->Compare(b, request.sort); });
193 }
194
195 if (request.reverse)
196 std::reverse(fLastSortedItems.begin(), fLastSortedItems.end());
197
198 fLastSortMethod = request.sort;
199 fLastSortReverse = request.reverse;
200 }
201
202 const std::regex expr(request.regex);
203
204 int id = 0;
205 for (auto &item : fLastSortedItems) {
206
207 // check if element is hidden
208 if (!request.hidden && item->IsHidden())
209 continue;
210
211 if (!request.regex.empty() && !item->IsFolder() && !std::regex_match(item->GetName(), expr))
212 continue;
213
214 if ((id >= request.first) && ((request.number == 0) || (id < request.first + request.number)))
215 reply.nodes.emplace_back(item);
216
217 id++;
218 }
219
220 reply.first = request.first;
221 reply.nchilds = id; // total number of childs
222
223 return true;
224}
225
226/////////////////////////////////////////////////////////////////////////
227/// Process browser request, returns string with JSON of RBrowserReply data
228
230{
231 RBrowserReply reply;
232
233 reply.path = request.path;
234 reply.first = 0;
235 reply.nchilds = 0;
236
237 ProcessBrowserRequest(request, reply);
238
240}
241
242/////////////////////////////////////////////////////////////////////////
243/// Returns element with path, specified as string
244
245std::shared_ptr<Browsable::RElement> RBrowserData::GetElement(const std::string &str)
246{
247 auto path = DecomposePath(str, true);
248
249 return GetSubElement(path);
250}
251
252/////////////////////////////////////////////////////////////////////////
253/// Returns element with path, specified as Browsable::RElementPath_t
254
255std::shared_ptr<Browsable::RElement> RBrowserData::GetElementFromTop(const Browsable::RElementPath_t &path)
256{
257 return GetSubElement(path);
258}
259
260/////////////////////////////////////////////////////////////////////////
261/// Returns sub-element starting from top, using cached data
262
263std::shared_ptr<Browsable::RElement> RBrowserData::GetSubElement(const Browsable::RElementPath_t &path)
264{
265 if (path.empty())
266 return fTopElement;
267
268 // first check direct match in cache
269 for (auto &entry : fCache)
270 if (entry.first == path)
271 return entry.second;
272
273 // find best possible entry in cache
274 int pos = 0;
275 auto elem = fTopElement;
276
277 for (auto &entry : fCache) {
278 if (entry.first.size() >= path.size())
279 continue;
280
281 auto comp = Browsable::RElement::ComparePaths(path, entry.first);
282
283 if ((comp > pos) && (comp == (int) entry.first.size())) {
284 pos = comp;
285 elem = entry.second;
286 }
287 }
288
289 while (pos < (int) path.size()) {
290 std::string subname = path[pos];
291 int indx = Browsable::RElement::ExtractItemIndex(subname);
292
293 auto iter = elem->GetChildsIter();
294 if (!iter)
295 return nullptr;
296
297 if (!iter->Find(subname, indx)) {
298 if (indx < 0)
299 return nullptr;
300 iter = elem->GetChildsIter();
301 if (!iter || !iter->Find(subname))
302 return nullptr;
303 }
304
305 elem = iter->GetElement();
306
307 if (!elem)
308 return nullptr;
309
310 auto subpath = path;
311 subpath.resize(pos+1);
312 fCache.emplace_back(subpath, elem);
313 pos++; // switch to next element
314 }
315
316 return elem;
317}
318
319/////////////////////////////////////////////////////////////////////////
320/// Clear internal objects cache
321
323{
324 fCache.clear();
325}
const Bool_t kFALSE
Definition: RtypesCore.h:101
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t b
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
#define gROOT
Definition: TROOT.h:404
static int ExtractItemIndex(std::string &name)
Extract index from name Index coded by client with ###<indx>$$$ suffix Such coding used by browser to...
Definition: RElement.cxx:164
static int ComparePaths(const RElementPath_t &path1, const RElementPath_t &path2)
Compare two paths, Returns number of elements matches in both paths.
Definition: RElement.cxx:131
static RElementPath_t ParsePath(const std::string &str)
Parse string path to produce RElementPath_t One should avoid to use string pathes as much as possible...
Definition: RElement.cxx:102
Representation of single item in the browser.
Definition: RItem.hxx:24
static std::shared_ptr< RElement > Browse(std::unique_ptr< RHolder > &obj)
Create browsable element for the object Created element may take ownership over the object.
Definition: RProvider.cxx:268
static RElementPath_t ProvideTopEntries(std::shared_ptr< RGroup > &comp, const std::string &workdir="")
Provide top entries for file system On windows it is list of existing drivers, on Linux it is "Files ...
Definition: RSysFile.cxx:535
void SetTopElement(std::shared_ptr< Browsable::RElement > elem)
set top element for browsing
std::string fLastSortMethod
! last sort method
std::shared_ptr< Browsable::RElement > GetSubElement(const Browsable::RElementPath_t &path)
Returns sub-element starting from top, using cached data.
Browsable::RElementPath_t DecomposePath(const std::string &path, bool relative_to_work_element)
Decompose path to elements Returns array of names for each element in the path, first element either ...
bool ProcessBrowserRequest(const RBrowserRequest &request, RBrowserReply &reply)
Process browser request.
std::vector< std::pair< Browsable::RElementPath_t, std::shared_ptr< Browsable::RElement > > > fCache
! already requested elements
std::shared_ptr< Browsable::RElement > GetElementFromTop(const Browsable::RElementPath_t &path)
Returns element with path, specified as Browsable::RElementPath_t.
void ClearCache()
Clear internal objects cache.
std::vector< const Browsable::RItem * > fLastSortedItems
! sorted child items, used in requests
bool fLastAllChilds
! if all chlds were extracted
std::string ProcessRequest(const RBrowserRequest &request)
Process browser request, returns string with JSON of RBrowserReply data.
Browsable::RElementPath_t fWorkingPath
! path showed in Breadcrumb
bool fLastSortReverse
! last request reverse order
Browsable::RElementPath_t fLastPath
! path to last used element
std::shared_ptr< Browsable::RElement > fTopElement
! top element
void SetWorkingPath(const Browsable::RElementPath_t &path)
set working directory relative to top element
std::shared_ptr< Browsable::RElement > fLastElement
! last element used in request
std::shared_ptr< Browsable::RElement > GetElement(const std::string &str)
Returns element with path, specified as string.
std::vector< std::unique_ptr< Browsable::RItem > > fLastItems
! created browser items - used in requests
void ResetLastRequestData(bool with_element)
Reset all data correspondent to last request.
void CreateDefaultElements()
Create default elements shown in the RBrowser.
Reply on browser request.
std::vector< const Browsable::RItem * > nodes
list of pointers, no ownership!
std::vector< std::string > path
reply path
int nchilds
total number of childs in the node
int first
first node in returned list
Request send from client to get content of path element.
std::vector< std::string > path
requested path
int first
first child to request
int number
number of childs to request, 0 - all childs
std::string sort
kind of sorting
A log configuration for a channel, e.g.
Definition: RLogger.hxx:101
static TString ToJSON(const T *obj, Int_t compact=0, const char *member_name=nullptr)
Definition: TBufferJSON.h:75
@ kSkipTypeInfo
do not store typenames in JSON
Definition: TBufferJSON.h:48
@ kNoSpaces
no new lines plus remove all spaces around "," and ":" symbols
Definition: TBufferJSON.h:39
const char * Data() const
Definition: TString.h:369
std::vector< std::string > RElementPath_t
Definition: RElement.hxx:21
RLogChannel & BrowserLog()
Log channel for Browser diagnostics.
auto * a
Definition: textangle.C:12