45using namespace std::string_literals;
80 bool DrawElement(std::shared_ptr<Browsable::RElement> &elem,
const std::string & =
"")
override
83 auto code = elem->GetContent(
"text");
90 auto json = elem->GetContent(
"json");
94 fTitle = elem->GetName() +
".json";
105 auto img = elem->GetContent(
"image64");
110 fFileName = elem->GetContent(
"filename");
127 std::string msg =
fIsEditor ?
"EDITOR:"s :
"IMAGE:"s;
154 std::string
GetKind()
const override {
return "info"s; }
157 bool DrawElement(std::shared_ptr<Browsable::RElement> &,
const std::string & =
"")
override {
return false; }
164 std::ostringstream pathtmp;
165 pathtmp <<
gSystem->TempDirectory() <<
"/info." <<
gSystem->GetPid() <<
".log";
167 std::ofstream ofs(pathtmp.str(), std::ofstream::out | std::ofstream::app);
171 gSystem->RedirectOutput(pathtmp.str().c_str(),
"a");
172 gROOT->ProcessLine(
".g");
173 gSystem->RedirectOutput(
nullptr);
175 std::ifstream infile(pathtmp.str());
184 gSystem->Unlink(pathtmp.str().c_str());
189 int indx = 0, last_prompt = -1;
190 for (
auto &
line : logs) {
196 if (last_prompt < 0) {
205 for (
auto &
line : logs) {
237 std::string
GetKind()
const override {
return "catched"s; }
288 if (
gROOT->IsWebDisplayBatch()) {
289 ::Warning(
"RBrowser::RBrowser",
"The RBrowser cannot run in web batch mode");
293 std::ostringstream pathtmp;
294 pathtmp <<
gSystem->TempDirectory() <<
"/command." <<
gSystem->GetPid() <<
".log";
301 fTimer = std::make_unique<RBrowserTimer>(10,
kTRUE, *
this);
307 fWebWindow->SetDefaultPage(
"file:rootui5sys/browser/browser.html");
309 std::string sortby =
gEnv->GetValue(
"WebGui.Browser.SortBy",
"name"),
310 reverse =
gEnv->GetValue(
"WebGui.Browser.Reverse",
"no"),
311 hidden =
gEnv->GetValue(
"WebGui.Browser.ShowHidden",
"no"),
312 lastcycle =
gEnv->GetValue(
"WebGui.Browser.LastCycle",
"");
314 if (sortby !=
"name" && sortby !=
"size" && sortby !=
"none")
317 reverse = (reverse ==
"on" || reverse ==
"yes" || reverse ==
"1") ?
"true" :
"false";
318 hidden = (hidden ==
"on" || hidden ==
"yes" || hidden ==
"1") ?
"true" :
"false";
319 if (lastcycle ==
"on" || lastcycle ==
"yes" || lastcycle ==
"1")
321 else if (lastcycle ==
"off" || lastcycle ==
"no" || lastcycle ==
"0")
324 fWebWindow->SetUserArgs(
TString::Format(
"{ sort: \"%s\", reverse: %s, hidden: %s }", sortby.c_str(), reverse.c_str(), hidden.c_str()).Data());
328 [
this](
unsigned connid,
const std::string &arg) {
ProcessMsg(connid, arg); });
354 widget->fBrowser =
this;
364 return widget ? true :
false;
370 if (catched && (catched->fWindow == &win))
387 fWebWindow->GetManager()->SetShowCallback(
nullptr);
388 fWebWindow->GetManager()->SetDeleteCallback(
nullptr);
398 std::unique_ptr<RBrowserRequest> request;
401 request = std::make_unique<RBrowserRequest>();
403 request->number = 100;
414 return "BREPL:"s +
fBrowsable.ProcessRequest(*request.get());
422 if (fname.empty())
return;
424 std::ofstream
f(fname);
433 if (file_path.rfind(
".py") == file_path.length() - 3) {
435 exec.
Form(
"TPython::ExecScript(\"%s\");", file_path.c_str());
449 std::string opt = args.back();
453 path.insert(path.end(), args.begin(), args.end());
458 if (!elem)
return ""s;
460 auto dflt_action = elem->GetDefaultAction();
464 std::string widget_kind;
467 widget_kind =
"rcanvas";
469 widget_kind =
"tcanvas";
479 new_widget->fBrowser =
this;
488 elem->GetChildsIter();
493 SendProgress(connid, progress);
497 if (widget && widget->DrawElement(elem, opt)) {
498 widget->SetPath(path);
499 return widget->SendWidgetContent();
504 [path](
const std::shared_ptr<RBrowserWidget> &wg) { return path == wg->GetPath(); });
507 return "SELECT_WIDGET:"s + (*iter)->GetName();
513 std::string widget_kind;
514 switch(dflt_action) {
521 default: widget_kind.clear();
524 if (!widget_kind.empty()) {
525 auto new_widget =
AddWidget(widget_kind);
529 if (new_widget->DrawElement(elem, opt))
530 new_widget->SetPath(path);
537 for (
auto &pathelem : path)
552 path.insert(path.end(), args.begin(), args.end());
557 if (!elem)
return ""s;
561 SendProgress(connid, progress);
565 if (widget && widget->DrawElement(elem,
"<append>")) {
566 widget->SetPath(path);
567 return widget->SendWidgetContent();
582 if (!
fWebWindow->NumConnections() || always_start_new_browser) {
625 std::shared_ptr<RBrowserWidget> widget;
627 if (kind ==
"editor"s)
628 widget = std::make_shared<RBrowserEditorWidget>(
name,
true);
629 else if (kind ==
"image"s)
630 widget = std::make_shared<RBrowserEditorWidget>(
name,
false);
631 else if (kind ==
"info"s)
632 widget = std::make_shared<RBrowserInfoWidget>(
name);
641 widget->fBrowser =
this;
653 if (!win || kind.empty())
658 auto widget = std::make_shared<RBrowserCatchedWidget>(
name, win, kind);
684 [
name, kind](
const std::shared_ptr<RBrowserWidget> &widget) {
685 return kind.empty() ? name == widget->GetName() : kind == widget->GetKind();
699 auto iter = std::find_if(
fWidgets.begin(),
fWidgets.end(), [
name](std::shared_ptr<RBrowserWidget> &widget) { return name == widget->GetName(); });
712 std::vector<std::string> arr;
714 std::string path =
gSystem->UnixPathName(
gSystem->HomeDirectory());
715 path +=
"/.root_hist" ;
716 std::ifstream infile(path);
720 while (std::getline(infile,
line) && (arr.size() < 1000)) {
721 if(!(std::find(arr.begin(), arr.end(),
line) != arr.end())) {
722 arr.emplace_back(
line);
735 std::vector<std::string> arr;
740 while (std::getline(infile,
line) && (arr.size() < 10000)) {
741 arr.emplace_back(
line);
753 std::vector<std::vector<std::string>> reply;
755 reply.emplace_back(
fBrowsable.GetWorkingPath());
759 reply.emplace_back(std::vector<std::string>({ widget->GetKind(), widget->GetUrl(), widget->GetName(), widget->GetTitle() }));
766 if (history.size() > 0) {
767 history.insert(history.begin(),
"history"s);
768 reply.emplace_back(history);
772 if (logs.size() > 0) {
773 logs.insert(logs.begin(),
"logs"s);
774 reply.emplace_back(logs);
777 reply.emplace_back(std::vector<std::string>({
784 reply.emplace_back(std::vector<std::string>({
786 gEnv->GetValue(
"WebGui.Browser.Expand",
"no"),
790 std::string msg =
"INMSG:";
802 long long millisec =
gSystem->Now();
808 fWebWindow->Send(connid,
"PROGRESS:"s + std::to_string(progr));
829 std::vector<std::string> arr = { widget->GetKind(), widget->GetUrl(), widget->GetName(), widget->GetTitle(),
839 std::vector<std::string> del_names;
842 if (!widget->IsValid())
843 del_names.push_back(widget->GetName());
845 if (!del_names.empty())
848 for (
auto name : del_names)
852 widget->CheckModified();
870 unsigned connid = std::stoul(arr.back()); arr.pop_back();
871 std::string kind = arr.back(); arr.pop_back();
873 if (kind ==
"DBLCLK") {
875 if (reply.empty()) reply =
"NOPE";
876 }
else if (kind ==
"DROP") {
878 if (reply.empty()) reply =
"NOPE";
891 R__LOG_DEBUG(0,
BrowserLog()) <<
"ProcessMsg len " << arg0.length() <<
" substr(30) " << arg0.substr(0, 30);
893 std::string kind, msg;
894 auto pos = arg0.find(
":");
895 if (
pos == std::string::npos) {
898 kind = arg0.substr(0,
pos);
899 msg = arg0.substr(
pos+1);
902 if (kind ==
"QUIT_ROOT") {
906 }
else if (kind ==
"BRREQ") {
909 if (!json.empty())
fWebWindow->Send(connid, json);
911 }
else if (kind ==
"LASTCYCLE") {
915 }
else if (kind ==
"DBLCLK") {
918 if (arr && (arr->size() > 2)) {
919 arr->push_back(kind);
920 arr->push_back(std::to_string(connid));
928 }
else if (kind ==
"DROP") {
931 if (arr && arr->size()) {
932 arr->push_back(kind);
933 arr->push_back(std::to_string(connid));
941 }
else if (kind ==
"WIDGET_SELECTED") {
945 auto reply = widget->SendWidgetContent();
946 if (!reply.empty())
fWebWindow->Send(connid, reply);
948 }
else if (kind ==
"CLOSE_TAB") {
950 }
else if (kind ==
"GETWORKPATH") {
952 }
else if (kind ==
"CHPATH") {
956 }
else if (kind ==
"CMD") {
957 std::string sPrompt =
"root []";
960 sPrompt = ((
TRint*)
gROOT->GetApplication())->GetPrompt();
961 Gl_histadd((
char *)msg.c_str());
965 ofs << sPrompt << msg << std::endl;
969 gROOT->ProcessLine(msg.c_str());
970 gSystem->RedirectOutput(
nullptr);
973 auto widget = std::dynamic_pointer_cast<RBrowserInfoWidget>(
FindWidget(
""s,
"info"s));
977 widget = std::dynamic_pointer_cast<RBrowserInfoWidget>(new_widget);
979 fWebWindow->Send(connid,
"SELECT_WIDGET:"s + widget->GetName());
984 widget->RefreshFromLogs(sPrompt + msg,
GetRootLogs());
988 }
else if (kind ==
"GETHISTORY") {
993 }
else if (kind ==
"GETLOGS") {
1002 }
else if (kind ==
"SYNCEDITOR") {
1004 if (arr && (arr->size() > 4)) {
1005 auto editor = std::dynamic_pointer_cast<RBrowserEditorWidget>(
FindWidget(arr->at(0)));
1007 editor->fFirstSend =
true;
1008 editor->fTitle = arr->at(1);
1009 editor->fFileName = arr->at(2);
1010 if (!arr->at(3).empty()) editor->fContent = arr->at(4);
1011 if ((arr->size() == 6) && (arr->at(5) ==
"SAVE"))
1013 if ((arr->size() == 6) && (arr->at(5) ==
"RUN")) {
1020 }
else if (kind ==
"GETINFO") {
1021 auto info = std::dynamic_pointer_cast<RBrowserInfoWidget>(
FindWidget(msg));
1024 fWebWindow->Send(connid, info->SendWidgetContent());
1026 }
else if (kind ==
"NEWWIDGET") {
1030 }
else if (kind ==
"NEWCHANNEL") {
1032 if (arr && (arr->size() == 2)) {
1037 }
else if (kind ==
"CDWORKDIR") {
1045 }
else if (kind ==
"OPTIONS") {
1047 if (arr && (arr->size() == 3)) {
1080 if (widget->GetTitle() != title)
1083 if (!kind.empty() && (widget->GetKind() != kind))
1087 fWebWindow->Send(0,
"SELECT_WIDGET:"s + widget->GetName());
#define R__LOG_ERROR(...)
#define R__LOG_DEBUG(DEBUGLEVEL,...)
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
bool Bool_t
Boolean (0=false, 1=true) (bool).
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
static bool IsLastKeyCycle()
Is only last cycle from the list of keys is shown.
static void SetLastKeyCycle(bool on=true)
Set flag to show only last cycle from the list of keys.
static int ExtractItemIndex(std::string &name)
Extract index from name Index coded by client with ###<indx>$$$ suffix Such coding used by browser to...
@ kActImage
can be shown in image viewer, can provide image
@ kActDraw6
can be drawn inside ROOT6 canvas
@ kActCanvas
indicate that it is canvas and should be drawn directly
@ kActTree
can be shown in tree viewer
@ kActGeom
can be shown in geometry viewer
@ kActBrowse
just browse (expand) item
@ kActEdit
can provide data for text editor
@ kActDraw7
can be drawn inside ROOT7 canvas
static std::string GetPathAsString(const RElementPath_t &path)
Converts element path back to string.
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...
static bool SetClassDrawOption(const ClassArg &, const std::string &)
Set draw option for the class Return true if entry for the class exists.
static std::string GetClassDrawOption(const ClassArg &)
Return configured draw option for the class.
static RElementPath_t GetWorkingPath(const std::string &workdir="")
Return working path in browser hierarchy.
RBrowserTimer(Long_t milliSec, Bool_t mode, RBrowser &br)
!< browser processing postponed requests
void Timeout() override
timeout handler used to process postponed requests in main ROOT thread
Web-based ROOT files and objects browser.
std::unique_ptr< RBrowserTimer > fTimer
! timer to handle postponed requests
RBrowserData fBrowsable
! central browsing element
std::shared_ptr< RBrowserWidget > AddWidget(const std::string &kind)
Creates new widget.
std::vector< std::string > GetRootHistory()
Get content of history file.
void AddInitWidget(const std::string &kind)
Create new widget and send init message to the client.
std::vector< std::vector< std::string > > fPostponed
! postponed messages, handled in timer
std::shared_ptr< RWebWindow > fWebWindow
! web window to browser
std::string ProcessDrop(unsigned connid, std::vector< std::string > &args)
Process drop of item in the current tab.
int fWidgetCnt
! counter for created widgets
std::shared_ptr< RBrowserWidget > GetActiveWidget() const
std::string ProcessDblClick(unsigned connid, std::vector< std::string > &args)
Process dbl click on browser item.
void ClearOnClose(const std::shared_ptr< void > &handle)
Set handle which will be cleared when connection is closed.
std::string fActiveWidgetName
! name of active widget
RBrowser(bool use_rcanvas=false)
constructor
void SetWorkingPath(const std::string &path)
Set working path in the browser.
void Hide()
Hide ROOT Browser.
std::string NewWidgetMsg(std::shared_ptr< RBrowserWidget > &widget)
Create message which send to client to create new widget.
bool fCatchWindowShow
! if arbitrary RWebWindow::Show calls should be catched by browser
std::string fPromptFileOutput
! file name for prompt output
void Show(const RWebDisplayArgs &args="", bool always_start_new_browser=false)
Show or update RBrowser in web window If web window already started - just refresh it like "reload" b...
std::string GetCurrentWorkingDirectory()
Return the current directory of ROOT.
void SetUseRCanvas(bool on=true)
std::shared_ptr< RBrowserWidget > FindWidget(const std::string &name, const std::string &kind="") const
Find widget by name or kind.
std::shared_ptr< RBrowserWidget > AddCatchedWidget(RWebWindow *win, const std::string &kind)
Add widget catched from external scripts.
bool GetUseRCanvas() const
std::vector< std::shared_ptr< RBrowserWidget > > fWidgets
! all browser widgets
virtual ~RBrowser()
destructor
void ProcessSaveFile(const std::string &fname, const std::string &content)
Process file save command in the editor.
float fLastProgressSend
! last value of send progress
std::string GetWindowUrl(bool remote)
Return URL parameter for the window showing ROOT Browser See ROOT::RWebWindow::GetUrl docu for more d...
std::string ProcessBrowserRequest(const std::string &msg)
Process browser request.
std::vector< std::string > GetRootLogs()
Get content of log file.
void ProcessMsg(unsigned connid, const std::string &arg)
Process received message from the client.
void CheckWidgtesModified(unsigned connid)
Check if any widget was modified and update if necessary.
void CloseTab(const std::string &name)
Close and delete specified widget.
void ProcessPostponedRequests()
Process postponed requests - decouple from websocket handling Only requests which can take longer tim...
unsigned fConnId
! default connection id
bool ActivateWidget(const std::string &title, const std::string &kind="")
Activate widget in RBrowser One should specify title and (optionally) kind of widget like "tcanvas" o...
void SendInitMsg(unsigned connid)
Process client connect.
void SendProgress(unsigned connid, float progr)
Send generic progress message to the web window Should show progress bar on client side.
long long fLastProgressSendTm
! time when last progress message was send
void ProcessRunMacro(const std::string &file_path)
Process run macro command in the editor.
void Sync()
Run widget Sync method - processing pending actions.
static bool IsMessageToStartDialog(const std::string &msg)
Check if this could be the message send by client to start new file dialog If returns true,...
static std::shared_ptr< RFileDialog > Embed(const std::shared_ptr< RWebWindow > &window, unsigned connid, const std::string &args)
Create dialog instance to use as embedded dialog inside other widget Embedded dialog started on the c...
Holds different arguments for starting browser with RWebDisplayHandle::Display() method.
const std::string & GetWidgetKind() const
returns widget kind
Represents web window, which can be shown in web browser or any other supported environment.
static std::shared_ptr< RWebWindow > Create()
Create new RWebWindow Using default RWebWindowsManager.
static unsigned ShowWindow(std::shared_ptr< RWebWindow > window, const RWebDisplayArgs &args="")
Static method to show web window Has to be used instead of RWebWindow::Show() when window potentially...
This class creates the ROOT Application Environment that interfaces to the windowing system eventloop...
static TString ToJSON(const T *obj, Int_t compact=0, const char *member_name=nullptr)
@ kNoSpaces
no new lines plus remove all spaces around "," and ":" symbols
static Bool_t FromJSON(T *&obj, const char *json)
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
const char * Data() const
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
TTimer(const TTimer &)=delete
ROOT::RLogChannel & BrowserLog()
Log channel for Browser diagnostics.