51#include <qapplication.h>
58#include <qmessagebox.h>
59#include <qpushbutton.h>
60#include <qscrollbar.h>
62#include <qtextbrowser.h>
65#include <qboxlayout.h>
66#include <qbuttongroup.h>
67#include <qcolordialog.h>
69#include <qcompleter.h>
70#include <qfiledialog.h>
72#include <qheaderview.h>
73#include <qlistwidget.h>
74#include <qmainwindow.h>
77#include <qradiobutton.h>
78#include <qscrollarea.h>
79#include <qstandarditemmodel.h>
80#include <qstringlist.h>
82#include <qtablewidget.h>
83#include <qtabwidget.h>
84#include <qtextstream.h>
88#include <QInputDialog>
90#include <QDoubleSpinBox>
98# include "moc_G4UIQt.cpp"
102static G4bool exitSession =
true;
103static G4bool exitPause =
true;
126 : fMainWindow(nullptr),
127 fCommandLabel(nullptr),
128 fCommandArea(nullptr),
129 fCoutTBTextArea(nullptr),
130 fUITabWidget(nullptr),
131 fCoutFilter(nullptr),
134 fHistoryTBTableList(nullptr),
135 fHelpTreeWidget(nullptr),
136 fHelpTBWidget(nullptr),
137 fTimeWindowWidget(nullptr),
138 fHistoryTBWidget(nullptr),
139 fCoutDockWidget(nullptr),
140 fUIDockWidget(nullptr),
141 fSceneTreeWidget(nullptr),
142 fNewSceneTreeWidget(nullptr),
143 fNewSceneTreeItemTreeWidget(nullptr),
145 fNewSceneTreeSlider(nullptr),
146 fUnwrapButtonWidget(nullptr),
147 fFadeButtonWidget(nullptr),
148 fXrayButtonWidget(nullptr),
149 fViewerPropertiesWidget(nullptr),
150 fPickInfosWidget(nullptr),
152 fViewerTabWidget(nullptr),
155 fHelpVSplitter(nullptr),
156 fParameterHelpLabel(nullptr),
157 fParameterHelpTable(nullptr),
158 fToolbarApp(nullptr),
159 fToolbarUser(nullptr),
160 fStringSeparator(
"__$$$@%%###__"),
162 fSearchIcon(nullptr),
167 fRotateIcon(nullptr),
169 fZoomInIcon(nullptr),
170 fZoomOutIcon(nullptr),
171 fWireframeIcon(nullptr),
173 fPointCloudIcon(nullptr),
174 fHiddenLineRemovalIcon(nullptr),
175 fHiddenLineAndSurfaceRemovalIcon(nullptr),
176 fPerspectiveIcon(nullptr),
178 fCommandIcon(nullptr),
182 fPickTargetIcon(nullptr),
184 fResetCameraIcon(nullptr),
185 fResetTargetPointIcon(nullptr)
186#ifdef G4MULTITHREADED
188 fThreadsFilterComboBox(nullptr)
191 fDefaultViewerFirstPageHTMLText(
""),
192 fViewerPropertiesDialog(nullptr),
193 fPickInfosDialog(nullptr),
194 fLastCompleteCommand(
""),
195 fMoveSelected(false),
196 fRotateSelected(true),
197 fPickSelected(false),
198 fZoomInSelected(false),
199 fZoomOutSelected(false)
207 G4cout <<
"G4UIQt : Unable to init Qt. Aborted" <<
G4endl;
217 Q_FOREACH (QWidget* widget, QApplication::allWidgets()) {
218 if ((!found) && (widget->inherits(
"QMainWindow"))) {
228 G4cout <<
"G4UIQt : Found an external App with a QMainWindow already defined. Aborted"
235 fMainWindow =
new QMainWindow();
236 fMainWindow->setAttribute(Qt::WA_DeleteOnClose);
238 fMainWindow->setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
239 fMainWindow->setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
240 fMainWindow->setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
241 fMainWindow->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
243 CreateViewerWidget();
244 fMainWindow->addDockWidget(Qt::LeftDockWidgetArea, CreateUITabWidget());
245 fMainWindow->addDockWidget(Qt::BottomDockWidgetArea, CreateCoutTBWidget());
247 CreateNewSceneTreeWidget();
250 SetDefaultIconsToolbar();
254#ifdef G4MULTITHREADED
259 fMainWindow->setWindowTitle(QFileInfo(QCoreApplication::applicationFilePath()).fileName());
264 int width = QGuiApplication::primaryScreen()->geometry().size().width() * 0.9;
265 int height = QGuiApplication::primaryScreen()->geometry().size().height() * 0.9;
266 fMainWindow->resize(width, height);
267 fMainWindow->move((QGuiApplication::primaryScreen()->geometry().size().width() - width) / 2,
268 (QGuiApplication::primaryScreen()->geometry().size().height() - height) / 4);
271 fCommandArea->setFocus(Qt::TabFocusReason);
275 qRegisterMetaType<QTextCursor>(
"QTextCursor");
281 fMainWindow->setVisible(
false);
291#ifdef G4MULTITHREADED
299 fDefaultIcons = aVal;
301 if (! fMainWindow->isVisible()) {
305 if (fToolbarApp !=
nullptr) {
307 fToolbarApp->setVisible(
true);
311 fToolbarApp->setVisible(
false);
316void G4UIQt::SetDefaultIconsToolbar()
319 if (fToolbarApp ==
nullptr) {
320 fToolbarApp =
new QToolBar();
321 fToolbarApp->setIconSize(QSize(20, 20));
322 fMainWindow->addToolBar(Qt::TopToolBarArea, fToolbarApp);
326 AddIcon(
"Open macro file",
"open",
"/control/execute");
327 AddIcon(
"Save viewer state",
"save",
"/vis/viewer/save");
330 fToolbarApp->addAction(QIcon(*fParamIcon),
"Viewer properties",
this,
331 [
this]() { this->ViewerPropertiesIconCallback(0); });
336 AddIcon(
"Zoom out",
"zoom_out",
"");
337 AddIcon(
"Zoom in",
"zoom_in",
"");
338 AddIcon(
"Rotate",
"rotate",
"");
341 AddIcon(
"Hidden line removal",
"hidden_line_removal",
"");
342 AddIcon(
"Hidden line and hidden surface removal",
"hidden_line_and_surface_removal",
"");
343 AddIcon(
"Surfaces",
"solid",
"");
344 AddIcon(
"Wireframe",
"wireframe",
"");
345 AddIcon(
"PointCloud",
"point_cloud",
"");
348 AddIcon(
"Perspective",
"perspective",
"");
349 AddIcon(
"Orthographic",
"ortho",
"");
350 AddIcon(
"ResetCamera",
"reset_camera",
"");
351 AddIcon(
"Reset target point",
"resetTargetPoint",
"/vis/viewer/set/targetPoint 0 0 0 m");
352 AddIcon(
"Run beam on",
"runBeamOn",
"/run/beamOn 1");
353 AddIcon(
"Exit Application",
"exit",
"exit");
358void G4UIQt::CreateIcons()
360 const char *
const save[]={
388 " +++++++++++++++++++++++++ ",
389 " +@##+$%%%%%%%%%%%%%%%&*$%&+ ",
390 " +=-;@>,,''',,,,,,,',,)&!,)+ ",
391 " +;-~@>,,,,,,,,,,,,,,,>$!,)+ ",
392 " +=-~@>,,,,,{]]]]]^,,,>*&$&+ ",
393 " +=-~@>,,,,,'{^{^^{,,,>*#=#+ ",
394 " +=-~@>,,,,,,,,,,,,,,,>@~/=+ ",
395 " +=-~@>,,,{{{''''{',,,>@~-=+ ",
396 " +=-~@>,,'^]]]]]]({,,,>@~-=+ ",
397 " +=-~@>,,,{{{{{{{{{,,,>@~-=+ ",
398 " +=-~@>,,,,,'{^{{^{,,,>@~-=+ ",
399 " +=-~@>,,,,,]]]]]]],,,>@~-=+ ",
400 " +=-~*>,,,,,,,,,,,,,,,>@~-=+ ",
401 " +=-~@>,,,,,,,,,,,,,,,>@~-=+ ",
402 " +=-/=$%%%%%%%%%%%%%%%$=/-=+ ",
403 " +=---;###############;---=+ ",
404 " +=---////////////////----=+ ",
405 " +=----------------///----=+ ",
406 " +=---=@##############@#--=+ ",
407 " +=---@+++++++++++*%))_+~-=+ ",
408 " +=---#+++++++++++&:,,>@~-=+ ",
409 " +=---#+++++++++++$',,>@~-=+ ",
410 " +=---#+++++++++++&!,,>@~-=+ ",
411 " +=/--#+++++++++++&',,>@~-=+ ",
412 " @;--#+++++++++++$',,>@~-=+ ",
413 " @;;@+++++++++++*)!>%@=;#+ ",
414 " @++++++++++++++*&**++@++ ",
419 fSaveIcon =
new QPixmap(save);
421 const char *
const search[] = {
433 "OOOOOOOOOOOOOOOOOOO",
434 "OOOOOOOOOOOOOOOOOOO",
435 "OOOOOOOo. .oOOOOOO",
438 "OOOOO. XOOOOX .OOOO",
441 "OOOOO. XOOOOo .OOOO",
445 "OOOOOOOOOOOOO. XOO",
446 "OOOOOOOOOOOOOO. XOO",
447 "OOOOOOOOOOOOOOOoOOO",
448 "OOOOOOOOOOOOOOOOOOO",
449 "OOOOOOOOOOOOOOOOOOO",
450 "OOOOOOOOOOOOOOOOOOO",
451 "OOOOOOOOOOOOOOOOOOO"
453 fSearchIcon =
new QPixmap(search);
455 const char *
const clear[] = {
467 "OOOOOOOOOOOOOOOOOOOO",
470 "OOOOOOOOOOOOOOOOOOOO",
471 "OOOOOOOOOOOOOOOOOOOO",
472 "OOOO XXXXXXXXXX OOOO",
473 "OOO XOOOOOOOOOO OOO",
474 "OOOOXOooOooOooO OOOO",
475 "OOOOXOooOooOooO OOOO",
476 "OOOOXOooOooOooO OOOO",
477 "OOOOXOooOooOooO OOOO",
478 "OOOOXOooOooOooO OOOO",
479 "OOOOXOooOooOooO OOOO",
480 "OOOOXOooOooOooO OOOO",
481 "OOOOXOooOooOooO OOOO",
482 "OOOOXOooOooOooO OOOO",
483 "OOOOXOooOooOooO OOOO",
484 "OOOOXOOOOOOOOOO OOOO",
485 "OOOOOooooooooooOOOOO",
486 "OOOOOO........OOOOOO"
489 fClearIcon =
new QPixmap(clear);
492 const char *
const open[]={
536 " {]^/((_({- %%%%%%%%%%% ",
537 " {(^_^^^^:<{{{{{{{{{{{{{[& ",
538 " {/_/(((((/]]]]]]]]]]]/]!# ",
539 " {/^(((((_^^^^^^^^^^^^^^:# ",
540 " {/^(((_^^____________^^}$ ",
541 " {/^(((((/////////////((!# ",
542 " {/^/^_:<|||||||||||||||@@****1 ",
543 " {/^/^(<[)||||||||||||||))!!}<; ",
544 " {/^_(:|234444444444444444432)1 ",
545 " {/_^/<)34444444444444444443}, ",
546 " {/^(2{:41111111111111111142|5 ",
547 " {3^3<:31111111111111111143}- ",
548 " {/^2<:31111111111111111441|' ",
549 " {_/<:41111111111111111143}, ",
550 " {(4<:31111111111111111144!# ",
551 " )4))44111111111111111144}, ",
552 " )2<:31111111111111111144{# ",
553 " @|:14444444444444444444}* ",
554 " ;@434444444444444444434<# ",
555 " ;[))))))))))))))))))))!~ ",
556 " ++++++++++++++++++++++;% ",
560 fOpenIcon =
new QPixmap(open);
563 const char *
const move[]={
596 " ')&$$$$*@@ @@*$$$$&)' ",
597 " ')&$$$$*@@ @@*$$$$&+' ",
614 fMoveIcon =
new QPixmap(move);
616 const char *
const rotate[]={
652 " --------!*{{{*&, ",
653 " -------=){*{{{>>{) ",
654 " ,!-----= ){& ,&{{@",
662 " !-!!======!!(((---! ",
663 " ='--------------! ",
678 fRotateIcon =
new QPixmap(rotate);
680 const char *
const pick[]={
696 "*********oo*********",
697 "*********oo*********",
698 "******$O. .O%******",
699 "****&o .O..O O*****",
700 "***&X @**oo**@ X****",
701 "***o $***oo***$ O***",
702 "**% @**********@ %**",
703 "**O.***********& +**",
704 "**.O*****@@*****o.**",
705 "oo .oo**@ #*&XX. oo",
706 "oo .oo**@ #*&oo. oO",
707 "**.O*****##*****oX**",
708 "**O ***********& +**",
709 "**% @****&&****+ &**",
710 "***O $***Xo***# +***",
711 "****X @&*Xo*&+ o****",
712 "*****O o..o +*****",
713 "******%+. X+&******",
714 "*********oo*********",
715 "*********oO*********"
717 fPickIcon =
new QPixmap(pick);
719 const char *
const zoom_in[]={
741 " ++.%%%+&&&*%%.++ ",
742 " .+#%%%%+&&&*%%.#+ ",
743 " ++..%%%+&&&*%%%.++ ",
744 " +#.+++++&&&*++++.+ ",
745 " @.+&&&&&&&&&&&&&+@ ",
746 " @#+&&&&&&&&&&&&&+@ ",
747 " @.+&&&&&&&&&&&&&+. ",
748 " +++@***+&&&****@+. ",
749 " ....++++&&&*++++.. ",
750 " ++.===+&&&*%=.++ ",
751 " @..==+&&&*=..@#& ",
752 " .@+#.+&&&@-+@@*@ ",
765 fZoomInIcon =
new QPixmap(zoom_in);
767 const char *
const zoom_out[]={
789 " ++.$$$$$$$$$$.++ ",
790 " .+#$$$$$$$$$$$.#+ ",
791 " ++..$$$$$$$$$$$.++ ",
792 " +#.+++++++++++++.+ ",
793 " @.+&&&&&&&&&&&&&+@ ",
794 " @#+&&&&&&&&&&&&&+@ ",
795 " @.+&&&&&&&&&&&&&+. ",
796 " +++@***********@+. ",
797 " ....++++++++++++.. ",
798 " ++.===$$$$$$=.++ ",
799 " @..===$$$$=..@#& ",
800 " .@+#.$$$..-+@@*@ ",
813 fZoomOutIcon =
new QPixmap(zoom_out);
815 const char *
const wireframe[]={
844 " +&********&@-***; ",
845 " +@@@&**&@@@@@@$ @*-&>&+ ",
846 " +*****&+ %*@ ,**'# ",
847 " @***)!~ @*{&*****+ ",
848 " @*!]***&+ +-*^**'~!*@ ",
849 " @*~ +@&**&@@@@@@&****&+ ~*@ ",
850 " @*@ +&********&-*= @*@ ",
851 " @*@ $%@-*-@$ @*@ @*@ ",
859 " @*@ =*-+ @*@ @*@ ",
860 " @*@ $%@@&****&@-*-+ @*@ ",
861 " @*@ $@&*****&@@&******&~~!*@ ",
862 " @*{/***&@@%$ $@-*-&*****+ ",
863 " @*)*)(-~ @*@ ~)**] ",
864 " +*******&@@@@+ %*_+]**] ",
865 " +@@@@@&******&@%+_*^**]# ",
874 fWireframeIcon =
new QPixmap(wireframe);
876 const char *
const solid[]={
914 " +-;>>>>>>>>>,')!~ ",
915 " {]@@-;>>>>>>>>>>>>^/(_= ",
916 " {:>>>>>>>>>>>>>>>>><//[)!= ",
917 " ]>>>>>>>>>>>>>>>>>><////[)} ",
918 " @>>>>>>>>>>>>>>>>>><//////| ",
919 " @>>>>>>>>>>>>>>>>>><//////| ",
920 " @>>>>>>>>>>>>>>>>>><//////| ",
921 " @>>>>>>>>>>>>>>>>>><//////| ",
922 " @>>>>>>>>>>>>>>>>>><//////| ",
923 " @>>>>>>>>>>>>>>>>>><//////| ",
924 " @>>>>>>>>>>>>>>>>>><//////| ",
925 " @>>>>>>>>>>>>>>>>>><//////| ",
926 " @>>>>>>>>>>>>>>>>>><//////| ",
927 " @>>>>>>>>>>>>>>>>>><//////| ",
928 " @>>>>>>>>>>>>>>>>>><//////| ",
929 " @>>>>>>>>>>>>>>>>>><//////| ",
930 " @>>>>>>>>>>>>>>>>>><//////| ",
931 " @>>>>>>>>>>>>>>>>>><//////| ",
932 " @>>>>>>>>>>>>>>>>>></////[1 ",
933 " @>>>>>>>>>>>>>>>>>><////[*2 ",
934 " {:>>>>>>>>>>>>>>>>><//[)12 ",
935 " +@@@@@-;>>>>>>>>>><[)13 ",
944 fSolidIcon =
new QPixmap(solid);
946 const char *
const hidden_line_removal[]={
966 " +#$$$$$$$$#@&$$$* ",
967 " =-@@#$$#@@@@@-= @$&#;>= ",
968 " =$$$$$#+ -$@ *$$%+ ",
969 " -$&@-= -$- #$$$= ",
985 " -$&@@@-= -$- =>;, ",
986 " =$$$$$$$#@@@-= -$'+#$$, ",
987 " =-@@@@#$$$$$$#@-+'$)$$#+ ",
996 fHiddenLineRemovalIcon =
new QPixmap(hidden_line_removal);
998 const char *
const hidden_line_and_surface_removal[]={
1044 " ++@%####&*=-#+;>, ",
1045 " +++++@'=)))))))!)~+{]^++ ",
1046 " +$%&*=)!!!!!!!!!)~+/(]_+++ ",
1047 " +#-))!!!!!!!!!!!)~+/(::<[+ ",
1048 " +#)!!!!!!!!!!!!!!}+/::::{+ ",
1049 " +#)!!!!!!!!!!!!!!}+/::::{+ ",
1050 " +#)!!!!!!!!!!!!!!}+/::::{+ ",
1051 " +#)!!!!!!!!!!!!!!}+/::::{+ ",
1052 " +#)!!!!!!!!!!!!!!}+/::::{+ ",
1053 " +#)!!!!!!!!!!!!!!}+/::::{+ ",
1054 " +#)!!!!!!!!!!!!!!}+/::::{+ ",
1055 " +#)!!!!!!!!!!!!!!}+/::::{+ ",
1056 " +#)!!!!!!!!!!!!!!}+/::::{+ ",
1057 " +#)!!!!!!!!!!!!!!}+/::::{+ ",
1058 " +#)!!!!!!!!!!!!!!}+/::::{+ ",
1059 " +#)!!!!!!!!!!!!!!}+/::::{+ ",
1060 " +#)!!!!!!!!!!!!!!}+/::::{+ ",
1061 " +#)!!!!!!!!!!!!!!}+/:::|1+ ",
1062 " +$#}}~23!!!!!!!!)~+/(]45, ",
1063 " +++++++@#}}~23!!)~+678++ ",
1064 " ++++++@#~90+a++ ",
1073 fHiddenLineAndSurfaceRemovalIcon =
new QPixmap(hidden_line_and_surface_removal);
1075 const char *
const perspective[]={
1085 " ................ ",
1086 " ....+++++++++++++++. ",
1087 " ...++++..+.........+++. ",
1088 " ..++..............++..+. ",
1089 " .+++++++++++++++++.. .+. ",
1090 " .+...............+. .+. ",
1091 " .+. .+. .+. .+. ",
1092 " .+. .+. .+. .+. ",
1093 " .+. .+. .+. .+. ",
1094 " .+. .+. .+. .+. ",
1095 " .+. .+. .+. .+. ",
1096 " .+. .+. .+. .+. ",
1097 " .+. .+. .+. .+. ",
1098 " .+. .+. .+. .+. ",
1099 " .+. .+......+....+. ",
1100 " .+. ..++++++.+.++++. ",
1101 " .+. .++.......+...+.. ",
1102 " .+. .++. .+..++. ",
1103 " .+. ..+.. .+..+. ",
1106 " .+++.............++. ",
1107 " .+++++++++++++++++. ",
1108 " ................... ",
1113 fPerspectiveIcon =
new QPixmap(perspective);
1115 const char *
const ortho[]={
1123 " ................... ",
1124 " ..@@@@@@@@@@@@@@@@@. ",
1125 " ..@@@.............@@@. ",
1126 " ..@@.@. ..@..@. ",
1127 " ..@@ ..@. .@@...@. ",
1128 " ..@@..............@@.. .@. ",
1129 " .@@@@@@@@@@@@@@@@@.. .@. ",
1130 " .@...............@. .@. ",
1131 " .@. .@. .@. .@. ",
1132 " .@. .@. .@. .@. ",
1133 " .@. .@. .@. .@. ",
1134 " .@. .@. .@. .@. ",
1135 " .@. .@. .@. .@. ",
1136 " .@. .@. .@. .@. ",
1137 " .@. .@. .@. .@. ",
1138 " .@. .@. .@. .@. ",
1139 " .@. .@. .@. .@. ",
1140 " .@. .@. .@. .@. ",
1141 " .@. .@........@......@. ",
1142 " .@. .@@@@@@@@@.@.@@@@@@. ",
1143 " .@. .@@+........@....@@.. ",
1144 " .@...@. .@...@... ",
1146 " .@@@.............@@@.. ",
1147 " .@@@@@@@@@@@@@@@@@... ",
1148 " ................... ",
1153 fOrthoIcon =
new QPixmap(ortho);
1155 const char *
const commandIcon[]={
1183 "66666666666666666666",
1184 "66%++++++++++++++&56",
1185 "6$ o..o......o..o *6",
1186 "6+o...o*<441;@.o..+6",
1187 "6+..o@1553<354$..o+6",
1188 "6+..o<5<@ .*54#o.+6",
1197 "6+..O25<@ X=54#o.+6",
1198 "6+.o.@1553<354$...@6",
1199 "6+o..oo*<44<;@o..o+6",
1200 "6$ .o..o.....o..o *6",
1201 "66%+++++OOOO+++++*66",
1202 "66666666666666666666"
1204 fCommandIcon =
new QPixmap(commandIcon);
1206 const char *
const dirIcon[]={
1234 "66666666666666666666",
1235 "66$oOOOOOOOOOOOOo%66",
1238 "6o =635533666$ o6",
1239 "6o -65:+ +165X o6",
1248 "6o -65:+ @265X o6",
1249 "6o =635543665# O6",
1252 "66$OOOoo....OOOOo%66",
1253 "66666666666666666666"}
1255 fDirIcon =
new QPixmap(dirIcon);
1258 const char *
const runIcon[]={
1295 "rrrrrrrr%<<2rrrrrrrr",
1296 "rrrrr5=$$$$===rrrrrr",
1297 "rrrr<##$$$$$---&rrrr",
1298 "rrr=###$$$$-----%rrr",
1299 "rr=####$$$$------&rr",
1300 "r2@####7##$-------rr",
1301 "r.@####048$-------Or",
1302 "r.@####q4ee=----$@.r",
1303 " .@@###w4eee5%$#@@@X",
1304 " .@@@..w4eeeeqo..@@X",
1305 " .@..ooe<eeee7Oooo@X",
1306 " ..oooOe2eee6OOOooo ",
1307 "rOooOO+e2ew2+++++O+r",
1308 "r:oO+++e30,;;;;;++Or",
1309 "r :++;:9,>,,>>:;;1rr",
1310 "rr*1;:>,333333,>32rr",
1311 "rrr66,1367777637<rrr",
1312 "rrrr509799999905rrrr",
1313 "rrrrr=8wqwwww8-rrrrr",
1314 "rrrrrrrr4444rrrrrrrr"
1316 fRunIcon =
new QPixmap(runIcon);
1318 const char *
const paramIcon[]={
1357 "wwwwwwww5 5wwwwwwww",
1358 "wwwwwwww, ,wwwwwwww",
1359 "www&;ww7+ +9ww=-www",
1365 "5<+ .wwwwwww0. +<5",
1368 "5<+ .wwwwwww0X +<5",
1374 "www*>ww7+ +7ww=:www",
1375 "wwwwwwww1 1wwwwwwww",
1376 "wwwwwwww5 5wwwwwwww"
1378 fParamIcon =
new QPixmap(paramIcon);
1380 const char *
const exitIcon[]={
1446 " rMMMM# jMMM MMMMx ",
1447 " OMMMMk jMMM 8MMMM9 ",
1448 " xMMMM jMMM pMMMM ",
1449 " MMMM jMMM xMMM8 ",
1460 " <MMMMMp: $rMMMMMp ",
1461 " yMMMMMMMMMMMMMMk ",
1468 fExitIcon=
new QPixmap(exitIcon);
1470 const char *
const resetCamera[]={
1478 " .......................... ",
1479 " .@@@@@@@@@@@@@@@@@@@@@@@@. ",
1484 " .@. .@@@@@@@@@@. .@. ",
1485 " .@. .@. .@. .@. ",
1486 " .@. .@. .@. .@. ",
1487 " .@. .@. .@. .@. ",
1488 " .@. .@. .@. .@. ",
1489 " .@. .@. .@. .@. ",
1490 " .@. .@. .@. .@. ",
1491 " .@. .@. .@. .@. ",
1492 " .@. .@. .@. .@. ",
1493 " .@. .@. .@. .@. ",
1494 " .@. .@. .@. .@. ",
1495 " .@. .@. .@. .@. ",
1496 " .@. .@. .@. .@. ",
1497 " .@. .@@@@@@@@@@. .@. ",
1502 " .@@@@@@@@@@@@@@@@@@@@@@@@. ",
1503 " .......................... ",
1508 fResetCameraIcon =
new QPixmap(resetCamera);
1510 const char *
const resetTargetPointIcon[]={
1536 " .@@@@@@@@@@@@@@@@@@@@ ",
1537 " .@.................... ",
1548 fResetTargetPointIcon =
new QPixmap(resetTargetPointIcon);
1550 const char *
const pointCloudIcon[] = {
1587 fPointCloudIcon =
new QPixmap(pointCloudIcon);
1595 auto qVariant = item->data(0, Qt::UserRole);
1596 std::istringstream iss(qVariant.toString().toStdString());
1597 void* itemAddress; iss >> itemAddress;
1601 QColor ConvertG4ColourToQColor(
const G4Colour& g4Colour)
1603 return QColor((
int)(g4Colour.
GetRed()*255),
1605 (
int)(g4Colour.
GetBlue()*255),
1609 G4Colour ConvertQColorToG4Colour(
const QColor& qColor)
1611 return G4Color(qColor.red()/255.,
1612 qColor.green()/255.,
1614 qColor.alpha()/255.);
1618 G4int thisSceneTreePVDepth = -1;
1619 const G4int maxInherentSliderValue = 100;
1620 G4double transparencyByDepthValue = 0.;
1621 G4int transparencyByDepthOption = 1;
1624void G4UIQt::CreateNewSceneTreeWidget()
1626 fNewSceneTreeWidget =
new QWidget;
1627 fNewSceneTreeWidget->setStyleSheet (
"padding: 0px ");
1628 fNewSceneTreeWidget->setLayout(
new QVBoxLayout);
1629 fNewSceneTreeWidget->layout()->setContentsMargins(0,0,0,0);
1630 fNewSceneTreeWidget->setWindowTitle(
"some name");
1632 fSceneTreeWidget->layout()->addWidget(fNewSceneTreeWidget);
1635 fNewSceneTreeItemTreeWidget =
new NewSceneTreeItemTreeWidget;
1636 fNewSceneTreeItemTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
1637 fNewSceneTreeWidget->layout()->addWidget(fNewSceneTreeItemTreeWidget);
1641 auto helpWidget =
new QWidget();
1642 auto helpLayout =
new QVBoxLayout();
1643 auto zero =
new QLabel(); zero->setText(
"Show\nall");
1644 auto one =
new QLabel(); one->setText(
"Hide\nall");
1645 auto depthWidget =
new QWidget();
1646 auto showBox =
new QWidget(depthWidget);
1647 auto showBoxLayout =
new QHBoxLayout();
1649 fNewSceneTreeSlider =
new QSlider(Qt::Horizontal);
1650 fNewSceneTreeSlider->setMaximum(maxInherentSliderValue);
1651 fNewSceneTreeSlider->setMinimum(0);
1652 fNewSceneTreeSlider->setTickPosition(QSlider::TicksAbove);
1653 fNewSceneTreeSlider->setTickInterval(10);
1655 auto buttonBox =
new QWidget();
1656 auto buttonBoxlayout =
new QHBoxLayout();
1657 buttonBox->setLayout(buttonBoxlayout);
1658 fUnwrapButtonWidget =
new QRadioButton(
"Unwrap");
1659 fUnwrapButtonWidget->setChecked(
true);
1660 fFadeButtonWidget =
new QRadioButton(
"Fade");
1661 fXrayButtonWidget =
new QRadioButton(
"X-ray");
1662 buttonBoxlayout->addWidget(fUnwrapButtonWidget);
1663 buttonBoxlayout->addWidget(fFadeButtonWidget);
1664 buttonBoxlayout->addWidget(fXrayButtonWidget);
1665 buttonBoxlayout->setContentsMargins(0,0,0,0);
1666 buttonBox->setLayout(buttonBoxlayout);
1668 showBoxLayout->setContentsMargins(0,0,0,0);
1669 showBoxLayout->addWidget(zero);
1670 showBoxLayout->addWidget(fNewSceneTreeSlider);
1671 showBoxLayout->addWidget(one);
1672 showBox->setLayout(showBoxLayout);
1673 helpLayout->addWidget(showBox);
1674 helpWidget->setLayout(helpLayout);
1675 helpLayout->setContentsMargins(0,0,0,0);
1676 helpLayout->addWidget(buttonBox);
1677 fNewSceneTreeWidget->layout()->addWidget(helpWidget);
1680 connect(fNewSceneTreeItemTreeWidget, &QTreeWidget::itemClicked,
1681 [&](QTreeWidgetItem* item){SceneTreeItemClicked(item);});
1683 connect(fNewSceneTreeItemTreeWidget, &QTreeWidget::itemDoubleClicked,
1684 [&](QTreeWidgetItem* item){SceneTreeItemDoubleClicked(item);});
1687 connect(fNewSceneTreeItemTreeWidget, &QTreeWidget::itemExpanded,
1688 [&](QTreeWidgetItem* item){SceneTreeItemExpanded(item);});
1689 connect(fNewSceneTreeItemTreeWidget, &QTreeWidget::itemCollapsed,
1690 [&](QTreeWidgetItem* item){SceneTreeItemCollapsed(item);});
1693 connect(fNewSceneTreeSlider, &QSlider::valueChanged,
1694 [&](
int value){SliderValueChanged(value);});
1695 connect(fNewSceneTreeSlider, &QSlider::sliderReleased,
1696 [&]{SliderReleased();});
1699 connect(fUnwrapButtonWidget, &QRadioButton::clicked,
1700 [&]{SliderRadioButtonClicked(1);});
1701 connect(fFadeButtonWidget, &QRadioButton::clicked,
1702 [&]{SliderRadioButtonClicked(2);});
1703 connect(fXrayButtonWidget, &QRadioButton::clicked,
1704 [&]{SliderRadioButtonClicked(3);});
1715 fNewSceneTreeItemTreeWidget->clear();
1720 fNewSceneTreeItemTreeWidget->setHeaderLabel (root.
GetDescription().c_str());
1723 auto item =
new QTreeWidgetItem(fNewSceneTreeItemTreeWidget);
1726 fNewSceneTreeItemTreeWidget->insertTopLevelItem(0,item);
1729 item->setText(0, model.GetModelType().c_str());
1735 std::ostringstream oss; oss << std::hex << &model;
1736 auto data = QVariant(oss.str().c_str());
1737 item->setData(0, Qt::UserRole, data);
1740 G4String toolTipMessage = model.GetModelDescription();
1741 if (!model.GetFurtherInfo().empty()) {
1742 toolTipMessage +=
"\n " + model.GetFurtherInfo();
1744 item->setToolTip(0, toolTipMessage.c_str());
1748 (0, model.GetVisAttributes().IsVisible()? Qt::Checked: Qt::Unchecked);
1751 item->setExpanded(model.IsExpanded());
1754 thisSceneTreePVDepth = -1;
1755 BuildPVQTree(model,item);
1793 fNewSceneTreeSlider->blockSignals(
true);
1794 fNewSceneTreeSlider->setValue(depth * maxInherentSliderValue / fMaxPVDepth);
1795 fNewSceneTreeSlider->blockSignals(
false);
1797 fUnwrapButtonWidget->blockSignals(
true);
1798 fUnwrapButtonWidget->setChecked(
true);
1799 fUnwrapButtonWidget->blockSignals(
false);
1801 else if (option == 2) {
1802 fFadeButtonWidget->blockSignals(
true);
1803 fFadeButtonWidget->setChecked(
true);
1804 fFadeButtonWidget->blockSignals(
false);
1806 else if (option == 3) {
1807 fXrayButtonWidget->blockSignals(
true);
1808 fXrayButtonWidget->setChecked(
true);
1809 fXrayButtonWidget->blockSignals(
false);
1816void G4UIQt::BuildPVQTree(
const G4SceneTreeItem& g4stItem, QTreeWidgetItem* qtwItem)
1818 if (fMaxPVDepth < thisSceneTreePVDepth) fMaxPVDepth = thisSceneTreePVDepth;
1819 thisSceneTreePVDepth++;
1820 const auto& g4stChildren = g4stItem.
GetChildren();
1821 for (
const auto& g4stChild: g4stChildren) {
1822 QStringList qStringList;
1823 qStringList.append(g4stChild.GetDescription().c_str());
1824 auto newQTWItem =
new QTreeWidgetItem(qStringList);
1827 qtwItem->addChild(newQTWItem);
1833 std::ostringstream oss; oss << std::hex << &g4stChild;
1834 auto data = QVariant(oss.str().c_str());
1835 newQTWItem->setData(0, Qt::UserRole, data);
1839 auto& nameCopyNo = g4stChild.GetDescription();
1840 auto name = nameCopyNo.substr(0,nameCopyNo.find(
':'));
1841 oss.str(
""); oss << nameCopyNo <<
1842 ": Click to make visible and get more information."
1843 "\n This may not work if the volume is in the \"base path\". (Hover on"
1844 "\n G4PhysicalVolumeModel to see base path.) If this is the case,"
1845 "\n \"/vis/scene/add/volume " << name <<
"\" to bring into the displayed tree.)";
1846 newQTWItem->setToolTip(0, oss.str().c_str());
1848 oss.str(
""); oss << g4stChild.GetPVPath() <<
1849 "\nTo see properties, right-click/dump.";
1850 newQTWItem->setToolTip(0, oss.str().c_str());
1854 newQTWItem->setCheckState
1855 (0, g4stChild.GetVisAttributes().IsVisible()? Qt::Checked: Qt::Unchecked);
1858 newQTWItem->setExpanded(g4stChild.IsExpanded());
1861 QPixmap pixmap = QPixmap(QSize(16, 16));
1862 pixmap.fill(ConvertG4ColourToQColor(g4stChild.GetVisAttributes().GetColour()));
1863 QPainter painter(&pixmap);
1864 painter.setPen(Qt::black);
1865 painter.drawRect(0,0,15,15);
1866 newQTWItem->setIcon(0,pixmap);
1869 BuildPVQTree(g4stChild,newQTWItem);
1871 thisSceneTreePVDepth--;
1874void G4UIQt::SceneTreeItemClicked(QTreeWidgetItem* item)
1876 if (item ==
nullptr)
return;
1877 auto sceneTreeItem = ConvertToG4SceneTreeItem(item);
1878 if (sceneTreeItem ==
nullptr)
return;
1883 G4String argument =
"false", inverse =
"true";
1884 auto newCheckState = item->checkState(0);
1886 = sceneTreeItem->GetVisAttributes().IsVisible()? Qt::Checked: Qt::Unchecked;
1887 switch (sceneTreeItem->GetType()) {
1896 if (newCheckState != oldCheckState) {
1897 if (newCheckState == Qt::Checked) argument =
"true";
1899 (
"/vis/scene/activateModel \"" + sceneTreeItem->GetModelDescription() +
"\" " + argument);
1907 if (newCheckState != oldCheckState) {
1908 if (newCheckState == Qt::Checked) {
1909 argument =
"true"; inverse =
"false";
1911 uiMan->ApplyCommand(
"/vis/set/touchable" + sceneTreeItem->GetPVPath());
1912 uiMan->ApplyCommand(
"/vis/touchable/set/visibility " + argument);
1913 static G4bool first =
true;
1914 if (first && sceneTreeItem->GetChildren().size() > 0 && argument ==
"false") {
1917 (
"To make all descendants invisible, select, then right-click/daughtersInvisible/true.");
1918 msgBox.setStandardButtons(QMessageBox::Ok);
1927void G4UIQt::SceneTreeItemDoubleClicked(QTreeWidgetItem* item)
1929 if (item ==
nullptr)
return;
1930 auto sceneTreeItem = ConvertToG4SceneTreeItem(item);
1931 if (sceneTreeItem ==
nullptr)
return;
1934 auto oldQColor = ConvertG4ColourToQColor(sceneTreeItem->GetVisAttributes().GetColour());
1935 auto newQColor = QColorDialog::getColor
1936 (oldQColor, fNewSceneTreeItemTreeWidget,
"", QColorDialog::ShowAlphaChannel);
1937 if (!newQColor.isValid())
return;
1938 if (newQColor == oldQColor)
return;
1940 auto newColour = ConvertQColorToG4Colour(newQColor);
1941 std::ostringstream oss; oss << std::setprecision(2)
1942 << newColour.GetRed() <<
' ' << newColour.GetGreen()
1943 <<
' ' << newColour.GetBlue() <<
' ' << newColour.GetAlpha();
1945 uiMan->ApplyCommand(
"/vis/set/touchable" + sceneTreeItem->GetPVPath());
1946 uiMan->ApplyCommand(
"/vis/touchable/set/colour " + oss.str());
1954 if (newColour.GetAlpha() == 0.) {
1955 sceneTreeItem->AccessVisAttributes().SetColour(newColour);
1959void G4UIQt::SceneTreeItemExpanded(QTreeWidgetItem* item)
1961 if (item ==
nullptr)
return;
1962 auto sceneTreeItem = ConvertToG4SceneTreeItem(item);
1963 if (sceneTreeItem ==
nullptr)
return;
1967 sceneTreeItem->SetExpanded(
true);
1971void G4UIQt::SceneTreeItemCollapsed(QTreeWidgetItem* item)
1973 if (item ==
nullptr)
return;
1974 auto sceneTreeItem = ConvertToG4SceneTreeItem(item);
1975 if (sceneTreeItem ==
nullptr)
return;
1979 sceneTreeItem->SetExpanded(
false);
1983void G4UIQt::SliderValueChanged(
G4int value)
1985 transparencyByDepthValue = value;
1986 std::ostringstream oss;
1987 oss << fMaxPVDepth*transparencyByDepthValue/maxInherentSliderValue
1988 <<
' ' << transparencyByDepthOption;
1991 auto keepVerbose = uiMan->GetVerboseLevel();
1992 uiMan->SetVerboseLevel(0);
1993 uiMan->ApplyCommand(
"/vis/viewer/set/transparencyByDepth " + oss.str());
1994 uiMan->SetVerboseLevel(keepVerbose);
1997void G4UIQt::SliderReleased()
1999 transparencyByDepthValue = fNewSceneTreeSlider->value();
2000 std::ostringstream oss;
2001 oss << fMaxPVDepth*transparencyByDepthValue/maxInherentSliderValue
2002 <<
' ' << transparencyByDepthOption;
2005 uiMan->ApplyCommand(
"/vis/viewer/set/transparencyByDepth " + oss.str());
2008void G4UIQt::SliderRadioButtonClicked(
G4int buttonNo) {
2009 transparencyByDepthOption = buttonNo;
2010 std::ostringstream oss;
2011 oss << fMaxPVDepth*transparencyByDepthValue/maxInherentSliderValue
2012 <<
' ' << transparencyByDepthOption;
2015 uiMan->ApplyCommand(
"/vis/viewer/set/transparencyByDepth " + oss.str());
2018void G4UIQt::NewSceneTreeItemTreeWidget::mousePressEvent(QMouseEvent* ev)
2020#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
2021 auto currentMousePressPosition = ev->globalPos();
2023 auto currentMousePressPosition = ev->globalPosition().toPoint();
2026 if (ev->button() == Qt::RightButton) {
2027 auto item = currentItem();
2029 auto sceneTreeItem = ConvertToG4SceneTreeItem(item);
2030 if (sceneTreeItem) {
2038 enum CommandType {withoutParameter, withABool, withAnInteger, withADouble, withAString};
2039 static std::map<G4String,CommandType> alphabetical;
2040 static G4bool first =
true;
2047 alphabetical[
"centreAndZoomInOn"] = withoutParameter;
2048 alphabetical[
"centreOn"] = withoutParameter;
2049 alphabetical[
"dump"] = withoutParameter;
2050 alphabetical[
"extentForField"] = withoutParameter;
2051 alphabetical[
"localAxes"] = withoutParameter;
2052 alphabetical[
"showExtent"] = withoutParameter;
2053 alphabetical[
"twinkle"] = withoutParameter;
2054 alphabetical[
"volumeForField"] = withoutParameter;
2057 alphabetical[
"daughtersInvisible"] = withABool;
2058 alphabetical[
"forceAuxEdgeVisible"] = withABool;
2059 alphabetical[
"forceCloud"] = withABool;
2060 alphabetical[
"forceSolid"] = withABool;
2061 alphabetical[
"forceWireframe"] = withABool;
2062 alphabetical[
"visibility"] = withABool;
2064 alphabetical[
"lineSegmentsPerCircle"] = withAnInteger;
2065 alphabetical[
"numberOfCloudPoints"] = withAnInteger;
2067 alphabetical[
"lineWidth"] = withADouble;
2069 alphabetical[
"lineStyle"] = withAString;
2073 std::vector<QAction*> actions;
2074 std::vector<QMenu*> menus;
2076 for (
const auto& action : alphabetical) {
2077 const auto& af = action.first;
2079 if (action.second == withoutParameter) {
2081 auto qAction =
new QAction(af.c_str(),
this);
2082 actions.push_back(qAction);
2083 topMenu.addAction(qAction);
2084 connect(qAction, &QAction::triggered,
this,
2085 [
this, &af, &sceneTreeItem]{ActWithoutParameter(af, sceneTreeItem);});
2087 }
else if (action.second == withABool) {
2089 auto menu =
new QMenu(af.c_str());
2090 menus.push_back(menu);
2091 topMenu.addMenu(menu);
2092 auto qActionTrue =
new QAction(
"true",
this);
2093 actions.push_back(qActionTrue);
2094 menu->addAction(qActionTrue);
2095 connect(qActionTrue, &QAction::triggered,
this,
2096 [
this, &af, &sceneTreeItem]{ActWithABool(af, sceneTreeItem,
true);});
2097 auto qActionFalse =
new QAction(
"false",
this);
2098 actions.push_back(qActionFalse);
2099 menu->addAction(qActionFalse);
2100 connect(qActionFalse, &QAction::triggered,
this,
2101 [
this, &af, &sceneTreeItem]{ActWithABool(af, sceneTreeItem,
false);});
2103 }
else if (action.second == withAnInteger) {
2105 auto qAction =
new QAction(af.c_str(),
this);
2106 actions.push_back(qAction);
2107 topMenu.addAction(qAction);
2108 connect(qAction, &QAction::triggered,
this,
2109 [
this, &af, &sceneTreeItem]{ActWithAnInteger(af, sceneTreeItem);});
2111 }
else if (action.second == withADouble) {
2113 auto qAction =
new QAction(af.c_str(),
this);
2114 actions.push_back(qAction);
2115 topMenu.addAction(qAction);
2116 connect(qAction, &QAction::triggered,
this,
2117 [
this, &af, &sceneTreeItem]{ActWithADouble(af, sceneTreeItem);});
2119 }
else if (action.second == withAString) {
2121 auto qAction =
new QAction(af.c_str(),
this);
2122 actions.push_back(qAction);
2123 topMenu.addAction(qAction);
2124 connect(qAction, &QAction::triggered,
this,
2125 [
this, &af, &sceneTreeItem]{ActWithAString(af, sceneTreeItem);});
2129 topMenu.exec(currentMousePressPosition);
2132 for (
auto action : actions) {
2137 for (
auto menu : menus) {
2146 QTreeWidget::mousePressEvent(ev);
2149void G4UIQt::NewSceneTreeItemTreeWidget::ActWithoutParameter
2150 (
const G4String& action, G4SceneTreeItem* sceneTreeItem)
2153 if (action ==
"dump") {
2155 auto widget =
new QWidget;
2157 auto layout =
new QVBoxLayout;
2158 widget->setLayout(layout);
2160 auto label =
new QLabel;
2161 label->setAlignment(Qt::AlignHCenter);
2162 std::ostringstream oss;
2163 oss <<
"<b>" << sceneTreeItem->
GetPVPath() <<
"<br>Full dump printed to G4cout</b>";
2164 label->setText(oss.str().c_str());
2165 label->setTextFormat(Qt::RichText);
2166 layout->addWidget(label);
2168 auto scrollArea =
new QScrollArea;
2169 auto content =
new QLabel;
2170 std::ostringstream oss1;
2172 content->setText(oss1.str().c_str());
2173 scrollArea->setWidget(content);
2174 layout->addWidget(scrollArea);
2179 uiMan->ApplyCommand(
"/vis/set/touchable" + sceneTreeItem->
GetPVPath());
2180 uiMan->ApplyCommand(
"/vis/touchable/" + action);
2183void G4UIQt::NewSceneTreeItemTreeWidget::ActWithABool
2184 (
const G4String& action, G4SceneTreeItem* sceneTreeItem,
G4bool whatever)
2187 uiMan->ApplyCommand(
"/vis/set/touchable" + sceneTreeItem->
GetPVPath());
2188 G4String which = whatever?
"true":
"false";
2189 uiMan->ApplyCommand(
"/vis/touchable/set/" + action +
' ' + which);
2192void G4UIQt::NewSceneTreeItemTreeWidget::ActWithAnInteger
2193(
const G4String& action, G4SceneTreeItem* sceneTreeItem)
2196 auto newValue = QInputDialog::getInt(
this, action.c_str(), action.c_str(),
2197 0, 0, 9999999, 1, &ok);
2200 uiMan->ApplyCommand(
"/vis/set/touchable" + sceneTreeItem->
GetPVPath());
2201 uiMan->ApplyCommand(
"/vis/touchable/set/" + action +
' '
2206void G4UIQt::NewSceneTreeItemTreeWidget::ActWithADouble
2207 (
const G4String& action, G4SceneTreeItem* sceneTreeItem)
2210 auto newValue = QInputDialog::getDouble(
this, action.c_str(), action.c_str(),
2214 uiMan->ApplyCommand(
"/vis/set/touchable" + sceneTreeItem->
GetPVPath());
2215 uiMan->ApplyCommand(
"/vis/touchable/set/" + action +
' '
2220void G4UIQt::NewSceneTreeItemTreeWidget::ActWithAString
2221 (
const G4String& action, G4SceneTreeItem* sceneTreeItem)
2224 auto command = uiMan->FindCommand(
"/vis/touchable/set/" + action);
2226 QStringList qStringList;
2227 const auto& candidates = command->GetParameter(0)->GetParameterCandidates();
2228 std::istringstream iss(candidates);
2230 while (iss >> candidate) qStringList.append(candidate.c_str());
2232 auto chosenValue = QInputDialog::getItem(
this, action.c_str(), action.c_str(), qStringList,
2235 uiMan->ApplyCommand(
"/vis/set/touchable" + sceneTreeItem->
GetPVPath());
2236 G4String g4ChosenValue = chosenValue.toStdString();
2237 uiMan->ApplyCommand(
"/vis/touchable/set/" + action +
' ' + g4ChosenValue);
2245QWidget* G4UIQt::CreateHistoryTBWidget()
2247 fHistoryTBWidget =
new QWidget();
2249 auto layoutHistoryTB =
new QVBoxLayout();
2250 fHistoryTBTableList =
new QListWidget();
2251 fHistoryTBTableList->setSelectionMode(QAbstractItemView::SingleSelection);
2252 connect(fHistoryTBTableList, SIGNAL(itemSelectionChanged()), SLOT(CommandHistoryCallback()));
2254 layoutHistoryTB->addWidget(fHistoryTBTableList);
2256 fHistoryTBWidget->setLayout(layoutHistoryTB);
2257 return fHistoryTBWidget;
2262QWidget* G4UIQt::CreateHelpTBWidget()
2264 fHelpTBWidget =
new QWidget();
2266 auto helpWidget =
new QWidget();
2267 auto helpLayout =
new QHBoxLayout();
2268 auto vLayout =
new QVBoxLayout();
2269 fHelpVSplitter =
new QSplitter(Qt::Vertical);
2270 fHelpLine =
new QLineEdit();
2271 helpLayout->addWidget(
new QLabel(
"Search :"));
2272 helpLayout->addWidget(fHelpLine);
2273 connect(fHelpLine, SIGNAL(editingFinished()),
this, SLOT(LookForHelpStringCallback()));
2278 fParameterHelpLabel =
new QTextEdit();
2279 fParameterHelpLabel->setReadOnly(
true);
2280 fParameterHelpTable =
new QTableWidget();
2284 if (fHelpTreeWidget !=
nullptr) {
2285 fHelpVSplitter->addWidget(fHelpTreeWidget);
2286 fHelpVSplitter->setStretchFactor(0,4);
2288 fHelpVSplitter->addWidget(fParameterHelpLabel);
2289 fHelpVSplitter->addWidget(fParameterHelpTable);
2291 fParameterHelpLabel->setVisible(
false);
2292 fParameterHelpTable->setVisible(
false);
2293 QSizePolicy policy = QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
2294 policy.setVerticalStretch(1);
2295 fParameterHelpLabel->setSizePolicy(policy);
2296 fParameterHelpTable->setSizePolicy(policy);
2298 vLayout->addWidget(helpWidget);
2299 vLayout->addWidget(fHelpVSplitter, 1);
2300 vLayout->setContentsMargins(5, 5, 5, 5);
2302 helpWidget->setLayout(helpLayout);
2303 fHelpTBWidget->setLayout(vLayout);
2305 return fHelpTBWidget;
2312 auto cm2ns = [](
double scale)
2313 {
return std::pow(10., std::floor(std::log10((scale*cm/c_light)/
ns)));};
2316 double detectorScale = 100.;
2317 double detectorTimescaleNano = cm2ns(detectorScale);
2320 double timeSliceInterval = detectorTimescaleNano/100;
2321 double timeSliceIntervalSpinBoxSingleStep = detectorTimescaleNano/100.;
2322 double timeSliceIntervalSpinBoxMaximum = detectorTimescaleNano*100;
2325 double duration = detectorTimescaleNano/10;
2326 const double durationSpinBoxSingleStep = detectorTimescaleNano/10.;
2327 const double durationSpinBoxMaximum = detectorTimescaleNano*1000;
2330 double startTime = 0.;
2331 double timeSliderValue = 0.;
2332 double timeSliderMinimum = 0.;
2333 double timeSliderMaximum = detectorTimescaleNano;
2334 double timeSliderIncrement = detectorTimescaleNano/100;
2335 double timeSliderIncrementSpinBoxSingleStep = detectorTimescaleNano/100.;
2336 double timeSliderIncrementSpinBoxMaximum = detectorTimescaleNano;
2339 const double spinBoxSingleStep = detectorTimescaleNano/10.;
2340 const double spinBoxMaximum = detectorTimescaleNano*1000;
2343QWidget* G4UIQt::CreateTimeWindowWidget()
2346 const int topMargins = 5;
2347 const int panelLeftRightMargins = 5;
2348 const int panelTopBottomMargins = 0;
2351 fTimeWindowWidget =
new QWidget;
2352 auto topLayout =
new QVBoxLayout(fTimeWindowWidget);
2353 topLayout->setContentsMargins(topMargins, topMargins, topMargins, topMargins);
2356 auto timeSliceIntervalSpinBox =
new QDoubleSpinBox;
2357 auto durationSpinBox =
new QDoubleSpinBox;
2358 auto timeSliderIncrementSpinBox =
new QDoubleSpinBox;
2359 auto timeSliderMinSpinBox =
new QDoubleSpinBox;
2360 auto timeSliderMaxSpinBox =
new QDoubleSpinBox;
2361 auto timeSliderValueSpinBox =
new QDoubleSpinBox;
2364 auto header =
new QLabel;
2365 header->setAlignment(Qt::AlignHCenter);
2366 header->setText(
"Time window control");
2367 topLayout->addWidget(header);
2371 auto prepareEventsPanel =
new QLabel;
2372 prepareEventsPanel->setFrameStyle(QFrame::Panel);
2373 auto prepareEventsLayout =
new QVBoxLayout(prepareEventsPanel);
2374 prepareEventsLayout->setContentsMargins
2375 (panelLeftRightMargins, panelTopBottomMargins, panelLeftRightMargins, panelTopBottomMargins);
2376 topLayout->addWidget(prepareEventsPanel);
2377 topLayout->setStretchFactor(prepareEventsPanel, 10);
2381 static int nEvents = 1;
2384 auto prepareTitle =
new QLabel;
2385 prepareTitle->setFixedHeight(20);
2386 prepareTitle->setAlignment(Qt::AlignHCenter);
2387 prepareTitle->setText(
"Prepare event(s)");
2388 prepareEventsLayout->addWidget(prepareTitle);
2392 auto widget =
new QWidget;
2393 auto layout =
new QHBoxLayout(widget);
2394 layout->setContentsMargins(0,0,0,0);
2395 auto label =
new QLabel;
2396 label->setText(
"Detector scale");
2397 layout->addWidget(label);
2398 auto spinBox =
new QDoubleSpinBox;
2399 spinBox->setRange(0., detectorScale*1000);
2400 spinBox->setValue(detectorScale);
2401 spinBox->setSingleStep(detectorScale/10.);
2402 spinBox->setSuffix(
" cm");
2404 (
"This is rough guidance for the default values of"
2405 "\nsome of the parameters below, so that they better"
2406 "\ncorrespond to the physical dimensions of the detector."
2407 "\nIt sets the default values, but you can still make"
2408 "\nyour own adjustments.");
2409 layout->addWidget(spinBox);
2410 prepareEventsLayout->addWidget(widget);
2411 connect(spinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [=](
double scale){
2412 detectorTimescaleNano = cm2ns(scale);
2414 timeSliceInterval = detectorTimescaleNano/100;
2415 timeSliceIntervalSpinBox->setRange(0., timeSliceIntervalSpinBoxMaximum);
2416 timeSliceIntervalSpinBox->setSingleStep(timeSliceInterval);
2417 timeSliceIntervalSpinBox->setValue(timeSliceInterval);
2419 duration = detectorTimescaleNano/10.;
2420 durationSpinBox->setRange(0., detectorTimescaleNano*100.);
2421 durationSpinBox->setSingleStep(detectorTimescaleNano/100.);
2422 durationSpinBox->setValue(duration);
2424 timeSliderIncrementSpinBox->setRange(0., detectorTimescaleNano/100.);
2425 timeSliderIncrementSpinBox->setValue(detectorTimescaleNano/100.);
2427 timeSliderMaxSpinBox->setRange(0., detectorTimescaleNano);
2428 timeSliderMaxSpinBox->setSingleStep(detectorTimescaleNano/10.);
2429 timeSliderMaxSpinBox->setValue(detectorTimescaleNano);
2434 auto widget =
new QWidget;
2435 auto layout =
new QHBoxLayout(widget);
2436 layout->setContentsMargins(0,0,0,0);
2437 auto label =
new QLabel;
2438 label->setText(
"Number of events");
2439 layout->addWidget(label);
2440 auto spinBox =
new QSpinBox;
2441 spinBox->setRange(1, 9999);
2442 layout->addWidget(spinBox);
2443 prepareEventsLayout->addWidget(widget);
2444 connect(spinBox, QOverload<int>::of(&QSpinBox::valueChanged), [](
int n){
2450 auto widget =
new QWidget;
2451 auto layout =
new QHBoxLayout(widget);
2452 layout->setContentsMargins(0,0,0,0);
2453 auto label =
new QLabel;
2454 label->setText(
"Time slice interval");
2455 layout->addWidget(label);
2456 timeSliceIntervalSpinBox->setRange(0., timeSliceIntervalSpinBoxMaximum);
2457 timeSliceIntervalSpinBox->setValue(timeSliceInterval);
2458 timeSliceIntervalSpinBox->setSingleStep(timeSliceIntervalSpinBoxSingleStep);
2459 timeSliceIntervalSpinBox->setDecimals(3);
2460 timeSliceIntervalSpinBox->setSuffix(
" ns");
2461 timeSliceIntervalSpinBox->setToolTip
2462 (
"This should be about 1/100 of the time taken for"
2463 "\nlight to travel across the field of view.");
2464 layout->addWidget(timeSliceIntervalSpinBox);
2465 prepareEventsLayout->addWidget(widget);
2466 connect(timeSliceIntervalSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
2468 timeSliceInterval = dt;
2474 auto button =
new QPushButton(
"Prepare");
2475 prepareEventsLayout->addWidget(button);
2477 (
"Or do it yourself. You will need:"
2478 "\n /vis/scene/add/trajectories rich"
2479 "\nCreate a trajectories model, then"
2480 "\n /vis/modeling/trajectories/<model-name>/default/setTimeSliceInterval 0.01 ns"
2481 "\nthen set colours, step points, linewidth, etc., as desired,"
2482 "\nand /run/beamOn one or more events."
2484 connect(button, &QPushButton::clicked,
this, [](){
2486 ui->ApplyCommand(
"/vis/scene/add/trajectories rich");
2487 static G4int modelNo = 0;
2490 (
"/vis/modeling/trajectories/create/drawByCharge " + modelName);
2492 (
"/vis/modeling/trajectories/" + modelName +
"/default/setTimeSliceInterval "
2495 (
"/vis/modeling/trajectories/" + modelName +
"/default/setLineWidth 5");
2497 (
"/vis/modeling/trajectories/" + modelName +
"/default/setDrawStepPts true");
2499 (
"/vis/modeling/trajectories/" + modelName +
"/default/setStepPtsSize 10");
2501 (
"/vis/modeling/trajectories/" + modelName +
"/default/setStepPtsFillStyle filled");
2503 (
"/vis/modeling/trajectories/" + modelName +
"/default/setDrawAuxPts true");
2505 (
"/vis/modeling/trajectories/" + modelName +
"/default/setAuxPtsSize 10");
2507 (
"/vis/modeling/trajectories/" + modelName +
"/default/setAuxPtsFillStyle filled");
2514 auto spacer =
new QWidget;
2515 prepareEventsLayout->addWidget(spacer);
2516 prepareEventsLayout->setStretchFactor(spacer, 1);
2522 auto timeParametersPanel =
new QLabel;
2523 timeParametersPanel->setFrameStyle(QFrame::Panel);
2524 auto timeParametersLayout =
new QVBoxLayout(timeParametersPanel);
2525 timeParametersLayout->setContentsMargins
2526 (panelLeftRightMargins, panelTopBottomMargins, panelLeftRightMargins, panelTopBottomMargins);
2527 topLayout->addWidget(timeParametersPanel);
2528 topLayout->setStretchFactor(timeParametersPanel, 10);
2529 auto startTimeSpinBox =
new QDoubleSpinBox;
2534 auto header =
new QLabel;
2535 header->setFixedHeight(20);
2536 header->setAlignment(Qt::AlignHCenter);
2537 header->setText(
"Time parameters");
2538 timeParametersLayout->addWidget(header);
2542 auto widget =
new QWidget;
2543 auto layout =
new QHBoxLayout(widget);
2544 layout->setContentsMargins(0,0,0,0);
2545 auto label =
new QLabel;
2546 label->setText(
"Start time");
2547 layout->addWidget(label);
2548 startTimeSpinBox->setRange(0., spinBoxMaximum);
2549 startTimeSpinBox->setSingleStep(spinBoxSingleStep);
2550 startTimeSpinBox->setDecimals(3);
2551 startTimeSpinBox->setSuffix(
" ns");
2552 startTimeSpinBox->setToolTip(
"Start of time window");
2553 layout->addWidget(startTimeSpinBox);
2554 timeParametersLayout->addWidget(widget);
2555 connect(startTimeSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
2559 ui->ApplyCommand(
"/vis/viewer/set/timeWindow/startTime "
2566 auto widget =
new QWidget;
2567 auto layout =
new QHBoxLayout(widget);
2568 layout->setContentsMargins(0,0,0,0);
2569 auto label =
new QLabel;
2570 label->setText(
"Duration");
2571 layout->addWidget(label);
2572 durationSpinBox->setRange(0., durationSpinBoxMaximum);
2573 durationSpinBox->setValue(duration);
2574 durationSpinBox->setSingleStep(durationSpinBoxSingleStep);
2575 durationSpinBox->setDecimals(3);
2576 durationSpinBox->setSuffix(
" ns");
2577 durationSpinBox->setToolTip
2578 (
"Duration of time window, typically"
2579 "\n10x the time slice interval.");
2580 layout->addWidget(durationSpinBox);
2581 timeParametersLayout->addWidget(widget);
2582 connect(durationSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
2586 ui->ApplyCommand(
"/vis/viewer/set/timeWindow/startTime "
2593 auto widget =
new QWidget;
2594 auto layout =
new QHBoxLayout(widget);
2595 layout->setContentsMargins(0,0,0,0);
2596 auto label =
new QLabel;
2597 label->setText(
"Fade factor");
2598 layout->addWidget(label);
2599 auto spinBox =
new QDoubleSpinBox;
2600 spinBox->setRange(0., 1.);
2601 spinBox->setValue(1.);
2602 spinBox->setSingleStep(spinBoxSingleStep);
2604 (
"Factor by which time-sliced objects fade over"
2605 "\nthe duration of the window, giving an impression"
2606 "\nof direction of motion.");
2607 layout->addWidget(spinBox);
2608 timeParametersLayout->addWidget(widget);
2609 connect(spinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [](
double f){
2611 ui->ApplyCommand(
"/vis/viewer/set/timeWindow/fadeFactor " +
2617 auto widget =
new QRadioButton(
"Display head time");
2618 widget->setChecked(
false);
2620 (
"Displays the time corresponding to end/head of"
2621 "\nthe time window. The font size, position and"
2622 "\ncolour can be set with /vis/viewer/set/timeWindow/");
2623 timeParametersLayout->addWidget(widget);
2624 connect(widget, &QRadioButton::clicked, [=](){
2625 G4String checked =
"false";
2626 if (widget->isChecked()) checked =
"true";
2628 ui->ApplyCommand(
"/vis/viewer/set/timeWindow/displayHeadTime " + checked);
2633 auto button =
new QPushButton(
"Apply");
2634 button->setToolTip(
"Applies the above settings");
2635 timeParametersLayout->addWidget(button);
2636 connect(button, &QPushButton::clicked,
this, [](){
2638 ui->ApplyCommand(
"/vis/viewer/set/timeWindow/startTime "
2645 auto spacer =
new QWidget;
2646 timeParametersLayout->addWidget(spacer);
2647 timeParametersLayout->setStretchFactor(spacer, 1);
2653 auto timeEvolutionPanel =
new QLabel;
2654 timeEvolutionPanel->setFrameStyle(QFrame::Panel);
2655 auto timeEvolutionLayout =
new QVBoxLayout(timeEvolutionPanel);
2656 timeEvolutionLayout->setContentsMargins
2657 (panelLeftRightMargins, panelTopBottomMargins, panelLeftRightMargins, panelTopBottomMargins);
2658 topLayout->addWidget(timeEvolutionPanel);
2659 topLayout->setStretchFactor(timeEvolutionPanel, 15);
2663 const int sliderIntMaximum = 1000;
2664 const int sliderIntTickInterval = 100;
2665 static int sliderIntValue = 0;
2666 static double desiredfps = 10.;
2667 static G4bool stopRun =
false;
2668 auto timeEvolutionSlider =
new QSlider(Qt::Horizontal);
2671 auto header =
new QLabel;
2672 header->setFixedHeight(20);
2673 header->setAlignment(Qt::AlignHCenter);
2674 header->setText(
"Time evolution");
2675 timeEvolutionLayout->addWidget(header);
2679 auto widget =
new QWidget;
2680 auto layout =
new QHBoxLayout(widget);
2681 layout->setContentsMargins(0,0,0,0);
2682 auto label =
new QLabel;
2683 label->setText(
"Increment");
2684 layout->addWidget(label);
2685 timeSliderIncrementSpinBox->setRange(0., timeSliderIncrementSpinBoxMaximum);
2686 timeSliderIncrementSpinBox->setValue(timeSliderIncrement);
2687 timeSliderIncrementSpinBox->setSingleStep(timeSliderIncrementSpinBoxSingleStep);
2688 timeSliderIncrementSpinBox->setDecimals(3);
2689 timeSliderIncrementSpinBox->setSuffix(
" ns");
2690 timeSliderIncrementSpinBox->setToolTip(
"Time step of the time evolution sequence");
2691 layout->addWidget(timeSliderIncrementSpinBox);
2692 timeEvolutionLayout->addWidget(widget);
2693 connect(timeSliderIncrementSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
2695 timeSliderIncrement = inc;
2700 auto widget =
new QWidget;
2701 auto layout =
new QHBoxLayout(widget);
2702 layout->setContentsMargins(0,0,0,0);
2703 timeEvolutionLayout->addWidget(widget);
2704 auto label1 =
new QLabel(
"min");
2705 label1->setAlignment(Qt::AlignBottom | Qt::AlignHCenter);
2706 layout->addWidget(label1);
2707 auto label2 =
new QLabel(
"value");
2708 label2->setAlignment(Qt::AlignBottom | Qt::AlignHCenter);
2709 layout->addWidget(label2);
2710 auto label3 =
new QLabel(
"max");
2711 label3->setAlignment(Qt::AlignBottom | Qt::AlignHCenter);
2712 layout->addWidget(label3);
2716 auto widget =
new QWidget;
2717 auto layout =
new QHBoxLayout(widget);
2718 layout->setContentsMargins(0,0,0,0);
2719 timeEvolutionLayout->addWidget(widget);
2720 timeSliderMinSpinBox->setRange(0., spinBoxMaximum);
2721 timeSliderMinSpinBox->setSingleStep(spinBoxSingleStep);
2722 timeSliderMinSpinBox->setDecimals(3);
2723 timeSliderMinSpinBox->setSuffix(
" ns");
2724 layout->addWidget(timeSliderMinSpinBox);
2725 connect(timeSliderMinSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
2727 timeSliderMinimum = smin;
2729 timeSliderValueSpinBox->setRange(0., spinBoxMaximum);
2730 timeSliderValueSpinBox->setSingleStep(spinBoxSingleStep);
2731 timeSliderValueSpinBox->setDecimals(3);
2732 timeSliderValueSpinBox->setSuffix(
" ns");
2733 layout->addWidget(timeSliderValueSpinBox);
2734 connect(timeSliderValueSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
2736 timeSliderValue = sv;
2738 timeSliderMaxSpinBox->setRange(0., spinBoxMaximum);
2739 timeSliderMaxSpinBox->setSingleStep(spinBoxSingleStep);
2740 timeSliderMaxSpinBox->setValue(timeSliderMaximum);
2741 timeSliderMaxSpinBox->setDecimals(3);
2742 timeSliderMaxSpinBox->setSuffix(
" ns");
2743 layout->addWidget(timeSliderMaxSpinBox);
2744 connect(timeSliderMaxSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
2746 timeSliderMaximum = smax;
2751 timeEvolutionSlider->setMaximum(sliderIntMaximum);
2752 timeEvolutionSlider->setMinimum(0);
2753 timeEvolutionSlider->setTickPosition(QSlider::TicksAbove);
2754 timeEvolutionSlider->setTickInterval(sliderIntTickInterval);
2755 timeEvolutionSlider->setToolTip
2756 (
"Move time window. Click on a position or slide"
2757 "\nwith middle button/3-finger pad gesture.");
2758 timeEvolutionLayout->addWidget(timeEvolutionSlider);
2759 connect(timeEvolutionSlider, &QSlider::valueChanged, [=](
int value){
2760 sliderIntValue = value;
2761 startTime = timeSliderMinimum
2762 + sliderIntValue * (timeSliderMaximum - timeSliderMinimum) / sliderIntMaximum;
2763 startTimeSpinBox->setValue(startTime);
2764 timeSliderValueSpinBox->setValue(startTime);
2767 auto keepVerbose = ui->GetVerboseLevel();
2768 ui->SetVerboseLevel(0);
2769 ui->ApplyCommand(
"/vis/viewer/set/timeWindow/startTime "
2772 ui->SetVerboseLevel(keepVerbose);
2774 connect(timeEvolutionSlider, &QSlider::sliderReleased, [=](){
2775 sliderIntValue = timeEvolutionSlider->value();
2776 startTime = timeSliderMinimum
2777 + sliderIntValue * (timeSliderMaximum - timeSliderMinimum) / sliderIntMaximum;
2778 startTimeSpinBox->setValue(startTime);
2779 timeSliderValueSpinBox->setValue(startTime);
2781 ui->ApplyCommand(
"/vis/viewer/set/timeWindow/startTime "
2785 connect(timeEvolutionSlider, &QSlider::sliderPressed, [=](){
2787 sliderIntValue = timeEvolutionSlider->value();
2788 startTime = timeSliderMinimum
2789 + sliderIntValue * (timeSliderMaximum - timeSliderMinimum) / sliderIntMaximum;
2790 startTimeSpinBox->setValue(startTime);
2795 auto widget =
new QWidget;
2796 auto layout =
new QHBoxLayout(widget);
2797 layout->setContentsMargins(0,0,0,0);
2798 auto label =
new QLabel;
2799 label->setText(
"Desired fps");
2800 layout->addWidget(label);
2801 auto fpsSpinBox =
new QDoubleSpinBox;
2802 fpsSpinBox->setRange(1., 99.);
2803 fpsSpinBox->setSingleStep(1.);
2804 fpsSpinBox->setValue(10.);
2805 fpsSpinBox->setSuffix(
" fps");
2806 fpsSpinBox->setToolTip
2807 (
"Desired frames per second. Since re-rendering each"
2808 "\nframe is CPU-intensive, this might not be achieved.");
2809 layout->addWidget(fpsSpinBox);
2810 timeEvolutionLayout->addWidget(widget);
2811 connect(fpsSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
2818 auto button =
new QPushButton(
"Go");
2819 button->setToolTip(
"Run the time evolution sequence");
2820 timeEvolutionLayout->addWidget(button);
2821 connect(button, &QPushButton::clicked, [=](){
2824 auto keepVerbose = ui->GetVerboseLevel();
2825 ui->SetVerboseLevel(0);
2826 for (startTime = timeSliderMinimum;
2827 startTime <= timeSliderMaximum; startTime += timeSliderIncrement) {
2829 auto a = std::chrono::steady_clock::now();
2830 startTimeSpinBox->setValue(startTime);
2831 timeSliderValueSpinBox->setValue(startTime);
2832 sliderIntValue = sliderIntMaximum
2833 * (startTime - timeSliderMinimum) / (timeSliderMaximum - timeSliderMinimum);
2834 timeEvolutionSlider->setValue(sliderIntValue);
2835 ui->ApplyCommand(
"/vis/viewer/set/timeWindow/startTime "
2838 auto b = std::chrono::steady_clock::now();
2839 auto timeTaken = b - a;
2840 auto desiredTime = std::chrono::duration<double>(1./desiredfps);
2841 auto timeLeft = desiredTime - timeTaken;
2842 if (timeLeft > std::chrono::duration<double>::zero()) {
2843 std::this_thread::sleep_for(timeLeft);
2847 ui->SetVerboseLevel(keepVerbose);
2852 auto spacer =
new QWidget;
2853 timeEvolutionLayout->addWidget(spacer);
2854 timeEvolutionLayout->setStretchFactor(spacer, 1);
2860 auto header =
new QLabel;
2861 header->setAlignment(Qt::AlignHCenter);
2863 (
"Further time window commands are"
2864 "\navailable in /vis/viewer/set/timeWindow/."
2865 "\n\nYou can capture views, including"
2866 "\nrotation and zooming, with /vis/viewer/save,"
2867 "\nand play back with /vis/viewer/interpolate."
2868 "\n\nSee examples/extended/visualization/movies.");
2869 topLayout->addWidget(header);
2873 auto spacer =
new QWidget;
2874 topLayout->addWidget(spacer);
2875 topLayout->setStretchFactor(spacer, 1);
2878 return fTimeWindowWidget;
2883G4UIDockWidget* G4UIQt::CreateCoutTBWidget()
2885 auto coutTBWidget =
new QWidget();
2887 auto layoutCoutTB =
new QVBoxLayout();
2889 fCoutTBTextArea =
new QTextEdit();
2891 fCoutFilter =
new QLineEdit();
2892 fCoutFilter->setToolTip(
"Filter output by...");
2894 fCoutFilter->addAction(*fSearchIcon, QLineEdit::TrailingPosition);
2895 fCoutFilter->setStyleSheet(
"border-radius:7px;");
2897 auto coutTBClearButton =
new QPushButton();
2898 coutTBClearButton->setIcon(*fClearIcon);
2899 coutTBClearButton->setToolTip(
"Clear console output");
2900 coutTBClearButton->setStyleSheet(
"border-radius:7px;");
2901 connect(coutTBClearButton, SIGNAL(clicked()), SLOT(ClearButtonCallback()));
2903 fCoutFilter, SIGNAL(textEdited(
const QString&)), SLOT(CoutFilterCallback(
const QString&)));
2905 auto coutTBSaveOutputButton =
new QPushButton();
2906 coutTBSaveOutputButton->setIcon(*fSaveIcon);
2907 coutTBSaveOutputButton->setToolTip(
"Save console output");
2908 coutTBSaveOutputButton->setStyleSheet(
"border-radius:7px;");
2909 connect(coutTBSaveOutputButton, SIGNAL(clicked()), SLOT(SaveOutputCallback()));
2911 fCoutTBTextArea->setReadOnly(
true);
2913 auto coutButtonWidget =
new QWidget();
2914 auto layoutCoutTBButtons =
new QHBoxLayout();
2916#ifdef G4MULTITHREADED
2918 fThreadsFilterComboBox =
new QComboBox();
2919 fThreadsFilterComboBox->setInsertPolicy(QComboBox::InsertAlphabetically);
2921 fThreadsFilterComboBox, SIGNAL(activated(
int)),
this, SLOT(ThreadComboBoxCallback(
int)));
2923 UpdateCoutThreadFilter();
2925 fThreadsFilterComboBox->setToolTip(
"Thread selection in output");
2926 layoutCoutTBButtons->addWidget(
new QLabel(
" Threads:"));
2927 layoutCoutTBButtons->addWidget(fThreadsFilterComboBox);
2930 layoutCoutTBButtons->addWidget(fCoutFilter);
2931 layoutCoutTBButtons->addWidget(coutTBClearButton);
2932 layoutCoutTBButtons->addWidget(coutTBSaveOutputButton);
2933 coutButtonWidget->setLayout(layoutCoutTBButtons);
2936 layoutCoutTBButtons->setContentsMargins(3, 3, 3, 0);
2938 layoutCoutTB->addWidget(coutButtonWidget);
2939 layoutCoutTB->addWidget(fCoutTBTextArea);
2941 coutTBWidget->setLayout(layoutCoutTB);
2943 fCoutTBTextArea->setMinimumSize(100, 100);
2946 auto commandLineWidget =
new QWidget();
2947 auto layoutCommandLine =
new QHBoxLayout();
2951 fCommandLabel =
new QLabel(
"");
2952 fCommandArea =
new QLineEdit();
2956 fCommandArea->activateWindow();
2958 fCommandArea->setFocusPolicy(Qt::StrongFocus);
2959 fCommandArea->setFocus(Qt::TabFocusReason);
2960 fCommandArea->setToolTip(
"Apply command");
2962 layoutCommandLine->addWidget(fCommandLabel);
2963 layoutCommandLine->addWidget(fCommandArea);
2966 connect(fCommandArea, SIGNAL(returnPressed()), SLOT(CommandEnteredCallback()));
2968 fCommandArea, SIGNAL(textEdited(
const QString&)), SLOT(CommandEditedCallback(
const QString&)));
2970 commandLineWidget->setLayout(layoutCommandLine);
2971 commandLineWidget->setMinimumSize(50, 50);
2973 layoutCoutTB->addWidget(commandLineWidget);
2975 fCoutDockWidget =
new G4UIDockWidget(
"Output");
2976 fCoutDockWidget->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
2978 fCoutDockWidget->setWidget(coutTBWidget);
2979 return fCoutDockWidget;
2984QWidget* G4UIQt::CreateVisParametersTBWidget() {
return nullptr; }
2988G4UIDockWidget* G4UIQt::CreateUITabWidget()
2990 fUITabWidget =
new QTabWidget();
2993 fUITabWidget->addTab(CreateSceneTreeWidget(),
"Scene tree");
2994 fUITabWidget->addTab(CreateHelpTBWidget(),
"Help");
2995 fUITabWidget->addTab(CreateTimeWindowWidget(),
"Time");
2996 fUITabWidget->addTab(CreateHistoryTBWidget(),
"History");
2997 fUITabWidget->setCurrentWidget(fHelpTBWidget);
2999 fUITabWidget->setTabToolTip(0,
"Tree of scene items");
3000 fUITabWidget->setTabToolTip(1,
"Help widget");
3001 fUITabWidget->setTabToolTip(2,
"Time window widdget");
3002 fUITabWidget->setTabToolTip(3,
"All commands history");
3003 connect(fUITabWidget, SIGNAL(currentChanged(
int)), SLOT(ToolBoxActivated(
int)));
3005 fUIDockWidget =
new G4UIDockWidget(
"");
3006 fUIDockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
3008 fUIDockWidget->setWidget(fUITabWidget);
3010 return fUIDockWidget;
3013QWidget* G4UIQt::CreateSceneTreeWidget()
3015 fSceneTreeWidget =
new QWidget();
3016 auto layout =
new QVBoxLayout();
3017 fSceneTreeWidget->setLayout(layout);
3019 fSceneTreeWidget->setVisible(
false);
3021 return fSceneTreeWidget;
3024void G4UIQt::CreateViewerWidget()
3030 (
"<table width='100%'>"
3032 "<td width='30%'></td>"
3034 "<div style='color: rgb(140, 31, 31); font-size: xx-large;"
3035 "font-family: Garamond, serif; padding-bottom: 0px; font-weight: normal'>"
3036 "Geant4: "+QApplication::applicationName ().toStdString()+
3038 "</td><td width='40%'> <br/><i>http://cern.ch/geant4/</i></td>"
3047 "<div style='background:#EEEEEE;'>"
3050 "<li><b>Start a new viewer :</b><br />"
3051 "<i>'/vis/open/...', for example '/vis/open OGL'</i>"
3053 "<li><b>Draw the detector :</b><br />"
3054 "<i>'/vis/drawVolume'</i>"
3056 "<li><b>Execute a macro file :</b><br />"
3057 "<i>'/control/execute my_macro_file'</i>"
3059 "<li><b>Interacting with the viewer :</b><br />"
3061 "Different viewers may behave somewhat differently, but the table gives a guide."
3068 "<div style='background:#EEEEEE;'><br><br>"
3069 "<table border=\"1\">"
3070 "<tr><th>Action</th><th>Mouse actions</th><th>Trackpad actions</th></tr>"
3073 "<td>left-button-press move or middle-button-move</td>"
3074 "<td>one-finger-press-move or three-finger-move</td>"
3076 "<tr><td>Zoom</td><td>right-button-move</td><td>two-finger-move</td></tr>"
3077 "<tr><td>Zoom to cursor</td><td>SHIFT-Zoom</td><td>SHIFT-Zoom</td></tr>"
3078 "<tr><td>Pan</td><td>SHIFT-Rotate</td><td>SHIFT-Rotate</td></tr>"
3085 "<div style='background:#EEEEEE;'>"
3086 "<b>Documentation :</b>"
3088 "<li><b>Visualisation publication :</b><br />"+
3090 "<a href='https://doi.org/10.48550/arXiv.1212.6923'>"
3091 "The Geant4 Visualisation System - A Multi-Driver Graphics System</b><br />"
3092 "Allison, J. et al., International Journal of Modeling, Simulation,"
3093 " and Scientific Computing, Vol. 4, Suppl. 1 (2013) 1340001"
3094 "</a><br/>http://www.worldscientific.com/doi/abs/10.1142/S1793962313400011"
3100 "<div style='background:#EEEEEE;'>"
3101 "<b>Getting Help :</b>"
3105 "If problems arise, try "
3106 "<a href='https://cern.ch/geant4-forum'>"
3107 "browsing the user forum"
3109 "to see whether or not your problem has already been encountered.<br />"
3110 "If it hasn't, you can post it and Geant4 developers will do their best to find"
3111 " a solution. This is also a good place to<br />"
3112 "discuss Geant4 topics in general."
3114 " https://cern.ch/geant4-forum"
3122 if (fViewerTabWidget ==
nullptr) {
3123#if QT_VERSION < 0x060000
3124 fViewerTabWidget =
new G4QTabWidget();
3126 fViewerTabWidget =
new QTabWidget();
3128 fMainWindow->setCentralWidget(fViewerTabWidget);
3129 fViewerTabWidget->setTabsClosable(
true);
3131 fViewerTabWidget->setUsesScrollButtons(
true);
3133 connect(fViewerTabWidget, SIGNAL(tabCloseRequested(
int)),
this, SLOT(TabCloseCallback(
int)));
3134#if QT_VERSION < 0x060000
3135 connect(fViewerTabWidget, SIGNAL(currentChanged(
int)), SLOT(UpdateTabWidget(
int)));
3137 connect(fViewerTabWidget, SIGNAL(currentChanged(
int)),
this, SLOT(UpdateTabWidget(
int)));
3142 QSizePolicy policy = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
3143 policy.setVerticalStretch(4);
3144 fViewerTabWidget->setSizePolicy(policy);
3146 fViewerTabWidget->setMinimumSize(40, 40);
3157 if (fViewerPropertiesDialog ==
nullptr) {
3158 CreateViewerPropertiesDialog();
3160 return fViewerPropertiesWidget;
3167 if (fPickInfosDialog ==
nullptr) {
3168 CreatePickInfosDialog();
3170 return fPickInfosWidget;
3177 if (fViewerTabWidget ==
nullptr) {
3180 fViewerTabWidget->addTab(aWidget, title.c_str());
3189 if (fViewerTabWidget ==
nullptr) {
3194 if (UI ==
nullptr)
return false;
3195 std::ifstream file(UI->
FindMacroPath(fileName.c_str()).data());
3197 std::string content((std::istreambuf_iterator<char>(file)), (std::istreambuf_iterator<char>()));
3199 auto text =
new QTextEdit();
3200 text->setAcceptRichText(
true);
3201 text->setContentsMargins(5, 5, 5, 5);
3202 text->setText(QString(
"<pre>") + content.c_str() +
"</pre>");
3203 text->setReadOnly(
true);
3204 fViewerTabWidget->addTab(text, title.c_str());
3217#if QT_VERSION < 0x060000
3218 if (fViewerTabWidget ==
nullptr) {
3219 CreateViewerWidget();
3223 if (aWidget ==
nullptr) {
3226#if QT_VERSION < 0x060000
3228 aWidget->setParent(fViewerTabWidget);
3231 fViewerTabWidget->addTab(aWidget, name);
3233 fViewerTabWidget->setCurrentIndex(fViewerTabWidget->count() - 1);
3236 fViewerTabWidget->setLastTabCreated(fViewerTabWidget->currentIndex());
3242 QObject::disconnect(fViewerTabWidget, SIGNAL(currentChanged(
int)),
this, SLOT(UpdateTabWidget(
int)));
3243 fViewerTabWidget->addTab(aWidget, name);
3244 fViewerTabWidget->setCurrentIndex(fViewerTabWidget->count() - 1);
3245 QObject::connect(fViewerTabWidget, SIGNAL(currentChanged(
int)),
this, SLOT(UpdateTabWidget(
int)));
3258 if (! text.empty()) {
3259 fDefaultViewerFirstPageHTMLText = text;
3261 if (fStartPage ==
nullptr) {
3262 fStartPage =
new QTextBrowser();
3263 fStartPage->setContentsMargins(5, 5, 5, 5);
3264 fStartPage->setReadOnly(
true);
3266 fStartPage->setOpenExternalLinks(
true);
3267 fStartPage->setHtml(fDefaultViewerFirstPageHTMLText.c_str());
3270#if QT_VERSION < 0x060000
3271void G4UIQt::UpdateTabWidget(
int tabNumber)
3273 if (fViewerTabWidget ==
nullptr) {
3277 fViewerTabWidget->setCurrentIndex(tabNumber);
3280 fViewerTabWidget->setTabSelected(
false);
3282 fViewerTabWidget->setVisible(
true);
3285 fViewerTabWidget->setTabSelected(
true);
3288void G4UIQt::UpdateTabWidget(
int)
3293 if (fViewerTabWidget->currentWidget() !=
nullptr) {
3294 auto edit =
dynamic_cast<QTextEdit*
>(fViewerTabWidget->currentWidget());
3295 if (edit ==
nullptr) {
3296 QString text = fViewerTabWidget->tabText(fViewerTabWidget->currentIndex());
3297 QString paramSelect = QString(
"/vis/viewer/select ") + text;
3306void G4UIQt::ResizeTabWidget(QResizeEvent* e)
3308 if (fViewerTabWidget !=
nullptr) {
3309 for (
G4int a = 0; a < fViewerTabWidget->count(); a++) {
3310 fViewerTabWidget->widget(a)->resize(e->size());
3321 exitSession =
false;
3323 QCoreApplication::sendPostedEvents();
3325 fMainWindow->setVisible(
true);
3327 if (fDefaultIcons) {
3328 fToolbarApp->setVisible(
true);
3332 fToolbarApp->setVisible(
false);
3338 UpdateCommandCompleter();
3341 fHistoryTBTableList->installEventFilter(
this);
3342 fCommandArea->installEventFilter(
this);
3345 fCommandArea->setFocus();
3360 if (aPrompt ==
nullptr)
return;
3362 fCommandLabel->setText((
char*)aPrompt.data());
3368 fMainWindow->close();
3382 if (aState ==
nullptr)
return;
3384 if (aState ==
"G4_pause> ") {
3385 SecondaryLoop(
"Pause, type continue to exit this state");
3388 if (aState ==
"EndOfEvent") {
3390 SecondaryLoop(
"End of event, type continue to exit this state");
3398void G4UIQt::SecondaryLoop(
const G4String& aPrompt)
3400 if (aPrompt ==
nullptr)
return;
3406 ((QApplication*)interactorManager)->processEvents(QEventLoop::WaitForMoreEvents);
3407 if (exitPause)
break;
3412#ifdef G4MULTITHREADED
3428 if (aString.empty())
return 0;
3430#ifdef G4MULTITHREADED
3440#ifdef G4MULTITHREADED
3443 std::cout << aString << std::flush;
3454 for (
G4int i = 0; i < (
G4int)aString.length() - 1; ++i) {
3455 if (aString[i] ==
'\n') {
3456 aStringWithStyle +=
"<br>";
3458 else if (aString[i] ==
' ') {
3459 aStringWithStyle +=
" ";
3461 else if (aString[i] ==
'\t') {
3462 aStringWithStyle +=
" ";
3464 else if (aString[i] ==
'<') {
3465 aStringWithStyle +=
"<";
3468 aStringWithStyle += aString[i];
3472 aStringWithStyle =
"<span style='font-family:courier;'>" + aStringWithStyle +
"</span>";
3475 aStringWithStyle =
"<span>" + aStringWithStyle +
"</span>";
3480 G4UIOutputString(QString((
char*)aStringWithStyle.data()), GetThreadPrefix());
3481 fG4OutputString.push_back(txt);
3483#ifdef G4MULTITHREADED
3484 QString result = FilterOutput(txt, fThreadsFilterComboBox->currentText(), fCoutFilter->text());
3486 QString result = FilterOutput(txt,
"", fCoutFilter->text());
3489 if (result.isEmpty()) {
3495 result = QString(
"<span style='background:") + pal.link().color().name() +
";'> </span>" +
3496 "<span style='background: Pink;'> " + result +
"</span>";
3498 result = QString(
"<font color=\"Green\">") + result + QString(
"</font>");
3500 fCoutTBTextArea->append(result);
3501 fCoutTBTextArea->ensureCursorVisible();
3503#ifdef G4MULTITHREADED
3504 UpdateCoutThreadFilter();
3517 if (aString.empty())
return 0;
3525#ifdef G4MULTITHREADED
3535#ifdef G4MULTITHREADED
3538 std::cout << aString << std::flush;
3549 for (
G4int i = 0; i < (
G4int)aString.length() - 1; ++i) {
3550 if (aString[i] ==
'\n') {
3551 aStringWithStyle +=
"<br>";
3553 else if (aString[i] ==
' ') {
3554 aStringWithStyle +=
" ";
3556 else if (aString[i] ==
'\t') {
3557 aStringWithStyle +=
" ";
3559 else if (aString[i] ==
'<') {
3560 aStringWithStyle +=
"<";
3563 aStringWithStyle += aString[i];
3567 aStringWithStyle =
"<span style='font-family:courier;'>" + aStringWithStyle +
"</span>";
3570 aStringWithStyle =
"<span>" + aStringWithStyle +
"</span>";
3575 G4UIOutputString(QString((
char*)aStringWithStyle.data()), GetThreadPrefix());
3576 fG4OutputString.push_back(txt);
3578#ifdef G4MULTITHREADED
3579 QString result = FilterOutput(txt, fThreadsFilterComboBox->currentText(), fCoutFilter->text());
3581 QString result = FilterOutput(txt,
"", fCoutFilter->text());
3584 if (result.isEmpty()) {
3592 result = QString(
"<span style='background:") + pal.link().color().name() +
3593 ";'> </span>" +
"<span style='background:" + pal.highlight().color().name() +
3594 ";'> " + result +
"</span>";
3599 fCoutTBTextArea->append(result);
3600 fCoutTBTextArea->ensureCursorVisible();
3602#ifdef G4MULTITHREADED
3603 UpdateCoutThreadFilter();
3607 fLastErrMessage = aString;
3618 if (aString.empty())
return 0;
3620#ifdef G4MULTITHREADED
3630#ifdef G4MULTITHREADED
3633 std::cerr << aString << std::flush;
3644 for (
G4int i = 0; i < (
G4int)aString.length() - 1; ++i) {
3645 if (aString[i] ==
'\n') {
3646 aStringWithStyle +=
"<br>";
3648 else if (aString[i] ==
' ') {
3649 aStringWithStyle +=
" ";
3651 else if (aString[i] ==
'\t') {
3652 aStringWithStyle +=
" ";
3654 else if (aString[i] ==
'<') {
3655 aStringWithStyle +=
"<";
3658 aStringWithStyle += aString[i];
3662 aStringWithStyle =
"<span style='font-family:courier;'>" + aStringWithStyle +
"</span>";
3665 aStringWithStyle =
"<span>" + aStringWithStyle +
"</span>";
3671 G4UIOutputString(QString((
char*)aStringWithStyle.data()).trimmed(), GetThreadPrefix(),
"error");
3672 fG4OutputString.push_back(txt);
3674#ifdef G4MULTITHREADED
3675 QString result = FilterOutput(txt, fThreadsFilterComboBox->currentText(), fCoutFilter->text());
3677 QString result = FilterOutput(txt,
"", fCoutFilter->text());
3679 if (result.isEmpty()) {
3684 if (QString(aString.data()).trimmed() !=
"") {
3689 fLastErrMessage +=
"\n" + aString;
3690 QString criticalMessage = fLastErrMessage.data();
3691 criticalMessage = criticalMessage.toHtmlEscaped();
3692 QMessageBox::critical(fMainWindow,
"Error", QString(fLastErrMessage));
3695 fCoutTBTextArea->append(QString(
"<font color=\"Red\">") + result + QString(
"</font>"));
3696 fCoutTBTextArea->ensureCursorVisible();
3698 if (QString(aString.data()).trimmed() !=
"") {
3699 fLastErrMessage += aString;
3701#ifdef G4MULTITHREADED
3702 UpdateCoutThreadFilter();
3710#ifdef G4MULTITHREADED
3712 if (UI ==
nullptr)
return "";
3720 return threadPrefix;
3723#ifdef G4MULTITHREADED
3724void G4UIQt::UpdateCoutThreadFilter()
3727 if (UI ==
nullptr)
return;
3730 if (fThreadsFilterComboBox->count() < 2) {
3731 if (fThreadsFilterComboBox->findText(
"All", Qt::MatchExactly) == -1) {
3732 fThreadsFilterComboBox->addItem(
"All");
3735 if (fThreadsFilterComboBox->count() < 2) {
3736 if (fThreadsFilterComboBox->findText(
"Master", Qt::MatchExactly) == -1) {
3737 fThreadsFilterComboBox->addItem(
"Master");
3741 G4String prefix = GetThreadPrefix();
3742 if (! prefix.empty()) {
3743 if (fThreadsFilterComboBox->findText(prefix.data(), Qt::MatchExactly) == -1) {
3744 fThreadsFilterComboBox->addItem(prefix.data());
3757 if (aName ==
nullptr)
return;
3758 if (aLabel ==
nullptr)
return;
3760 auto fileMenu =
new QMenu(aLabel);
3761 fMainWindow->menuBar()->addMenu(fileMenu);
3774 if (aMenu ==
nullptr)
return;
3775 if (aLabel ==
nullptr)
return;
3776 if (aCommand ==
nullptr)
return;
3780 if (parentTmp ==
nullptr) {
3785 G4cout <<
"Menu name " << aMenu <<
" does not exist, please define it before using it."
3793 if (UI ==
nullptr)
return;
3797 std::size_t cmdEndPos = cmd.find_first_of(
" \t");
3798 if (cmdEndPos != std::string::npos) {
3799 cmd.erase(cmdEndPos);
3802 if (treeTop->
FindPath(cmd) ==
nullptr) {
3803 if (cmd !=
"ls" && cmd.substr(0, 3) !=
"ls " && cmd !=
"pwd" && cmd !=
"cd" &&
3804 cmd.substr(0, 3) !=
"cd " && cmd !=
"help" && cmd.substr(0, 5) !=
"help " &&
3805 cmd[0] !=
'?' && cmd !=
"hist" && cmd !=
"history" && cmd[0] !=
'!' && cmd !=
"exit" &&
3806 cmd !=
"cont" && cmd !=
"continue")
3812 G4cout <<
"Warning: command '" << cmd
3813 <<
"' does not exist, please define it before using it." <<
G4endl;
3818 QString cmd_tmp = QString(aCommand);
3819 parentTmp->addAction(aLabel,
this, [
this, cmd_tmp]() { this->ButtonCallback(cmd_tmp); });
3827 const char* aLabel,
const char* aIconFile,
const char* aCommand,
const char* aFileName)
3829 if (aLabel ==
nullptr)
return;
3831 if (aCommand ==
nullptr) {
3832 if (std::string(aIconFile) ==
"user_icon") {
3837 G4bool userToolBar =
false;
3839 if (! fDefaultIcons) {
3842 if (std::string(aIconFile) ==
"user_icon") {
3845 pix =
new QPixmap(UImanager->
FindMacroPath(aFileName).data());
3846 if (pix->isNull()) {
3850 G4cout <<
"Warning: file '" << aFileName
3851 <<
"' is incorrect or does not exist, this command will not be build" <<
G4endl;
3856 else if (std::string(aIconFile) ==
"open") {
3859 else if (std::string(aIconFile) ==
"save") {
3862 else if (std::string(aIconFile) ==
"move") {
3865 else if (std::string(aIconFile) ==
"rotate") {
3868 else if (std::string(aIconFile) ==
"pick") {
3871 else if (std::string(aIconFile) ==
"zoom_in") {
3874 else if (std::string(aIconFile) ==
"zoom_out") {
3877 else if (std::string(aIconFile) ==
"wireframe") {
3878 pix = fWireframeIcon;
3880 else if (std::string(aIconFile) ==
"solid") {
3883 else if (std::string(aIconFile) ==
"point_cloud") {
3884 pix = fPointCloudIcon;
3886 else if (std::string(aIconFile) ==
"hidden_line_removal") {
3887 pix = fHiddenLineRemovalIcon;
3889 else if (std::string(aIconFile) ==
"hidden_line_and_surface_removal") {
3890 pix = fHiddenLineAndSurfaceRemovalIcon;
3892 else if (std::string(aIconFile) ==
"perspective") {
3893 pix = fPerspectiveIcon;
3895 else if (std::string(aIconFile) ==
"ortho") {
3898 else if (std::string(aIconFile) ==
"runBeamOn") {
3901 else if (std::string(aIconFile) ==
"exit") {
3904 else if (std::string(aIconFile) ==
"reset_camera") {
3905 pix = fResetCameraIcon;
3907 else if (std::string(aIconFile) ==
"resetTargetPoint") {
3908 pix = fResetTargetPointIcon;
3915 G4cout <<
"Parameter" << aIconFile <<
" not defined" <<
G4endl;
3919 QToolBar* currentToolbar =
nullptr;
3921 if (fToolbarUser ==
nullptr) {
3922 fToolbarUser =
new QToolBar();
3923 fToolbarUser->setIconSize(QSize(20, 20));
3924 fMainWindow->addToolBar(Qt::TopToolBarArea, fToolbarUser);
3926 currentToolbar = fToolbarUser;
3929 if (fToolbarApp ==
nullptr) {
3930 fToolbarApp =
new QToolBar();
3931 fToolbarApp->setIconSize(QSize(20, 20));
3932 fMainWindow->addToolBar(Qt::TopToolBarArea, fToolbarApp);
3934 currentToolbar = fToolbarApp;
3939 QList<QAction*> list = currentToolbar->actions();
3941 for (
auto i : list) {
3942 if (i->text() == QString(aLabel)) {
3944 if (UI ==
nullptr)
return;
3947 G4cout <<
"Warning: A toolBar icon \"" << aLabel <<
"\" already exists with the same name!"
3954 if (std::string(aIconFile) ==
"open") {
3955 QString txt = aCommand + fStringSeparator + aLabel;
3956 currentToolbar->addAction(
3957 QIcon(*pix), aIconFile,
this, [
this, txt]() { this->OpenIconCallback(txt); });
3961 else if (std::string(aIconFile) ==
"save") {
3962 QString txt = aCommand + fStringSeparator + aLabel;
3963 currentToolbar->addAction(
3964 QIcon(*pix), aIconFile,
this, [
this, txt]() { this->SaveIconCallback(txt); });
3967 else if ((std::string(aIconFile) ==
"move") || (std::string(aIconFile) ==
"rotate") ||
3968 (std::string(aIconFile) ==
"pick") || (std::string(aIconFile) ==
"zoom_out") ||
3969 (std::string(aIconFile) ==
"zoom_in"))
3971 QString txt = QString(aIconFile);
3972 QAction* action = currentToolbar->addAction(
3973 QIcon(*pix), aIconFile,
this, [
this, txt]() { this->ChangeCursorAction(txt); });
3974 action->setCheckable(
true);
3975 action->setChecked(
false);
3976 action->setData(aIconFile);
3978 if (std::string(aIconFile) ==
"rotate") {
3984 else if ((std::string(aIconFile) ==
"hidden_line_removal") ||
3985 (std::string(aIconFile) ==
"hidden_line_and_surface_removal") ||
3986 (std::string(aIconFile) ==
"solid") ||
3987 (std::string(aIconFile) ==
"wireframe") ||
3988 (std::string(aIconFile) ==
"point_cloud"))
3990 QString txt = QString(aIconFile);
3991 QAction* action = currentToolbar->addAction(
3992 QIcon(*pix), aIconFile,
this, [
this, txt]() { this->ChangeSurfaceStyle(txt); });
3993 action->setCheckable(
true);
3994 action->setChecked(
true);
3995 action->setData(aIconFile);
4003 if (std::string(aIconFile) ==
"solid") {
4015 else if ((std::string(aIconFile) ==
"perspective") || (std::string(aIconFile) ==
"ortho")) {
4016 QString txt = QString(aIconFile);
4017 QAction* action = currentToolbar->addAction(
4018 QIcon(*pix), aIconFile,
this, [
this, txt]() { this->ChangePerspectiveOrtho(txt); });
4019 action->setCheckable(
true);
4020 action->setChecked(
true);
4021 action->setData(aIconFile);
4023 if (std::string(aIconFile) ==
"perspective") {
4026 if (std::string(aIconFile) ==
"ortho") {
4031 else if (std::string(aIconFile) ==
"reset_camera") {
4032 currentToolbar->addAction(QIcon(*pix), aIconFile,
this, [
this]() { this->ResetCameraCallback(); });
4037 if (UI ==
nullptr)
return;
4039 if (aCommand !=
nullptr) {
4040 std::string str = aCommand;
4041 std::string::size_type pos = str.find(
' ');
4042 if (pos != std::string::npos) {
4043 str = str.substr(0, pos).c_str();
4045 if (treeTop->
FindPath(str.c_str()) ==
nullptr) {
4050 G4cout <<
"Warning: command '" << aCommand
4051 <<
"' does not exist, please define it before using it." <<
G4endl;
4055 QString txt = QString(aCommand);
4056 currentToolbar->addAction(QIcon(*pix), aCommand,
this,
4057 [
this, txt]() { this->ButtonCallback(txt); });
4072 if (fMainWindow->menuBar()->isNativeMenuBar() == aVal)
return;
4075 fMainWindow->menuBar()->setNativeMenuBar(aVal);
4080void G4UIQt::ActivateCommand(
G4String newCommand)
4082 if (fHelpTreeWidget ==
nullptr) {
4086 std::size_t i = newCommand.find(
' ');
4087 G4String targetCom =
"";
4088 if (i != std::string::npos) {
4089 G4String newValue = newCommand.substr(i + 1, newCommand.length() - (i + 1));
4093 if (! targetCom.empty()) {
4094 OpenHelpTreeOnCommand(targetCom.data());
4097 fUITabWidget->setCurrentWidget(fHelpTBWidget);
4106void G4UIQt::InitHelpTreeAndVisParametersWidget()
4108 if (fHelpTreeWidget ==
nullptr) {
4109 fHelpTreeWidget =
new QTreeWidget();
4113 fHelpTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
4115 labels << QString(
"Command");
4116 fHelpTreeWidget->setHeaderLabels(labels);
4118 connect(fHelpTreeWidget, SIGNAL(itemSelectionChanged()),
this, SLOT(HelpTreeClicCallback()));
4119 connect(fHelpTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,
int)),
this,
4120 SLOT(HelpTreeDoubleClicCallback()));
4128void G4UIQt::FillHelpTree()
4130 if (fHelpTreeWidget ==
nullptr) {
4131 InitHelpTreeAndVisParametersWidget();
4134 QString searchText = fHelpLine->text();
4136 if (searchText ==
"") {
4144 if (fParameterHelpLabel !=
nullptr) {
4145 fParameterHelpLabel->setText(
"Choose a command in the command tree");
4146 fParameterHelpTable->setVisible(
false);
4149 if (fHelpLine !=
nullptr) {
4150 fHelpLine->setText(
"");
4154 if (UI ==
nullptr)
return;
4155 G4UIcommandTree* treeTop = UI->
GetTree();
4158 QTreeWidgetItem* newItem =
nullptr;
4159 QString commandText =
"";
4160 for (
G4int a = 0; a < treeSize; ++a) {
4164 commandText = QString((
char*)(treeTop->
GetTree(a + 1)->
GetPathName()).data()).trimmed();
4167 for (
G4int b = 0; b < fHelpTreeWidget->topLevelItemCount(); ++b) {
4168 if (newItem ==
nullptr) newItem = FindTreeItem(fHelpTreeWidget->topLevelItem(b), commandText);
4171 if (newItem ==
nullptr) {
4172 newItem =
new QTreeWidgetItem();
4173 newItem->setText(0, GetShortCommandPath(commandText));
4174 fHelpTreeWidget->addTopLevelItem(newItem);
4178 CreateHelpTree(newItem, treeTop->
GetTree(a + 1));
4186void G4UIQt::CreateHelpTree(QTreeWidgetItem* aParent, G4UIcommandTree* aCommandTree)
4188 if (aParent ==
nullptr)
return;
4189 if (aCommandTree ==
nullptr)
return;
4192 QTreeWidgetItem* newItem;
4194 QString commandText =
"";
4197 commandText = QString((
char*)(aCommandTree->
GetTree(a + 1)->
GetPathName()).data()).trimmed();
4200 newItem = FindTreeItem(aParent, commandText);
4201 if (newItem ==
nullptr) {
4202 newItem =
new QTreeWidgetItem();
4203 newItem->setText(0, GetShortCommandPath(commandText));
4204 aParent->addChild(newItem);
4206 CreateHelpTree(newItem, aCommandTree->
GetTree(a + 1));
4212 QStringList stringList;
4217 newItem = FindTreeItem(aParent, commandText);
4218 if (newItem ==
nullptr) {
4219 newItem =
new QTreeWidgetItem();
4220 newItem->setText(0, GetShortCommandPath(commandText));
4221 aParent->addChild(newItem);
4222 newItem->setExpanded(
false);
4232G4bool G4UIQt::CreateVisCommandGroupAndToolBox(
4233 G4UIcommand* aCommand, QWidget* aParent,
G4int aDepthLevel,
G4bool isDialog)
4235 QString commandText =
4236 QString((
char*)(aCommand->
GetCommandPath().data())).section(
"/", -aDepthLevel);
4238 if (commandText ==
nullptr) {
4244 QWidget* newParentWidget =
nullptr;
4246 QString commandSection = commandText.left(commandText.indexOf(
"/"));
4248 if (aDepthLevel == 1) {
4249 auto currentParent =
dynamic_cast<QToolBox*
>(aParent);
4250 if (currentParent !=
nullptr) {
4252 for (
G4int a = 0; a < currentParent->count(); ++a) {
4253 if (currentParent->itemText(a) == commandSection) {
4255 newParentWidget = currentParent->widget(a);
4261 newParentWidget =
new QGroupBox();
4262 newParentWidget->setLayout(
new QVBoxLayout());
4263 if (currentParent !=
nullptr) {
4264 currentParent->addItem(newParentWidget, commandSection);
4267 if (aParent->layout() ==
nullptr) {
4268 aParent->setLayout(
new QVBoxLayout());
4270 aParent->layout()->addWidget(newParentWidget);
4273 if (commandText.indexOf(
"/") == -1) {
4277 for (
G4int i_thGuidance = 0; i_thGuidance < n_guidanceEntry; i_thGuidance++) {
4278 guidance += QString((
char*)(aCommand->
GetGuidanceLine(i_thGuidance)).data()) +
"\n";
4280 newParentWidget->setToolTip(guidance);
4283 auto sc =
dynamic_cast<QScrollArea*
>(newParentWidget->parent()->parent());
4284 if (sc !=
nullptr) {
4285 sc->ensureWidgetVisible(newParentWidget);
4291 auto currentParent =
dynamic_cast<QGroupBox*
>(aParent);
4292 if (currentParent !=
nullptr) {
4295 if (aDepthLevel == 2) {
4296 auto parentToolBox =
dynamic_cast<QToolBox*
>(currentParent->parent()->parent()->parent());
4297 if (parentToolBox !=
nullptr) {
4302 for (
G4int a = 0; a < aParent->layout()->count(); ++a) {
4303 auto gb =
dynamic_cast<QGroupBox*
>(aParent->layout()->itemAt(a)->widget());
4304 if (gb !=
nullptr) {
4305 if (gb->title() == commandSection) {
4307 newParentWidget = gb;
4315 newParentWidget =
new QGroupBox();
4316 newParentWidget->setLayout(
new QVBoxLayout());
4317 if (aParent->layout() ==
nullptr) {
4318 aParent->setLayout(
new QVBoxLayout());
4320 aParent->layout()->addWidget(newParentWidget);
4326 for (
G4int i_thGuidance = 0; i_thGuidance < n_guidanceEntry; i_thGuidance++) {
4327 guidance += QString((
char*)(aCommand->
GetGuidanceLine(i_thGuidance)).data()) +
"\n";
4329 newParentWidget->setToolTip(guidance);
4334 if (commandText.indexOf(
"/") == -1) {
4335 if (CreateCommandWidget(aCommand, newParentWidget, isDialog)) {
4340 CreateVisCommandGroupAndToolBox(aCommand, newParentWidget, aDepthLevel - 1, isDialog);
4351G4bool G4UIQt::CreateCommandWidget(G4UIcommand* aCommand, QWidget* aParent,
G4bool isDialog)
4353 if (aCommand ==
nullptr) {
4359 if (n_parameterEntry > 0) {
4360 G4UIparameter* param;
4363 auto paramWidget =
new QWidget();
4364 auto gridLayout =
new QGridLayout();
4365 paramWidget->setLayout(gridLayout);
4368 unsigned int nbColorParameter = 0;
4369 G4bool isStillColorParameter =
false;
4370 G4bool isColorDialogAdded =
false;
4371 QLabel* redLabel =
nullptr;
4372 QLabel* greenLabel =
nullptr;
4373 QString redDefaultStr =
"";
4374 QString greenDefaultStr =
"";
4375 QString blueDefaultStr =
"";
4376 QWidget* redInput =
nullptr;
4377 QWidget* greenInput =
nullptr;
4379 for (
G4int i_thParameter = 0; i_thParameter < n_parameterEntry; i_thParameter++) {
4382 auto label =
new QLabel(QString((
char*)(param->
GetParameterName()).data()));
4384 if ((label->text() ==
"red") || (label->text() ==
"red_or_string")) {
4386 isStillColorParameter =
true;
4388 else if ((label->text() ==
"green") && isStillColorParameter) {
4391 else if ((label->text() ==
"blue") && isStillColorParameter) {
4394 else if (! isColorDialogAdded) {
4396 if (nbColorParameter == 1) {
4397 gridLayout->addWidget(redLabel, i_thParameter - 1, 0);
4398 gridLayout->addWidget(redInput, i_thParameter - 1, 1);
4400 else if (nbColorParameter == 2) {
4401 gridLayout->addWidget(redLabel, i_thParameter - 2, 0);
4402 gridLayout->addWidget(redInput, i_thParameter - 2, 1);
4403 gridLayout->addWidget(greenLabel, i_thParameter - 1, 0);
4404 gridLayout->addWidget(greenInput, i_thParameter - 1, 1);
4406 nbColorParameter = 0;
4409 QWidget* input =
nullptr;
4413 input =
new QLineEdit();
4415 dynamic_cast<QLineEdit*
>(input)->setText(QString((
char*)(param->
GetDefaultValue()).data()));
4417 if (((label->text() ==
"red") || (label->text() ==
"red_or_string")) &&
4418 isStillColorParameter)
4422 else if ((label->text() ==
"green") && isStillColorParameter) {
4425 else if ((label->text() ==
"blue") && isStillColorParameter) {
4430 input =
new QWidget();
4431 auto layout =
new QHBoxLayout();
4432 input->setLayout(layout);
4434 auto buttons =
new QButtonGroup();
4435 auto radioOff =
new QRadioButton(
"0");
4436 auto radioOn =
new QRadioButton(
"1");
4437 buttons->addButton(radioOn);
4438 buttons->addButton(radioOff);
4439 layout->addWidget(radioOn);
4440 layout->addWidget(radioOff);
4443 QString defaultValue = QString((
char*)(param->
GetDefaultValue()).data());
4444 if (defaultValue ==
"0") {
4445 radioOff->setChecked(
true);
4447 else if (defaultValue ==
"1") {
4448 radioOn->setChecked(
true);
4454 input =
new QComboBox();
4456 QStringList list = candidates.split(
" ");
4459 QString defaultValue = QString((
char*)(param->
GetDefaultValue()).data());
4460 for (
int a = 0; a < list.size(); a++) {
4461 dynamic_cast<QComboBox*
>(input)->addItem(list.at(a));
4462 if (list.at(a) == defaultValue) {
4463 dynamic_cast<QComboBox*
>(input)->setCurrentIndex(a);
4468 input =
new QLineEdit();
4470 dynamic_cast<QLineEdit*
>(input)->setText(QString((
char*)(param->
GetDefaultValue()).data()));
4473 input =
new QWidget();
4474 auto layout =
new QHBoxLayout();
4475 input->setLayout(layout);
4477 auto buttons =
new QButtonGroup();
4478 auto radioOff =
new QRadioButton(
"off");
4479 auto radioOn =
new QRadioButton(
"on");
4480 buttons->addButton(radioOn);
4481 buttons->addButton(radioOff);
4482 layout->addWidget(radioOn);
4483 layout->addWidget(radioOff);
4486 QString defaultValue = QString((
char*)(param->
GetDefaultValue()).data());
4487 if (defaultValue ==
"off") {
4488 radioOff->setChecked(
true);
4490 else if (defaultValue ==
"on") {
4491 radioOn->setChecked(
true);
4495 input =
new QLineEdit();
4496 dynamic_cast<QLineEdit*
>(input)->setText(QString((
char*)(param->
GetDefaultValue()).data()));
4499 txt +=
"\nParameter : " + QString((
char*)(param->
GetParameterName()).data()) +
"\n";
4503 txt +=
" Parameter type : " + QString(QChar(param->
GetParameterType())) +
"\n";
4505 txt +=
" Omittable : True\n";
4508 txt +=
" Omittable : False\n";
4511 txt +=
" Default value : taken from the current value\n";
4514 txt +=
" Default value : " + QString((
char*)(param->
GetDefaultValue()).data()) +
"\n";
4517 txt +=
" Parameter range : " + QString((
char*)(param->
GetParameterRange()).data()) +
"\n";
4524 if (isStillColorParameter && (nbColorParameter != 0)) {
4525 if ((label->text() ==
"red") || (label->text() ==
"red_or_string")) {
4529 else if (label->text() ==
"green") {
4533 else if (label->text() ==
"blue") {
4538 if ((redDefaultStr !=
"") && (redDefaultStr !=
"") && (redDefaultStr !=
"")) {
4540 redDefaultStr.toDouble(), greenDefaultStr.toDouble(), blueDefaultStr.toDouble());
4542 QPixmap pixmap = QPixmap(QSize(16, 16));
4544 QPainter painter(&pixmap);
4545 painter.setPen(Qt::black);
4546 painter.drawRect(0, 0, 15, 15);
4548 input =
new QPushButton(
"Change color");
4549 dynamic_cast<QPushButton*
>(input)->setIcon(pixmap);
4550 dynamic_cast<QPushButton*
>(input)->setAccessibleName(
4551 redDefaultStr +
" " + greenDefaultStr +
" " + blueDefaultStr);
4552 label =
new QLabel(
"Choose color");
4556 gridLayout->addWidget(label, i_thParameter - nbColorParameter, 0);
4557 input->setToolTip(
"Select the current color");
4558 gridLayout->addWidget(input, i_thParameter - nbColorParameter, 1);
4561 connect(
dynamic_cast<QPushButton*
>(input), &QPushButton::clicked,
4562 [
this, input]() { this->ChangeColorCallback(input); });
4563 isColorDialogAdded =
true;
4564 isStillColorParameter =
false;
4568 gridLayout->addWidget(label, i_thParameter - nbColorParameter, 0);
4569 input->setToolTip(txt);
4570 gridLayout->addWidget(input, i_thParameter - nbColorParameter, 1);
4576 gridLayout->addWidget(name, n_parameterEntry - nbColorParameter, 0);
4578 auto applyButton =
new QPushButton(
"Apply");
4580 gridLayout->addWidget(applyButton, n_parameterEntry - nbColorParameter, 1);
4581 connect(applyButton, &QPushButton::clicked,
4582 [
this, paramWidget]() { this->VisParameterCallback(paramWidget); });
4587 applyButton->setAutoDefault(
true);
4588 applyButton->setDefault(
true);
4590 auto cancelButton =
new QPushButton(tr(
"&Cancel"));
4591 cancelButton->setAutoDefault(
true);
4592 gridLayout->addWidget(cancelButton, n_parameterEntry - nbColorParameter, 1);
4593 gridLayout->addWidget(applyButton, n_parameterEntry - nbColorParameter, 0);
4595 connect(applyButton, &QPushButton::clicked,
4596 [
this, paramWidget]() { this->VisParameterCallback(paramWidget); });
4598 QWidget* parentCheck = aParent;
4599 QDialog* parentDialog =
nullptr;
4601 while ((parentCheck->parentWidget()) !=
nullptr) {
4602 parentCheck = parentCheck->parentWidget();
4603 parentDialog =
dynamic_cast<QDialog*
>(parentCheck);
4604 if (parentDialog !=
nullptr) {
4605 connect(applyButton, SIGNAL(clicked()), parentDialog, SLOT(accept()));
4606 connect(cancelButton, SIGNAL(clicked()), parentDialog, SLOT(reject()));
4615 if (aParent->layout() ==
nullptr) {
4616 aParent->setLayout(
new QVBoxLayout());
4618 aParent->layout()->addWidget(paramWidget);
4628QTreeWidgetItem* G4UIQt::FindTreeItem(QTreeWidgetItem* aParent,
const QString& aCommand)
4630 if (aParent ==
nullptr)
return nullptr;
4633 QString myCommand = aCommand;
4635 if (myCommand.lastIndexOf(
"/") == (myCommand.size() - 1)) {
4636 myCommand = myCommand.left(myCommand.size() - 1);
4639 if (GetLongCommandPath(aParent) == myCommand)
return aParent;
4641 QTreeWidgetItem* tmp =
nullptr;
4642 for (
G4int a = 0; a < aParent->childCount(); ++a) {
4643 if (tmp ==
nullptr) tmp = FindTreeItem(aParent->child(a), myCommand);
4655QString G4UIQt::GetCommandList(
const G4UIcommand* aCommand)
4658 if (aCommand ==
nullptr)
return txt;
4661 G4String rangeString = aCommand->
GetRange();
4665 if ((commandPath.empty()) && (rangeString.empty()) && (n_guidanceEntry == 0) &&
4666 (n_parameterEntry == 0))
4671 if ((commandPath.length() - 1) !=
'/') {
4672 txt +=
"Command " + QString((
char*)(commandPath).data()) +
"\n";
4674 txt +=
"Guidance :\n";
4676 for (
G4int i_thGuidance = 0; i_thGuidance < n_guidanceEntry; i_thGuidance++) {
4677 txt += QString((
char*)(aCommand->
GetGuidanceLine(i_thGuidance)).data()) +
"\n";
4679 if (! rangeString.empty()) {
4680 txt +=
" Range of parameters : " + QString((
char*)(rangeString).data()) +
"\n";
4682 if (n_parameterEntry > 0) {
4683 G4UIparameter* param;
4687 for (
G4int i_thParameter = 0; i_thParameter < n_parameterEntry; i_thParameter++) {
4689 txt +=
"\nParameter : " + QString((
char*)(param->
GetParameterName()).data()) +
"\n";
4692 txt +=
" Parameter type : " + QString(QChar(param->
GetParameterType())) +
"\n";
4694 txt +=
" Omittable : True\n";
4697 txt +=
" Omittable : False\n";
4700 txt +=
" Default value : taken from the current value\n";
4703 txt +=
" Default value : " + QString((
char*)(param->
GetDefaultValue()).data()) +
"\n";
4706 txt +=
" Parameter range : " + QString((
char*)(param->
GetParameterRange()).data()) +
"\n";
4724void G4UIQt::updateHelpArea(
const G4UIcommand* aCommand)
4726 if (fParameterHelpLabel ==
nullptr)
return;
4727 if (fParameterHelpTable ==
nullptr)
return;
4729 fParameterHelpLabel->setTextInteractionFlags(Qt::NoTextInteraction);
4731 if (aCommand ==
nullptr)
return;
4734 G4String rangeString = aCommand->
GetRange();
4738 if ((commandPath.empty()) && (rangeString.empty()) && (n_guidanceEntry == 0) &&
4739 (n_parameterEntry == 0))
4744 if ((commandPath.length() - 1) !=
'/') {
4745 txt +=
"<b>Command </b> " + QString((
char*)(commandPath).data()) +
"<br />";
4747 txt +=
"<b>Guidance :</b> ";
4748 QString tmpGuidance =
"";
4749 for (
G4int i_thGuidance = 0; i_thGuidance < n_guidanceEntry; i_thGuidance++) {
4750 tmpGuidance = QString((
char*)(aCommand->
GetGuidanceLine(i_thGuidance)).data());
4751 tmpGuidance = tmpGuidance.toHtmlEscaped();
4752 tmpGuidance.replace(
"\n",
"<br />");
4753 txt += tmpGuidance +
"<br />";
4755 if (! rangeString.empty()) {
4756 QString range = QString((
char*)(rangeString).data());
4757 range = range.toHtmlEscaped();
4758 txt +=
"<b>Range of parameters : </b> " + range +
"<br />";
4763 fParameterHelpLabel->setHtml(txt);
4765 if (n_parameterEntry > 0) {
4766 G4UIparameter* param;
4770 fParameterHelpTable->clear();
4771 fParameterHelpTable->setRowCount(n_parameterEntry);
4772 fParameterHelpTable->setColumnCount(8);
4773 fParameterHelpTable->setHorizontalHeaderLabels(
4774 QStringList() << tr(
"") << tr(
"Parameter") << tr(
"Guidance") << tr(
"Type") << tr(
"Ommitable")
4775 << tr(
"Default") << tr(
"Range") << tr(
"Candidate"));
4776 fParameterHelpTable->setColumnWidth(2, 60);
4778 fParameterHelpTable->verticalHeader()->setVisible(
false);
4779 fParameterHelpTable->setAlternatingRowColors(
true);
4780 fParameterHelpTable->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
4781 fParameterHelpTable->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch);
4782 fParameterHelpTable->setWordWrap(
true);
4784 QTableWidgetItem* t = fParameterHelpTable->horizontalHeaderItem(1);
4785 QFont fnt = t->font();
4786 G4int size = fnt.pointSize();
4787 fnt.setPointSize(size - 2);
4789 for (
G4int a = 0; a < n_parameterEntry; a++) {
4791 fParameterHelpTable->setItem(a, 0,
new QTableWidgetItem(QString::number(a + 1)));
4793 fParameterHelpTable->setItem(
4794 a, 1,
new QTableWidgetItem(QString((
char*)(param->
GetParameterName()).data())));
4796 fParameterHelpTable->setItem(
4799 fParameterHelpTable->setItem(
4803 fParameterHelpTable->setItem(a, 4,
new QTableWidgetItem(QString(
"True")));
4806 fParameterHelpTable->setItem(a, 4,
new QTableWidgetItem(QString(
"False")));
4809 fParameterHelpTable->setItem(
4810 a, 5,
new QTableWidgetItem(QString(
"taken from the current value")));
4813 fParameterHelpTable->setItem(
4814 a, 5,
new QTableWidgetItem(QString((
char*)(param->
GetDefaultValue()).data())));
4817 fParameterHelpTable->setItem(
4818 a, 6,
new QTableWidgetItem(QString((
char*)(param->
GetParameterRange()).data())));
4821 fParameterHelpTable->setItem(
4825 for (
G4int b = 0; b < 8; ++b) {
4826 QTableWidgetItem* tmp = fParameterHelpTable->item(a, b);
4827 if (tmp !=
nullptr) {
4828 tmp->setToolTip(tmp->text());
4829 tmp->setFlags(Qt::NoItemFlags);
4832 fParameterHelpTable->resizeRowToContents(a);
4834 for (
G4int c = 0; c < 8; ++c) {
4836 fParameterHelpTable->resizeColumnToContents(c);
4839 fParameterHelpLabel->setVisible(
true);
4840 fParameterHelpTable->setVisible(
true);
4849G4bool G4UIQt::IsGUICommand(
const G4UIcommand* aCommand)
4851 if (aCommand ==
nullptr)
return false;
4855 if (n_parameterEntry > 0) {
4856 G4UIparameter* param;
4860 for (
G4int i_thParameter = 0; i_thParameter < n_parameterEntry; i_thParameter++) {
4881G4bool G4UIQt::GetHelpChoice(
G4int&) {
return true; }
4890G4bool G4UIQt::eventFilter(
4891 QObject* aObj, QEvent* aEvent)
4893 G4bool tabKeyPress =
false;
4894 G4bool moveCommandCursor =
false;
4895 if (aObj ==
nullptr)
return false;
4896 if (aEvent ==
nullptr)
return false;
4898 if (aObj == fHistoryTBTableList) {
4899 if (aEvent->type() == QEvent::KeyPress) {
4900 fCommandArea->setFocus();
4904 if (aObj == fCompleter->popup()) {
4905 if (aEvent->type() == QEvent::KeyPress) {
4906 auto e =
static_cast<QKeyEvent*
>(aEvent);
4907 if (e->key() == (Qt::Key_Tab)) {
4911 else if (aEvent->type() == QEvent::Hide) {
4913 QString c = fCommandArea->text();
4914 fLastCompleteCommand = c.left(c.indexOf(
"<"));
4918 if (aObj == fCommandArea) {
4919 if (aEvent->type() == QEvent::KeyPress) {
4920 auto e =
static_cast<QKeyEvent*
>(aEvent);
4921 if ((e->key() == (Qt::Key_Down)) || (e->key() == (Qt::Key_PageDown)) ||
4922 (e->key() == (Qt::Key_Up)) || (e->key() == (Qt::Key_PageUp)))
4924 G4int selection = fHistoryTBTableList->currentRow();
4925 if (fHistoryTBTableList->count() != 0) {
4926 if (selection == -1) {
4927 selection = fHistoryTBTableList->count() - 1;
4930 if (e->key() == (Qt::Key_Down)) {
4931 if (selection < (fHistoryTBTableList->count() - 1)) selection++;
4933 else if (e->key() == (Qt::Key_PageDown)) {
4934 selection = fHistoryTBTableList->count() - 1;
4936 else if (e->key() == (Qt::Key_Up)) {
4937 if (selection > 0) selection--;
4939 else if (e->key() == (Qt::Key_PageUp)) {
4943 fHistoryTBTableList->clearSelection();
4944 fHistoryTBTableList->item(selection)->setSelected(
true);
4945 fHistoryTBTableList->setCurrentItem(fHistoryTBTableList->item(selection));
4947 moveCommandCursor =
true;
4949 else if (e->key() == (Qt::Key_Tab)) {
4952 else if (((e->modifiers() == Qt::ControlModifier) || (e->modifiers() == Qt::MetaModifier)) &&
4953 (e->key() == Qt::Key_A))
4955 fCommandArea->home(
false);
4958 else if (((e->modifiers() == Qt::ControlModifier) || (e->modifiers() == Qt::MetaModifier)) &&
4959 (e->key() == Qt::Key_E))
4961 fCommandArea->end(
false);
4965 else if (aEvent->type() == QEvent::Paint) {
4966 if (fLastCompleteCommand !=
"") {
4967 fCommandArea->setText(fLastCompleteCommand);
4968 fLastCompleteCommand =
"";
4973 G4String ss =
Complete(fCommandArea->text().toStdString().c_str());
4974 fCommandArea->setText((
char*)(ss.data()));
4975 fCommandArea->setFocus();
4984 if (moveCommandCursor) {
4985 fCommandArea->setCursorPosition((
int)fCommandArea->text().length());
4986 fCommandArea->setCursorPosition(4);
4990 res = QObject::eventFilter(aObj, aEvent);
4995void G4UIQt::UpdateCommandCompleter()
4997 if (fCommandArea ==
nullptr)
return;
5000 fCommandArea->setCompleter(
nullptr);
5001 if (fCompleter !=
nullptr) {
5002 if (fCompleter->popup() !=
nullptr) {
5003 fCompleter->popup()->removeEventFilter(
this);
5007 QStandardItemModel* model = CreateCompleterModel(
"/");
5008 fCompleter =
new QCompleter(model);
5012 G4UIcommandTree* commandTreeTop = UI->
GetTree();
5014 if (aTree !=
nullptr) {
5016 fCompleter->setMaxVisibleItems(Ndir);
5018 fCommandArea->setCompleter(fCompleter);
5019 fCompleter->popup()->installEventFilter(
this);
5022QStandardItemModel* G4UIQt::CreateCompleterModel(
const G4String& aCmd)
5024 QList<QStandardItem*> dirModelList;
5025 QList<QStandardItem*> commandModelList;
5026 QList<QStandardItem*> subDirModelList;
5027 QList<QStandardItem*> subCommandModelList;
5032 G4String pName = aCmd;
5033 G4String remainingPath = aCmd;
5034 G4String empty =
"";
5035 G4String matchingPath = empty;
5038 auto jpre = pName.rfind(
'/');
5039 if (jpre != G4String::npos) pName.erase(jpre + 1);
5041 G4UIcommandTree* commandTreeTop = UI->
GetTree();
5043 if (aTree !=
nullptr) {
5048 for (
G4int idir = 1; idir <= Ndir; ++idir) {
5051 if (fpdir.find(remainingPath, 0) == 0) {
5053 matchingPath = fpdir;
5061 auto item1 =
new QStandardItem(fpdir.data());
5062 QIcon i = QIcon(*fDirIcon);
5064 item1->setIcon(QIcon(*fDirIcon));
5065 dirModelList.append(item1);
5068 QStandardItemModel* subModel = CreateCompleterModel(fpdir.data());
5069 for (
G4int a = 0; a < subModel->rowCount(); ++a) {
5071 auto tempItem =
new QStandardItem(subModel->item(a)->text());
5072 tempItem->setIcon(subModel->item(a)->icon());
5073 tempItem->setToolTip(subModel->item(a)->toolTip());
5074 tempItem->setData(subModel->item(a)->data());
5077 if (tempItem->data() == 1) {
5079 subDirModelList.append(tempItem);
5082 else if (tempItem->data() == 0) {
5083 subCommandModelList.append(tempItem);
5090 G4int n_parameterEntry;
5091 G4String rangeString;
5092 G4int n_guidanceEntry;
5093 G4UIcommand* command;
5094 G4UIparameter* param;
5095 std::string tooltip;
5098 for (
G4int icmd = 1; icmd <= Ncmd; ++icmd) {
5108 if (longCommandName.find(remainingPath, 0) == 0) {
5110 matchingPath = longCommandName +
" ";
5113 strtmp = longCommandName +
" ";
5118 for (
G4int i_thGuidance = 0; i_thGuidance < n_guidanceEntry; i_thGuidance++) {
5119 tooltip += std::string((command->
GetGuidanceLine(i_thGuidance)).data());
5120 if (i_thGuidance < n_guidanceEntry - 1) {
5126 for (
G4int a = 0; a < n_parameterEntry; a++) {
5138 auto item =
new QStandardItem(G4String(longCommandName + params).data());
5140 item->setIcon(QIcon(*fCommandIcon));
5141 item->setToolTip(tooltip.c_str());
5143 commandModelList.append(item);
5148 auto model =
new QStandardItemModel();
5150 model->setColumnCount(1);
5153 for (
auto a : dirModelList) {
5154 model->appendRow(a);
5156 for (
auto a : subDirModelList) {
5157 model->appendRow(a);
5159 for (
auto a : commandModelList) {
5160 model->appendRow(a);
5162 for (
auto a : subCommandModelList) {
5163 model->appendRow(a);
5181void G4UIQt::ClearButtonCallback()
5183 fCoutTBTextArea->clear();
5184 fG4OutputString.clear();
5196void G4UIQt::CommandEnteredCallback()
5199 fCommandArea->setText(fCommandArea->text().trimmed());
5200#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
5201 QStringList list = fCommandArea->text().split(QRegularExpression(
"[\r\n]"),QString::SkipEmptyParts);
5203 QStringList list = fCommandArea->text().split(QRegularExpression(
"[\r\n]"),Qt::SkipEmptyParts);
5207 for (
G4int a = 0; a < list.size(); ++a) {
5208 QString txt(list[a].trimmed());
5210 fHistoryTBTableList->addItem(txt);
5211 fHistoryTBTableList->clearSelection();
5212 fHistoryTBTableList->setCurrentItem(
nullptr);
5213 fCommandArea->setText(
"");
5215 if (interactorManager !=
nullptr) {
5219 G4String command = txt.toStdString().c_str();
5220 if (command.substr(0, 4) !=
"help") {
5224 ActivateCommand(command);
5229 fCommandArea->setFocus();
5235 UpdateCommandCompleter();
5244void G4UIQt::CommandEditedCallback(
const QString&)
5246#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
5247 QStringList list = fCommandArea->text().split(QRegularExpression(
"[\r\n]"), QString::SkipEmptyParts);
5249 QStringList list = fCommandArea->text().split(QRegularExpression(
"[\r\n]"), Qt::SkipEmptyParts);
5252 if (list.size() > 1) {
5253 for (
G4int a = 0; a < list.size() - 1; ++a) {
5255 fCommandArea->setText(list[a]);
5257 CommandEnteredCallback();
5260 fCommandArea->setText(list[list.size() - 1]);
5266void G4UIQt::VisParameterCallback(QWidget* widget)
5268 if (widget ==
nullptr) {
5273 auto grid =
dynamic_cast<QGridLayout*
>(widget->layout());
5274 if (grid ==
nullptr) {
5278 QWidget*
name =
grid->itemAtPosition(
grid->rowCount() - 1, 0)->widget();
5279 if (
dynamic_cast<QLabel*
>(name) ==
nullptr) {
5282 command += (
dynamic_cast<QLabel*
>(
name))->text() +
" ";
5284 for (
G4int a = 0; a <
grid->rowCount() - 1; ++a) {
5285 QWidget* widgetTmp =
grid->itemAtPosition(a, 1)->widget();
5288 if (widgetTmp !=
nullptr) {
5289 if (
dynamic_cast<QLineEdit*
>(widgetTmp) !=
nullptr) {
5290 command += (
dynamic_cast<QLineEdit*
>(widgetTmp))->text() +
" ";
5292 else if (
dynamic_cast<QComboBox*
>(widgetTmp) !=
nullptr) {
5293 command += (
dynamic_cast<QComboBox*
>(widgetTmp))
5294 ->itemText((
dynamic_cast<QComboBox*
>(widgetTmp))->currentIndex()) +
5299 else if (
dynamic_cast<QPushButton*
>(widgetTmp) !=
nullptr) {
5300 command += widgetTmp->accessibleName() +
" ";
5304 else if (
dynamic_cast<QWidget*
>(widgetTmp) !=
nullptr) {
5305 if (widgetTmp->layout()->count() > 0) {
5306 if (
dynamic_cast<QRadioButton*
>(widgetTmp->layout()->itemAt(0)->widget()) !=
nullptr) {
5307 QAbstractButton* checked =
5308 (
dynamic_cast<QRadioButton*
>(widgetTmp->layout()->itemAt(0)->widget()))
5311 if (checked !=
nullptr) {
5312 command += (
dynamic_cast<QRadioButton*
>(widgetTmp->layout()->itemAt(0)->widget()))
5323 if (command !=
"") {
5325 if (UI !=
nullptr) {
5336void G4UIQt::ButtonCallback(
const QString& aCommand)
5341 if (UI ==
nullptr)
return;
5342 G4UIcommandTree* treeTop = UI->
GetTree();
5344 G4UIcommand* command = treeTop->
FindPath(ss);
5346 if (command !=
nullptr) {
5348 if (IsGUICommand(command)) {
5349 auto menuParameterDialog =
new QDialog();
5351 if (CreateVisCommandGroupAndToolBox(command, menuParameterDialog, 1,
true)) {
5352 menuParameterDialog->setWindowTitle(aCommand);
5353 menuParameterDialog->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
5356 menuParameterDialog->exec();
5359 delete menuParameterDialog;
5373void G4UIQt::HelpTreeClicCallback()
5375 QTreeWidgetItem* item =
nullptr;
5376 if (fHelpTreeWidget ==
nullptr)
return;
5378 QList<QTreeWidgetItem*> list = fHelpTreeWidget->selectedItems();
5379 if (list.isEmpty())
return;
5380 item = list.first();
5381 if (item ==
nullptr)
return;
5384 if (UI ==
nullptr)
return;
5385 G4UIcommandTree* treeTop = UI->
GetTree();
5387 std::string itemText = GetLongCommandPath(item).toStdString();
5390 if (item->childCount() > 0) {
5393 G4UIcommand* command = treeTop->
FindPath(itemText.c_str());
5395 if (command !=
nullptr) {
5396 updateHelpArea(command);
5400 if (path !=
nullptr) {
5403 fParameterHelpLabel->setVisible(
true);
5404 fParameterHelpLabel->setText(path->
GetTitle().data());
5405 fParameterHelpTable->setVisible(
false);
5412void G4UIQt::HelpTreeDoubleClicCallback()
5414 HelpTreeClicCallback();
5416 QTreeWidgetItem* item =
nullptr;
5417 if (fHelpTreeWidget ==
nullptr)
return;
5419 QList<QTreeWidgetItem*> list = fHelpTreeWidget->selectedItems();
5420 if (list.isEmpty())
return;
5421 item = list.first();
5422 if (item ==
nullptr)
return;
5424 fCommandArea->clear();
5425 fCommandArea->setText(GetLongCommandPath(item));
5431void G4UIQt::CommandHistoryCallback()
5433 QListWidgetItem* item =
nullptr;
5434 if (fHistoryTBTableList ==
nullptr)
return;
5436 QList<QListWidgetItem*> list = fHistoryTBTableList->selectedItems();
5437 if (list.isEmpty())
return;
5438 item = list.first();
5439 if (item ==
nullptr)
return;
5440 fCommandArea->setText(item->text());
5443void G4UIQt::ThreadComboBoxCallback(
int) { CoutFilterCallback(
""); }
5445void G4UIQt::CoutFilterCallback(
const QString&)
5447 FilterAllOutputTextArea();
5449 fCoutTBTextArea->repaint();
5450 fCoutTBTextArea->verticalScrollBar()->setSliderPosition(
5451 fCoutTBTextArea->verticalScrollBar()->maximum());
5454void G4UIQt::SaveOutputCallback()
5456 QString fileName = QFileDialog::getSaveFileName(
5457 fMainWindow,
"Save console output as...", fLastOpenPath,
"Save output as...");
5458 if (fileName !=
"") {
5459 QFile data(fileName);
5460 if (data.open(QFile::WriteOnly | QFile::Truncate)) {
5461 QTextStream out(&data);
5462 out << fCoutTBTextArea->toPlainText();
5469QString G4UIQt::FilterOutput(
5470 const G4UIOutputString& output,
const QString& currentThread,
const QString& filter)
5472#ifdef G4MULTITHREADED
5473 if ((currentThread ==
"All") || (currentThread == output.
fThread.data())) {
5475 if (currentThread ==
"") {
5477 if (output.
fText.contains(QRegularExpression(filter))) {
5478 return output.
fText;
5484void G4UIQt::FilterAllOutputTextArea()
5486 QString currentThread =
"";
5487#ifdef G4MULTITHREADED
5488 currentThread = fThreadsFilterComboBox->currentText();
5489 if (currentThread ==
"Master") {
5493 QString filter = fCoutFilter->text();
5494 G4String previousOutputStream =
"";
5499 fCoutTBTextArea->clear();
5501 for (
auto& out : fG4OutputString) {
5502 if (FilterOutput(out, currentThread, filter) !=
"") {
5504 if (out.fOutputStream != previousOutputStream) {
5505 previousOutputStream = out.fOutputStream;
5506 if (out.fOutputStream ==
"info") {
5510 else if (out.fOutputStream ==
"warning") {
5511 pref =
"<font color=\"DarkYellow\">";
5515 pref =
"<font color=\"Red\">";
5519 fCoutTBTextArea->append(pref + out.fText + post);
5528void G4UIQt::LookForHelpStringCallback()
5530 fHelpLine->setText(fHelpLine->text().trimmed());
5531 QString searchText = fHelpLine->text();
5533 fParameterHelpLabel->setText(
"");
5534 fParameterHelpTable->setVisible(
false);
5535 if (searchText ==
"") {
5537 fHelpTreeWidget->clear();
5543 OpenHelpTreeOnCommand(searchText);
5546void G4UIQt::OpenHelpTreeOnCommand(
const QString& searchText)
5549 ApplyShellCommand(
"help "+G4String(searchText.toStdString()), exitSession, exitPause);
5551#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
5558 if (UI ==
nullptr)
return;
5559 G4UIcommandTree* treeTop = UI->
GetTree();
5564 fHelpTreeWidget->clear();
5570#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
5572 QMap<G4int, QString> commandResultMap;
5573 QMap<G4int, QString> commandChildResultMap;
5574 for (
G4int a = 0; a < treeSize; ++a) {
5576 tmp = GetCommandList(command).count(searchText, Qt::CaseInsensitive);
5578 commandResultMap.insertMulti(
5582 commandChildResultMap = LookForHelpStringInChildTree(treeTop->
GetTree(a + 1), searchText);
5584 if (! commandChildResultMap.empty()) {
5585 QMap<int, QString>::const_iterator i = commandChildResultMap.constBegin();
5586 while (i != commandChildResultMap.constEnd()) {
5587 commandResultMap.insertMulti(i.key(), i.value());
5590 commandChildResultMap.clear();
5595 QMultiMap<G4int, QString> commandResultMap;
5596 QMultiMap<G4int, QString> commandChildResultMap;
5597 for (
G4int a = 0; a < treeSize; ++a) {
5599 tmp = (int)GetCommandList(command).count(searchText, Qt::CaseInsensitive);
5601 commandResultMap.insert(tmp, QString((
char*)(treeTop->
GetTree(a + 1)->
GetPathName()).data()));
5604 commandChildResultMap = LookForHelpStringInChildTree(treeTop->
GetTree(a + 1), searchText);
5606 if (! commandChildResultMap.empty()) {
5607 auto i = commandChildResultMap.constBegin();
5608 while (i != commandChildResultMap.constEnd()) {
5609 commandResultMap.insert(i.key(), i.value());
5612 commandChildResultMap.clear();
5618 fHelpTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
5619 fHelpTreeWidget->setColumnCount(2);
5621 labels << QString(
"Command") << QString(
"Match");
5622 fHelpTreeWidget->setHeaderLabels(labels);
5624 if (commandResultMap.empty()) {
5625 fParameterHelpLabel->setText(
"No match found");
5626 fParameterHelpTable->setVisible(
false);
5630 auto i = commandResultMap.constEnd();
5634 QString progressChar =
"|";
5635 QString progressStr =
"|";
5637 QTreeWidgetItem* newItem;
5640 if (i == commandResultMap.constBegin()) {
5643 for (
G4int a = 0; a <
G4int(i.key() * multValue); ++a) {
5644 progressStr += progressChar;
5646 newItem =
new QTreeWidgetItem();
5647 QString commandStr = i.value().trimmed();
5649 if (commandStr.indexOf(
"/") == 0) {
5650 commandStr = commandStr.right(commandStr.size() - 1);
5653 newItem->setText(0, commandStr);
5654 newItem->setText(1, progressStr);
5655 fHelpTreeWidget->addTopLevelItem(newItem);
5656 newItem->setForeground(1, QBrush(Qt::blue));
5660 fHelpTreeWidget->resizeColumnToContents(0);
5661 fHelpTreeWidget->sortItems(1, Qt::DescendingOrder);
5666#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
5668QMap<G4int, QString> G4UIQt::LookForHelpStringInChildTree(
5669 G4UIcommandTree* aCommandTree,
const QString& text)
5671 QMap<G4int, QString> commandResultMap;
5672 if (aCommandTree == NULL)
return commandResultMap;
5675 QMap<G4int, QString> commandChildResultMap;
5677 const G4UIcommand* command = aCommandTree->
GetGuidance();
5678 tmp = GetCommandList(command).count(text, Qt::CaseInsensitive);
5680 commandResultMap.insertMulti(
5684 commandChildResultMap = LookForHelpStringInChildTree(aCommandTree->
GetTree(a + 1), text);
5685 if (! commandChildResultMap.empty()) {
5687 QMap<G4int, QString>::const_iterator i = commandChildResultMap.constBegin();
5688 while (i != commandChildResultMap.constEnd()) {
5689 commandResultMap.insertMulti(i.key(), i.value());
5692 commandChildResultMap.clear();
5697 const G4UIcommand* command = aCommandTree->
GetCommand(a + 1);
5698 tmp = GetCommandList(command).count(text, Qt::CaseInsensitive);
5700 commandResultMap.insertMulti(
5704 return commandResultMap;
5708QMultiMap<G4int, QString> G4UIQt::LookForHelpStringInChildTree(
5709 G4UIcommandTree* aCommandTree,
const QString& text)
5711 QMultiMap<G4int, QString> commandResultMap;
5712 if (aCommandTree ==
nullptr)
return commandResultMap;
5715 QMultiMap<G4int, QString> commandChildResultMap;
5717 const G4UIcommand* command = aCommandTree->
GetGuidance();
5718 tmp = (int)GetCommandList(command).count(text, Qt::CaseInsensitive);
5720 commandResultMap.insert(
5724 commandChildResultMap = LookForHelpStringInChildTree(aCommandTree->
GetTree(a + 1), text);
5725 if (! commandChildResultMap.empty()) {
5727 auto i = commandChildResultMap.constBegin();
5728 while (i != commandChildResultMap.constEnd()) {
5729 commandResultMap.insert(i.key(), i.value());
5732 commandChildResultMap.clear();
5737 const G4UIcommand* command = aCommandTree->
GetCommand(a + 1);
5738 tmp = (int)GetCommandList(command).count(text, Qt::CaseInsensitive);
5740 commandResultMap.insert(
5744 return commandResultMap;
5748QString G4UIQt::GetShortCommandPath(QString& commandPath)
5750 if (commandPath.indexOf(
"/") == 0) {
5751 commandPath = commandPath.right(commandPath.size() - 1);
5754 commandPath = commandPath.right(commandPath.size() - commandPath.lastIndexOf(
"/", -2) - 1);
5756 if (commandPath.lastIndexOf(
"/") == (commandPath.size() - 1)) {
5757 commandPath = commandPath.left(commandPath.size() - 1);
5763QString G4UIQt::GetLongCommandPath(QTreeWidgetItem* item)
5765 if (item ==
nullptr)
return "";
5768 QString itemText =
"";
5769 itemText = item->text(0);
5771 while (item->parent() !=
nullptr) {
5772 itemText = item->parent()->text(0) +
"/" + itemText;
5773 item = item->parent();
5775 itemText =
"/" + itemText;
5780void G4UIQt::ChangeColorCallback(QWidget* widget)
5782 if (widget ==
nullptr) {
5786 auto button =
dynamic_cast<QPushButton*
>(widget);
5787 if (button ==
nullptr) {
5790 QString value = button->accessibleName();
5793 old.setRgbF(value.section(
" ", 0, 1).toDouble(), value.section(
" ", 1, 2).toDouble(),
5794 value.section(
" ", 2, 3).toDouble());
5796 QColorDialog::getColor(old, fUITabWidget,
"Change color", QColorDialog::ShowAlphaChannel);
5798 if (color.isValid()) {
5800 QPixmap pixmap = QPixmap(QSize(16, 16));
5802 QPainter painter(&pixmap);
5803 painter.setPen(Qt::black);
5804 painter.drawRect(0, 0, 15, 15);
5806 button->setAccessibleName(QString::number(color.redF()) +
" " +
5807 QString::number(color.greenF()) +
" " +
5808 QString::number(color.blueF()) +
" ");
5809 button->setIcon(pixmap);
5813void G4UIQt::ChangeCursorAction(
const QString& action)
5817 if (fToolbarApp ==
nullptr)
return;
5819 QList<QAction*> list = fToolbarApp->actions();
5821 if (action ==
"pick") {
5822 for (
auto i : list) {
5823 if (i->data().toString() ==
"pick") {
5824 fPickSelected = !fPickSelected;
5825 i->setChecked(fPickSelected);
5826 if (fPickSelected) {
5828 CreatePickInfosDialog();
5831 if (fPickInfosDialog !=
nullptr) fPickInfosDialog->hide();
5838 fMoveSelected =
true;
5839 fRotateSelected =
true;
5840 fZoomInSelected =
true;
5841 fZoomOutSelected =
true;
5843 for (
auto i : list) {
5844 if (i->data().toString() == action) {
5845 i->setChecked(
true);
5847 else if (i->data().toString() ==
"move") {
5848 fMoveSelected =
false;
5849 i->setChecked(
false);
5851 else if (i->data().toString() ==
"rotate") {
5852 fRotateSelected =
false;
5853 i->setChecked(
false);
5855 else if (i->data().toString() ==
"zoom_in") {
5856 fZoomInSelected =
false;
5857 i->setChecked(
false);
5859 else if (i->data().toString() ==
"zoom_out") {
5860 fZoomOutSelected =
false;
5861 i->setChecked(
false);
5873void G4UIQt::ChangeSurfaceStyle(
const QString& action)
5877 if (fToolbarApp ==
nullptr)
return;
5878 QList<QAction*> list = fToolbarApp->actions();
5879 for (
auto i : list) {
5880 if (i->data().toString() == action) {
5881 i->setChecked(
true);
5883 else if (i->data().toString() ==
"hidden_line_removal") {
5884 i->setChecked(
false);
5886 else if (i->data().toString() ==
"hidden_line_and_surface_removal") {
5887 i->setChecked(
false);
5889 else if (i->data().toString() ==
"solid") {
5890 i->setChecked(
false);
5892 else if (i->data().toString() ==
"wireframe") {
5893 i->setChecked(
false);
5895 else if (i->data().toString() ==
"point_cloud") {
5896 i->setChecked(
false);
5900 if (action ==
"hidden_line_removal") {
5904 else if (action ==
"hidden_line_and_surface_removal") {
5908 else if (action ==
"solid") {
5912 else if (action ==
"wireframe") {
5916 else if (action ==
"point_cloud") {
5922void G4UIQt::OpenIconCallback(
const QString& aParam)
5924 QString aCommand = aParam.left(aParam.indexOf(fStringSeparator));
5925 QString aLabel = aParam.mid(aParam.indexOf(fStringSeparator) + fStringSeparator.length());
5927 QString nomFich = QFileDialog::getOpenFileName(fMainWindow, aLabel, fLastOpenPath,
5928 "Macro files (*.mac);;Geant4 files( *.mac *.g4* *.in);;All (*.*)");
5929 if (nomFich !=
"") {
5931 (QString(aCommand) + QString(
" ") + nomFich).toStdString().c_str());
5933 fLastOpenPath = dir.absoluteFilePath(nomFich);
5937void G4UIQt::SaveIconCallback(
const QString& aParam)
5939 QString aCommand = aParam.left(aParam.indexOf(fStringSeparator));
5940 QString aLabel = aParam.mid(aParam.indexOf(fStringSeparator) + fStringSeparator.length());
5943 QFileDialog::getSaveFileName(fMainWindow, aLabel, fLastOpenPath,
"Macro files (*.mac)");
5944 if (nomFich !=
"") {
5946 (QString(aCommand) + QString(
" ") + nomFich).toStdString().c_str());
5948 fLastOpenPath = dir.absoluteFilePath(nomFich);
5952void G4UIQt::CreateViewerPropertiesDialog()
5954 if (fViewerPropertiesDialog !=
nullptr) {
5957 fViewerPropertiesDialog =
new QDialog();
5959 fViewerPropertiesDialog->setWindowTitle(
"Viewer properties");
5960 fViewerPropertiesDialog->setSizePolicy(
5961 QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
5963 if (fViewerPropertiesWidget ==
nullptr) {
5964 fViewerPropertiesWidget =
new QWidget();
5965 auto layoutPropertiesWidget =
new QVBoxLayout();
5966 fViewerPropertiesWidget->setLayout(layoutPropertiesWidget);
5968 CreateEmptyViewerPropertiesWidget();
5971 auto layoutDialog =
new QVBoxLayout();
5973 layoutDialog->addWidget(fViewerPropertiesWidget);
5974 layoutDialog->setContentsMargins(0, 0, 0, 0);
5975 fViewerPropertiesDialog->setLayout(layoutDialog);
5978void G4UIQt::CreatePickInfosDialog()
5980 if (fPickInfosDialog !=
nullptr) {
5984 fPickInfosDialog =
new QDialog();
5985 fPickInfosDialog->setWindowTitle(
"Pick infos");
5986 QSize screenSize = QGuiApplication::primaryScreen()->geometry().size();
5987 fPickInfosDialog->resize(screenSize.width() * 0.3, screenSize.height() * 0.3);
5988 fPickInfosDialog->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
5989 fPickInfosDialog->setWindowFlags(Qt::WindowStaysOnTopHint);
5991 if (fPickInfosWidget ==
nullptr) {
5992 fPickInfosWidget =
new QWidget();
5993 auto layoutPickInfos =
new QVBoxLayout();
5994 fPickInfosWidget->setLayout(layoutPickInfos);
5996 CreateEmptyPickInfosWidget();
5999 auto layoutDialog =
new QVBoxLayout();
6001 layoutDialog->addWidget(fPickInfosWidget);
6002 layoutDialog->setContentsMargins(0, 0, 0, 0);
6003 fPickInfosDialog->setLayout(layoutDialog);
6006void G4UIQt::CreateEmptyViewerPropertiesWidget()
6008 if (fViewerPropertiesWidget ==
nullptr)
return;
6009 if (fViewerPropertiesWidget->layout() ==
nullptr)
return;
6011 if (fViewerPropertiesWidget->layout()->count() != 0) {
6012 while ((wItem = fViewerPropertiesWidget->layout()->takeAt(0)) !=
nullptr) {
6013 delete wItem->widget();
6018 auto label =
new QLabel(
"No viewer - Please open a viewer first");
6019 fViewerPropertiesWidget->layout()->addWidget(label);
6020 fViewerPropertiesDialog->setWindowTitle(
"No viewer");
6021 fViewerPropertiesDialog->setVisible(
false);
6024void G4UIQt::CreateEmptyPickInfosWidget()
6027 if (fPickInfosWidget->layout()->count() != 0) {
6028 while ((wItem = fPickInfosWidget->layout()->takeAt(0)) !=
nullptr) {
6029 delete wItem->widget();
6034 auto label =
new QLabel(
"Click on the object you want to pick");
6035 fPickInfosWidget->layout()->addWidget(label);
6036 fPickInfosDialog->setWindowTitle(
"Nothing to pick");
6039void G4UIQt::ViewerPropertiesIconCallback(
int)
6041 CreateViewerPropertiesDialog();
6043 fViewerPropertiesDialog->show();
6044 fViewerPropertiesDialog->raise();
6045 fViewerPropertiesDialog->activateWindow();
6048void G4UIQt::ChangePerspectiveOrtho(
const QString& action)
6052 if (fToolbarApp ==
nullptr)
return;
6053 QList<QAction*> list = fToolbarApp->actions();
6054 QString checked =
"";
6055 for (
auto i : list) {
6056 if (i->data().toString() == action) {
6057 i->setChecked(
true);
6058 checked = i->data().toString();
6060 else if (i->data().toString() ==
"perspective") {
6061 i->setChecked(
false);
6063 else if (i->data().toString() ==
"ortho") {
6064 i->setChecked(
false);
6068 if ((action ==
"ortho") && (checked ==
"ortho")) {
6071 else if ((action ==
"perspective") && (checked ==
"perspective")) {
6076void G4UIQt::ResetCameraCallback() {
6083 fMoveSelected =
true;
6084 fRotateSelected =
false;
6085 fZoomInSelected =
false;
6086 fZoomOutSelected =
false;
6088 if (fToolbarApp ==
nullptr)
return;
6089 QList<QAction*> list = fToolbarApp->actions();
6090 for (
auto i : list) {
6091 if (i->data().toString() ==
"move") {
6092 i->setChecked(
true);
6094 else if (i->data().toString() ==
"rotate") {
6095 i->setChecked(
false);
6097 else if (i->data().toString() ==
"zoom_in") {
6098 i->setChecked(
false);
6100 else if (i->data().toString() ==
"zoom_out") {
6101 i->setChecked(
false);
6109 fRotateSelected =
true;
6110 fMoveSelected =
false;
6111 fZoomInSelected =
false;
6112 fZoomOutSelected =
false;
6114 if (fToolbarApp ==
nullptr)
return;
6115 QList<QAction*> list = fToolbarApp->actions();
6116 for (
auto i : list) {
6117 if (i->data().toString() ==
"rotate") {
6118 i->setChecked(
true);
6120 else if (i->data().toString() ==
"move") {
6121 i->setChecked(
false);
6123 else if (i->data().toString() ==
"zoom_in") {
6124 i->setChecked(
false);
6126 else if (i->data().toString() ==
"zoom_out") {
6127 i->setChecked(
false);
6135 fPickSelected = !fPickSelected;
6137 QToolBar* toolbar = fToolbarApp;
6138 if (! fDefaultIcons) {
6139 toolbar = fToolbarUser;
6141 if (toolbar ==
nullptr)
return;
6143 QList<QAction*> list = toolbar->actions();
6144 for (
auto i : list) {
6145 if (i->data().toString() ==
"pick") {
6146 i->setChecked(fPickSelected);
6154 fZoomInSelected =
true;
6155 fMoveSelected =
false;
6156 fRotateSelected =
false;
6157 fZoomOutSelected =
false;
6159 QToolBar* toolbar = fToolbarApp;
6160 if (! fDefaultIcons) {
6161 toolbar = fToolbarUser;
6163 if (toolbar ==
nullptr)
return;
6165 QList<QAction*> list = toolbar->actions();
6166 for (
auto i : list) {
6167 if (i->data().toString() ==
"zoom_in") {
6168 i->setChecked(
true);
6170 else if (i->data().toString() ==
"move") {
6171 i->setChecked(
false);
6173 else if (i->data().toString() ==
"rotate") {
6174 i->setChecked(
false);
6176 else if (i->data().toString() ==
"zoom_out") {
6177 i->setChecked(
false);
6185 fZoomOutSelected =
true;
6186 fMoveSelected =
false;
6187 fRotateSelected =
false;
6188 fZoomInSelected =
false;
6190 QToolBar* toolbar = fToolbarApp;
6191 if (! fDefaultIcons) {
6192 toolbar = fToolbarUser;
6194 if (toolbar ==
nullptr)
return;
6196 QList<QAction*> list = toolbar->actions();
6197 for (
auto i : list) {
6198 if (i->data().toString() ==
"zoom_out") {
6199 i->setChecked(
true);
6201 else if (i->data().toString() ==
"move") {
6202 i->setChecked(
false);
6204 else if (i->data().toString() ==
"rotate") {
6205 i->setChecked(
false);
6207 else if (i->data().toString() ==
"zoom_in") {
6208 i->setChecked(
false);
6217 QToolBar* toolbar = fToolbarApp;
6218 if (! fDefaultIcons) {
6219 toolbar = fToolbarUser;
6221 if (toolbar ==
nullptr)
return;
6223 QList<QAction*> list = toolbar->actions();
6224 for (
auto i : list) {
6225 if (i->data().toString() ==
"solid") {
6226 i->setChecked(
true);
6228 else if (i->data().toString() ==
"hidden_line_removal") {
6229 i->setChecked(
false);
6231 else if (i->data().toString() ==
"hidden_line_and_surface_removal") {
6232 i->setChecked(
false);
6234 else if (i->data().toString() ==
"wireframe") {
6235 i->setChecked(
false);
6237 else if (i->data().toString() ==
"point_cloud") {
6238 i->setChecked(
false);
6247 QToolBar* toolbar = fToolbarApp;
6248 if (! fDefaultIcons) {
6249 toolbar = fToolbarUser;
6251 if (toolbar ==
nullptr)
return;
6253 QList<QAction*> list = toolbar->actions();
6254 for (
auto i : list) {
6255 if (i->data().toString() ==
"wireframe") {
6256 i->setChecked(
true);
6258 else if (i->data().toString() ==
"hidden_line_removal") {
6259 i->setChecked(
false);
6261 else if (i->data().toString() ==
"hidden_line_and_surface_removal") {
6262 i->setChecked(
false);
6264 else if (i->data().toString() ==
"solid") {
6265 i->setChecked(
false);
6267 else if (i->data().toString() ==
"point_cloud") {
6268 i->setChecked(
false);
6277 QToolBar* toolbar = fToolbarApp;
6278 if (! fDefaultIcons) {
6279 toolbar = fToolbarUser;
6281 if (toolbar ==
nullptr)
return;
6283 QList<QAction*> list = toolbar->actions();
6284 for (
auto i : list) {
6285 if (i->data().toString() ==
"hidden_line_removal") {
6286 i->setChecked(
true);
6288 else if (i->data().toString() ==
"solid") {
6289 i->setChecked(
false);
6291 else if (i->data().toString() ==
"hidden_line_and_surface_removal") {
6292 i->setChecked(
false);
6294 else if (i->data().toString() ==
"wireframe") {
6295 i->setChecked(
false);
6297 else if (i->data().toString() ==
"point_cloud") {
6298 i->setChecked(
false);
6307 QToolBar* toolbar = fToolbarApp;
6308 if (! fDefaultIcons) {
6309 toolbar = fToolbarUser;
6312 if (toolbar ==
nullptr)
return;
6314 QList<QAction*> list = toolbar->actions();
6315 for (
auto i : list) {
6316 if (i->data().toString() ==
"hidden_line_and_surface_removal") {
6317 i->setChecked(
true);
6319 else if (i->data().toString() ==
"solid") {
6320 i->setChecked(
false);
6322 else if (i->data().toString() ==
"hidden_line_removal") {
6323 i->setChecked(
false);
6325 else if (i->data().toString() ==
"wireframe") {
6326 i->setChecked(
false);
6328 else if (i->data().toString() ==
"point_cloud") {
6329 i->setChecked(
false);
6338 QToolBar* toolbar = fToolbarApp;
6339 if (!fDefaultIcons) {
6340 toolbar = fToolbarUser;
6342 if (toolbar ==
nullptr)
return;
6344 QList<QAction*> list = toolbar->actions();
6345 for (
auto i : list) {
6346 if (i->data().toString() ==
"point_cloud") {
6347 i->setChecked(
true);
6349 else if (i->data().toString() ==
"wireframe") {
6350 i->setChecked(
false);
6352 else if (i->data().toString() ==
"hidden_line_removal") {
6353 i->setChecked(
false);
6355 else if (i->data().toString() ==
"hidden_line_and_surface_removal") {
6356 i->setChecked(
false);
6358 else if (i->data().toString() ==
"solid") {
6359 i->setChecked(
false);
6369 QToolBar* toolbar = fToolbarApp;
6370 if (! fDefaultIcons) {
6371 toolbar = fToolbarUser;
6373 if (toolbar ==
nullptr)
return;
6375 QList<QAction*> list = toolbar->actions();
6376 for (
auto i : list) {
6377 if (i->data().toString() ==
"perspective") {
6378 i->setChecked(
true);
6380 else if (i->data().toString() ==
"ortho") {
6381 i->setChecked(
false);
6390 QToolBar* toolbar = fToolbarApp;
6391 if (! fDefaultIcons) {
6392 toolbar = fToolbarUser;
6395 if (toolbar ==
nullptr)
return;
6397 QList<QAction*> list = toolbar->actions();
6398 for (
auto i : list) {
6399 if (i->data().toString() ==
"ortho") {
6400 i->setChecked(
true);
6402 else if (i->data().toString() ==
"perspective") {
6403 i->setChecked(
false);
6408#if QT_VERSION < 0x060000
6410 : QTabWidget(aParent),
6417 setMinimumSize(100, 100);
6418 QSizePolicy policy = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
6419 setSizePolicy(policy);
6430 if (!
GetOutputList().contains(QString(
" ") + outputStream +
" ")) {
6439void G4UIQt::TabCloseCallback(
int a)
6441 if (fViewerTabWidget ==
nullptr)
return;
6444 QWidget* temp = fViewerTabWidget->widget(a);
6446#if QT_VERSION < 0x060000
6448 fViewerTabWidget->removeTab(a);
6452 for (
G4int c = 0; c < fViewerTabWidget->count(); ++c) {
6453 if (fViewerTabWidget->tabText(c).contains(
"viewer")) {
6459 CreateEmptyViewerPropertiesWidget();
6465 QObject::disconnect(fViewerTabWidget, SIGNAL(currentChanged(
int)),
this, SLOT(UpdateTabWidget(
int)));
6466 fViewerTabWidget->removeTab(a);
6467 QObject::connect(fViewerTabWidget, SIGNAL(currentChanged(
int)),
this, SLOT(UpdateTabWidget(
int)));
6469 G4int lastViewerTabIndex = -1;
6470 for (
G4int c = 0; c < fViewerTabWidget->count(); ++c) {
6471 if (fViewerTabWidget->tabText(c).contains(
"viewer")) {
6472 lastViewerTabIndex = c;
6480 if (lastViewerTabIndex==(-1)) {
6481 CreateEmptyViewerPropertiesWidget();
6483 UpdateTabWidget(lastViewerTabIndex);
6488void G4UIQt::ToolBoxActivated(
int a)
6490 if (fUITabWidget->widget(a) == fHelpTBWidget) {
6494 else if (fUITabWidget->widget(a) == fSceneTreeWidget) {
6495 fSceneTreeWidget->setVisible(
true);
6499#if QT_VERSION < 0x060000
6502 if (currentWidget() !=
nullptr) {
6506 QString text = tabText(currentIndex());
6509 auto edit =
dynamic_cast<QTextEdit*
>(currentWidget());
6510 if (edit ==
nullptr) {
6511 QString paramSelect = QString(
"/vis/viewer/select ") + text;
6513 if (UI !=
nullptr) {
G4TemplateAutoLock< G4Mutex > G4AutoLock
#define G4MUTEX_INITIALIZER
G4GLOB_DLL std::ostream G4cout
G4double GetAlpha() const
G4double GetGreen() const
G4String GetFullPrefixString() const
G4String GetPrefixString() const
static G4Qt * getInstance()
void FlushAndWaitExecution() override
const G4String & GetDescription() const
const std::list< G4SceneTreeItem > & GetChildren() const
const G4String & GetPVPath() const
const std::map< G4String, G4AttDef > * GetAttDefs() const
std::vector< G4AttValue > * GetAttValues() const
static G4StateManager * GetStateManager()
G4UIOutputString(const QString &text, const G4String &thread="", const G4String &outputstream="info")
G4bool AddTabWidget(QWidget *, QString)
QWidget * GetViewerPropertiesWidget()
void SetIconOrthoSelected()
void UpdateSceneTree(const G4SceneTreeItem &) override
G4UIsession * SessionStart() override
void SetStartPage(const std::string &)
void UpdateDrawingStyle(G4int style) override
G4bool AddViewerTabFromFile(std::string fileName, std::string title)
G4int ReceiveG4cout(const G4String &) override
void SetIconZoomInSelected()
void PauseSessionStart(const G4String &) override
void AddMenu(const char *, const char *) override
void UpdateProjectionStyle(G4int style) override
QWidget * GetSceneTreeWidget()
G4int ReceiveG4cerr(const G4String &) override
void AddButton(const char *, const char *, const char *) override
void SetOutputStyle(const char *destination, const char *style) override
void SetIconZoomOutSelected()
void SetIconHLRSelected()
void ClearMenu() override
void SetIconPerspectiveSelected()
void UpdateTransparencySlider(G4double depth, G4int option) override
void NativeMenu(G4bool aVal) override
QWidget * GetPickInfosWidget()
void DefaultIcons(G4bool aVal) override
void SetIconSolidSelected()
G4int ReceiveG4debug(const G4String &) override
void SetIconRotateSelected()
void Prompt(const G4String &)
void SetIconCoudPointSelected()
void SetIconWireframeSelected()
void SetIconMoveSelected()
G4bool AddViewerTab(QWidget *w, std::string title)
void TogglePickSelection()
void AddIcon(const char *userLabel, const char *iconFile, const char *command, const char *file_name="") override
void SetIconHLHSRSelected()
G4int GetCommandEntry() const
const G4UIcommand * GetGuidance() const
G4UIcommand * GetCommand(G4int i)
const G4String & GetPathName() const
G4int GetTreeEntry() const
G4UIcommandTree * GetTree(G4int i)
G4UIcommandTree * FindCommandTree(const char *commandPath)
const G4String GetTitle() const
G4String GetFirstMatchedString(const G4String &, const G4String &) const
G4UIcommand * FindPath(const char *commandPath) const
std::size_t GetParameterEntries() const
const G4String & GetGuidanceLine(G4int i) const
G4UIparameter * GetParameter(G4int i) const
static G4String ConvertToString(G4bool boolVal)
const G4String & GetCommandPath() const
std::size_t GetGuidanceEntries() const
const G4String & GetCommandName() const
const G4String & GetRange() const
void SetCoutDestination(G4UIsession *const value)
G4UIcommandTree * GetTree() const
G4int ApplyCommand(const char *aCommand)
bool IsLastCommandOutputTreated()
G4int GetVerboseLevel() const
G4String FindMacroPath(const G4String &fname) const
static G4UImanager * GetUIpointer()
G4MTcoutDestination * GetThreadCout()
void SetSession(G4UIsession *const value)
void SetG4UIWindow(G4UIsession *const value)
void SetLastCommandOutputTreated()
const G4String & GetParameterCandidates() const
const G4String & GetParameterGuidance() const
G4bool IsOmittable() const
const G4String & GetParameterRange() const
G4bool GetCurrentAsDefault() const
char GetParameterType() const
const G4String & GetParameterName() const
const G4String & GetDefaultValue() const
G4String ModifyToFullPathCommand(const char *aCommandLine) const
G4String Complete(const G4String &)
void TerminalHelp(const G4String &)
void ApplyShellCommand(const G4String &, G4bool &, G4bool &)
virtual void ExitHelp() const =0
G4Interactor GetInteractor(const G4String &)
void SetStyleUtility(const G4String &destination, const G4String &style)
std::map< G4String, OutputStyle > fOutputStyles
void AddInteractor(G4String, G4Interactor)
void EnableSecondaryLoop()
G4Interactor GetMainInteractor()
void DisableSecondaryLoop()
static G4MTGLOB_DLL G4coutDestination * masterG4coutDestination
const char * name(G4int ptype)
void strip(G4String &str, char ch=' ')
Remove leading and trailing characters from string.
G4bool contains(const G4String &str, std::string_view ss)
Check if a string contains a given substring.
G4String lstrip_copy(G4String str, char ch=' ')
Return copy of string with leading characters removed.