Category Archives: macOS

Updating application icons for macOS 26 Tahoe and Liquid Glass

The application icon for my data wrangling software looks like this on a Mac up to macOS 15.x:

However, Apple has once again nuked everything from orbit. Now it looks like this in macOS 26 Tahoe when the application is inactive or if you choose any Icon & widget style apart from Default:

Thanks Apple. It is such a joy to develop for Mac.

With some help from a designer and hours of going around in circles, I have finally managed to fix things to support the new ‘liquid glass’ look. This is how it should look in the next release, depending on the setting in Appearance>Icon & widget style:

Default
Dark
Clear/Light
Clear/Dark
Tinted

I’m not convinced it is an improvement in terms of usability. But, at least my app icon doesn’t look like shit.

What you need to know

The new macOS 26 icon format is .icon. It is a folder full of various resources and is totally different to the old .icns format.

The .icon file can be created by Apple Icon Composer. I used a freelancer on Fiverr who did a good job of converting my existing vector artwork and was very cheap. The .icon file should contain a maximum of 4 groups (which seem to be like layers) other it won’t compile to a resource properly.

Note that macOS hide the extension of .icon folders by default, which was a source of some confusion.

The .icon file then has to be processed into an Assets.car file using actool. For example:

xcrun actool application.icon --compile ./icons/macosx --output-format human-readable-text --notices --warnings --errors --output-partial-info-plist temp.plist --app-icon Icon --include-all-app-icons --enable-on-demand-resources NO --development-region en --target-device mac --minimum-deployment-target 26.0 --platform macosx

You will need to change the bold parts above, as appropriate.

I had to update my Mac laptop to macOS 26, Xcode 26 and the macOS 26 SDK for the above to work.

You can check the Assets.car file using assetutil to create a .json file listing the contents:

xcrun --sdk macosx assetutil --info ./icons/macosx/Assets.car > ./icons/macosx/temp.json 

You will need to change the bold parts above, as appropriate.

Then you need to reference the new icon in your existing application .plist file. For example, add at the same level as CFBundleGetInfoString:

<key>CFBundleIconName</key>
<string>application</string>

You will need to change the bold part above, as appropriate. I believe the string value if based on the file stem of the original .icon file. But I’m not 100% sure about that. Look at the .json file produced by assetutil for clues. Mine contained this:

The temp.plist file generated by actool is apparently supposed to give you a .plist file that refers to the icon resource. It didn’t and was completely useless.

Then place both Assets.car and your old .icns file in the Resource folder of your application (before you sign it). That way it should look ok on both macOS 26 and earlier OSes.

If you develop using XCode, it will probably do some of the above for you. I develop in C++/Qt using Qt Creator, so I had to do it all manually.

I was able to generate the Assets.car on macOS 26 and then incorporate it into the build on my macOS 12 development machine.

I hope the above saves someone a few hours. Now I need to repeat the process for PerfectTablePlan.

You might also find this post useful (where I got some of the information):

https://www.hendrik-erz.de/post/supporting-liquid-glass-icons-in-apps-without-xcode

Inputting and outputting to Excel XLSX/XLS using the LibXL library

I needed a way to input from and output to Excel .xlsx and .xls file in my data wrangling software, Easy Data Transform. I had previously used Qt’s ActiveQt classes to talk to Excel via ActiveX, in my seating planner software, PerfectTablePlan. But this came with distinct limitations:

  • Excel must be installed on the customer computer.
  • ActiveQt only works on Windows.

I wanted to be able to read and write Excel file on Windows and Mac from my C++/Qt application, whether Excel is installed or not. I would rather commit suicide with a cheese grater, than try to write my own code to parse whatever horrific format Excel is written in. So I looked around for a library.

I ended up buying a licence for LibXL, from XLWare, back in 2019. It has been working great ever since. I now also use it in PerfectTablePlan v7.

Things to like:

  • Available as a library for Windows, Mac, Linux and iOS (I have only used it for Windows and Mac, so far).
  • Accessible from lots of languages, including: C, C++, .Net, Delphi, PHP, Python, PowerBASIC and Fortran.
  • Example code is available in C++, C, C# and Delphi.
  • Good support.
  • Regular updates.
  • Reasonable pricing.
  • No per-user fees.

The API is a little low-level for my taste, but I guess that is inevitable when you support C as well as C++. Reading and writing is slow compared to reading and writing the same data to/from a CSV file. But, no doubt, that is due to the limitations of the Excel file format.

I don’t have any affiliation with LibXL beyond being a paying customer, and I haven’t been asked to write this. I just wanted to give a shout-out to the developer, Dmytro, for his sterling work. Long may it continue.

Easy Data Transform v2

I released Easy Data Transform v2 today. After no fewer than 80 (!) v1 production releases since 2019, this is the first paid upgrade.

Major improvements include:

  • Schema versioning, so you can automatically handle changes to the column structure of an input (e.g. additional or missing columns).
  • A new Verify transform so you can check a dataset has the expected values.

Currently there are 48 different verification checks you can make:

  • At least 1 non-empty value
  • Contains
  • Don’t allow listed values
  • Ends with
  • Integer except listed special value(s)
  • Is local file
  • Is local folder
  • Is lower case
  • Is sentence case
  • Is title case
  • Is upper case
  • Is valid EAN13
  • Is valid email
  • Is valid telephone number
  • Is valid UPC-A
  • Match column name
  • Matches regular expression
  • Maximum characters
  • Maximum number of columns
  • Maximum number of rows
  • Maximum value
  • Minimum characters
  • Minimum number of columns
  • Minimum number of rows
  • Minimum value
  • No blank values
  • No carriage returns
  • No currency
  • No digits
  • No double spaces
  • No duplicate column names
  • No duplicate values
  • No empty rows
  • No empty values
  • No gaps in values
  • No leading or trailing whitespace
  • No line feeds
  • No non-ASCII
  • No non-printable
  • No punctuation
  • No symbols
  • No Tab characters
  • No whitespace
  • Numeric except listed special value(s)
  • Only allow listed values
  • Require listed values
  • Starts with
  • Valid date in format

You can see any fails visually, with colour coding by severity:

  • Side-by-side comparison of dataset headers:
  • Side-by-side comparison of dataset data values:
  • Lots of extra matching options for the Lookup transform:

Allowing you to do exotic lookups such as:

Plus lots of other changes.

In v1 there were issues related to how column-related changes cascaded through the system. This was the hardest thing to get right, and it took a fairly big redesign to fix all the issues. As a bonus, you can now disconnect and reconnect nodes, and it remembers all the column-based options (within certain limits). These changes make Easy Data Transform feel much more robust to use, as you can now make lots of changes without worrying too much about breaking things further downstream.

Easy Data Transform now supports:

  • 9 input formats (including various CSV variants, Excel, XML and JSON)
  • 66 different data transforms (such as Join, Filter, Pivot, Sample and Lookup)
  • 11 output formats (including various CSV variants, Excel, XML and JSON)
  • 56 text encodings

This allows you to snap together a sequence of nodes like Lego, to very quickly transform or analyse your data. Unlike a code-based approach (such as R or Python) or a command line tool, it is extremely visual, with pretty-much instant feedback every time you make a change. Plus, no pesky syntax to remember.

data wrangling

Eating my own dogfood, using Easy Data Transform to create an email marketing campaign from various disparate data sources (mailing lists, licence key databases etc).

Easy Data Transform is all written in C++ with memory compression and reference counting, so it is fast and memory efficient and can handle multi-million row datasets with no problem.

While many of my competitors are transitioning to the web, Easy Data Transform remains a local tool for Windows and Mac. This has several major advantages:

  • Your sensitive data stays on your computer.
  • Less latency.
  • I don’t have to pay your compute and bandwidth costs, which means I can charge an affordable one-time fee for a perpetual licence.

I think privacy is only going to become ever more of a concern as rampaging AIs try to scrape every single piece of data they can find.

Usage-based fees for online data tools are no small matter. For a range of usage fee horror stories, such as enabling debug logging in a large production ETL pipeline resulting in $100k of extra costs in a week, see this Reddit post. Some of my customers have processed more than a billion rows in Easy Data Transform. Not bad for $99!

It has been a lot of hard work, but I am please with how far Easy Data Transform has come. I think Easy Data Transform is now a comprehensive, fast and robust tool for file-based data wrangling. If you have some data to wrangle, give it a try! It is only $99+tax ($40+tax if you are upgrading from v1) and there is a fully functional, 7 day free trial here:

Download Easy Data Transform v2

I am very grateful to my customers, who have been a big help in providing feedback. This has improved the product no end. Many heads are better than one!

The next big step is going to be adding the ability to talk directly to databases, REST APIs and other data sources. I also hope at some point to add the ability to visualize data using graphs and charts. Watch this space!

Winterfest 2023

Winterfest 2023 is on. Loads of quality software for Mac and Windows from independent vendors, at a discount. This includes my own Easy Data Transform and Hyper Plan, which are on sale with a 25% discount.

Find out more at artisanalsoftwarefestival.com .

Summerfest 2023

Summerfest 2023 is on. Loads of quality software for Mac and Windows from independent vendors, at a discount. This includes my own Easy Data Transform and Hyper Plan, which are on sale with a 25% discount.

Find out more at artisanalsoftwarefestival.com .

Experiences promoting niche software

This is a guest post from fellow software developer, Simon Kravis.

It’s sometimes said that software development is only 10% of what’s required to earn money from software and I can attest to that. Since 2018 I have been developing photo captioning and related software, more as a retirement diversion than a serious source of income (after a career mostly involved in writing scientific and engineering analysis software), in the hope that sales income would at least cover running costs. My best marketing tool has been writing reviews of the class of software that I produce, and the hosting site (Hub Pages) provides some useful analytics on how often these are accessed and for how long. Below is the graph for an article on tagging.

The decline since early 2022 is hard to explain – the article is periodically updated so the steady decline is not due to diminishing ‘freshness’ – which for Google is probably a file Modified date.

Here is another review article profile (Scanning Multiple Photos) showing a similar decline:

But another (Best Photo Captioning Software) has held up, though at a low level.

I offer digital photo captioning software (Caption Pro) on Windows and Mac platforms, and an iPhone captioning app (CaptionEdit), with the Windows version dating back to 2017. I also offer part of the functionality of Caption Pro on Windows for auto-cropping scans of multiple paper photos (ImageSplit). On Windows neither Caption Pro software downloads or sales seem to correlate with review accesses, despite about 1/3 of web site accesses coming from the review. However, downloads do show some correlation with Caption Pro web site sessions, as shown in the graph below.

Sales do not correlate with downloads, which perhaps explains why most advertising for niche products is not successful – it may increase downloads but this does not appear to increase sales. The observed proportion of downloads resulting in sales for ImageSplit and Caption Pro are 6% and 9% respectively. The lack of correlation between sales and downloads may be due to the small number of sales per month, which results in random fluctuation dominating the results.

The decision to enter the Apple “Walled Garden” of software was partly at the prompting of friends rather than a commercial evaluation. Apple Developer membership (costing ~US$100 per year) is required to prevent software being blocked from installation through being from an unknown publisher. Further costs were purchasing a fairly modern Mac on which to perform development, as the App Store will only accept software developed using recent versions of the Xcode development environment, which will only run on fairly recent hardware. The App Store takes a commission of 15% on sales, which is quite reasonable when compared to the difficulty of implementing e-commerce on Windows, where a PayPal account eases the problem of low-value foreign-currency transactions, but e-commerce plug-ins may stop working after years for no discernible reason. The review process for software acceptance into the App Store is generally fast, but seemly trivial issues can require resubmission. Features which have passed one review may be rejected in a later one. The review process is generally fast, but on one occasion took 4 weeks.

Caption Pro for Mac has been available (via the App Store) only since Sep 2021.It appears within the top 6 results for a search using “Caption Photos”, which is the source for most downloads. About 3.5% of downloads result in sales. This figure is much less than the Windows version of the same app, despite Mac users’ reputation for being more willing to pay for software. The iPhone app did not appear at all initially when searching for “Caption Photos” in the App Store. After 6 months it began appearing as result number 140, after it had 360 downloads. This poor ranking performance is probably because “Caption Photos” is a very popular keyword used by many apps, including those that only caption videos. It has had very few downloads and sales, despite Apple Search Ads and Apptimizer campaigns. The number of downloads increased dramatically during the Apptimizer campaign between Jan 24 and Feb 2 (as they were purchased) but the change in ranking from these downloads did not result in any sales, perhaps because no installs were purchased. The Apple search ads campaign (which resulted in the app being shown as an ad 1 in 50 times when the search phrase “Caption Photos” was used) did not greatly affect downloads or sales. A Facebook ad campaign to show a link to the app whenever “Genealogy” or “Genealogy Software” was searched for was also unsuccessful, and very expensive, as Facebook charges by impressions rather than clicks. Additional backlinks to the web site were purchased in September 2022 from Links Management in an attempt to improve the web site Google ranking, but this did not appear to have any effect on web traffic.

Mac and Windows users contacting me with problems have had a wide range of experience level – from completely naïve to former programmers. Most have been from the US, which reflects the geographic distribution of sales. There have many downloads to non-English speaking countries but very few sales.

Some results from the Mac and iPhone Apps are shown below:

On balance, developing for Apple platforms was not a good commercial decision, as the advantages of a mostly captive audience (completely captive in the case of the iPhone) do not seem to result in higher rates of downloads or sales. Competition for iPhone apps is so intense that niche products without massive advertising budgets are unlikely to succeed. The same is likely to apply to Android phone apps, which anecdotally have a less rigorous review process. My experience is that advertising and backlink purchase for any platform are not effective in increasing sales for niche software.

Simon Kravis runs Aleka Consulting, a small software and consultancy company in Canberra, Australia specializing in information management and offering a number of software products. He has mainly developed scientific and engineering programs, starting in the era of paper tape.

Moving from altool to notarytool for Mac notarization

This is an update to my 2018 article How to notarize your software on macOS.

I have been using altool to notarize my Mac apps for some years. However Apple, being Apple, have deprecated altool in favour of the new notarytool. altool will stop working at some point in 2023. And Apple, being Apple, have made little attempt to keep consistency between the two.

I didn’t find anything online to tell me how arguments between the two tools related. Consequently I spent a while trying to guess which arguments mapped to which. I got locked out for a while for trying to wrong combination too many times. In the end I went from this:

xcrun altool -t osx -f <mydmg>.dmg --primary-bundle-id <com.company.product> --notarize-app --username <apple-account-email> --password <password>

... wait for approval email ...

xcrun altool --username <apple-account-email> --password <password> --notarization-info <RequestUUID>

To this:

xcrun notarytool submit <mydmg>.dmg --apple-id <apple-account-email> --team-id <teamid> --password <password> --verbose --wait 

On the plus side the --wait option doesn’t exit until the notarization is complete, which means you can easily do you whole build, sign and notarize process in a single script. Hoorah.

Note that you still need to run the ‘stapling’ step after notarization:

xcrun stapler staple -v <mydmg>.dmg

More details on notarytool arguments at:

https://keith.github.io/xcode-man-pages/notarytool.1.html

Winterfest 2022

Easy Data Transform and Hyper Plan Professional edition are both on sale for 25% off at Winterfest 2022. So now might be a good time to give them a try (both have free trials). There is also some other great products from other small vendors on sale, including Tinderbox, Scrivener and Devonthink. Some of the software is Mac only, but Easy Data Transform and Hyper Plan are available for both Mac and Windows (one license covers both OSs).

Creating a Mac Universal binary for Intel and ARM M1/M2 with Qt

Apple has transitioned Macs from Intel to ARM (M1/M2) chips. In the process it has provided an emulation layer (Rosetta2) to ensure that the new ARM Macs can still run applications created for Intel Macs. The emulation works very well, but is quoted to be some 20% slower than running native ARM binaries. That may not seem like a lot, but it is significant on processor intensive applications such as my own data wrangling software, which often processes datasets with millions of rows through complex sequences of merging, splitting, reformatting, filtering and reshaping. Also people who have just spent a small fortune on a shiny new ARM Mac can get grumpy about not having a native ARM binary to run on it. So I have been investigating moving Easy Data Transform from an Intel binary to a Universal (‘fat'[1]) binary containing both Intel and ARM binaries. This is a process familiar from moving my seating planner software for Mac from PowerPC to Intel chips some years ago. Hopefully I will have retired before the next chip change on the Mac.

My software is built on-top of the excellent Qt cross-platfom framework. Qt announced support for Mac Universal binaries in Qt 6.2 and Qt 5.15.9. I am sticking with Qt 5 for now, because it better supports multiple text encodings and because I don’t see any particular advantage to switching to Qt 6 yet. But, there is a wrinkle. Qt 5.15.3 and later are only available to Qt customers with commercial licenses. I want to use the QtCharts component in Easy Data Transform v2, and QtCharts requires a commercial license (or GPL, which is a no-go for me). I also want access to all the latest bug fixes for Qt 5. So I decided to switch from the free LGPL license and buy a commercial Qt license. Thankfully I was eligible for the Qt small business license which is currently $499 per year. The push towards commercial licensing is controversial with Qt developers, but I really appreciate Qt and all the work that goes into it, so I am happy to support the business (not enough to pay the eye-watering fee for a full enterprise license though!).

Moving from producing an Intel binary using LGPL Qt to producing a Universal binary using commercial Qt involved several major stumbling points that took me hours and a lot of googling to sort out. I’m going to spell them out here to save you that pain. You’re welcome.

  • The latest Qt 5 LTS releases are not available via the Qt maintenance tool if you have open source Qt installed. After you buy your commercial licence you need to delete your open source installation and all the associated license files. Here is the information I got from Qt support:
I assume that you were previously using open source version, is that correct?

Qt 5.15.10 should be available through the maintenance tool but it is required to remove the old open source installation completely and also remove the open source license files from your system.

So, first step is to remove the old Qt installation completely. Then remove the old open source licenses which might exist. Instructions for removing the license files:

****************************
Unified installer/maintenancetool/qtcreator will save all licenses (downloaded from the used Qt Account) inside the new qtlicenses.ini file. You need to remove the following files to fully reset the license information.

Windows
"C:/Users/%USERNAME%/AppData/Roaming/Qt/qtlicenses.ini"
"C:/Users/%USERNAME%/AppData/Roaming/Qt/qtaccount.ini"

Linux
"/home/$USERNAME/.local/share/Qt/qtlicenses.ini"
"/home/$USERNAME/.local/share/Qt/qtaccount.ini"

OS X
"/Users/$USERNAME/Library/Application Support/Qt/qtlicenses.ini"
"/Users/$USERNAME/Library/Application Support/Qt/qtaccount.ini"

As a side note: If the files above cannot be found $HOME/.qt-license(Linux/macOS) or %USERPROFILE%\.qt-license(Windows) file is used as a fallback. .qt-license file can be downloaded from Qt Account. https://account.qt.io/licenses
Be sure to name the Qt license file as ".qt-license" and not for example ".qt-license.txt".

***********************************************************************

After removing the old installation and the license files, please download the new online installer via your commercial Qt Account.
You can login there at:
https://login.qt.io/login

After installing Qt with commercial license, it should be able to find the Qt 5.15.10 also through the maintenance tool in addition to online installer.
  • Then you need to download the commercial installer from your online Qt account and reinstall all the Qt versions you need. Gigabytes of it. Time to drink some coffee. A lot of coffee.
  • In your .pro file you need to add:
macx {
QMAKE_APPLE_DEVICE_ARCHS = x86_64 arm64
}
  • Note that the above doubles the build time of your application, so you probably don’t want it set for day to day development.
  • You can use macdeployqt to create your deployable Universal .app but, and this is the critical step that took me hours to work out, you need to use <QtDir>/macos/bin/macdeployqt not <QtDir>/clang_64/bin/macdeployqt . Doh!
  • You can check the .app is Universal using the lipo command, e.g.:
lipo -detailed_info EasyDataTransform.app/Contents/MacOS/EasyDataTransform
  • I was able to use my existing practise of copying extra files (third party libraries, help etc) into the .app file and then digitally signing everything using codesign –deep [2]. Thankfully the only third party library I use apart from Qt (the excellent libXL library for Excel) is available as a Universal framework.
  • I notarize the application, as before.

I did all the above on an Intel iMac using the latest Qt 5 LTS release (Qt 5.15.10) and XCode 13.4 on macOS 12. I then tested it on an ARM MacBook Air. No doubt you can also build Universal binaries on an ARM Mac.

Unsurprisingly the Universal app is substantially larger than the Intel-only version. My Easy Data Transform .dmg file (which also includes a lot of help documentation) went from ~56 MB to ~69 MB. However that is still positively anorexic compared to many bloated modern apps (looking at you Electron).

A couple of tests I did on an ARM MacBook Air showed ~16% improvement in performance. For example joining two 500,000 row x 10 column tables went from 4.5 seconds to 3.8 seconds. Obviously the performance improvement depends on the task and the system. One customer reported batch processing 3,541 JSON Files and writing the results to CSV went from 12.8 to 8.1 seconds, a 37% improvement.

[1] I’m not judging.

[2] Apparently the use of –deep is frowned on by Apple. But it works (for now anyway). Bite me, Apple.

Summerfest 2022

Easy Data Transform and Hyper Plan Professional edition are both on sale for 25% off at Summerfest 2022. So now might be a good time to give them a try (both have free trials). There is also some other great products from other small vendors on sale, including Tinderbox, Scrivener and Devonthink. Some of the software is Mac only, but Easy Data Transform and Hyper Plan are available for both Mac and Windows (one license covers both). Sale ends 12th July.