Category Archives: qt

Bloviate

I wondered what it would look like if you took a body of text and then used it to generate new text, using Markov chains of different lengths. So I knocked up  quick program to try it.  ‘Bloviate’.

bloviate

Bloviate analyses your source text to find every sequence of N characters and then works out the frequency of characters that come next.

For example, if you set N=3 and your source text contains the following character sequences staring with ‘the’:

‘the ‘, ‘then’, ‘they’, ‘the ‘

Then ‘the’ should be followed 50% of the time by a space, 25% of the time by an ‘n’ and 25% of the time by a ‘y’.

Bloviate then creates output text, starting with the first N characters of the source text and filling in the rest randomly using the same sequence frequencies as the source text.

Note that a character is a character to Bloviate. It treats upper and lower case as different characters, makes no attempt to differentiate between letters, punctuation and white space and does not attempt to clean up the source text. Which also means it works on any language.

Bloviate also tells you the average number of different characters following each unique sequence of N, which I will call F here. As F approaches 1.0 the output text becomes closer and closer to the input text.

Using ‘Goldilocks and the 3 bears’ as input:

If N=1 (F=7.05) the output is garbage. Albeit garbage with the same character pair frequency as the original.

On cre She sl s ramy raked cheais Bus ore than s sherd up m. ged. bend staireomest p!”Sof ckstirigrorr a ry ps.

” f waine tind s aso Sowa t antthee aime bupis stht stooomed pie k is beche p!

At N=3 (F=1.44) it looks close to English, but jibberish:

Once up and been sight,” she this timed. Pretty so soon, she second soft. She screame up and she screame hot!” cried the Mama bed the Papa been sleeping in the Papa bear

“Someone’s bear growl.

At N=5 (F=1.14) it starts to look like proper English, but semantically weird:

Once upon a time, so she went for a walked right,” she lay down into the kitchen, Goldilocks sat in the porridge from the three chair,” growled, “Someone’s been sitting my porridge and she tasted the door, and ran down the bedroom. Goldilocks woke up and she second bowl.

And it comes out with occasional gems such as:

“Someone’s been sitting my porridge,” said the bedroom.

At N=10 (F=1.03) it starts to become reasonably coherent:

Once upon a time, there was a little tired. So, she walked into the forest. Pretty soon, she came upon a house. She knocked and, when no one answered, she walked right in.

At the table in the kitchen, there were three bowls of porridge.

At N=15 (F=1.01) it starts to get pretty close to the original text, but doesn’t follow quite the same order:

Once upon a time, there was a little girl named Goldilocks. She went for a walk in the forest. Pretty soon, she came upon a house. She knocked and, when no one answered, she walked right in.

At the table in the kitchen, there were three bowls of porridge. Goldilocks was very tired by this time, so she went upstairs to the bedroom. She lay down in the first bed, but it was too hard. Then she lay down in the third bed and it was just right. Goldilocks fell asleep.

At N=12 (F=1.07) the whole 680k characters of ‘Pride and prejudice’ produces:

It is a truth universally contradict it. Besides, there was a motive within her of goodwill which could not help saying:

“Oh, that my dear mother had more command over herself! She can have her own way.”

As she spoke she observed him looking at her earnest desire for their folly or their vice. He was fond of them.”

Obviously the source text is important. The Bohemian Rhapsody lyrics make nearly as much (or as little sense) at N=5 (F=1.08) as the original:

Is this to me, for me, to me

Mama, just a poor boy from this to me

Any way the truth

Mama, life? Is this time tomorrow

Carry on as if nothing all behind and face the truth

Mama, ooh, didn’t mean to me, baby!

Just gotta leave me and lightning, very fright out, just killed a man

Put a gun against his head

Pulled my time to die?

At N=12 (F=1.05) 160k characters of Trump election speeches produces:

Hillary brought death and disaster to Iraq, Syria and Libya, she empowered Iran, and she unleashed ISIS. Now she wants to raise your taxes very substantially. Highest taxed nation in the world is a tenant of mine in Manhattan, so many great people. These are people that have been stolen, stolen by either very stupid politicians ask me the question, how are you going to get rid of all the emails?” “Yes, ma’am, they’re gonna stay in this country blind. My contract with the American voter begins with a plan to end government that will not protect its people is a government corruption at the State Department of Justice is trying as hard as they can to protect religious liberty;

Supply your own joke.

I knocked together Bloviate in C++/Qt in a couple of hours, so it is far from commercial quality. But it is fairly robust, runs on Windows and Mac and can rewrite the whole of ‘Pride and prejudice’ in a few seconds. The core of Bloviate is just a map of the frequency of characters mapped to the character sequence they follow:

QMap< QString, QMap< QChar, int > >

You can get the Windows binaries here (~8MB, should work from Windows 7 onwards).

You can get the Mac binaries here (~11MB, should work from macOS 10.12 onwards).

Note that the Bloviate executable is tiny compared to the Qt library files. I could have tried to reduce the size of the downloads, but I didn’t.

To use Bloviate just:

  1. paste your source text in the left pane
  2. set the sequence length
  3. press the ‘Go >’ button

I included some source text files in the downloads.

You can get the source for Bloviate here (~1MB).

It should build on Qt 4 or 5 and is licensed as creative commons. If you modify it, just give me an attribution and send me a link to anything interesting you come up with.

How to notarize your software on macOS

** Please note: WordPress keeps mangling my code examples by changing double dash to single dash. I tried to fix it. But it changed them all back again! If anyone knows how to get around this, please put something in the comments. **

Apple now wants you to ‘notarize’ your software. This is a process where you upload your software to Apple’s server so it can be scanned and certified malware free. This will probably become compulsory at some point, even (especially?) if your software isn’t in the Apple app store. Apple says:

Give users even more confidence in your software by submitting it to Apple to be notarized. The service automatically scans your Developer ID-signed software and performs security checks. When it’s ready to export for distribution, a ticket is attached to your software to let Gatekeeper know it’s been notarized.

When users on macOS Mojave first open a notarized app, installer package, or disk image, they’ll see a more streamlined Gatekeeper dialog and have confidence that it is not known malware.

Note that in an upcoming release of macOS, Gatekeeper will require Developer ID signed software to be notarized by Apple.

Documentation on notarization is a bit thin on the ground, especially if you want to notarize software that wasn’t built using XCode (I build my software using QtCreator). So I am writing up my experiences here.

First you need to ensure you have macOS 10.14 and XCode 10 installed (with command line tools) and you need a current Apple developer account.

Codesign your app with ‘hardened runtime’ using –options runtime :

codesign –deep –force –verify –verbose –sign “Developer ID Application:<developer id>” –options runtime <app file>

E.g.:

codesign –deep –force –verify –verbose –sign “Developer ID Application: Acme Ltd” –options runtime myApp.app

A ‘hardened runtime’ limits the data and resourced an application can access. I’m not sure what the exact ramification of this are. But it doesn’t seem to have restrict my software from doing anything it could do previously.

You can check the signing with:

codesign –verify –verbose=4 <app file>

E.g.:

codesign –verify –verbose=4 myApp.app

Now package your app into a .dmg (e.g. using DropDMG). Then upload the .dmg to Apple’s servers:

xcrun altool -t osx -f <dmg file> –primary-bundle-id <bundle id> –notarize-app –username <username>

E.g.:

xcrun altool -t osx -f myApp.dmg –primary-bundle-id com.acme.myapp –notarize-app –username me@acme.com

You will be prompted for your Apple developer password (or you can include it on the command line).

You now have to wait a few minutes. If the upload is successful “No errors uploading ” will be shown and a unique ID will be returned. You then have to use this to request your upload be scanned:

xcrun altool –notarization-info <notarize ID> -u <username>

E.g.:

xcrun altool –notarization-info xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx -u me@acme.com

You will be prompted for your Apple developer password (or you can include it on the command line).

Hopefully you will see “Status Message: Package Approved”. If the notarization fails, you should be sent a link to an online log file describing the issue. If the notarization completes successfully you need to ‘staple’ the results to your .dmg:

xcrun stapler staple -v <dmg file>

E.g.:

xcrun stapler staple -v myApp.dmg

The stapler outputs a log including some odd phrases. Mine included: “Humanity must endure”, “Let’s see how that works out. “, “Adding 1 blobs to superblob. What about Blob?” and “Enjoy”. Weird. Hopefully it will end with “The staple and validate action worked!”.

Finally you can unpack your .dmg into a .app and verify it with:

spctl -a -v <app file>

E.g.

spctl -a -v /Applications/myApp.app

On macOS 10.14 (but not earlier OSs) it should say “source=Notarized Developer ID”. Your software should now run on 10.14 without a warning dialog. Congratulations!

It all seems rather clumsy. As you have to wait asynchronously for the unique ID to be returned from step 1 before you can complete step 2, it is not easy to fully automate in a script. This is a major pain the arse. If anyone works out a way to automate it the whole process, please let me know.

Here are some links to the various posts that I gleaned this information from:

https://cycling74.com/forums/apple-notarizing-for-mojave-10-14-and-beyond
https://www.mbsplugins.de/archive/2018-11-02/Notarize_apps_for_MacOS
https://forum.xojo.com/50655-how-to-codesign-and-notarise-your-app-for-macos-10-14-and-highe
https://forum.xojo.com/49408-10-14-hardened-runtime-and-app-notarization/11
https://stackoverflow.com/questions/53112078/how-to-upload-dmg-file-for-notarization-in-xcode
https://lapcatsoftware.com/articles/debugging-mojave.html

Qt is broken on macOS right now

Let me say up front that I am a big fan of the Qt framework. I have been working with it continuously since the late 90s. Both of my commercial products (PerfectTablePlan and Hyper Plan) are written on top of Qt. But Qt is quite broken on macOS right now. In fact I struggled to find a version of Qt 5 that supported recent versions of macOS and didn’t have a showstopper bug. I must have wasted a couple of weeks grappling with these issues. I am putting my notes here in the hope that they help someone else.

Here are the 4 bugs in macOS version of Qt that have causing me the most headaches:

Qt Version
bug v5.9.6 v5.10.1 v5.11.0 v5.11.1 v5.11.2
QFontDialog broken (link) ok ok ok ss ss
QStaticText::size() returns wrong value for rich text
with line breaks
ss ss ok ok ok
widgets such as QTableWidget do not repaint correctly (link) ok cwa cwa cwa cwa
default QComboBox size is incorrect (link)
ok ok cwa ok ok

Where:

ok = bug not present.

cwa = bug present, but can workaround.

ss= bug present, making release unusable for me (showstopper).

Consequently Qt 5.11.0 is the only usable release on macOS for me and I have to kludge my way around two quite nasty bugs. While the QStaticText issue is fairly obscure (but important for me), how in the hell did QFontDialog get completely broken without anyone noticing? And then not get fixed for two whole releases?! I also know other developers who are having to stick with earlier versions of Qt due to the bugginess of the recent versions of Qt on macOS. This isn’t good enough.

Thankfully the recent versions of Qt are much more solid on Windows.

** Feb-2019 Update: Qt 5.12.0 seems to be a big improvement. **

** Mar-2019 Update: I had to revert PerfectTablePlan to Qt 5.11.0 because versions built with 5.12.0 and 5.12.1 kept crashing deep in Qt. **

** Sep-2019 Update: I had to revert PerfectTablePlan to Qt 5.11.0  again because versions built with 5.12.4 kept crashing deep in Qt. **

** Oct-2019 Update: Qt 5.12.5 fixes all the bugs above and doesn’t seem to introduce any major new bugs that I care about. **

Getting Qt 5.9 working on Windows (eventually)

I have had Qt 5.5 and 5.6 installed on my development machines for some time. Now that I have purchased a new Mac development box (an iMac with a lickably beautiful 27″ screen) I thought it was a good time to update to a more recent version of Qt. I went for Qt 5.9, rather than Qt 5.10, as 5.9 has been designated as an LTS (long term support) release. Upgrading turned into a real chore. I am quickly writing it up here in the hope that it helps someone else, and as a reminder to myself a few years down the line.

I like to build Qt from source. Because then I know it was built using the same compiler, headers, SDK etc as I am using to build my product. And I have more control over how Qt is configured. Also I can patch the source and rebuild it, if I need to. But I have had problems building Qt on Mac before. So I decided to install the pre-built binaries on my new Mac. I installed the latest version of XCode and then the Q5.9.4 binaries. This was a couple of big downloads, but it all went pretty smoothly.

I successfully built Qt 5.5 from source on my Windows machine previously, so I decided to try that for Qt 5.9. I have Visual Studio 2010 installed. This isn’t supported for Qt 5.9.4, so I downloaded Visual Studio 2017. I unzipped the Qt source into C:\Qt\5.9.4, ran ‘x86 native tools command prompt for VS 2017’, made sure Python and Perl were in the path and then:

cd C:\Qt\5.9.4

set QTDIR=C:\Qt\5.9.4\qtbase

set PATH=%QTDIR%\bin;%PATH%

configure -opensource -confirm-license -opengl desktop -nomake tests -nomake examples -no-plugin-manifests -debug-and-release -platform win32-msvc -verbose

nmake

Note that you are told by the nmake script to do nmake install at the end of this. But it tells you somewhere in the Qt Windows documentation not to do this, unless you have set the prefix argument (confusing, I know)

The build failed part way through making qtwebengine. Something to do with a path being too long for Perl or Python (I forget). It seems to be a known problem. Odd as the root path was just C:\Qt\5.9.4. I don’t need qtwebengine at present, so I deleted everything and tried again with -skip qtwebengine:

configure -opensource -confirm-license -opengl desktop -skip qtwebengine -nomake tests -nomake examples -no-plugin-manifests -debug-and-release -platform win32-msvc -verbose

nmake

It seemed to complete ok this time. But using this version of Qt to build Hyper Plan I got an error:

Unknown module(s) in QT:svg

On further examination the SVG DLL  had been built, but hadn’t been copied to the C:\Qt\5.9.4\qtbase\bin folder. Similarly for a lot of the other Qt DLLs. I couldn’t find any obvious reason for this looking through logs, Stackoverflow and Googling. I could possibly do without the SVG functionality, but I wasn’t sure what else was broken. So I decided to give up on bulding from source on Windows as well.

I download the Qt 5.9.4 binaries for Visual Studio 2017. This seemed to go ok, but then I discovered that I could only build a 64-bit application from these. No 32-bit version was available for Visual Studio 2017. Many of my customers are still on 32 bit versions of Windows. So I need to be able to ship my product as a 32 bit executable + DLLs[1].

So I uninstalled Visual Studio 2017 and installed Visual Studio 2015. I then got an error message about Visual Studio 2017 redistributables that I hadn’t uninstalled. So I had to uninstall those and run a repair install on Visual Studio 2015. That seemed to work ok. So then I download the 32-bit Qt 5.9.4 binaries for Visual Studio 2015. I had to download these into a different top level folder (C:\Qtb), so as not to risk wiping existing Qt installs that I had previously managed to build from source.

Eventually I managed to build Hyper Plan and PerfectTablePlan on Mac and Windows. What a palaver though! Qt is an amazing framework and I am very grateful for everyone who works on it. But I wish they would make it a bit easier to install and upgrade! Has anyone actually managed to get Qt 5.9 built from source on Windows?

[1] I don’t bother shipping a 64-bit executable on Windows as the 32-bit executable works fine on 64-bit versions of Windows (my software doesn’t require excessive amounts of memory). I only ship a 64-bit executable on macOS as almost no-one uses 32-bit versions of macOS now.

Pretty printing C++ with Clang-Format

I use some of the code generation and refactoring tools in QtCreator. These save a lot of time, but they don’t format C++ code how I like it. For example they produce C++ code like this:

void MyClass::foo(int *x)

But I like my code formatted like this:

void MyClass::foo( int* x )

The differences may seem minor, but they are a source of significant irritation to me. I like my code how I like it, goddammit! And consistent formatting enhances readability. However re-formatting it by hand is time-consuming and tedious.

What I need is a tool that can enforce consistent formatting in the style that I like, or something close. I have tried to use automatic C++ formatting (pretty printing) tools in the past, but I couldn’t get them to produce a format that was close enough to what I wanted. But I have finally found the tool for the job. Clang-Format.

Clang-Format is part of the LLVM family of tools. It is a free, command-line tool that reformats C++, Objective-C or C according to the settings in a config file. As with many free tools, it isn’t terribly well documented. Some of the documentation on the web is out of date and some of it is incomplete. But I have managed to find out enough to configure it how I like it.

To run it you just need to place your options in a .clang-format file, make sure the clang-format executable is in the path and then run it:

clang-format.exe -i -style=file <C++ file>

Here are the settings I am currently using in my .clang-format file:

Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false
AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
  AfterClass:      true
  AfterControlStatement: true
  AfterEnum:       true
  AfterFunction:   true
  AfterNamespace:  true
  AfterObjCDeclaration: true
  AfterStruct:     true
  AfterUnion:      false
  BeforeCatch:     true
  BeforeElse:      true
  IndentBraces:    false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Allman
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
ColumnLimit: 0
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 0
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IndentCaseLabels: true
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
PenaltyBreakBeforeFirstCallParameter: 100
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 10000
PointerAlignment: Left
ReflowComments: true
SortIncludes: false
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: true
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: true
SpacesInParentheses: true
SpacesInSquareBrackets: true
Standard: Cpp11
TabWidth: 4
UseTab: Never

It took me a few hours of fiddling with the settings to find the best combination. It would be really useful if someone could write a tool that would analyze your C++ code and create a .clang-format file for you. You would probably only want to do this once though, so I don’t think it has much potential as a commercial product.

There are only two things I couldn’t get quite right in the formatting:

  1. I couldn’t get it to add a blank line after public, protected and private declarations. I fixed this with a quick Perl hack (see below).
  2. I couldn’t get it to indent continuation lines how I would like (ideally indented 1 or 2 spaces from the first line). It is a small price to pay and I am just putting up with it for now.

Perhaps there are options to do these and I just didn’t find them.

Here is the Windows .bat script I used to format all the C++ files in a folder.

for %%f in (*.h *.cpp *.inl) do (
clang-format.exe -i -style=file %%f
)

for %%f in (*.h) do (
clang-format.exe -i -style=file %%f
perl -p -i.bak -e "s/public:/public:\n/g" %%f
perl -p -i.bak -e "s/protected:/protected:\n/g" %%f
perl -p -i.bak -e "s/private:/private:\n/g" %%f
perl -p -i.bak -e "s/    Q_OBJECT/Q_OBJECT/g" %%f
)

del *.bak
del *.tmp

No doubt there is a more elegant way to do the Perl, but it works.

I now just run this batch periodically to keep my code beautiful and consistent.

Signing Qt applications for Mac OS X 10.9.5 and 10.10

I have written previously about signing Qt applications for Mac OS X. It all worked fine until I upgraded to Mac OS X 10.9.5, which broke my signing script. Those Apple chaps do love to break stuff. Grrr.

The problem appears to be that the directory structure of the app bundle has changed and the Qt4 macdeployqt command does not conform to the new layout (I believe this is also the case for Qt5). Oh joy. I managed to work out how to get it working again after a bit of digging around. The good news is that Apple have also made the codesign command easier with a --deep option to traverse and sign the whole bundle in a single command. About time.

So here is the basic process to build and sign your Qt .app on the latest versions of Mac OS X:

# deploy Qt frameworks into .app bundle
$QTDIR/bin/macdeployqt <your_app>.app -verbose=1
# optionally delete unwanted framework and plugin folders, e.g.:
# rm -f -r <your_app>.app/Contents/Frameworks/QtDeclarative.framework
# rm -f -r <your_app>.app/Contents/PlugIns/sqldrivers
# correct .app bundle structure
python rebundle.py $QTDIR <your_app>.app
# sign .app bundle (including frameworks and plugins)
codesign --deep --force --verify --verbose --sign "Developer ID Application: <your developer id>" <your_app>.app
# the 2 lines below are just for verification/diagnostics
otool -L <your_app>.app/Contents/MacOS/<your_app>
codesign --verify --verbose=4 <your_app>.app

(Sorry about the small font, but I wanted to avoid confusing line wraps).

I then invoke DropDmg to create a .dmg image file complete with licence and background image. This is all stuck it all in a bash script, which I can pretty much forget about it (until Apple break something else).

In the above rebundle.py is a Python script  written by some public spirited individual that can be downloaded from github (thank you, ‘kingcheez’). Note that you can just find and replace all the ‘5’ characters in the script by ‘4’ if you are still using Qt4.

The first time I ran my script I ended up with a whopping 50MB .app file. It turns out that the cp -r commands in my script don’t preserve symbolic links. So you end up with 3 copies of each framework library. You can avoid this by using cp -R instead.

On the subject of signing for Mac, Apple recently sent out an email stating:

Signatures created with OS X Mountain Lion 10.8.5 or earlier (v1 signatures) will be obsoleted and Gatekeeper will no longer recognize them. Users may receive a Gatekeeper warning and will need to exempt your app to continue using it. To ensure your apps will run without warning on updated versions of OS X, they must be signed on OS X Mavericks 10.9 or later (v2 signatures). … Apps signed with v2 signatures will work on older versions of OS X.

So you are going to have to start signing using 10.9, whether you like it or not.

How to build Qt 4.8.5 on Mac OS X 10.9

I prefer to build Qt from source. I have been trying to build Qt 4.8.5 on Mac OS X 10.9 (Mavericks). I managed in the end, but it took a few tweaks. Online information about how to do this was fragmentary, so I am documenting it here in case it is useful to someone else.

1. Webkit doesn’t build. I don’t need it so I disabled it using configure option:

-no-webkit

2. The corewlan plugin doesn’t build. I don’t need it (I think, I’ve never heard of it before) so I disabled it using this fix from stackoverflow.

3. The TIFF image format plugin doesn’t build. I don’t need it so I disabled it using configure option:

-no-libtiff

My final configure command was:

./configure -nomake demos -nomake examples -debug-and-release -no-multimedia -no-audio-backend -no-phonon -no-phonon-backend -no-gif -no-openssl -no-webkit -no-libtiff

There will be lots of warnings that Qt 4.8.5 isn’t compatible with Mac OS X 10.9. But you can ignore these (or comment out the warning in the appropriate Qt header file).

I have done some brief experiments and it seems to work ok. Hopefully there will be a Qt 4.8.6 that fixes these issues. Note that you also need to make some tweaks to your application code. See:

Fixing Qt 4 for Mac OS X 10.9

** UPDATE April-2014 **

Qt 4.8.6 has been released. This appears to build fine on Mac OS X 10.9.