Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Native look for Qt applications on Gtk systems #88

Closed
probonopd opened this issue Sep 7, 2016 · 44 comments
Closed

Native look for Qt applications on Gtk systems #88

probonopd opened this issue Sep 7, 2016 · 44 comments

Comments

@probonopd
Copy link
Member

We should try to make Qt applications look native.

https://bugreports.qt.io/browse/QTBUG-53844

https://forum.manjaro.org/t/solved-qt-apps-theming-broken-after-last-nights-update/6471

@probonopd
Copy link
Member Author

probonopd commented Jan 12, 2017

Need to find out why the Ubuntu global menu works for one of the Qt-based AppImages mentioned there but not for the others: http://forum.freecadweb.org/viewtopic.php?f=10&t=15525&start=30#p152606

Update: Adding the appmenu-qt5 or appmenu-qt (for Qt 4 apps) package to the ingredients should improve it for Ubuntu.

@probonopd
Copy link
Member Author

Also see AppImage/AppImageKit#125 (comment) (Qt Platform Theme integration plugins for the KDE Plasma workspaces. Unofficial mini version).

@probonopd
Copy link
Member Author

probonopd commented Nov 18, 2017

See https://github.com/MartinBriza/adwaita-qt to make it look native on GTK.

adwaita-qt

@probonopd
Copy link
Member Author

probonopd commented Nov 18, 2017

On Ubuntu, /usr/lib/x86_64-linux-gnu/qt5/plugins/platformthemes/libqgtk3.so is present from the package qt5-gtk-platformtheme. Perhaps we need to find and bundle this or at least symlink to it?

@martinrotter
Copy link

Just side note. Do we have confirmed if QIcon::fromTheme(...) works in AppImage? It seems that my application - https://github.com/martinrotter/textosaurus/releases/tag/0.9.2 - does not work correctly. You can launch it and change icon theme in tools/settings/gui to some custom icon theme - for example Papirus (or other you have installed).

Then if you restart application, the icons for buttons/menus are not loaded correctly. When I use the app outside of AppImage (e.g. I install it with distro package manager), everything works. Is QIcon::fromTheme(..) somehow "sandboxed" away?

@probonopd
Copy link
Member Author

Neither linuxdeployqt nor AppImage are sandboxing anything. It is more likely that the application or some Qt library is trying to load something from a hardcoded location within /usr. Can you verify what is going on using sudo strace -eopen -f Your.AppImage 2>&1 | grep ENOENT?

@sudo-give-me-coffee
Copy link
Contributor

This worked with LXImage-QT on XFCE Vanilla:

  • Included GTK theme support plugins for QT5 no AppImage

And run:

lximageqt.AppImage -style=GTK+

And the GTK theme is used instead of Fusion

Maybe a Script checking for Desktop Environment?

@sudo-give-me-coffee
Copy link
Contributor

QIcon::fromTheme(..) only worked with QT5ct for me

@probonopd
Copy link
Member Author

This worked with LXImage-QT on XFCE Vanilla

With which exact AppImage is this working for you? Please provide a URL so that I can test. This would be a big step forward. Thanks.

@martinrotter
Copy link

@probonopd OK, will do tonight. It is just weird.

@martinrotter
Copy link

Btw, just to mention. Flatpak'ed version of the same application does not suffer from the problem.

@probonopd
Copy link
Member Author

probonopd commented May 17, 2018

From https://community.kde.org/Guidelines_and_HOWTOs/Flatpak#Styles_and_integration_with_other_desktops I deduce that when creating an AppImage, one might consider to bundle

  1. Adwaita icon theme (can't it be assumed to be "there" on the target systems?)
  2. Adwaita KStyle https://github.com/MartinBriza/adwaita-qt.git
  3. QGnomePlatform Qt platform theme (according to this, this Qt 5 platform theme applies the appearance settings of GNOME for Qt applications. It does not provide a Qt style itself, instead it requires a style that support both Qt and GTK+.)

inside the AppImage.

What I am not sure about, though, is why all of this is apparently needed for Qt 5 when in fact in earlier versions of Qt it was "just working", and widgets looked like Gtk+ widgets on Gtk+ systems.

What is also not clear to me is the relationship between this issue and Qt vs. KDE and Gtk+ vs. GNOME. What I am looking for is the best way to make all Qt applications (including, but not limited to, KDE ones) look native on Gtk+ systems (including, but not limited to, GNOME ones).

@sandman7920
Copy link

sandman7920 commented Jun 18, 2018

According to Qt's documentation

Plugins linked with a Qt library that has a higher version number will not be loaded by a library with a lower version number.

Example: Qt 5.0.0 will not load a plugin built with Qt 5.0.1.

Plugins linked with a Qt library that has a lower major version number will not be loaded by a library with a higher major version number.

Example: Qt 5.0.1 will not load a plugin built with Qt 4.8.2.
Example: Qt 5.1.1 will load plugins built with Qt 5.1.0 and Qt 5.0.3.

I ended up writing a wrapper script that improve (not resovle, KDE dialogs on some system are not native) native look.

FILE_TO_RUN.wrapper

#!/bin/sh

# clear LD_LIBRARY_PATH (set from AppRun)
# without clear "qtpaths --plugin-dir" returns $HERE/usr/lib
OLD_LD_LIBRARY_PATH="${LD_LIBRARY_PATH}"
export LD_LIBRARY_PATH=

SELF="`readlink -f "${0}"`"
EXEC="${SELF%.wrapper}"
HERE="${SELF%/*}"

QT_PLUGIN_PATH="${HERE}/../plugins"

PLUGINS_KF5="`kf5-config --qt-plugins 2>/dev/null`"
[ ! -z ${PLUGINS_KF5} ] && QT_PLUGIN_PATH="${QT_PLUGIN_PATH}:${PLUGINS_KF5}"

PLUGINS_QT5="`qtpaths --plugin-dir 2>/dev/null`"
[ ! -z ${PLUGINS_QT5} ] && [ "${PLUGINS_QT5}" != "${PLUGINS_KF5}" ] && QT_PLUGIN_PATH="${QT_PLUGIN_PATH}:${PLUGINS_QT5}"

export QT_PLUGIN_PATH
export LD_LIBRARY_PATH="${OLD_LD_LIBRARY_PATH}"
exec "${EXEC}" "${@}"

[Desktop Entry]
Exec=MyExecutable.wrapper

Note
Your AppImage must be bundled/compiled with Qt >= QT_ON_HOST

@probonopd
Copy link
Member Author

Thanks @sandman7920, that is very clever. Maybe this should be added to https://cgit.kde.org/scratch/brauch/appimage-exec-wrapper.git/ (discussed at AppImage/AppImageKit#396)?

@probonopd
Copy link
Member Author

So sad that Qt 5.2.1 looked correct on Gtk+ based systems like Xubuntu 18.04 but newer Qt versions don't, anymore.

native

Qt regression, really?! Can anyone confirm that things actually worsened?

@sandman7920
Copy link

From Qt 5.6+ full version definition is embedded in library.
On start
if (plugin_version <= this.version)
try_load(plugin)

objdump -p libQt5Gui.so.5

Version definitions:
1 0x01 0x04de00d5 libQt5Gui.so.5
2 0x00 0x0dcbd2c9 Qt_5_PRIVATE_API
3 0x00 0x00058a25 Qt_5
4 0x02 0x058a2810 Qt_5.0
Qt_5
5 0x02 0x058a2811 Qt_5.1
Qt_5.0
6 0x02 0x058a2812 Qt_5.2
Qt_5.1
7 0x02 0x058a2813 Qt_5.3
Qt_5.2
8 0x02 0x058a2814 Qt_5.4
Qt_5.3
9 0x02 0x058a2815 Qt_5.5
Qt_5.4
10 0x02 0x058a2816 Qt_5.6
Qt_5.5
11 0x02 0x058a2817 Qt_5.7
Qt_5.6
12 0x02 0x058a2818 Qt_5.8
Qt_5.7
13 0x02 0x058a2819 Qt_5.9
Qt_5.8
14 0x02 0x08a28110 Qt_5.10
Qt_5.9
15 0x00 0x08a28111 Qt_5.11
Qt_5.10

@sandman7920
Copy link

sandman7920 commented Jun 18, 2018

Also FILE_TO_RUN.wrapper causes strange behavior inside AppImage
ENV["APPIMAGE"] return /path/to/Application.AppImage.wrapper

This was bug inside application.AppImage, not runtime

@sandman7920
Copy link

sandman7920 commented Jun 19, 2018

This is a nightmare, on some system "KDEPlasmaPlatformTheme.so" cannot be loaded due QImage ABI change, on some is loaded and finally on
Kubuntu 18.04 shipped with Qt 5.9.5 my app is with 5.11.0

Cannot mix incompatible Qt library (version 0x50905) with this library (version 0x50b00)
Aborted (core dumped)

@sandman7920
Copy link

sandman7920 commented Jun 19, 2018

Progress.
In order plugins to be loaded correctly all Qt5 libraries (preferably from qt.io 5.11.0 GLIBC_2.17 compatible) used by them must be shipped with AppImage.

For gtk "platformthemes/libqgtk3.so" plugin must be bundled (preferred from qt.io)

For KDE "platformthemes/KDEPlasmaPlatformTheme.so" (do not bundle this plugin)

libQt5Concurrent.so.5
libQt5Core.so.5
libQt5DBus.so.5
libQt5Gui.so.5
libQt5Network.so.5
libQt5PrintSupport.so.5
libQt5Qml.so.5
libQt5QuickControls2.so.5
libQt5Quick.so.5
libQt5QuickTemplates2.so.5
libQt5Script.so.5
libQt5Svg.so.5
libQt5TextToSpeech.so.5
libQt5Widgets.so.5
libQt5X11Extras.so.5
libQt5Xml.so.5

must be bundled

I will attach list with all libraries used by KDE plugins (extracted from Arch).

Maybe will be a good idea linuxdeployqt to have something like -bundle-kde-deps

Note:
libQt5Script is deprecated (used by kio->kded plugin) and must be installed separated

On clean ubuntu/kubuntu install qtpaths returns could not find a Qt installation of
#88 (comment)

kde_qt5_theme_list.txt
kde_qt5_full_list.txt
kde_plugins_so.txt

@sandman7920
Copy link

sandman7920 commented Jun 19, 2018

Screenshots

Ubuntu 14.04

Unity
unity_ubuntu_14 04

KDE4
kde4_ubuntu_14 04

Ubuntu 16.04

Gnome
gnome_ubuntu_16 04

KDE
kde_ubuntu_16 04

Ubuntu 18.04

Gnome
gnome_ubuntu_18 04

KDE
kde_ubuntu_18 04

@probonopd
Copy link
Member Author

Hi @sandman7920 that looks awesome. Can you achieve the same result when using Qt from https://launchpad.net/~beineri?

@sandman7920
Copy link

sandman7920 commented Jun 19, 2018

All Qt version should be fine as long they are newer than Qt on client machine.

new wrapper
https://github.com/sandman7920/AppImageQt5run/releases

To run usr/bin/MyQt5Executable

cd AppDir
cp /some/path/appimage.qt5run usr/bin/MyQt5Executable.qt5run
ln -s usr/bin/MyQt5Executable.qt5run AppRun

This is c++ wrapper linked with Qt 5.1.1.
Wrapper make call to QCoreApplication::libraryPaths() function and return system path.
Executable must be compiled without RPATH/RUNPATH

main.cpp

#include <QCoreApplication>
#include <QStringList>
#include <iostream>
#include <string>
#include <unistd.h>

int main(int /*argc*/, char *argv[], char **envp) {
    char *real_path;
    char *appDir = getenv("APPDIR");

    if (appDir != nullptr) {
        real_path = realpath(std::string(appDir).append("/AppRun").c_str(), nullptr);
    } else {
        real_path = realpath(argv[0], nullptr);
    }

    if (real_path == nullptr) return 1;

    const std::string self(real_path);

    size_t pos = self.find(".qt5run");
    if (pos == std::string::npos) return 1;

    real_path[pos] = '\0';
    argv[0] = real_path;

    pos = self.find_last_of('/');
    const std::string appPath = (pos != std::string::npos) ? self.substr(0, pos) : "";

    std::string qt_plugins = std::string(appPath).append("/../plugins");
    for (auto const &qstring: QCoreApplication::libraryPaths()) {
        qt_plugins.push_back(':');
        qt_plugins.append(qstring.toStdString());
    }

    setenv("QT_PLUGIN_PATH", qt_plugins.c_str(), 1);

    if (getenv("QT5_DEBUG_RUN") != nullptr) {
        std::cerr << "QT_PLUGIN_PATH: " << qt_plugins << '\n'
                  << "EXECUTABLE: " << argv[0] << std::endl;
    }

    return execve(argv[0], argv, envp);
}

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(AppImageQt5run)

set(APP_NAME "appimage.qt5run")
set(CMAKE_SKIP_BUILD_RPATH  TRUE)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/bin")

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -fPIC -DQT_CORE_LIB")
if(LINK_RUNTIME)
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
endif()

set(QT_ROOT "${CMAKE_CURRENT_LIST_DIR}/Qt_5.1.1")

include_directories(SYSTEM ${QT_ROOT}/include)
include_directories(SYSTEM ${QT_ROOT}/include/QtCore)
link_directories(${QT_ROOT}/lib)

add_executable(${APP_NAME} "main.cpp")
target_link_libraries(${APP_NAME} -Wl,--rpath-link=${QT_ROOT}/lib -lQt5Core)

@probonopd
Copy link
Member Author

Can you make an AppImage of an example Qt application on Travis CI using Qt from https://launchpad.net/~beineri?

@sandman7920
Copy link

Tomorrow :)
I need some sleep (it's midnight here)

@sandman7920
Copy link

Last wrapper has fundamental logic error.
I am assuming all systems have Qt5 installed

@probonopd
Copy link
Member Author

I am assuming all systems have Qt5 installed

That, of course, is not something we can assume. Looking forward to the sample app, but no hurries.

@sandman7920
Copy link

sandman7920 commented Jun 21, 2018

https://github.com/sandman7920/Qt5Demo

This demo is build on Ubuntu 16.04 with libraries from https://launchpad.net/~beineri/+archive/ubuntu/opt-qt-5.10.1-xenial

I have build demos with Qt 5.10.1 on purpose. One can see the difference running demos on
Ubuntu and then on Arch, Arch is with latest libraries 5.11.0 and demo apps don't have native look in plasma

Qt libraries from qt.io have less external dependencies

objdump -p qt_io/5.11.0/libQt5Gui.so.5|grep NEEDED
  NEEDED               libQt5Core.so.5
  NEEDED               libpthread.so.0
  NEEDED               libGL.so.1
  NEEDED               libz.so.1
  NEEDED               libstdc++.so.6
  NEEDED               libm.so.6
  NEEDED               libgcc_s.so.1
  NEEDED               libc.so.6

objdump -p /usr/lib/libQt5Gui.so.5|grep NEEDED
libpng16.so.16

  NEEDED               libQt5Core.so.5
  NEEDED               libpthread.so.0
  NEEDED               libGL.so.1
  NEEDED               libpng16.so.16
  NEEDED               libharfbuzz.so.0
  NEEDED               libz.so.1
  NEEDED               libstdc++.so.6
  NEEDED               libm.so.6
  NEEDED               libgcc_s.so.1
  NEEDED               libc.so.6

@probonopd
Copy link
Member Author

probonopd commented Jun 22, 2018

Qt libraries from qt.io have less external dependencies

Interesting find!

Arch is with latest libraries 5.11.0 and demo apps don't have native look in plasma

What happens if you bundle the KDE look&feel plugin but NOT its dependencies?

@sandman7920
Copy link

I have rebuild KDEPlasmaPlatformTheme, kio with qt.5.11 and bundle it, but strange crashes starter to happen.

@probonopd
Copy link
Member Author

I have rebuild KDEPlasmaPlatformTheme, kio with qt.5.11 and bundle it, but strange crashes starter to happen.

Can you track them down? What is crashing, and why?

@sandman7920
Copy link

sandman7920 commented Jun 23, 2018

@actionless
Copy link

is there any way to preserve qt5ct settings for app packaged as AppImage?

@probonopd
Copy link
Member Author

probonopd commented Dec 2, 2018

Looks like to achieve the same result but with newer Qt, we need to find and use the GTK2 style and the GTK2 platform theme. What a shame that this is no longer "just working" by default.

https://askubuntu.com/a/910143/545939 says:

The look and feel of Qt5 applications is determined by platform themes and styles. The platform theme is responsible for icons, fonts, etc. and the style controls how widgets are rendered. I think you'll find your application such as Qt Creator is using the GTK3 platform theme as standard.

The problem has occurred since Qt5.7. In this release, the GTK2 platform theme and style was removed and replaced with the GTK3 platform theme. I've recently been in discussion with the Qt developers and it appears there isn't a GTK3 style to complement the platform theme and there are currently no plans to implement this in the future. Therefore, on Ubuntu, the default style is "Fusion" using the GTK3 platform theme.

There are a couple of methods to add a native style as follows:

The old GTK2 platform theme and style are still available in a separate package called qtstyleplugins that can be downloaded here. Unfortunately, the GTK2 style is not compatible with the GTK3 platform theme. If you want to use the GTK2 style you will have to use the GTK2 platform theme. This will mean your dialogs etc. do not look native in Ubuntu 17.04. However, you may prefer it to "Fusion".

You didn't state what desktop environment you are using. There is a third party platform theme and style called QGnomePlatform available here and adwaita-qt available here. This provides a fully native look and feel when using Ubuntu Gnome.

For Qt Creator, I'm not 100% sure if it uses global theme/style locations. You may have to install them in {Qt_installation_folder}\Tools\QtCreator\lib\Qt\Plugins\platformthemes\ and {Qt_installation_folder}\Tools\QtCreator\lib\Qt\Plugins\styles.

https://askubuntu.com/questions/706528/qt-apps-stopped-inheriting-gtk-themes/748186#748186 says:

On Ubuntu 17.10 Qt4 apps do inherit the global GTK theme, while Qt5 don't. Since libqt5libqgtk2 isn't available in the official Ubuntu repositories anymore, we have to use another workaround:

Install qt5-style-plugins from the Ubuntu repositories. Type gedit ~/.profile in the terminal and add export QT_QPA_PLATFORMTHEME=gtk2 to the last line. Adding it to sudo gedit /etc/environment works too, but I prefer ~/.profile.

Reboot and enjoy!

@probonopd
Copy link
Member Author

is there any way to preserve qt5ct settings for app packaged as AppImage?

Isn't qt5ct writing a configuration file? In this case, its settings can be applied to the qt.conf file that linuxdeployqt and other tools like it create. This has nothing to do with AppImage. AppImage is just a self-mounting filesystem that runs whatever the author has placed inside (similar to an ISO or zip file).

@actionless
Copy link

qt5ct is a platform theme:

/usr/lib/qt/plugins/platformthemes/
/usr/lib/qt/plugins/platformthemes/libqt5ct.so
/usr/lib/qt/plugins/styles/
/usr/lib/qt/plugins/styles/libqt5ct-style.so

@probonopd
Copy link
Member Author

probonopd commented Dec 2, 2018

Interesting, I was not aware of that. Yes, then should be possible to bundle this platform theme and style using -extra-plugins=styles/libqt5ct-style.so,platformthemes/libqt5ct.so.

Also see probonopd/linuxdeployqt#60

Do you have a screenshot of how libqt5ct looks on e.g., a Xfce system?

@actionless
Copy link

actionless commented Dec 2, 2018

it's not a new type of style, but a wrapper to finetune the existing Qt5 styles (ct stands for Configuration Tool):

2018-12-02--1543741312_781x967_scrot

@probonopd
Copy link
Member Author

Does this mean that it is using other, existing themes and styles internally? Then those would need to be bundled as well, I guess.

@actionless
Copy link

as input it is using config from /.config/qt5ct/

so, in order for application to use qt5ct it should be bundled with application itself?

@probonopd
Copy link
Member Author

You mean $HOME/.config/qt5ct/? Is there also another location (ideally, relative to the location of the used Qt installation)? These questions should really go to the qt5ct developers, since I have no clue about how qt5ct works. Please ask them "how to bundle qt5ct with applications that bundle a private copy of Qt".

@actionless
Copy link

yes, sorry, i mistyped and not included ~

it's not needed for my own app, i just was wondering is it something to report to app's packager or it can be solved on a user side

@probonopd
Copy link
Member Author

The application developer who makes an AppImage (or, more generally, "bundles a private copy of Qt with the application") needs to also bundle and configure qt5ct. How exactly this works would need to be asked from the qt5ct devs.

@vitaly-zdanevich
Copy link

Hi, what is the progress on this?

@probonopd
Copy link
Member Author

probonopd commented Mar 27, 2023

While trying to make Qt application look like Gtk applications is doable, we have concluded that it is currently not worth the effort. Pulling Gtk stuff into AppImages that could otherwise be Gtk free introduces too many potential pitfalls, so we are no longer trying to do it. Also, Gtk is moving into the direction of an ever-changing "moving target" with no obvious ABI compatibility guarantees, which makes it is very hard to support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants