Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
/gui/webdisplay/ @linev
/gui/cefdisplay/ @linev
/gui/qt6webdisplay/ @linev
/gui/qt6canvas/ @linev
/gui/webgui6/ @linev
/gui/fitpanelv7/ @linev
/gui/browsable/ @bellenot @linev
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/root-ci-config/buildconfig/global.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ opengl=ON
pyroot=ON
pythia8=OFF
qt6web=OFF
qt6canv=OFF
roofit=ON
roofit_multiprocess=OFF
root7=ON
Expand Down
2 changes: 2 additions & 0 deletions cmake/modules/RootBuildOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ ROOT_BUILD_OPTION(mpi OFF "Enable support for Message Passing Interface (MPI)")
ROOT_BUILD_OPTION(opengl ON "Enable support for OpenGL (requires libGL and libGLU)")
ROOT_BUILD_OPTION(pyroot ON "Enable support for automatic Python bindings (PyROOT)")
ROOT_BUILD_OPTION(pythia8 OFF "Enable support for Pythia 8.x [GPL]")
ROOT_BUILD_OPTION(qt6canv OFF "Enable Qt6 canvas (requires Qt6::Gui)")
ROOT_BUILD_OPTION(qt6web OFF "Enable support for Qt6 web-based display (requires Qt6::WebEngineCore and Qt6::WebEngineWidgets)")
ROOT_BUILD_OPTION(roofit ON "Build the advanced fitting package RooFit, and RooStats for statistical tests. If xml is available, also build HistFactory.")
ROOT_BUILD_OPTION(roofit_multiprocess OFF "Build RooFit::MultiProcess and multi-process RooFit::TestStatistics classes (requires ZeroMQ >= 4.3.5 built with -DENABLE_DRAFTS and cppzmq).")
Expand Down Expand Up @@ -222,6 +223,7 @@ if(all)
set(opengl_defvalue ON)
set(pythia8_defvalue ON)
set(pyroot_defvalue ON)
set(qt6canv_defvalue ON)
set(qt6web_defvalue ON)
set(r_defvalue ON)
set(roofit_defvalue ON)
Expand Down
28 changes: 24 additions & 4 deletions core/gui/src/TGuiFactory.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,26 @@ TApplicationImp *TGuiFactory::CreateApplicationImp(const char *classname, int *a

TCanvasImp *TGuiFactory::CreateCanvasImp(TCanvas *c, const char *title, UInt_t width, UInt_t height)
{
TString canvName;
if (gROOT->IsWebDisplay()) {
auto ph = gROOT->GetPluginManager()->FindHandler("TCanvasImp", "TWebCanvas");
canvName = "TWebCanvas";
} else {
canvName = gEnv->GetValue("Canvas.Name", "");
// in batch web display should be configured explicitely
if (canvName == "TWebCanvas")
canvName.Clear();
}

if (!canvName.IsNull() && (canvName != "TRootCanvas") && (canvName != "TCanvasImp")) {
auto ph = gROOT->GetPluginManager()->FindHandler("TCanvasImp", canvName);

if (ph && ph->LoadPlugin() != -1) {
auto imp = (TCanvasImp *)ph->ExecPlugin(6, c, title, 0, 0, width, height);
if (imp)
return imp;
}

Error("CreateCanvasImp", "Fail to create TWebCanvas, please provide missing libWebGui6 or run 'root --web=off'");
Error("CreateCanvasImp", "Fail to create %s canvas implementation", canvName.Data());
}

return new TCanvasImp(c, title, width, height);
Expand All @@ -76,16 +86,26 @@ TCanvasImp *TGuiFactory::CreateCanvasImp(TCanvas *c, const char *title, UInt_t w

TCanvasImp *TGuiFactory::CreateCanvasImp(TCanvas *c, const char *title, Int_t x, Int_t y, UInt_t width, UInt_t height)
{
TString canvName;
if (gROOT->IsWebDisplay()) {
auto ph = gROOT->GetPluginManager()->FindHandler("TCanvasImp", "TWebCanvas");
canvName = "TWebCanvas";
} else {
canvName = gEnv->GetValue("Canvas.Name", "");
// in batch web display should be configured explicitely
if (canvName == "TWebCanvas")
canvName.Clear();
}

if (!canvName.IsNull() && (canvName != "TRootCanvas") && (canvName != "TCanvasImp")) {
auto ph = gROOT->GetPluginManager()->FindHandler("TCanvasImp", canvName);

if (ph && ph->LoadPlugin() != -1) {
auto imp = (TCanvasImp *)ph->ExecPlugin(6, c, title, x, y, width, height);
if (imp)
return imp;
}

Error("CreateCanvasImp", "Fail to create TWebCanvas, please provide missing libWebGui6 or run 'root --web=off'");
Error("CreateCanvasImp", "Fail to create %s canvas implementation", canvName.Data());
}

return new TCanvasImp(c, title, x, y, width, height);
Expand Down
5 changes: 5 additions & 0 deletions etc/plugins/TCanvasImp/P020_TQt6Canvas.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
void P020_TQt6Canvas()
{
gPluginMgr->AddHandler("TCanvasImp", "TQt6Canvas", "TQt6Canvas",
"ROOTQt6Canvas", "NewCanvas(TCanvas *, const char *, Int_t, Int_t, UInt_t, UInt_t)");
}
5 changes: 5 additions & 0 deletions etc/plugins/TGuiFactory/P020_TQt6GuiFactory.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
void P020_TQt6GuiFactory()
{
gPluginMgr->AddHandler("TGuiFactory", "qt6", "TQt6GuiFactory",
"ROOTQt6Canvas", "TQt6GuiFactory()");
}
4 changes: 4 additions & 0 deletions gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ add_subdirectory(guihtml)
add_subdirectory(recorder)
add_subdirectory(treemap)

if(qt6canv)
add_subdirectory(qt6canvas)
endif()

if(webgui)
if(cefweb)
add_subdirectory(cefdisplay)
Expand Down
14 changes: 8 additions & 6 deletions gui/gui/src/TRootGuiFactory.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,12 @@ TCanvasImp *TRootGuiFactory::CreateCanvasImp(TCanvas *c, const char *title,
UInt_t width, UInt_t height)
{
TString canvName = gEnv->GetValue("Canvas.Name", "TWebCanvas");
if (canvName == "TWebCanvas") {
auto ph = gROOT->GetPluginManager()->FindHandler("TCanvasImp", "TWebCanvas");
if (!canvName.IsNull() && (canvName != "TRootCanvas")) {
auto ph = gROOT->GetPluginManager()->FindHandler("TCanvasImp", canvName);

if (ph && ph->LoadPlugin() != -1) {
ShowWebCanvasWarning();
if (canvName == "TWebCanvas")
ShowWebCanvasWarning();
auto imp = (TCanvasImp *) ph->ExecPlugin(6, c, title, 0, 0, width, height);
if (imp) return imp;
}
Expand All @@ -98,11 +99,12 @@ TCanvasImp *TRootGuiFactory::CreateCanvasImp(TCanvas *c, const char *title,
Int_t x, Int_t y, UInt_t width, UInt_t height)
{
TString canvName = gEnv->GetValue("Canvas.Name", "TWebCanvas");
if (canvName == "TWebCanvas") {
auto ph = gROOT->GetPluginManager()->FindHandler("TCanvasImp", "TWebCanvas");
if (!canvName.IsNull() && (canvName != "TRootCanvas")) {
auto ph = gROOT->GetPluginManager()->FindHandler("TCanvasImp", canvName);

if (ph && ph->LoadPlugin() != -1) {
ShowWebCanvasWarning();
if (canvName == "TWebCanvas")
ShowWebCanvasWarning();
auto imp = (TCanvasImp *) ph->ExecPlugin(6, c, title, x, y, width, height);
if (imp) return imp;
}
Expand Down
49 changes: 49 additions & 0 deletions gui/qt6canvas/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Copyright (C) 1995-2026, Rene Brun and Fons Rademakers.
# All rights reserved.
#
# For the licensing terms see $ROOTSYS/LICENSE.
# For the list of contributors see $ROOTSYS/README/CREDITS.

############################################################################
# CMakeLists.txt file for building ROOT gui/qt6canvas package
############################################################################

find_package(Qt6 COMPONENTS Core Widgets CONFIG)

if(NOT Qt6_FOUND)
if(fail-on-missing)
message(FATAL_ERROR "Could NOT find Qt6 with Gui components")
else()
message(WARNING "Qt6 (Gui) not found, disabling option 'qt6canvas'")
set(qt6canv OFF CACHE BOOL "Disabled because Qt6 Gui not found" FORCE)
return()
endif()
endif()


set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

ROOT_STANDARD_LIBRARY_PACKAGE(ROOTQt6Canvas
HEADERS
TQt6Canvas.h
TQt6PadPainter.h
TQt6GuiFactory.h
SOURCES
src/QCanvasWidget.cpp
src/QPaintWidget.cpp
src/QRootMethodDialog.cpp
src/QRootContextMenu.cpp
src/TQt6Canvas.cxx
src/TQt6PadPainter.cxx
src/TQt6GuiFactory.cxx
LIBRARIES
Qt6::Widgets
DEPENDENCIES
Core
Gpad
)

target_include_directories(ROOTQt6Canvas PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
21 changes: 21 additions & 0 deletions gui/qt6canvas/inc/LinkDef.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Author: Sergey Linev, GSI 26/06/2026

/*************************************************************************
* Copyright (C) 1995-2026, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/

#ifdef __CLING__

#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;

#pragma link C++ class TQt6Canvas+;
#pragma link C++ class TQt6PadPainter+;
#pragma link C++ class TQt6GuiFactory+;

#endif
83 changes: 83 additions & 0 deletions gui/qt6canvas/inc/TQt6Canvas.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Author: Sergey Linev, GSI 26/06/2026

/*************************************************************************
* Copyright (C) 1995-2026, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/

#ifndef ROOT_TQt6Canvas
#define ROOT_TQt6Canvas

#include "TCanvasImp.h"

class TPad;
class TExec;
class QWidget;
class QCanvasWidget;
class QPaintWidget;

class TQt6Canvas : public TCanvasImp {

protected:

QCanvasWidget *fCanvasWidget = nullptr;
QPaintWidget *fPaintWidget = nullptr;

Bool_t fFixedSize = kFALSE; ///<! true when fixed-size canvas is configured
UInt_t fClientBits = 0; ///<! latest status bits from client like editor visible or not

void ProcessExecs(TPad *pad, TExec *extra = nullptr);

Bool_t PerformUpdate(Bool_t async) override;
TVirtualPadPainter *CreatePadPainter() override;

void AssignStatusBits(UInt_t bits);


public:
TQt6Canvas(TCanvas *c, const char *name, Int_t x, Int_t y, UInt_t width, UInt_t height);
~TQt6Canvas() override;

QPaintWidget *GetPaintWidget() const { return fPaintWidget; }

Int_t InitWindow() override;
void Close() override;
void Show() override;

UInt_t GetWindowGeometry(Int_t &x, Int_t &y, UInt_t &w, UInt_t &h) override;
void GetCanvasGeometry(Int_t wid, UInt_t &w, UInt_t &h) override;
void ResizeCanvasWindow(Int_t) override {}
void UpdateDisplay(Int_t = 0, Bool_t = kFALSE) override {}

void ShowMenuBar(Bool_t = kTRUE) override { }
void ShowStatusBar(Bool_t = kTRUE) override { }
void ShowEditor(Bool_t = kTRUE) override { }
void ShowToolBar(Bool_t = kTRUE) override { }
void ShowToolTips(Bool_t = kTRUE) override { }

void ForceUpdate() override;

void SetWindowPosition(Int_t x, Int_t y) override;
void SetWindowSize(UInt_t w, UInt_t h) override;
void SetWindowTitle(const char *newTitle) override;
void SetCanvasSize(UInt_t w, UInt_t h) override;
void Iconify() override;
void RaiseWindow() override;

Bool_t HasEditor() const override;
Bool_t HasMenuBar() const override;
Bool_t HasStatusBar() const override;
Bool_t HasToolBar() const override { return kFALSE; }
Bool_t HasToolTips() const override;

static TCanvasImp *NewCanvas(TCanvas *c, const char *name, Int_t x, Int_t y, UInt_t width, UInt_t height);

static TCanvas *CreateQt6Canvas(const char *name, const char *title, UInt_t width = 1200, UInt_t height = 800);

ClassDefOverride(TQt6Canvas, 0) // Qt6 implementation for TCanvasImp
};

#endif
37 changes: 37 additions & 0 deletions gui/qt6canvas/inc/TQt6ContextMenu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Author: Sergey Linev 2/07/2026

/*************************************************************************
* Copyright (C) 1995-2026, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/

#ifndef ROOT_QRootContextMenu
#define ROOT_QRootContextMenu

#include "TContextMenuImp.h"
#include "TObject.h"

class QRootContextMenu : public TObject, public TContextMenuImp {

private:

QRootContextMenu(const QRootContextMenu&) = delete;
QRootContextMenu& operator=(const QRootContextMenu&) = delete;

public:
QRootContextMenu(TContextMenu *c = nullptr, const char *name = "ROOT Context Menu");
~QRootContextMenu() override;

void DisplayPopup(Int_t x, Int_t y) override;
void Dialog(TObject *object, TMethod *method) override;
void Dialog(TObject *object, TFunction *function) override;

void RecursiveRemove(TObject *obj) override;

ClassDefOverride(QRootContextMenu,0) // Qt6 GUI context sensitive popup menu
};

#endif
38 changes: 38 additions & 0 deletions gui/qt6canvas/inc/TQt6GuiFactory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Author: Sergey Linev 2/07/2026

/*************************************************************************
* Copyright (C) 1995-2026, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/


#ifndef ROOT_TQt6GuiFactory
#define ROOT_TQt6GuiFactory


#include "TGuiFactory.h"


class TQt6GuiFactory : public TGuiFactory {

protected:
void ShowWebCanvasWarning();

public:
TQt6GuiFactory(const char *name = "RootQt6", const char *title = "ROOT Qt6 GUI Factory");
~TQt6GuiFactory() override {}

TApplicationImp *CreateApplicationImp(const char *classname, int *argc, char **argv) override;

TCanvasImp *CreateCanvasImp(TCanvas *c, const char *title, UInt_t width, UInt_t height) override;
TCanvasImp *CreateCanvasImp(TCanvas *c, const char *title, Int_t x, Int_t y, UInt_t width, UInt_t height) override;

TContextMenuImp *CreateContextMenuImp(TContextMenu *c, const char *name, const char *title) override;

ClassDefOverride(TQt6GuiFactory,0) //Factory for Qt6 GUI components
};

#endif
Loading