iOS plugin: Add native font dialog

[ChangeLog][iOS] Added native font dialog support for iOS.

Task-number: QTBUG-109059
Change-Id: If38e990e1c5e9fc1a303fce3e79c09c2d45daaa0
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Doris Verria 2022-11-30 11:30:41 +01:00
parent 67715b0095
commit 443af8cd45
4 changed files with 237 additions and 0 deletions

View File

@ -60,6 +60,7 @@ qt_internal_extend_target(QIOSIntegrationPlugin CONDITION NOT TVOS
qiosdocumentpickercontroller.h qiosdocumentpickercontroller.mm
qiosfiledialog.h qiosfiledialog.mm
qioscolordialog.h qioscolordialog.mm
qiosfontdialog.h qiosfontdialog.mm
qiosmenu.h qiosmenu.mm
qiosmessagedialog.h qiosmessagedialog.mm
qiostextinputoverlay.h qiostextinputoverlay.mm

View File

@ -0,0 +1,41 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIOSFONTDIALOG_H
#define QIOSFONTDIALOG_H
#include <QtCore/qeventloop.h>
#include <qpa/qplatformdialoghelper.h>
@interface QIOSFontDialogController : UIFontPickerViewController <UIFontPickerViewControllerDelegate,
UIAdaptivePresentationControllerDelegate>
@end
QT_BEGIN_NAMESPACE
class QIOSFontDialog : public QPlatformFontDialogHelper
{
public:
QIOSFontDialog();
~QIOSFontDialog();
void exec() override;
bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) override;
void hide() override;
void setCurrentFont(const QFont &) override;
QFont currentFont() const override;
void updateCurrentFont(const QFont &);
private:
QEventLoop m_eventLoop;
QIOSFontDialogController *m_viewController;
QFont m_currentFont;
};
QT_END_NAMESPACE
#endif // QIOSFONTDIALOG_H

View File

@ -0,0 +1,190 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#import <UIKit/UIKit.h>
#include <QtGui/qwindow.h>
#include <QtGui/qfontdatabase.h>
#include <QDebug>
#include <QtCore/private/qcore_mac_p.h>
#include <QtGui/private/qfont_p.h>
#include <QtGui/private/qfontengine_p.h>
#include "qiosfontdialog.h"
#include "qiosintegration.h"
@implementation QIOSFontDialogController {
QIOSFontDialog *m_fontDialog;
}
- (instancetype)initWithQIOSFontDialog:(QIOSFontDialog *)dialog
{
UIFontPickerViewControllerConfiguration *configuration = [[UIFontPickerViewControllerConfiguration alloc] init];
if (dialog->options()->testOption(QFontDialogOptions::MonospacedFonts)) {
UIFontDescriptorSymbolicTraits traits;
traits |= UIFontDescriptorTraitMonoSpace;
configuration.filteredTraits = traits;
}
configuration.includeFaces = YES;
if (self = [super initWithConfiguration:configuration]) {
m_fontDialog = dialog;
self.delegate = self;
self.presentationController.delegate = self;
}
[configuration release];
return self;
}
- (void)setQFont:(const QFont &)font
{
QFontInfo fontInfo(font);
auto family = fontInfo.family().toNSString();
auto size = fontInfo.pointSize();
NSDictionary *dictionary = @{
static_cast<NSString *>(UIFontDescriptorFamilyAttribute): family,
static_cast<NSString *>(UIFontDescriptorSizeAttribute): [NSNumber numberWithInt:size]
};
UIFontDescriptor *fd = [UIFontDescriptor fontDescriptorWithFontAttributes:dictionary];
UIFontDescriptorSymbolicTraits traits = 0;
if (font.style() == QFont::StyleItalic)
traits |= UIFontDescriptorTraitItalic;
if (font.weight() == QFont::Bold)
traits |= UIFontDescriptorTraitBold;
fd = [fd fontDescriptorWithSymbolicTraits:traits];
self.selectedFontDescriptor = fd;
}
- (void)updateQFont
{
UIFontDescriptor *font = self.selectedFontDescriptor;
if (!font)
return;
NSDictionary *attributes = font.fontAttributes;
UIFontDescriptorSymbolicTraits traits = font.symbolicTraits;
QFont newFont;
int size = qRound(font.pointSize);
QString family = QString::fromNSString([attributes objectForKey:UIFontDescriptorFamilyAttribute]);
if (family.isEmpty()) {
// If includeFaces is true, then the font descriptor won't
// have the UIFontDescriptorFamilyAttribute key set so we
// need to create a UIFont to get the font family
UIFont *f = [UIFont fontWithDescriptor:font size:size];
family = QString::fromNSString(f.familyName);
}
QString style;
if ((traits & (UIFontDescriptorTraitItalic | UIFontDescriptorTraitBold)) == (UIFontDescriptorTraitItalic | UIFontDescriptorTraitBold))
style = "Bold Italic";
else if (traits & UIFontDescriptorTraitItalic)
style = "Italic";
else if (traits & UIFontDescriptorTraitBold)
style = "Bold";
newFont = QFontDatabase::font(family, style, size);
if (m_fontDialog) {
m_fontDialog->updateCurrentFont(newFont);
emit m_fontDialog->currentFontChanged(newFont);
}
}
// ----------------------UIFontPickerViewControllerDelegate--------------------------
- (void)fontPickerViewControllerDidPickFont:(UIFontPickerViewController *)viewController
{
[self updateQFont];
emit m_fontDialog->accept();
}
- (void)fontPickerViewControllerDidCancel:(UIFontPickerViewController *)viewController
{
Q_UNUSED(viewController);
emit m_fontDialog->reject();
}
// ----------------------UIAdaptivePresentationControllerDelegate--------------------------
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController
{
Q_UNUSED(presentationController);
emit m_fontDialog->reject();
}
@end
QIOSFontDialog::QIOSFontDialog()
: m_viewController(nullptr)
{
}
QIOSFontDialog::~QIOSFontDialog()
{
hide();
}
void QIOSFontDialog::exec()
{
m_eventLoop.exec(QEventLoop::DialogExec);
}
bool QIOSFontDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
{
Q_UNUSED(windowFlags);
Q_UNUSED(windowModality);
if (!m_viewController) {
m_viewController = [[QIOSFontDialogController alloc] initWithQIOSFontDialog:this];
[m_viewController setQFont:m_currentFont];
}
if (windowModality == Qt::ApplicationModal || windowModality == Qt::WindowModal)
m_viewController.modalInPresentation = YES;
UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window
: qt_apple_sharedApplication().keyWindow;
if (!window)
return false;
// We can't present from view controller if already presenting
if (window.rootViewController.presentedViewController)
return false;
[window.rootViewController presentViewController:m_viewController animated:YES completion:nil];
return true;
}
void QIOSFontDialog::hide()
{
[m_viewController dismissViewControllerAnimated:YES completion:nil];
[m_viewController release];
m_viewController = nullptr;
if (m_eventLoop.isRunning())
m_eventLoop.exit();
}
void QIOSFontDialog::setCurrentFont(const QFont &font)
{
if (m_currentFont == font)
return;
m_currentFont = font;
if (m_viewController)
[m_viewController setQFont:font];
}
QFont QIOSFontDialog::currentFont() const
{
return m_currentFont;
}
void QIOSFontDialog::updateCurrentFont(const QFont &font)
{
m_currentFont = font;
}

View File

@ -22,6 +22,7 @@
#include "qiosfiledialog.h"
#include "qiosmessagedialog.h"
#include "qioscolordialog.h"
#include "qiosfontdialog.h"
#endif
QT_BEGIN_NAMESPACE
@ -100,6 +101,7 @@ bool QIOSTheme::usePlatformNativeDialog(QPlatformTheme::DialogType type) const
case FileDialog:
case MessageDialog:
case ColorDialog:
case FontDialog:
return !qt_apple_isApplicationExtension();
default:
return false;
@ -119,6 +121,9 @@ QPlatformDialogHelper *QIOSTheme::createPlatformDialogHelper(QPlatformTheme::Dia
case ColorDialog:
return new QIOSColorDialog();
break;
case FontDialog:
return new QIOSFontDialog();
break;
#endif
default:
return 0;