Skip to content

Add support for Qt6#72

Merged
sjg20 merged 37 commits into
masterfrom
devc
Mar 9, 2026
Merged

Add support for Qt6#72
sjg20 merged 37 commits into
masterfrom
devc

Conversation

@sjg20
Copy link
Copy Markdown
Owner

@sjg20 sjg20 commented Mar 9, 2026

Summary

  • Replace all deprecated/removed Qt5 APIs (QRegExp, QMatrix, QDesktopWidget,
    QLinkedList, setMargin(), viewOptions(), etc.) with their Qt6 equivalents,
    keeping Qt5 compatibility throughout
  • Handle Qt6 Poppler unique_ptr returns and QStateMachine module split with
    version-conditional code
  • Add dark mode support: detect dark theme via QPalette, load an alternate
    set of inverted XPM icons at runtime
  • Add Qt6 CI job mirroring the existing Qt5 one
  • Update build documentation with Qt6 dependencies and instructions

Test plan

  • Build and run tests with Qt5 (qmake && make && ./paperman -t)
  • Build and run tests with Qt6 (qmake6 -o Makefile.qt6 && make -f Makefile.qt6 && ./paperman -t)
  • Verify dark mode icons and colours render correctly
  • Check CI passes for both qt and qt6 jobs

🤖 Generated with Claude Code

sjg20 added 22 commits March 9, 2026 09:18
QApplication::desktop() is removed in Qt6. Use
QApplication::primaryScreen()->geometry() instead.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
QButtonGroup::buttonClicked(int) is deprecated in Qt 5.15 and removed
in Qt6. Use idClicked(int) which is available from Qt 5.15 onwards.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
QRegExp is removed in Qt6. Migrate utilDetectYear() and
utilDetectMonth() to use QRegularExpression with globalMatch() and
QRegularExpressionMatchIterator.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
QRegExp is removed in Qt6. The only use here is splitting OCR text
on page separators.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
QRegExp is removed in Qt6. The only use here is replacing /: with _
in filenames.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
QRegExp is removed in Qt6. Use QRegularExpression::match().hasMatch()
instead of QRegExp::match() == -1.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Add Qt6 configuration blocks to both .pro files and update pdfio.h to
include poppler-qt6.h when building with Qt6. Drop the Qt4 fallback.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
QDesktopWidget is removed in Qt6. Use
qApp->primaryScreen()->geometry() instead of qApp->desktop().

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
These files were already migrated to QRegularExpression in earlier
commits but still included the old qregexp.h header which does not
exist in Qt6.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
QLinkedList was removed in Qt6. The include in desk.cpp is unused so
simply remove it.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
QMatrix was removed in Qt6. Replace it with the API-compatible
QTransform class. For files that only included the header without
using it, just update the include. For files that use it, change the
type and replace setMatrix() calls with constructor assignment.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
QLayout::setMargin() was removed in Qt6. Replace all occurrences with
setContentsMargins(m, m, m, m) which is the equivalent call.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Replace setTime_t(), toTime_t() and fromTime_t() with their Qt6
equivalents setSecsSinceEpoch(), toSecsSinceEpoch() and
fromSecsSinceEpoch().

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Qt6 deletes the implicit QVariant(const char*) constructor. Wrap the
char array in QString() so that the implicit conversion goes through
QVariant(QString) instead.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
QAbstractItemView::viewOptions() was removed in Qt6. Use the
replacement initViewItemOption() which populates a
QStyleOptionViewItem by pointer instead.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
In Qt6, QStringList is a typedef for QList<QString> rather than a
separate class, so it cannot be forward-declared. Include the header
instead.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Poppler-qt6 returns std::unique_ptr from Document::load() and
Document::page() instead of raw pointers. Update the member and local
variables to use std::unique_ptr throughout, with Qt version
conditionals where the poppler-qt5 API still returns raw pointers.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
In Qt6, QKeyEventTransition moved from QtWidgets to the separate
QtStateMachine module. Add QT += statemachine for Qt6 builds.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Add explicit QStateMachine and QState includes since QtGui no longer
provides them in Qt6. Move signal-slot connections from pscan.ui to
pscan.cpp since Qt6 uic generates typed connections that cannot
resolve against the base QDialog class.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
QTextCodec was removed in Qt6. The include is unused so just remove
it.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
QPrinter::Portrait and QPrinter::A4 were removed in Qt6. Use the
equivalent QPageLayout::Portrait and QPageSize::A4 instead.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
In Qt6, QString::length() returns qsizetype (long long) instead of
int. Cast to int to match the %d format specifier since filenames
are never long enough to overflow.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
@sjg20 sjg20 changed the title Add Qt6 support with dark mode Add support for Qt6 Mar 9, 2026
sjg20 added 6 commits March 9, 2026 11:36
Qt6 deprecates operator+ for combining Qt::Modifier and Qt::Key.
Use operator| instead.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Replace QDropEvent::pos() with position().toPoint() and
itemDelegate(index) with itemDelegateForIndex(index).

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
In Qt6, container size() returns qsizetype (long long) instead of
int. Cast to int or unsigned to match %d/%u format specifiers in
printf() and qDebug() calls.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Replace deprecated isTopLevel() with isWindow(). Suppress the
nodiscard warning on QTranslator::load() since the translation file
is optional.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Replace the old string-based QMessageBox::warning(), critical(),
information() and constructor overloads with the StandardButtons
versions. Update return value checks from integer indices to
QMessageBox::StandardButton values.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
The initViewItemOption() method is only available in Qt6.  Use the
Qt5 viewOptions() equivalent when building with Qt5 so both versions
compile.  Also fix a too-short rst underline in the docs.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
sjg20 added 9 commits March 9, 2026 11:36
Remove hardcoded lightgray backgrounds from the desktop and page
views and use palette(mid) instead, which adapts to both light and
dark themes. Set the dir view to use palette(base) and palette(text)
so the folder tree is readable in dark mode. Use QPalette::WindowText
for delegate text instead of hardcoded black. Use palette(alternate-
base) for the search-mode background.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Add images/dark/ with inverted-colour versions of all toolbar icons
for use with dark desktop themes.  Add scripts/invert_xpm.py which
generates these by inverting both hex and named X11 colours in the
source XPMs.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Add utilIsDarkMode() to detect whether the theme is dark by comparing
text and background lightness, utilIconPath() to return the correct
resource prefix, and utilUpdateIcons() to swap toolbar icons to their
dark variants at runtime.

Call utilUpdateIcons() after setupUi() in the main window, page tools
and toolbar constructors.  Register the dark icons in maxview.qrc

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Some the icons look a bit strange when inverted, so update them manually
using gimp.

Signed-off-by: Simon Glass <sjg@chromium.org>
Fix several GNUmakefile problems:

- The literal ')' in the DEB_VERSION sed pattern closes the $(shell)
  call prematurely.  Use an rparen variable to escape it.
- '-include server.mk' triggers the catch-all rule when the file does
  not exist.  Add an empty-recipe target to suppress this.
- 'make distclean' forwards to the qmake Makefile which tries to
  regenerate itself.  Add a standalone distclean target.

Also add Makefile.qt6 to .gitignore and remove a stale debug message
from paperman-server.pro

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Make paperman a phony target that always forwards to the qmake
Makefile.  Without this, make sees the existing binary and skips the
build even when resource files (such as dark icons) have changed.

Add a 'make dark-icons' target for regenerating the dark icon set
from sources.  The dark icons are hand-maintained so this is not run
automatically.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Add a qt6 job that mirrors the existing Qt5 job but installs Qt6
packages and builds with qmake6.  This ensures the Qt6 port does not
regress.  Update the CI section in the development docs accordingly.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Make Qt6 the default toolchain for setup.sh since the project now
fully supports it.  The --qt flag now installs Qt6 dependencies
(including qt6-scxml-dev for the statemachine module).  Add --qt5
for the older toolchain.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Add the Qt6 package list as an alternative to the Qt5 dependencies and
document how to build with qmake6.  Update the CI section to mention
the new qt6 job.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
@sjg20 sjg20 merged commit 89d8507 into master Mar 9, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant