Introduction
Vortex Studio uses Qt's technologies for creating its multiple user interfaces. with third parties (https://doc.qt.io/qt-5.9/build-sources.html)
In Vortex Studio, Qt 5.9.6 source is specificbraries and built into binary libraries with specific Qt's configurations. Changes were made to he changes are listed in the
The following sections detail steps by steps on how to build Qt 5.9.6.
Syments
- VS2015 C++ compiler
- Python 2.7
Package downloads
- Qt 5.9.6 (qt-everywhere-opensource-src-5.9.6.zip)
- OpenSSL 1.0.2 (openssl-1.0.2p.tar.gz)
- Perl 5.28.0.1 (strawberry-perl-5.28.0.1-64bit.msi)
Building Qt 5.9.6 for Windows
1) Run strawberry-perl-5.28.0.1-64bit.msi to install
2) Create a folder ( c:\qt59_for_windows)
3) Unzip the content of OpenSSL package 1.0.2 to a specified folder (e.g. c:\qt59_for_windows\openssl)
4) Unzip the content of Qt 5.9.6 package to a specified folder (e.g. c:\qt59_for_windows\qt5.9.6)
5) Apply patches listed in the section Patches for Qt 5.9.6 used in Vortex Studio.
6) Create a file named Makefile in the folder created in step #2 with this content
CURRENTDIR:=$(shell pwd)
makeit: openssl qt5.9.6 ;
TOOLCHAIN:=x64_win32_vc14
export INCLUDE:=$(CURRENTDIR)\stage_qt5_$(TOOLCHAIN)\include;$(INCLUDE)
export LIB:=$(CURRENTDIR)\stage_qt5_$(TOOLCHAIN)\lib;$(LIB)
openssl:
(cd openssl && \
perl Configure VC-WIN64A --prefix=$(CURRENTDIR)\stage_qt5_$(TOOLCHAIN) && \
ms\do_win64a && \
nmake -f ms\ntdll.mak && \
nmake -f ms\ntdll.mak install)
qt5.9.6:
(mkdir build_qt5_$(TOOLCHAIN) & cd build_qt5_$(TOOLCHAIN) && \
$(CURRENTDIR)\qt5.9.6\configure -debug-and-release -force-debug-info -recheck -shared -opensource -confirm-license -no-system-proxies -openssl -opengl desktop -skip qtwebengine -nomake tests -nomake examples -prefix $(CURRENTDIR)\stage_qt5_$(TOOLCHAIN))
.PHONY: openssl qt5.9.6
7) Open the tools command prompt for VS2015 x64 as administrator
8)
> make
Building Qt 5.9.6 for Linux
1) Run strawberry-perl-5.28.0.1-64bit.msi to install
2) Create a folder (e.g. c:\qt59_for_windows)
3) Start a Terminal
4) Unzip the content of OpenSSL package 1.0.2 to a specified folder (e.g. c:\qt59_for_windows\openssl)
5) Unzip the content of Qt5.9.6 ackage to a specified folder (e.g. c:\qt59_for_windows\qt5.9.6)
6) Apply patches listed in the n Patches for Qt 5.9.6 used in Vortex Studio.
7) Create a file named Makefile in the folder created in step #2 with this content
CURRENTDIR:=$(shell pwd)
makeit: openssl qt5.9.6 ;
TOOLCHAIN:=x64_rhel7_gcc48
export INCLUDE:=$(CURRENTDIR)/stage_qt5_$(TOOLCHAIN)/include;$(INCLUDE)
export LIB:=$(CURRENTDIR)/stage_qt5_$(TOOLCHAIN)/lib;$(LIB)
openssl:
(cd openssl && \
perl Configure linux-x86_64 --prefix=$(CURRENTDIR)/stage_qt5_$(TOOLCHAIN) && \
$(MAKE) && \
chmod +x util/pod2mantest && \
chmod +x util/point.sh && \
$(MAKE) install)
qt5.9.6:
(mkdir -p build_qt5_$(TOOLCHAIN) && cd build_qt5_$(TOOLCHAIN) && \
chmod +x $(CURRENTDIR)/qt5/configure && \
chmod +x $(CURRENTDIR)/qt5/qtbase/configure && \
$(CURRENTDIR)/qt5.9.6/configure -shared -opensource -confirm-license -no-system-proxies -openssl -opengl desktop -skip qtwebengine -nomake tests -nomake examples -prefix $(CURRENTDIR)/stage_qt5_$(TOOLCHAIN) && \
$(MAKE) && \
$(MAKE) install)
.PHONY: openssl qt5.9.6
8) Run
> make
Patches for Qt 5.9.6 used in Vortex Studio
The following changes were made in the original Qt 5.9.6 sourc
1) Patch #1:
\\qtbase\src\gui\kernel\qoffscreensurface.cpp:
line 185: Added a check for valid qGuiApp
if (qGuiApp && QThread::currentThread() != qGuiApp->thread())
2) Patch #2:
\\qtbase\src\corelib\kernel\qcoreapplication.cpp:
Line 1105: Use a copy of extraData→eventFilters
bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiver, QEvent *event)
{
if (extraData) {
auto eventFiltersCopy = extraData->eventFilters;
// application event filters are only called for objects in the GUI thread
for (int i = 0; i < eventFiltersCopy.size(); ++i) {
QObject *obj = eventFiltersCopy.at(i);
if (!obj)
continue;
if (obj->d_func()->threadData != threadData) {
qWarning("QCoreApplication: Application event filter cannot be in a different thread.");
continue;
}
if (obj->eventFilter(receiver, event))
return true;
}
}
return false;
}
3) Patch #3:
\\qtbase\src\widgets\widgets\qdockarealayout.cpp:
Added a new function sizeHintForDock(...)
static QSize sizeHintForDock(QDockAreaLayoutInfo &dock)
{
QSize size_hint = dock.size();
if (!dock.restoredSizeHint.isNull()) {
const QList<QDockAreaLayoutItem> item_list = dock.item_list;
for (int i = 0; i < item_list.size(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
QLayoutItem *w = item.widgetItem;
if (!item.skip() && w != 0 && !w->widget()->isHidden() && !w->widget()->isWindow()) {
size_hint = dock.restoredSizeHint;
break;
}
}
}
return size_hint;
}
Several changes were made to the function void QDockAreaLayout::getGrid(..) to use the added functioDock(...)
void QDockAreaLayout::getGrid(QVector<QLayoutStruct> *_ver_struct_list,
QVector<QLayoutStruct> *_hor_struct_list)
{
QSize center_hint(0, 0);
QSize center_min(0, 0);
QSize center_max(0, 0);
const bool have_central = centralWidgetItem != 0 && !centralWidgetItem->isEmpty();
if (have_central) {
center_hint = centralWidgetRect.size();
if (!center_hint.isValid())
center_hint = centralWidgetItem->sizeHint();
center_min = centralWidgetItem->minimumSize();
center_max = centralWidgetItem->maximumSize();
}
QRect center_rect = rect;
if (!docks[QInternal::LeftDock].isEmpty())
center_rect.setLeft(rect.left() + docks[QInternal::LeftDock].rect.width() + sep);
if (!docks[QInternal::TopDock].isEmpty())
center_rect.setTop(rect.top() + docks[QInternal::TopDock].rect.height() + sep);
if (!docks[QInternal::RightDock].isEmpty())
center_rect.setRight(rect.right() - docks[QInternal::RightDock].rect.width() - sep);
if (!docks[QInternal::BottomDock].isEmpty())
center_rect.setBottom(rect.bottom() - docks[QInternal::BottomDock].rect.height() - sep);
QSize left_hint = sizeHintForDock(docks[QInternal::LeftDock]);
if (left_hint.isNull() || fallbackToSizeHints)
left_hint = docks[QInternal::LeftDock].sizeHint();
QSize left_min = docks[QInternal::LeftDock].minimumSize();
QSize left_max = docks[QInternal::LeftDock].maximumSize();
left_hint = left_hint.boundedTo(left_max).expandedTo(left_min);
QSize right_hint = sizeHintForDock(docks[QInternal::RightDock]);
if (right_hint.isNull() || fallbackToSizeHints)
right_hint = docks[QInternal::RightDock].sizeHint();
QSize right_min = docks[QInternal::RightDock].minimumSize();
QSize right_max = docks[QInternal::RightDock].maximumSize();
right_hint = right_hint.boundedTo(right_max).expandedTo(right_min);
QSize top_hint = sizeHintForDock(docks[QInternal::TopDock]);
if (top_hint.isNull() || fallbackToSizeHints)
top_hint = docks[QInternal::TopDock].sizeHint();
QSize top_min = docks[QInternal::TopDock].minimumSize();
QSize top_max = docks[QInternal::TopDock].maximumSize();
top_hint = top_hint.boundedTo(top_max).expandedTo(top_min);
QSize bottom_hint = sizeHintForDock(docks[QInternal::BottomDock]);
if (bottom_hint.isNull() || fallbackToSizeHints)
bottom_hint = docks[QInternal::BottomDock].sizeHint();
QSize bottom_min = docks[QInternal::BottomDock].minimumSize();
QSize bottom_max = docks[QInternal::BottomDock].maximumSize();
bottom_hint = bottom_hint.boundedTo(bottom_max).expandedTo(bottom_min);
if (_ver_struct_list != 0) {
QVector<QLayoutStruct> &ver_struct_list = *_ver_struct_list;
ver_struct_list.resize(3);
// top --------------------------------------------------
ver_struct_list[0].init();
ver_struct_list[0].stretch = 0;
ver_struct_list[0].sizeHint = top_hint.height();
ver_struct_list[0].minimumSize = top_min.height();
ver_struct_list[0].maximumSize = top_max.height();
ver_struct_list[0].expansive = false;
ver_struct_list[0].empty = docks[QInternal::TopDock].isEmpty();
ver_struct_list[0].pos = docks[QInternal::TopDock].rect.top();
ver_struct_list[0].size = docks[QInternal::TopDock].rect.height();
// center --------------------------------------------------
ver_struct_list[1].init();
ver_struct_list[1].stretch = center_hint.height();
bool tl_significant = corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea
|| docks[QInternal::TopDock].isEmpty();
bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea
|| docks[QInternal::BottomDock].isEmpty();
bool tr_significant = corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea
|| docks[QInternal::TopDock].isEmpty();
bool br_significant = corners[Qt::BottomRightCorner] == Qt::BottomDockWidgetArea
|| docks[QInternal::BottomDock].isEmpty();
int left = (tl_significant && bl_significant) ? left_hint.height() : 0;
int right = (tr_significant && br_significant) ? right_hint.height() : 0;
ver_struct_list[1].sizeHint = qMax(left, center_hint.height(), right);
left = (tl_significant && bl_significant) ? left_min.height() : 0;
right = (tr_significant && br_significant) ? right_min.height() : 0;
ver_struct_list[1].minimumSize = qMax(left, center_min.height(), right);
ver_struct_list[1].maximumSize = center_max.height();
ver_struct_list[1].expansive = have_central;
ver_struct_list[1].empty = docks[QInternal::LeftDock].isEmpty()
&& !have_central
&& docks[QInternal::RightDock].isEmpty();
ver_struct_list[1].pos = center_rect.top();
ver_struct_list[1].size = center_rect.height();
// bottom --------------------------------------------------
ver_struct_list[2].init();
ver_struct_list[2].stretch = 0;
ver_struct_list[2].sizeHint = bottom_hint.height();
ver_struct_list[2].minimumSize = bottom_min.height();
ver_struct_list[2].maximumSize = bottom_max.height();
ver_struct_list[2].expansive = false;
ver_struct_list[2].empty = docks[QInternal::BottomDock].isEmpty();
ver_struct_list[2].pos = docks[QInternal::BottomDock].rect.top();
ver_struct_list[2].size = docks[QInternal::BottomDock].rect.height();
for (int i = 0; i < 3; ++i) {
ver_struct_list[i].sizeHint
= qMax(ver_struct_list[i].sizeHint, ver_struct_list[i].minimumSize);
}
if (have_central && ver_struct_list[0].empty && ver_struct_list[2].empty)
ver_struct_list[1].maximumSize = QWIDGETSIZE_MAX;
}
if (_hor_struct_list != 0) {
QVector<QLayoutStruct> &hor_struct_list = *_hor_struct_list;
hor_struct_list.resize(3);
// left --------------------------------------------------
hor_struct_list[0].init();
hor_struct_list[0].stretch = 0;
hor_struct_list[0].sizeHint = left_hint.width();
hor_struct_list[0].minimumSize = left_min.width();
hor_struct_list[0].maximumSize = left_max.width();
hor_struct_list[0].expansive = false;
hor_struct_list[0].empty = docks[QInternal::LeftDock].isEmpty();
hor_struct_list[0].pos = docks[QInternal::LeftDock].rect.left();
hor_struct_list[0].size = docks[QInternal::LeftDock].rect.width();
// center --------------------------------------------------
hor_struct_list[1].init();
hor_struct_list[1].stretch = center_hint.width();
bool tl_significant = corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea
|| docks[QInternal::LeftDock].isEmpty();
bool tr_significant = corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea
|| docks[QInternal::RightDock].isEmpty();
bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea
|| docks[QInternal::LeftDock].isEmpty();
bool br_significant = corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea
|| docks[QInternal::RightDock].isEmpty();
int top = (tl_significant && tr_significant) ? top_hint.width() : 0;
int bottom = (bl_significant && br_significant) ? bottom_hint.width() : 0;
hor_struct_list[1].sizeHint = qMax(top, center_hint.width(), bottom);
top = (tl_significant && tr_significant) ? top_min.width() : 0;
bottom = (bl_significant && br_significant) ? bottom_min.width() : 0;
hor_struct_list[1].minimumSize = qMax(top, center_min.width(), bottom);
hor_struct_list[1].maximumSize = center_max.width();
hor_struct_list[1].expansive = have_central;
hor_struct_list[1].empty = !have_central;
hor_struct_list[1].pos = center_rect.left();
hor_struct_list[1].size = center_rect.width();
// right --------------------------------------------------
hor_struct_list[2].init();
hor_struct_list[2].stretch = 0;
hor_struct_list[2].sizeHint = right_hint.width();
hor_struct_list[2].minimumSize = right_min.width();
hor_struct_list[2].maximumSize = right_max.width();
hor_struct_list[2].expansive = false;
hor_struct_list[2].empty = docks[QInternal::RightDock].isEmpty();
hor_struct_list[2].pos = docks[QInternal::RightDock].rect.left();
hor_struct_list[2].size = docks[QInternal::RightDock].rect.width();
for (int i = 0; i < 3; ++i) {
hor_struct_list[i].sizeHint
= qMax(hor_struct_list[i].sizeHint, hor_struct_list[i].minimumSize);
}
if (have_central && hor_struct_list[0].empty && hor_struct_list[2].empty)
hor_struct_list[1].maximumSize = QWIDGETSIZE_MAX;
}
}
4) Patch #4:
\\qt5\qtbase\src\gui\painting\qpaintengineex.cpp
Line 55: Change made to QT_MAX_CACHED_GLYPH_SIZE
# define QT_MAX_CACHED_GLYPH_SIZE 512
\\qt5\qtbase\src\widgets\accessible\simplewidgets.cpp
Line 202: in the function QAccessibleButton::role(), added a check for valid ab variable
QAccessible::Role QAccessibleButton::role() const
{
QAbstractButton *ab = button();
if (ab) {
#if QT_CONFIG(menu)
if (QPushButton *pb = qobject_cast<QPushButton*>(ab)) {
if (pb->menu())
return QAccessible::ButtonMenu;
}
#endif
if (ab->isCheckable())
return ab->autoExclusive() ? QAccessible::RadioButton : QAccessible::CheckBox;
}
return QAccessible::Button;
}