Using QCustomPlot with special Qt define flags
Author: Emanuel Eichhammer

· · · ·
Using QCustomPlot with special Qt define flags

# Safe string casts with QT_NO_CAST_FROM_ASCII and QT_NO_CAST_TO_ASCII

QCustomPlot can be compiled with the special Qt flags `QT_NO_CAST_FROM_ASCII` and `QT_NO_CAST_TO_ASCII` out of the box. All strings used in the library are wrapped in QLatin1String to avoid casts from string/char literals. So if your project requires the added cast safety from these Qt flags, you can use QCustomPlot without any changes necessary.

# Avoiding Qt specific language extensions with QT_NO_KEYWORDS

QCustomPlot is a library based on and written in Qt. This means it uses Qt keywords such as `foreach`, `signal`, `slot` and `emit` for improved readability.

However, some projects wish to disable these Qt specific language extensions by using the define flag `QT_NO_KEYWORDS`. To compile QCustomPlot with that flag set, it is necessary to replace all occurrences of Qt keywords. This is easily done with QCustomPlot code, by using the following regular expression replacements:

Search pattern | Replace with
`(^|[^\a_])emit\s` | `\1Q_EMIT` —note the trailing space
`^( *)signals:` | `\1Q_SIGNALS:`
`(^|[^\a_])foreach( *)\(` | `\1Q_FOREACH\2(`

QCustomPlot code is written with these replacements in mind. They always work and catch all occurrences of used Qt keywords. Their functioning is also automatically tested upon every release.

The regular expressions can be applied in any IDE/Editor that supports them, including QtCreator itself. Below is a python script that is used to test the functioning of the regular expressions. It takes the names of the files to process (e.g. qcustomplot.cpp qcustomplot.h) from the command line and performs the replacement on them.

#!/usr/bin/env python
# This script is used to make the amalgamated sources qcustomplot.h/.cpp compatible
# to compiles with flag QT_NO_KEYWORDS set. It applies the following regular expression replacements
#
# (^|[^\a_])emit\s -> \1Q_EMIT
# ^( *)signals: -> \1Q_SIGNALS:
# (^|[^\a_])foreach( *)\( -> \1Q_FOREACH\2(
#
# to the files whose filenames are passed on the command line. The replacement can in principle be
# applied to the sources with any other tool or editor that knows regular expressions.
#
# To test: Copy freshly amalgamated qcustomplot.h/.cpp files into this directory, call this script on
# them, and then run qmake; make
import os, sys, re
baseDir = sys.path[0]
os.chdir(baseDir) # change current working dir to script dir
def performKeywordReplacement(filename):
print("making '"+filename+"' no-keywords-compatible...")
patterns = []
patterns.append((re.compile(r"(^|[^\a_])emit\s"), r"\1Q_EMIT "))
patterns.append((re.compile(r"^( *)signals:"), r"\1Q_SIGNALS:"))
patterns.append((re.compile(r"(^|[^\a_])foreach( *)\("), r"\1Q_FOREACH\2("))
inFile = open(filename)
outFilename = filename + ".tmp"
outFile = open(outFilename, "w")
for line in inFile:
for patt in patterns:
line = re.sub(patt[0], patt[1], line)
outFile.write(line)
outFile.close()
inFile.close()
os.remove(filename)
os.rename(outFilename, filename)
for filename in sys.argv[1:]:
if not os.path.isfile(filename):
print("file '"+filename+"' not found")
sys.exit(-1)
performKeywordReplacement(filename)