1 // This is the implementatation of an embedded qt.conf file.
2 //
3 // Copyright (c) 2021 Riverbank Computing Limited <info@riverbankcomputing.com>
4 //
5 // This file is part of PyQt5.
6 //
7 // This file may be used under the terms of the GNU General Public License
8 // version 3.0 as published by the Free Software Foundation and appearing in
9 // the file LICENSE included in the packaging of this file.  Please review the
10 // following information to ensure the GNU General Public License version 3.0
11 // requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 //
13 // If you do not wish to use this file under the terms of the GPL version 3.0
14 // then you may purchase a commercial license.  For more information contact
15 // info@riverbankcomputing.com.
16 //
17 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
18 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 
20 
21 #include <Python.h>
22 
23 #include <QByteArray>
24 #include <QDir>
25 #include <QFileInfo>
26 #include <QLatin1String>
27 
28 #include "qpycore_api.h"
29 
30 
31 static const unsigned char qt_resource_name[] = {
32   // qt
33   0x0,0x2,
34   0x0,0x0,0x7,0x84,
35   0x0,0x71,
36   0x0,0x74,
37     // etc
38   0x0,0x3,
39   0x0,0x0,0x6c,0xa3,
40   0x0,0x65,
41   0x0,0x74,0x0,0x63,
42     // qt.conf
43   0x0,0x7,
44   0x8,0x74,0xa6,0xa6,
45   0x0,0x71,
46   0x0,0x74,0x0,0x2e,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x66,
47 
48 };
49 
50 static const unsigned char qt_resource_struct[] = {
51   // :
52   0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,
53   // :/qt
54   0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x2,
55   // :/qt/etc
56   0x0,0x0,0x0,0xa,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x3,
57   // :/qt/etc/qt.conf
58   0x0,0x0,0x0,0x16,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,
59 
60 };
61 
62 
63 QT_BEGIN_NAMESPACE
64 bool qRegisterResourceData(int, const unsigned char *, const unsigned char *,
65         const unsigned char *);
66 QT_END_NAMESPACE
67 
68 
69 // Embed a qt.conf file.
qpycore_qt_conf()70 bool qpycore_qt_conf()
71 {
72     // Get PyQt5.__file__.
73     PyObject *pyqt5 = PyImport_ImportModule("PyQt5");
74 
75     if (!pyqt5)
76         return false;
77 
78     PyObject *init = PyObject_GetAttrString(pyqt5, "__file__");
79     Py_DECREF(pyqt5);
80 
81     if (!init)
82         return false;
83 
84     QString init_impl(qpycore_PyObject_AsQString(init));
85     Py_DECREF(init);
86 
87     if (init_impl.isEmpty())
88         return false;
89 
90     // Get the directory containing the PyQt5 extension modules.
91     QDir pyqt5_dir = QFileInfo(QDir::fromNativeSeparators(init_impl)).absoluteDir();
92     QString qt_dir_name = pyqt5_dir.absoluteFilePath(QLatin1String("Qt5"));
93 
94     // Check if there is a bundled copy of Qt.
95     if (QFileInfo(qt_dir_name).exists())
96     {
97         // Get the prefix path with non-native separators.
98         static QByteArray qt_conf = qt_dir_name.toLocal8Bit();
99 
100         qt_conf.prepend("[Paths]\nPrefix = ");
101         qt_conf.append("\n");
102 
103         // Prepend the 4-byte size.
104         int size = qt_conf.size();
105 
106         for (int i = 0; i < 4; ++i)
107         {
108             qt_conf.prepend(size & 0xff);
109             size >>= 8;
110         }
111 
112         // Register the structures.
113         qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name,
114                 (const unsigned char *)qt_conf.constData());
115     }
116 
117     return true;
118 }
119