Port the Gtk platform theme to Gtk+ 3

The major changes compared to the Gtk+ 2 version are:

 * Everything is ported to modern Gtk/Gdk API.
 * GtkFontChooserDialog is used instead of deprecated GtkFontSelectionDialog.
 * Hiding buttons on dialogs (like OK/Cancel) is no longer supported, as it is
   impossible to do that with dialogs using GtkHeaderBars.
 * Some workarounds were added to the QGtk3Theme constructor to correctly work
   with Gtk+ 3.

[ChangeLog][Platform Specific Changes] The Gtk+ platform theme has been ported
to Gtk+ 3.

Change-Id: Iacb01279b6432e0901e3bb1353d5792543cc76e4
Done-with: J-P Nurmi <jpnurmi@theqtcompany.com>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Reviewed-by: Lisandro Damián Nicanor Pérez Meyer <perezmeyer@gmail.com>
Reviewed-by: J-P Nurmi <jpnurmi@theqtcompany.com>
This commit is contained in:
Dmitry Shachnev 2015-11-04 00:06:19 +03:00
parent f05c75a1b9
commit e876391206
12 changed files with 174 additions and 175 deletions

12
configure vendored
View File

@ -5205,15 +5205,15 @@ fi
# auto-detect GTK style support # auto-detect GTK style support
if [ "$CFG_GLIB" = "yes" -a "$CFG_GTK" != "no" ]; then if [ "$CFG_GLIB" = "yes" -a "$CFG_GTK" != "no" ]; then
if [ -n "$PKG_CONFIG" ]; then if [ -n "$PKG_CONFIG" ]; then
QT_CFLAGS_QGTK2=`$PKG_CONFIG --cflags gtk+-2.0 ">=" 2.18 atk 2>/dev/null` QT_CFLAGS_QGTK3=`$PKG_CONFIG --cflags gtk+-3.0 2>/dev/null`
QT_LIBS_QGTK2=`$PKG_CONFIG --libs gtk+-2.0 2>/dev/null` QT_LIBS_QGTK3=`$PKG_CONFIG --libs gtk+-3.0 2>/dev/null`
QT_LIBS_QGOBJECT=`$PKG_CONFIG --libs gobject-2.0 2>/dev/null` QT_LIBS_QGOBJECT=`$PKG_CONFIG --libs gobject-2.0 2>/dev/null`
fi fi
if [ -n "$QT_CFLAGS_QGTK2" ] ; then if [ -n "$QT_CFLAGS_QGTK3" ] ; then
CFG_GTK=yes CFG_GTK=yes
QT_CONFIG="$QT_CONFIG gtk2" QT_CONFIG="$QT_CONFIG gtk3"
QMakeVar set QT_CFLAGS_QGTK2 "$QT_CFLAGS_QGTK2" QMakeVar set QT_CFLAGS_QGTK3 "$QT_CFLAGS_QGTK3"
QMakeVar set QT_LIBS_QGTK2 "$QT_LIBS_QGTK2" QMakeVar set QT_LIBS_QGTK3 "$QT_LIBS_QGTK3"
else else
if [ "$CFG_GTK" = "yes" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then if [ "$CFG_GTK" = "yes" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then
echo "GTK theme support cannot be enabled due to functionality tests!" echo "GTK theme support cannot be enabled due to functionality tests!"

View File

@ -713,9 +713,9 @@ QStringList QGenericUnixTheme::themeNames()
result.push_back(QLatin1String(QKdeTheme::name)); result.push_back(QLatin1String(QKdeTheme::name));
#endif #endif
} else if (gtkBasedEnvironments.contains(desktopName)) { } else if (gtkBasedEnvironments.contains(desktopName)) {
// prefer the GTK2 theme implementation with native dialogs etc. // prefer the GTK3 theme implementation with native dialogs etc.
result.push_back(QStringLiteral("gtk2")); result.push_back(QStringLiteral("gtk3"));
// fallback to the generic Gnome theme if loading the GTK2 theme fails // fallback to the generic Gnome theme if loading the GTK3 theme fails
result.push_back(QLatin1String(QGnomeTheme::name)); result.push_back(QLatin1String(QGnomeTheme::name));
} }
} }

View File

@ -1,3 +0,0 @@
{
"Keys": [ "gtk2" ]
}

View File

@ -1,21 +0,0 @@
TARGET = qgtk2
PLUGIN_TYPE = platformthemes
PLUGIN_EXTENDS = -
PLUGIN_CLASS_NAME = QGtk2ThemePlugin
load(qt_plugin)
QT += core-private gui-private platformsupport-private
CONFIG += X11
QMAKE_CXXFLAGS += $$QT_CFLAGS_QGTK2
LIBS += $$QT_LIBS_QGTK2
HEADERS += \
qgtk2dialoghelpers.h \
qgtk2theme.h
SOURCES += \
main.cpp \
qgtk2dialoghelpers.cpp \
qgtk2theme.cpp \

View File

@ -0,0 +1,3 @@
{
"Keys": [ "gtk3" ]
}

View File

@ -0,0 +1,21 @@
TARGET = qgtk3
PLUGIN_TYPE = platformthemes
PLUGIN_EXTENDS = -
PLUGIN_CLASS_NAME = QGtk3ThemePlugin
load(qt_plugin)
QT += core-private gui-private platformsupport-private
CONFIG += X11
QMAKE_CXXFLAGS += $$QT_CFLAGS_QGTK3
LIBS += $$QT_LIBS_QGTK3
HEADERS += \
qgtk3dialoghelpers.h \
qgtk3theme.h
SOURCES += \
main.cpp \
qgtk3dialoghelpers.cpp \
qgtk3theme.cpp

View File

@ -32,24 +32,24 @@
****************************************************************************/ ****************************************************************************/
#include <qpa/qplatformthemeplugin.h> #include <qpa/qplatformthemeplugin.h>
#include "qgtk2theme.h" #include "qgtk3theme.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QGtk2ThemePlugin : public QPlatformThemePlugin class QGtk3ThemePlugin : public QPlatformThemePlugin
{ {
Q_OBJECT Q_OBJECT
Q_PLUGIN_METADATA(IID QPlatformThemeFactoryInterface_iid FILE "gtk2.json") Q_PLUGIN_METADATA(IID QPlatformThemeFactoryInterface_iid FILE "gtk3.json")
public: public:
QPlatformTheme *create(const QString &key, const QStringList &params) Q_DECL_OVERRIDE; QPlatformTheme *create(const QString &key, const QStringList &params) Q_DECL_OVERRIDE;
}; };
QPlatformTheme *QGtk2ThemePlugin::create(const QString &key, const QStringList &params) QPlatformTheme *QGtk3ThemePlugin::create(const QString &key, const QStringList &params)
{ {
Q_UNUSED(params); Q_UNUSED(params);
if (!key.compare(QLatin1String(QGtk2Theme::name), Qt::CaseInsensitive)) if (!key.compare(QLatin1String(QGtk3Theme::name), Qt::CaseInsensitive))
return new QGtk2Theme; return new QGtk3Theme;
return 0; return 0;
} }

View File

@ -31,7 +31,7 @@
** **
****************************************************************************/ ****************************************************************************/
#include "qgtk2dialoghelpers.h" #include "qgtk3dialoghelpers.h"
#include <qeventloop.h> #include <qeventloop.h>
#include <qwindow.h> #include <qwindow.h>
@ -50,13 +50,13 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QGtk2Dialog : public QWindow class QGtk3Dialog : public QWindow
{ {
Q_OBJECT Q_OBJECT
public: public:
QGtk2Dialog(GtkWidget *gtkWidget); QGtk3Dialog(GtkWidget *gtkWidget);
~QGtk2Dialog(); ~QGtk3Dialog();
GtkDialog *gtkDialog() const; GtkDialog *gtkDialog() const;
@ -69,30 +69,30 @@ Q_SIGNALS:
void reject(); void reject();
protected: protected:
static void onResponse(QGtk2Dialog *dialog, int response); static void onResponse(QGtk3Dialog *dialog, int response);
private: private:
GtkWidget *gtkWidget; GtkWidget *gtkWidget;
}; };
QGtk2Dialog::QGtk2Dialog(GtkWidget *gtkWidget) : gtkWidget(gtkWidget) QGtk3Dialog::QGtk3Dialog(GtkWidget *gtkWidget) : gtkWidget(gtkWidget)
{ {
g_signal_connect_swapped(G_OBJECT(gtkWidget), "response", G_CALLBACK(onResponse), this); g_signal_connect_swapped(G_OBJECT(gtkWidget), "response", G_CALLBACK(onResponse), this);
g_signal_connect(G_OBJECT(gtkWidget), "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL); g_signal_connect(G_OBJECT(gtkWidget), "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL);
} }
QGtk2Dialog::~QGtk2Dialog() QGtk3Dialog::~QGtk3Dialog()
{ {
gtk_clipboard_store(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD)); gtk_clipboard_store(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
gtk_widget_destroy(gtkWidget); gtk_widget_destroy(gtkWidget);
} }
GtkDialog *QGtk2Dialog::gtkDialog() const GtkDialog *QGtk3Dialog::gtkDialog() const
{ {
return GTK_DIALOG(gtkWidget); return GTK_DIALOG(gtkWidget);
} }
void QGtk2Dialog::exec() void QGtk3Dialog::exec()
{ {
if (modality() == Qt::ApplicationModal) { if (modality() == Qt::ApplicationModal) {
// block input to the whole app, including other GTK dialogs // block input to the whole app, including other GTK dialogs
@ -106,7 +106,7 @@ void QGtk2Dialog::exec()
} }
} }
bool QGtk2Dialog::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) bool QGtk3Dialog::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent)
{ {
setParent(parent); setParent(parent);
setFlags(flags); setFlags(flags);
@ -114,29 +114,31 @@ bool QGtk2Dialog::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWind
gtk_widget_realize(gtkWidget); // creates X window gtk_widget_realize(gtkWidget); // creates X window
GdkWindow *gdkWindow = gtk_widget_get_window(gtkWidget);
if (parent) { if (parent) {
XSetTransientForHint(gdk_x11_drawable_get_xdisplay(gtkWidget->window), GdkDisplay *gdkDisplay = gdk_window_get_display(gdkWindow);
gdk_x11_drawable_get_xid(gtkWidget->window), XSetTransientForHint(gdk_x11_display_get_xdisplay(gdkDisplay),
gdk_x11_window_get_xid(gdkWindow),
parent->winId()); parent->winId());
} }
if (modality != Qt::NonModal) { if (modality != Qt::NonModal) {
gdk_window_set_modal_hint(gtkWidget->window, true); gdk_window_set_modal_hint(gdkWindow, true);
QGuiApplicationPrivate::showModalWindow(this); QGuiApplicationPrivate::showModalWindow(this);
} }
gtk_widget_show(gtkWidget); gtk_widget_show(gtkWidget);
gdk_window_focus(gtkWidget->window, 0); gdk_window_focus(gdkWindow, GDK_CURRENT_TIME);
return true; return true;
} }
void QGtk2Dialog::hide() void QGtk3Dialog::hide()
{ {
QGuiApplicationPrivate::hideModalWindow(this); QGuiApplicationPrivate::hideModalWindow(this);
gtk_widget_hide(gtkWidget); gtk_widget_hide(gtkWidget);
} }
void QGtk2Dialog::onResponse(QGtk2Dialog *dialog, int response) void QGtk3Dialog::onResponse(QGtk3Dialog *dialog, int response)
{ {
if (response == GTK_RESPONSE_OK) if (response == GTK_RESPONSE_OK)
emit dialog->accept(); emit dialog->accept();
@ -144,95 +146,78 @@ void QGtk2Dialog::onResponse(QGtk2Dialog *dialog, int response)
emit dialog->reject(); emit dialog->reject();
} }
QGtk2ColorDialogHelper::QGtk2ColorDialogHelper() QGtk3ColorDialogHelper::QGtk3ColorDialogHelper()
{ {
d.reset(new QGtk2Dialog(gtk_color_selection_dialog_new(""))); d.reset(new QGtk3Dialog(gtk_color_chooser_dialog_new("", 0)));
connect(d.data(), SIGNAL(accept()), this, SLOT(onAccepted())); connect(d.data(), SIGNAL(accept()), this, SLOT(onAccepted()));
connect(d.data(), SIGNAL(reject()), this, SIGNAL(reject())); connect(d.data(), SIGNAL(reject()), this, SIGNAL(reject()));
GtkWidget *gtkColorSelection = gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(d->gtkDialog())); g_signal_connect_swapped(d->gtkDialog(), "color-activated", G_CALLBACK(onColorChanged), this);
g_signal_connect_swapped(gtkColorSelection, "color-changed", G_CALLBACK(onColorChanged), this);
} }
QGtk2ColorDialogHelper::~QGtk2ColorDialogHelper() QGtk3ColorDialogHelper::~QGtk3ColorDialogHelper()
{ {
} }
bool QGtk2ColorDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) bool QGtk3ColorDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent)
{ {
applyOptions(); applyOptions();
return d->show(flags, modality, parent); return d->show(flags, modality, parent);
} }
void QGtk2ColorDialogHelper::exec() void QGtk3ColorDialogHelper::exec()
{ {
d->exec(); d->exec();
} }
void QGtk2ColorDialogHelper::hide() void QGtk3ColorDialogHelper::hide()
{ {
d->hide(); d->hide();
} }
void QGtk2ColorDialogHelper::setCurrentColor(const QColor &color) void QGtk3ColorDialogHelper::setCurrentColor(const QColor &color)
{ {
GtkDialog *gtkDialog = d->gtkDialog(); GtkDialog *gtkDialog = d->gtkDialog();
GtkWidget *gtkColorSelection = gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(gtkDialog)); if (color.alpha() < 255)
GdkColor gdkColor; gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(gtkDialog), true);
gdkColor.red = color.red() << 8; GdkRGBA gdkColor;
gdkColor.green = color.green() << 8; gdkColor.red = color.redF();
gdkColor.blue = color.blue() << 8; gdkColor.green = color.greenF();
gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(gtkColorSelection), &gdkColor); gdkColor.blue = color.blueF();
if (color.alpha() < 255) { gdkColor.alpha = color.alphaF();
gtk_color_selection_set_has_opacity_control(GTK_COLOR_SELECTION(gtkColorSelection), true); gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(gtkDialog), &gdkColor);
gtk_color_selection_set_current_alpha(GTK_COLOR_SELECTION(gtkColorSelection), color.alpha() << 8);
}
} }
QColor QGtk2ColorDialogHelper::currentColor() const QColor QGtk3ColorDialogHelper::currentColor() const
{ {
GtkDialog *gtkDialog = d->gtkDialog(); GtkDialog *gtkDialog = d->gtkDialog();
GtkWidget *gtkColorSelection = gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(gtkDialog)); GdkRGBA gdkColor;
GdkColor gdkColor; gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(gtkDialog), &gdkColor);
gtk_color_selection_get_current_color(GTK_COLOR_SELECTION(gtkColorSelection), &gdkColor); return QColor::fromRgbF(gdkColor.red, gdkColor.green, gdkColor.blue, gdkColor.alpha);
guint16 alpha = gtk_color_selection_get_current_alpha(GTK_COLOR_SELECTION(gtkColorSelection));
return QColor(gdkColor.red >> 8, gdkColor.green >> 8, gdkColor.blue >> 8, alpha >> 8);
} }
void QGtk2ColorDialogHelper::onAccepted() void QGtk3ColorDialogHelper::onAccepted()
{ {
emit accept(); emit accept();
emit colorSelected(currentColor()); emit colorSelected(currentColor());
} }
void QGtk2ColorDialogHelper::onColorChanged(QGtk2ColorDialogHelper *dialog) void QGtk3ColorDialogHelper::onColorChanged(QGtk3ColorDialogHelper *dialog)
{ {
emit dialog->currentColorChanged(dialog->currentColor()); emit dialog->currentColorChanged(dialog->currentColor());
} }
void QGtk2ColorDialogHelper::applyOptions() void QGtk3ColorDialogHelper::applyOptions()
{ {
GtkDialog *gtkDialog = d->gtkDialog(); GtkDialog *gtkDialog = d->gtkDialog();
gtk_window_set_title(GTK_WINDOW(gtkDialog), options()->windowTitle().toUtf8()); gtk_window_set_title(GTK_WINDOW(gtkDialog), options()->windowTitle().toUtf8());
GtkWidget *gtkColorSelection = gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(gtkDialog)); gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(gtkDialog), options()->testOption(QColorDialogOptions::ShowAlphaChannel));
gtk_color_selection_set_has_opacity_control(GTK_COLOR_SELECTION(gtkColorSelection), options()->testOption(QColorDialogOptions::ShowAlphaChannel));
GtkWidget *okButton = 0;
GtkWidget *cancelButton = 0;
GtkWidget *helpButton = 0;
g_object_get(G_OBJECT(gtkDialog), "ok-button", &okButton, "cancel-button", &cancelButton, "help-button", &helpButton, NULL);
if (okButton)
g_object_set(G_OBJECT(okButton), "visible", !options()->testOption(QColorDialogOptions::NoButtons), NULL);
if (cancelButton)
g_object_set(G_OBJECT(cancelButton), "visible", !options()->testOption(QColorDialogOptions::NoButtons), NULL);
if (helpButton)
gtk_widget_hide(helpButton);
} }
QGtk2FileDialogHelper::QGtk2FileDialogHelper() QGtk3FileDialogHelper::QGtk3FileDialogHelper()
{ {
d.reset(new QGtk2Dialog(gtk_file_chooser_dialog_new("", 0, d.reset(new QGtk3Dialog(gtk_file_chooser_dialog_new("", 0,
GTK_FILE_CHOOSER_ACTION_OPEN, GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK, NULL))); GTK_STOCK_OK, GTK_RESPONSE_OK, NULL)));
@ -243,11 +228,11 @@ QGtk2FileDialogHelper::QGtk2FileDialogHelper()
g_signal_connect_swapped(GTK_FILE_CHOOSER(d->gtkDialog()), "current-folder-changed", G_CALLBACK(onCurrentFolderChanged), this); g_signal_connect_swapped(GTK_FILE_CHOOSER(d->gtkDialog()), "current-folder-changed", G_CALLBACK(onCurrentFolderChanged), this);
} }
QGtk2FileDialogHelper::~QGtk2FileDialogHelper() QGtk3FileDialogHelper::~QGtk3FileDialogHelper()
{ {
} }
bool QGtk2FileDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) bool QGtk3FileDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent)
{ {
_dir.clear(); _dir.clear();
_selection.clear(); _selection.clear();
@ -256,12 +241,12 @@ bool QGtk2FileDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modal
return d->show(flags, modality, parent); return d->show(flags, modality, parent);
} }
void QGtk2FileDialogHelper::exec() void QGtk3FileDialogHelper::exec()
{ {
d->exec(); d->exec();
} }
void QGtk2FileDialogHelper::hide() void QGtk3FileDialogHelper::hide()
{ {
// After GtkFileChooserDialog has been hidden, gtk_file_chooser_get_current_folder() // After GtkFileChooserDialog has been hidden, gtk_file_chooser_get_current_folder()
// & gtk_file_chooser_get_filenames() will return bogus values -> cache the actual // & gtk_file_chooser_get_filenames() will return bogus values -> cache the actual
@ -272,18 +257,18 @@ void QGtk2FileDialogHelper::hide()
d->hide(); d->hide();
} }
bool QGtk2FileDialogHelper::defaultNameFilterDisables() const bool QGtk3FileDialogHelper::defaultNameFilterDisables() const
{ {
return false; return false;
} }
void QGtk2FileDialogHelper::setDirectory(const QUrl &directory) void QGtk3FileDialogHelper::setDirectory(const QUrl &directory)
{ {
GtkDialog *gtkDialog = d->gtkDialog(); GtkDialog *gtkDialog = d->gtkDialog();
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(gtkDialog), directory.toLocalFile().toUtf8()); gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(gtkDialog), directory.toLocalFile().toUtf8());
} }
QUrl QGtk2FileDialogHelper::directory() const QUrl QGtk3FileDialogHelper::directory() const
{ {
// While GtkFileChooserDialog is hidden, gtk_file_chooser_get_current_folder() // While GtkFileChooserDialog is hidden, gtk_file_chooser_get_current_folder()
// returns a bogus value -> return the cached value before hiding // returns a bogus value -> return the cached value before hiding
@ -300,7 +285,7 @@ QUrl QGtk2FileDialogHelper::directory() const
return QUrl::fromLocalFile(ret); return QUrl::fromLocalFile(ret);
} }
void QGtk2FileDialogHelper::selectFile(const QUrl &filename) void QGtk3FileDialogHelper::selectFile(const QUrl &filename)
{ {
GtkDialog *gtkDialog = d->gtkDialog(); GtkDialog *gtkDialog = d->gtkDialog();
if (options()->acceptMode() == QFileDialogOptions::AcceptSave) { if (options()->acceptMode() == QFileDialogOptions::AcceptSave) {
@ -312,7 +297,7 @@ void QGtk2FileDialogHelper::selectFile(const QUrl &filename)
} }
} }
QList<QUrl> QGtk2FileDialogHelper::selectedFiles() const QList<QUrl> QGtk3FileDialogHelper::selectedFiles() const
{ {
// While GtkFileChooserDialog is hidden, gtk_file_chooser_get_filenames() // While GtkFileChooserDialog is hidden, gtk_file_chooser_get_filenames()
// returns a bogus value -> return the cached value before hiding // returns a bogus value -> return the cached value before hiding
@ -328,12 +313,12 @@ QList<QUrl> QGtk2FileDialogHelper::selectedFiles() const
return selection; return selection;
} }
void QGtk2FileDialogHelper::setFilter() void QGtk3FileDialogHelper::setFilter()
{ {
applyOptions(); applyOptions();
} }
void QGtk2FileDialogHelper::selectNameFilter(const QString &filter) void QGtk3FileDialogHelper::selectNameFilter(const QString &filter)
{ {
GtkFileFilter *gtkFilter = _filters.value(filter); GtkFileFilter *gtkFilter = _filters.value(filter);
if (gtkFilter) { if (gtkFilter) {
@ -342,14 +327,14 @@ void QGtk2FileDialogHelper::selectNameFilter(const QString &filter)
} }
} }
QString QGtk2FileDialogHelper::selectedNameFilter() const QString QGtk3FileDialogHelper::selectedNameFilter() const
{ {
GtkDialog *gtkDialog = d->gtkDialog(); GtkDialog *gtkDialog = d->gtkDialog();
GtkFileFilter *gtkFilter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(gtkDialog)); GtkFileFilter *gtkFilter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(gtkDialog));
return _filterNames.value(gtkFilter); return _filterNames.value(gtkFilter);
} }
void QGtk2FileDialogHelper::onAccepted() void QGtk3FileDialogHelper::onAccepted()
{ {
emit accept(); emit accept();
@ -363,7 +348,7 @@ void QGtk2FileDialogHelper::onAccepted()
emit fileSelected(files.first()); emit fileSelected(files.first());
} }
void QGtk2FileDialogHelper::onSelectionChanged(GtkDialog *gtkDialog, QGtk2FileDialogHelper *helper) void QGtk3FileDialogHelper::onSelectionChanged(GtkDialog *gtkDialog, QGtk3FileDialogHelper *helper)
{ {
QString selection; QString selection;
gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(gtkDialog)); gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(gtkDialog));
@ -374,7 +359,7 @@ void QGtk2FileDialogHelper::onSelectionChanged(GtkDialog *gtkDialog, QGtk2FileDi
emit helper->currentChanged(QUrl::fromLocalFile(selection)); emit helper->currentChanged(QUrl::fromLocalFile(selection));
} }
void QGtk2FileDialogHelper::onCurrentFolderChanged(QGtk2FileDialogHelper *dialog) void QGtk3FileDialogHelper::onCurrentFolderChanged(QGtk3FileDialogHelper *dialog)
{ {
emit dialog->directoryEntered(dialog->directory()); emit dialog->directoryEntered(dialog->directory());
} }
@ -399,7 +384,7 @@ static GtkFileChooserAction gtkFileChooserAction(const QSharedPointer<QFileDialo
} }
} }
void QGtk2FileDialogHelper::applyOptions() void QGtk3FileDialogHelper::applyOptions()
{ {
GtkDialog *gtkDialog = d->gtkDialog(); GtkDialog *gtkDialog = d->gtkDialog();
const QSharedPointer<QFileDialogOptions> &opts = options(); const QSharedPointer<QFileDialogOptions> &opts = options();
@ -430,7 +415,6 @@ void QGtk2FileDialogHelper::applyOptions()
if (!initialNameFilter.isEmpty()) if (!initialNameFilter.isEmpty())
selectNameFilter(initialNameFilter); selectNameFilter(initialNameFilter);
#if GTK_CHECK_VERSION(2, 20, 0)
GtkWidget *acceptButton = gtk_dialog_get_widget_for_response(gtkDialog, GTK_RESPONSE_OK); GtkWidget *acceptButton = gtk_dialog_get_widget_for_response(gtkDialog, GTK_RESPONSE_OK);
if (acceptButton) { if (acceptButton) {
if (opts->isLabelExplicitlySet(QFileDialogOptions::Accept)) if (opts->isLabelExplicitlySet(QFileDialogOptions::Accept))
@ -448,10 +432,9 @@ void QGtk2FileDialogHelper::applyOptions()
else else
gtk_button_set_label(GTK_BUTTON(rejectButton), GTK_STOCK_CANCEL); gtk_button_set_label(GTK_BUTTON(rejectButton), GTK_STOCK_CANCEL);
} }
#endif
} }
void QGtk2FileDialogHelper::setNameFilters(const QStringList &filters) void QGtk3FileDialogHelper::setNameFilters(const QStringList &filters)
{ {
GtkDialog *gtkDialog = d->gtkDialog(); GtkDialog *gtkDialog = d->gtkDialog();
foreach (GtkFileFilter *filter, _filters) foreach (GtkFileFilter *filter, _filters)
@ -476,29 +459,29 @@ void QGtk2FileDialogHelper::setNameFilters(const QStringList &filters)
} }
} }
QGtk2FontDialogHelper::QGtk2FontDialogHelper() QGtk3FontDialogHelper::QGtk3FontDialogHelper()
{ {
d.reset(new QGtk2Dialog(gtk_font_selection_dialog_new(""))); d.reset(new QGtk3Dialog(gtk_font_chooser_dialog_new("", 0)));
connect(d.data(), SIGNAL(accept()), this, SLOT(onAccepted())); connect(d.data(), SIGNAL(accept()), this, SLOT(onAccepted()));
connect(d.data(), SIGNAL(reject()), this, SIGNAL(reject())); connect(d.data(), SIGNAL(reject()), this, SIGNAL(reject()));
} }
QGtk2FontDialogHelper::~QGtk2FontDialogHelper() QGtk3FontDialogHelper::~QGtk3FontDialogHelper()
{ {
} }
bool QGtk2FontDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) bool QGtk3FontDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent)
{ {
applyOptions(); applyOptions();
return d->show(flags, modality, parent); return d->show(flags, modality, parent);
} }
void QGtk2FontDialogHelper::exec() void QGtk3FontDialogHelper::exec()
{ {
d->exec(); d->exec();
} }
void QGtk2FontDialogHelper::hide() void QGtk3FontDialogHelper::hide()
{ {
d->hide(); d->hide();
} }
@ -569,43 +552,36 @@ static QFont qt_fontFromString(const QString &name)
return font; return font;
} }
void QGtk2FontDialogHelper::setCurrentFont(const QFont &font) void QGtk3FontDialogHelper::setCurrentFont(const QFont &font)
{ {
GtkFontSelectionDialog *gtkDialog = GTK_FONT_SELECTION_DIALOG(d->gtkDialog()); GtkFontChooser *gtkDialog = GTK_FONT_CHOOSER(d->gtkDialog());
gtk_font_selection_dialog_set_font_name(gtkDialog, qt_fontToString(font).toUtf8()); gtk_font_chooser_set_font(gtkDialog, qt_fontToString(font).toUtf8());
} }
QFont QGtk2FontDialogHelper::currentFont() const QFont QGtk3FontDialogHelper::currentFont() const
{ {
GtkFontSelectionDialog *gtkDialog = GTK_FONT_SELECTION_DIALOG(d->gtkDialog()); GtkFontChooser *gtkDialog = GTK_FONT_CHOOSER(d->gtkDialog());
gchar *name = gtk_font_selection_dialog_get_font_name(gtkDialog); gchar *name = gtk_font_chooser_get_font(gtkDialog);
QFont font = qt_fontFromString(QString::fromUtf8(name)); QFont font = qt_fontFromString(QString::fromUtf8(name));
g_free(name); g_free(name);
return font; return font;
} }
void QGtk2FontDialogHelper::onAccepted() void QGtk3FontDialogHelper::onAccepted()
{ {
emit currentFontChanged(currentFont()); emit currentFontChanged(currentFont());
emit accept(); emit accept();
emit fontSelected(currentFont()); emit fontSelected(currentFont());
} }
void QGtk2FontDialogHelper::applyOptions() void QGtk3FontDialogHelper::applyOptions()
{ {
GtkDialog *gtkDialog = d->gtkDialog(); GtkDialog *gtkDialog = d->gtkDialog();
const QSharedPointer<QFontDialogOptions> &opts = options(); const QSharedPointer<QFontDialogOptions> &opts = options();
gtk_window_set_title(GTK_WINDOW(gtkDialog), opts->windowTitle().toUtf8()); gtk_window_set_title(GTK_WINDOW(gtkDialog), opts->windowTitle().toUtf8());
GtkWidget *okButton = gtk_font_selection_dialog_get_ok_button(GTK_FONT_SELECTION_DIALOG(gtkDialog));
GtkWidget *cancelButton = gtk_font_selection_dialog_get_cancel_button(GTK_FONT_SELECTION_DIALOG(gtkDialog));
if (okButton)
gtk_widget_set_visible(okButton, !options()->testOption(QFontDialogOptions::NoButtons));
if (cancelButton)
gtk_widget_set_visible(cancelButton, !options()->testOption(QFontDialogOptions::NoButtons));
} }
QT_END_NAMESPACE QT_END_NAMESPACE
#include "qgtk2dialoghelpers.moc" #include "qgtk3dialoghelpers.moc"

View File

@ -31,8 +31,8 @@
** **
****************************************************************************/ ****************************************************************************/
#ifndef QGTK2DIALOGHELPERS_P_H #ifndef QGTK3DIALOGHELPERS_H
#define QGTK2DIALOGHELPERS_P_H #define QGTK3DIALOGHELPERS_H
#include <QtCore/qhash.h> #include <QtCore/qhash.h>
#include <QtCore/qlist.h> #include <QtCore/qlist.h>
@ -46,16 +46,16 @@ typedef struct _GtkFileFilter GtkFileFilter;
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QGtk2Dialog; class QGtk3Dialog;
class QColor; class QColor;
class QGtk2ColorDialogHelper : public QPlatformColorDialogHelper class QGtk3ColorDialogHelper : public QPlatformColorDialogHelper
{ {
Q_OBJECT Q_OBJECT
public: public:
QGtk2ColorDialogHelper(); QGtk3ColorDialogHelper();
~QGtk2ColorDialogHelper(); ~QGtk3ColorDialogHelper();
bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) Q_DECL_OVERRIDE; bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) Q_DECL_OVERRIDE;
void exec() Q_DECL_OVERRIDE; void exec() Q_DECL_OVERRIDE;
@ -68,19 +68,19 @@ private Q_SLOTS:
void onAccepted(); void onAccepted();
private: private:
static void onColorChanged(QGtk2ColorDialogHelper *helper); static void onColorChanged(QGtk3ColorDialogHelper *helper);
void applyOptions(); void applyOptions();
QScopedPointer<QGtk2Dialog> d; QScopedPointer<QGtk3Dialog> d;
}; };
class QGtk2FileDialogHelper : public QPlatformFileDialogHelper class QGtk3FileDialogHelper : public QPlatformFileDialogHelper
{ {
Q_OBJECT Q_OBJECT
public: public:
QGtk2FileDialogHelper(); QGtk3FileDialogHelper();
~QGtk2FileDialogHelper(); ~QGtk3FileDialogHelper();
bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) Q_DECL_OVERRIDE; bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) Q_DECL_OVERRIDE;
void exec() Q_DECL_OVERRIDE; void exec() Q_DECL_OVERRIDE;
@ -99,8 +99,8 @@ private Q_SLOTS:
void onAccepted(); void onAccepted();
private: private:
static void onSelectionChanged(GtkDialog *dialog, QGtk2FileDialogHelper *helper); static void onSelectionChanged(GtkDialog *dialog, QGtk3FileDialogHelper *helper);
static void onCurrentFolderChanged(QGtk2FileDialogHelper *helper); static void onCurrentFolderChanged(QGtk3FileDialogHelper *helper);
void applyOptions(); void applyOptions();
void setNameFilters(const QStringList &filters); void setNameFilters(const QStringList &filters);
@ -108,16 +108,16 @@ private:
QList<QUrl> _selection; QList<QUrl> _selection;
QHash<QString, GtkFileFilter*> _filters; QHash<QString, GtkFileFilter*> _filters;
QHash<GtkFileFilter*, QString> _filterNames; QHash<GtkFileFilter*, QString> _filterNames;
QScopedPointer<QGtk2Dialog> d; QScopedPointer<QGtk3Dialog> d;
}; };
class QGtk2FontDialogHelper : public QPlatformFontDialogHelper class QGtk3FontDialogHelper : public QPlatformFontDialogHelper
{ {
Q_OBJECT Q_OBJECT
public: public:
QGtk2FontDialogHelper(); QGtk3FontDialogHelper();
~QGtk2FontDialogHelper(); ~QGtk3FontDialogHelper();
bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) Q_DECL_OVERRIDE; bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) Q_DECL_OVERRIDE;
void exec() Q_DECL_OVERRIDE; void exec() Q_DECL_OVERRIDE;
@ -132,9 +132,9 @@ private Q_SLOTS:
private: private:
void applyOptions(); void applyOptions();
QScopedPointer<QGtk2Dialog> d; QScopedPointer<QGtk3Dialog> d;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE
#endif // QGTK2DIALOGHELPERS_P_H #endif // QGTK3DIALOGHELPERS_H

View File

@ -31,8 +31,8 @@
** **
****************************************************************************/ ****************************************************************************/
#include "qgtk2theme.h" #include "qgtk3theme.h"
#include "qgtk2dialoghelpers.h" #include "qgtk3dialoghelpers.h"
#include <QVariant> #include <QVariant>
#undef signals #undef signals
@ -42,7 +42,7 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
const char *QGtk2Theme::name = "gtk2"; const char *QGtk3Theme::name = "gtk3";
static QString gtkSetting(const gchar *propertyName) static QString gtkSetting(const gchar *propertyName)
{ {
@ -54,7 +54,21 @@ static QString gtkSetting(const gchar *propertyName)
return str; return str;
} }
QGtk2Theme::QGtk2Theme() void gtkMessageHandler(const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer unused_data) {
/* Silence false-positive Gtk warnings (we are using Xlib to set
* the WM_TRANSIENT_FOR hint).
*/
if (g_strcmp0(message, "GtkDialog mapped without a transient parent. "
"This is discouraged.") != 0) {
/* For other messages, call the default handler. */
g_log_default_handler(log_domain, log_level, message, unused_data);
}
}
QGtk3Theme::QGtk3Theme()
{ {
// gtk_init will reset the Xlib error handler, and that causes // gtk_init will reset the Xlib error handler, and that causes
// Qt applications to quit on X errors. Therefore, we need to manually restore it. // Qt applications to quit on X errors. Therefore, we need to manually restore it.
@ -63,9 +77,18 @@ QGtk2Theme::QGtk2Theme()
gtk_init(0, 0); gtk_init(0, 0);
XSetErrorHandler(oldErrorHandler); XSetErrorHandler(oldErrorHandler);
/* Initialize some types here so that Gtk+ does not crash when reading
* the treemodel for GtkFontChooser.
*/
g_type_ensure(PANGO_TYPE_FONT_FAMILY);
g_type_ensure(PANGO_TYPE_FONT_FACE);
/* Use our custom log handler. */
g_log_set_handler("Gtk", G_LOG_LEVEL_MESSAGE, gtkMessageHandler, NULL);
} }
QVariant QGtk2Theme::themeHint(QPlatformTheme::ThemeHint hint) const QVariant QGtk3Theme::themeHint(QPlatformTheme::ThemeHint hint) const
{ {
switch (hint) { switch (hint) {
case QPlatformTheme::SystemIconThemeName: case QPlatformTheme::SystemIconThemeName:
@ -77,7 +100,7 @@ QVariant QGtk2Theme::themeHint(QPlatformTheme::ThemeHint hint) const
} }
} }
QString QGtk2Theme::gtkFontName() const QString QGtk3Theme::gtkFontName() const
{ {
QString cfgFontName = gtkSetting("gtk-font-name"); QString cfgFontName = gtkSetting("gtk-font-name");
if (!cfgFontName.isEmpty()) if (!cfgFontName.isEmpty())
@ -85,7 +108,7 @@ QString QGtk2Theme::gtkFontName() const
return QGnomeTheme::gtkFontName(); return QGnomeTheme::gtkFontName();
} }
bool QGtk2Theme::usePlatformNativeDialog(DialogType type) const bool QGtk3Theme::usePlatformNativeDialog(DialogType type) const
{ {
switch (type) { switch (type) {
case ColorDialog: case ColorDialog:
@ -99,15 +122,15 @@ bool QGtk2Theme::usePlatformNativeDialog(DialogType type) const
} }
} }
QPlatformDialogHelper *QGtk2Theme::createPlatformDialogHelper(DialogType type) const QPlatformDialogHelper *QGtk3Theme::createPlatformDialogHelper(DialogType type) const
{ {
switch (type) { switch (type) {
case ColorDialog: case ColorDialog:
return new QGtk2ColorDialogHelper; return new QGtk3ColorDialogHelper;
case FileDialog: case FileDialog:
return new QGtk2FileDialogHelper; return new QGtk3FileDialogHelper;
case FontDialog: case FontDialog:
return new QGtk2FontDialogHelper; return new QGtk3FontDialogHelper;
default: default:
return 0; return 0;
} }

View File

@ -31,17 +31,17 @@
** **
****************************************************************************/ ****************************************************************************/
#ifndef QGTK2THEME_H #ifndef QGTK3THEME_H
#define QGTK2THEME_H #define QGTK3THEME_H
#include <private/qgenericunixthemes_p.h> #include <private/qgenericunixthemes_p.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QGtk2Theme : public QGnomeTheme class QGtk3Theme : public QGnomeTheme
{ {
public: public:
QGtk2Theme(); QGtk3Theme();
virtual QVariant themeHint(ThemeHint hint) const Q_DECL_OVERRIDE; virtual QVariant themeHint(ThemeHint hint) const Q_DECL_OVERRIDE;
virtual QString gtkFontName() const Q_DECL_OVERRIDE; virtual QString gtkFontName() const Q_DECL_OVERRIDE;
@ -54,4 +54,4 @@ public:
QT_END_NAMESPACE QT_END_NAMESPACE
#endif // QGTK2THEME_H #endif // QGTK3THEME_H

View File

@ -1,3 +1,3 @@
TEMPLATE = subdirs TEMPLATE = subdirs
contains(QT_CONFIG, gtk2): SUBDIRS += gtk2 contains(QT_CONFIG, gtk3): SUBDIRS += gtk3