ATLAS CalibrationConsole
This page presents a detailed description of the port from Qt3 to Qt4 for the ATLAS CalibrationConsole.
Qt provides some documentation on the classes that have changed.
There are also some manuals which may or may not be helpful:
Eventually one needs to run in SR1. Here's how to get setup there:
CalibrationConsole Projects
There are 11 main folders that make up the CalibrationConsole. Each of these folders contains a *.pro file, which is the Qt steering file. Each folder will be defined as a project.
[ps]
To open up and view all the files in a project, open Qt Creator, select Open Project and select the appropriate *.pro file.
One can compile the code from within Qt Creator, but I find it easier to do this from the command line. From the desired project:
- >> make JOBS=2 && make install.
The install part is essential. When you call the program
Console
, it pulls the libraries from the
installed
directory.
Occasionally .moc and .obj files will need to be cleaned because Qt is playing up. A
make clean
should do the trick, but it seems to fail sometimes. In this case do
- >> rm -r .moc .obj
- >> qmake
- >> make JOBS=2 && make install.
- In the .pro files there is a line such as "QT += qt3support". Remove this line to disable Qt3 support classes.
ui_ Type Files
In each project, as in all C++ projects, there are source (.cxx) and header (.h) files. In some projects there are also ui_* files. These describe the underlying graphical user interface for a specific menu. The following ui_ files are present (red indicates that there is still Qt3 classes being used):
CalibrationDataView |
Console |
CTViewer |
DcsMonitor |
Executor |
OHViewer |
ScanView |
ui_AxisRangeBase.h |
ui_CanStatusPanelBase.h |
ui_AddDirectoryFormBase.h (Q3GroupBox, Q3ListView) |
ui_DcsSubscriptionsBase.h |
ui_CommandListBase.h (Q3ListView, Q3ProgressBar) |
ui_ScanSerialNumberDialogBase.h |
ui_BocEditorBase.h (Q3ListView, Q3ComboBox) |
ui_DbTagsPanelBase.h |
ui_CloneTagsBase.h |
ui_EnterPatternFormBase.h |
|
|
ui_searchdbcoralformbase.h |
ui_ChangeBocSettingsBase.h (Q3Frame) |
ui_DetectorViewBase.h |
ui_ConfigEditBase.h |
ui_ProcessingFilesDialogBase.h (Q3ProgressBar, Q3ListView) |
|
|
|
ui_HistogramView.h (Q3ComboBox) |
ui_DetectorViewWindowBase.h |
ui_ConnectivityPanelBase.h |
|
|
|
|
ui_ObjectDataViewBase.h (Q3ListView) |
ui_DisablePanelBase.h |
ui_DontPanelBase.h |
|
|
|
|
ui_RodBufferViewBase.h (Q3ButtonGroup,Q3GroupBox,Q3ListView) |
ui_MainPanelBase.h |
ui_DontPanelStandbyBase.h |
|
|
|
|
ui_ScanPanelBase.h (Q3TextEdit,Q3GroupBox,Q3ProgressBar) |
ui_MessageDetailsBase.h |
ui_EditVectorFormBase.h |
|
|
|
|
|
ui_MetaDataDetailsBase.h |
ui_PartWinBase.h |
|
|
|
|
|
ui_MetaDataListBase.h (Q3GroupBox, Q3Header, Q3ListView) |
ui_PixCalibDataOfflineBase.h |
|
|
|
|
|
ui_ModuleListBase.h |
ui_PixScanPanelBase.h (Q3ListBox) |
|
|
|
|
|
ui_ModuleListViewBase.h |
ui_ScanSelectionBase.h (Q3ComboBox) |
|
|
|
|
|
ui_ModuleMaskBase.h (Q3Header, Q3ListView) |
|
|
|
|
|
|
ui_SaveDisableBase.h (Q3ButtonGroup) |
|
|
|
|
|
|
ui_SummaryHistogramViewBase.h |
|
|
|
|
|
|
Just because a project doesn't make use of ui_* files, doesn't mean it's not graphically orientated. Take PixDetectorView as an example. This whole project describes graphical objects likes shapes as well as scenes (somewhere to put the shapes). But because it never actually defines a GUI, it doesn't have any ui_* files.
It's also important to not that each ui_ file also has a further corresponding source and head file. For example, the project in-which the file ui_MainPanelBase.h lies also has
MainPanel.h/cxx. These two files WILL have further
Q3Support classes that may or may not be graphics orientated.
This way the ui_ files are used is described in this example for ui_configEditBase.h:
The ui_ file is included in the header file, which the class then inherits from. The method setupUi(this) "draws" all the elements in the ui_ file. The cxx file then has access to all the methods that objects in the ui_ file have. Take care to rewrite the objects methods in the cxx files. Often they are very different. Refer to the documentation that Qt provides.
Example of a ui_ file
#ifndef UI_DETECTORVIEWBASE_H
#define UI_DETECTORVIEWBASE_H
#include <QGroupBox>
#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QComboBox>
#include <QtGui/QHBoxLayout>
#include <QtGui/QHeaderView>
#include <QtGui/QPushButton>
#include <QtGui/QSpacerItem>
#include <QtGui/QVBoxLayout>
#include <QtGui/QWidget>
QT_BEGIN_NAMESPACE
class Ui_DetectorViewBase // the ui file get it's own class name.
{
public:
QVBoxLayout *vboxLayout;
QHBoxLayout *hboxLayout;
QPushButton *m_newWindowButton;
QSpacerItem *spacer2;
QHBoxLayout *hboxLayout1;
QPushButton *m_zoomOutButton;
QPushButton *m_zoomInButton;
QPushButton *m_viewButton;
QSpacerItem *spacer2_2;
QPushButton *m_printButton;
QPushButton *m_rotateButton;
QSpacerItem *spacer1;
QComboBox *m_categorySelector;
QComboBox *m_serialNumberSelector;
QComboBox *m_variableSelector;
QGroupBox *groupBox1;
QVBoxLayout *vboxLayout1;
// define the setupUi function called in the DetectorView header file
void setupUi(QWidget *DetectorViewBase)
{
if (DetectorViewBase->objectName().isEmpty())
DetectorViewBase->setObjectName(QString::fromUtf8("DetectorViewBase")); // This isn't actually needed but it is a relic of Qt3 -> Qt4 conversion.
DetectorViewBase->resize(600, 480); // Set the window size
DetectorViewBase->setFocusPolicy(Qt::WheelFocus);
vboxLayout = new QVBoxLayout(DetectorViewBase); // Define the main layout. Things will be added in descending order.
vboxLayout->setSpacing(6);
vboxLayout->setContentsMargins(0, 0, 0, 0);
vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
////////////// Toolbar //////////////
hboxLayout = new QHBoxLayout(); // A layout specifically for the toolbar
hboxLayout->setSpacing(6);
hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
m_newWindowButton = new QPushButton(DetectorViewBase); // Defines a new button...
m_newWindowButton->setObjectName(QString::fromUtf8("m_newWindowButton"));
m_newWindowButton->setIcon(QIcon(QPixmap(":/icons/images/filenew_2.png"))); // ...with an image.
m_newWindowButton->setFlat(true);
hboxLayout->addWidget(m_newWindowButton); // Add this button to the toolbar horizontal layout
spacer2 = new QSpacerItem(16, 20, QSizePolicy::Fixed, QSizePolicy::Minimum); // set some spacing between first button and the next.
hboxLayout->addItem(spacer2); // Add the spacing to the horizontal layout
// create a series of buttons and add them to their own layout (view + and -, rotate, view options)
hboxLayout1 = new QHBoxLayout();
hboxLayout1->setSpacing(0);
hboxLayout1->setContentsMargins(0, 0, 0, 0);
hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
m_zoomOutButton = new QPushButton(DetectorViewBase);
m_zoomOutButton->setObjectName(QString::fromUtf8("m_zoomOutButton"));
m_zoomOutButton->setIcon(QIcon(QPixmap(":/icons/images/viewmag-.png")));
m_zoomOutButton->setFlat(true);
hboxLayout1->addWidget(m_zoomOutButton);
m_zoomInButton = new QPushButton(DetectorViewBase);
m_zoomInButton->setObjectName(QString::fromUtf8("m_zoomInButton"));
m_zoomInButton->setIcon(QIcon(QPixmap(":/icons/images/viewmag+.png")));
m_zoomInButton->setFlat(true);
hboxLayout1->addWidget(m_zoomInButton);
m_rotateButton = new QPushButton(DetectorViewBase);
m_rotateButton->setObjectName(QString::fromUtf8("m_rotateButton"));
m_rotateButton->setMaximumSize(QSize(100, 100));
m_rotateButton->setIcon(QIcon(QPixmap(":/icons/images/rotate.png")));
m_rotateButton->setFlat(true);
hboxLayout->addWidget(m_rotateButton);
m_viewButton = new QPushButton(DetectorViewBase);
m_viewButton->setObjectName(QString::fromUtf8("m_viewButton"));
m_viewButton->setIcon(QIcon(QPixmap(":/icons/images/eye.png")));
m_viewButton->setFlat(true);
hboxLayout1->addWidget(m_viewButton);
hboxLayout->addLayout(hboxLayout1); // Add the horizontal layout to the parent horizontal layout
spacer2_2 = new QSpacerItem(16, 20, QSizePolicy::Fixed, QSizePolicy::Minimum); // Create another spacer between buttons in the toolbar...
hboxLayout->addItem(spacer2_2); // ... and add it to the main horizontal layout
// Create the file print button and add to the horizontal layout
m_printButton = new QPushButton(DetectorViewBase);
m_printButton->setObjectName(QString::fromUtf8("m_printButton"));
m_printButton->setMaximumSize(QSize(100, 100));
m_printButton->setIcon(QIcon(QPixmap(":/icons/images/fileprint.png")));
m_printButton->setFlat(true);
hboxLayout->addWidget(m_printButton);
spacer1 = new QSpacerItem(20, 20, QSizePolicy::Fixed, QSizePolicy::Minimum);
hboxLayout->addItem(spacer1);
// Create some QComboBoxes
m_categorySelector = new QComboBox(DetectorViewBase);
m_categorySelector->setObjectName(QString::fromUtf8("m_categorySelector"));
QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(3), static_cast<QSizePolicy::Policy>(0));
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(m_categorySelector->sizePolicy().hasHeightForWidth());
m_categorySelector->setSizePolicy(sizePolicy);
m_categorySelector->setMinimumSize(QSize(75, 0)); // just some styling options
hboxLayout->addWidget(m_categorySelector);
m_serialNumberSelector = new QComboBox(DetectorViewBase);
m_serialNumberSelector->setObjectName(QString::fromUtf8("m_serialNumberSelector"));
hboxLayout->addWidget(m_serialNumberSelector);
m_variableSelector = new QComboBox(DetectorViewBase);
m_variableSelector->setObjectName(QString::fromUtf8("m_variableSelector"));
sizePolicy.setHeightForWidth(m_variableSelector->sizePolicy().hasHeightForWidth());
m_variableSelector->setSizePolicy(sizePolicy);
m_variableSelector->setMinimumSize(QSize(80, 0));
hboxLayout->addWidget(m_variableSelector); // and add them to the H. layout
///////////////////////////////////////////////////////////////
vboxLayout->addLayout(hboxLayout); // add the horizonal layout to the topmost position of the vertical layout
groupBox1 = new QGroupBox(DetectorViewBase);
vboxLayout1 = new QVBoxLayout();
vboxLayout1->addStretch(2);
groupBox1->setLayout(vboxLayout1);
vboxLayout->addWidget(groupBox1);
// connect verious clicked signals to various custom slots that are defined in .h and .cxx files. Note, you don't have to do it here, but its a good way to organise code.
retranslateUi(DetectorViewBase);
QObject::connect(m_categorySelector, SIGNAL(activated(QString)), DetectorViewBase, SLOT(changedCategory(QString)));
QObject::connect(m_variableSelector, SIGNAL(activated(QString)), DetectorViewBase, SLOT(changedVariable(QString)));
QObject::connect(m_serialNumberSelector, SIGNAL(activated(QString)), DetectorViewBase, SLOT(changedSerialNumber(QString)));
QObject::connect(m_newWindowButton, SIGNAL(clicked()), DetectorViewBase, SLOT(cloneView()));
QObject::connect(m_zoomInButton, SIGNAL(clicked()), DetectorViewBase, SLOT(zoomIn()));
QObject::connect(m_zoomOutButton, SIGNAL(clicked()), DetectorViewBase, SLOT(zoomOut()));
QObject::connect(m_rotateButton, SIGNAL(clicked()), DetectorViewBase, SLOT(rotateView()));
QObject::connect(m_printButton, SIGNAL(clicked()), DetectorViewBase, SLOT(printToFile())); // i.e.: Connect the print button widget, so that when pressed, it calls the printToFile() function defined in the cxx file.
QMetaObject::connectSlotsByName(DetectorViewBase);
} // setupUi
// some qt magic that sets further options.
void retranslateUi(QWidget *DetectorViewBase)
{
...
} // retranslateUi
};
namespace Ui {
class DetectorViewBase: public Ui_DetectorViewBase {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_DETECTORVIEWBASE_H
The resulting code creates the area outlined in red in the following image (minus the detector/crates inside the view):
PixDetectorView
The PixDetectorView required quite a bit of work. Qt4 rewrote its
graphics view framework. Therefore, many things changed with the hope of creating and manipulating custom objects being much easier in Qt4. The concept of a "canvas" has been replaced with a "scene". Graphics objects have to be added to a scene. The scene is displayed in a
GraphicsView. This
GraphicsView now handles object transformations such as zooming, clicking, rotating etc.
There really are a lot of class changes and implementations so it might just be easier to look at the code, but one major change is the following:
- Any reference to some sort of Logo has been taken out. This is the "dynamic" image that greets you before you click on a module (so currently there is just white space there). This was implemented in an extremely complicated way using the Q3CanvasPixmapArray and Q3CanvasSprite classes. These classes were discontinued in Qt4. Rather than waste time getting this semi-aesthetically pleasing object working, it was simply removed. Something may be added at a later date.
An example of the new
PixDetectorView in it's full window and rotated options is shown here:
Unfortunately the text does not rate with the image, and this will not likely change.
Resource files
Qt4 has a new system when it comes to dealing with importing images. The old way would be as follows:
#include <Qt3Support/Q3MimeSourceFactory>
...
m_clearFilterButton->setIcon(QPixmap(qPixmapFromMimeSource("gtk-clear.png")));
The new way is to do:
#include <QPixmap>
...
m_clearFilterButton->setIcon(QIcon(QPixmap(":/icons/images/gtk-clear.png")));
In order for this to work, one has to have a "Resource file" where images can be added. This in the project under the "Resources" tab. For more information see Qt's documentation,
here
Old vs New
For the most part, functionality should remain the same or very similar to the old Console. Here are some screenshots of some new GUIs. (Better quality images will be uploaded at a later stage)
Testing new version
- When selecting crates from initial Gui at startup, are these correctly applied?
- Are all button images loaded? Specifically above the pixel detector window.
- Check "rotate view" button.
- Executors scan progress bar (this probably won't work)
More to come...
Priority list
- Scaled PP0ZoomView so there's no overlap
- Document leftover Q3 classes in other pixel code applications
- Left over Q3 classes in ui_ and .cxx/h files
- Fix Q3 Classes in Applications that are not CalibrationConsole (converting to ui_ etc)
For next "shifter"
Warnings/old code
- There are a good amount of unused parameters such as "name", "modal, "fl". This is a relic of the port. These parameters are not needed in the function calls, but can't be removed in steps due to changing function calls number of parameters. This has to be fixed in 1 go. An example, in Console/EditVectorForm.cxx, line 84:
EditVectorForm::EditVectorForm(const QString &title, const QString &text, bool integer, QWidget* parent, const char* name, bool modal, Qt::WFlags fl )
Many methods depend on EditVectorForm having 7 parameters. Those need to be updated accordingly.
- For RodMon, when starting the GUI a few warning messages appear such as
Object::connect: No such signal ...
. This is quite odd since those signals do exist and the functions it refers to all seem to work.
- Anything to do with a "Logo" has been taken out. The old method used Q3CanvasPixmaps and sprites which are no longer supported in Qt4. As a result, it's just easier not to have logos. Unfortunately, a lot of function calls rely on this logo object. For example:
m_detectorView=std::unique_ptr<PixCon::RodStatusMonitor_MainPanel>(new PixCon::RodStatusMonitor_MainPanel( user_mode,
partition_name,
m_calibrationData,
histogram_cache,
palette,
m_categories,
context_menu,
boost::shared_ptr<PixDet::ILogoFactory>(new PixDet::FullDetectorLogoFactory),
visualiser_list,
boost::shared_ptr<PixCon::IsMonitorManager>(new PixCon::IsMonitorManager),
*this) );
Note the line
boost::shared_ptr<PixDet::ILogoFactory>(new PixDet::FullDetectorLogoFactory)
Until all these calls are fixed (removed), they eventually point to empty functions for now. For example:
namespace PixCon {
CTLogoFactory::CTLogoFactory() {
//DEPRECATEDFUNCTION
}
void CTLogoFactory::drawLogo(DetectorCanvasView *canvas_view, const QRectF &pos)
{
//DEPRECATEDFUNCTION
}
}
One can search for the places this occurs by grepping for "DEPRECATEDFUNCTION".
- Implement a double click to go straight to defualt histogram on staves. (As opposed to right clicking then going through the menus).
Known bugs
- When trying to open histograms from old scans, CC crashes. This does not occur if a scan has been run in currently opened console window. It only crashes when no scans have been run, and someone tries to open histograms from an old scan.
Q3ListView
This is a more difficult class to port as so much of Calibration Console relies on the old structure this class provided. This is potentially the hardest leftover class to convert the rest of the CC to pure Qt4.
Q3ListView is associated with
Q3ListViewItem and Q3Header.
The easiest way to see this is in an example using the
ConnectivityBasePanel. Click to see the OLD and NEW versions.
--
JoshuaWyattSmith - 2015-11-14