From b25f6acec4ce962daadad66f485efe32a512ed8f Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 3 Nov 2019 20:21:28 -0600 Subject: [PATCH] libaudqt: hook up a font entry widget --- src/libaudqt/Makefile | 1 + src/libaudqt/font-entry.cc | 195 ++++++++++++++++++++++++++++++++ src/libaudqt/libaudqt.h | 5 + src/libaudqt/meson.build | 1 + src/libaudqt/prefs-builder.cc | 5 +- src/libaudqt/prefs-widget-qt.cc | 25 ++++ src/libaudqt/prefs-widget.h | 9 ++ 7 files changed, 240 insertions(+), 1 deletion(-) create mode 100644 src/libaudqt/font-entry.cc diff --git a/src/libaudqt/Makefile b/src/libaudqt/Makefile index 0dad7693d0..7e9b2003fc 100644 --- a/src/libaudqt/Makefile +++ b/src/libaudqt/Makefile @@ -10,6 +10,7 @@ SRCS = about-qt.cc \ equalizer-qt.cc \ file-entry.cc \ fileopener.cc \ + font-entry.cc \ images.cc \ infopopup-qt.cc \ infowin-qt.cc \ diff --git a/src/libaudqt/font-entry.cc b/src/libaudqt/font-entry.cc new file mode 100644 index 0000000000..73351f16ba --- /dev/null +++ b/src/libaudqt/font-entry.cc @@ -0,0 +1,195 @@ +/* + * font-entry.cc + * Copyright 2015 John Lindgren + * Copyright 2019 Ariadne Conill + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions, and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions, and the following disclaimer in the documentation + * provided with the distribution. + * + * This software is provided "as is" and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising from + * the use of this software. + */ + +#include "libaudqt.h" + +#include +#include +#include +#include + +#include +#include + +namespace audqt { + +class FontEntry : public QLineEdit { +public: + FontEntry (QWidget * parent = nullptr, const char * font = nullptr) : + QLineEdit (parent), + m_action (get_icon ("dialog-text-and-font"), _("Set Font"), nullptr) + { + addAction (& m_action, TrailingPosition); + connect (& m_action, & QAction::triggered, this, & FontEntry::show_dialog); + + if (font) + setText (font); + + end (false); + } + +private: + QFontDialog * create_dialog (); + void show_dialog (); + + QAction m_action; + QPointer m_dialog; +}; + +/* parse a subset of Pango font descriptions */ +static QFont * qfont_from_string (const char * name) +{ + auto family = str_copy (name); + int size = 0; + QFont::Weight weight = QFont::Normal; + QFont::Style style = QFont::StyleNormal; + QFont::Stretch stretch = QFont::Unstretched; + + while (1) + { + /* check for attributes */ + bool attr_found = false; + const char * space = strrchr (family, ' '); + + if (space) + { + const char * attr = space + 1; + int num = str_to_int (attr); + + attr_found = true; + + if (num > 0) + size = num; + else if (! strcmp (attr, "Light")) + weight = QFont::Light; + else if (! strcmp (attr, "Bold")) + weight = QFont::Bold; + else if (! strcmp (attr, "Oblique")) + style = QFont::StyleOblique; + else if (! strcmp (attr, "Italic")) + style = QFont::StyleItalic; + else if (! strcmp (attr, "Condensed")) + stretch = QFont::Condensed; + else if (! strcmp (attr, "Expanded")) + stretch = QFont::Expanded; + else + attr_found = false; + } + + if (! attr_found) + { + auto font = new QFont ((const char *) family); + + /* check for a recognized font family */ + if (! space || font->exactMatch ()) + { + if (size > 0) + font->setPointSize (size); + if (weight != QFont::Normal) + font->setWeight (weight); + if (style != QFont::StyleNormal) + font->setStyle (style); + if (stretch != QFont::Unstretched) + font->setStretch (stretch); + + return font; + } + + delete font; + } + + family.resize (space - family); + } +} + +QFontDialog * FontEntry::create_dialog () +{ + auto dialog = new QFontDialog (this); + + QObject::connect (dialog, & QFontDialog::fontSelected, [this] (const QFont & font) { + auto family = font.family ().toUtf8 (); + + // build the description string + StringBuf font_str = str_copy ((const char *) family); + + auto weight = font.weight (); + auto style = font.style (); + auto stretch = font.stretch (); + + if (weight == QFont::Light) + font_str = str_concat({font_str, " Light"}); + else if (weight == QFont::Bold) + font_str = str_concat({font_str, " Bold"}); + + if (style == QFont::StyleOblique) + font_str = str_concat({font_str, " Oblique"}); + else if (style == QFont::StyleItalic) + font_str = str_concat({font_str, " Italic"}); + + if (stretch == QFont::Condensed) + font_str = str_concat ({font_str, " Condensed"}); + else if (stretch == QFont::Expanded) + font_str = str_concat ({font_str, " Expanded"}); + + font_str = str_concat({font_str, " ", int_to_str (font.pointSize ())}); + + font_entry_set_font (this, font_str); + }); + + return dialog; +} + +void FontEntry::show_dialog () +{ + if (! m_dialog) + m_dialog = create_dialog (); + + auto font = qfont_from_string (font_entry_get_font (this)); + if (! font) + { + window_bring_to_front (m_dialog); + return; + } + + m_dialog->setCurrentFont (*font); + delete font; + + window_bring_to_front (m_dialog); +} + +EXPORT QLineEdit * font_entry_new (QWidget * parent, const char * font) +{ + return new FontEntry (parent, font); +} + +EXPORT String font_entry_get_font (QLineEdit * entry) +{ + QByteArray text = entry->text ().toUtf8 (); + + return String (text); +} + +EXPORT void font_entry_set_font (QLineEdit * entry, const char * font) +{ + entry->setText (font); + entry->end (false); +} + +} // namespace audqt diff --git a/src/libaudqt/libaudqt.h b/src/libaudqt/libaudqt.h index 8f828cdf5f..5ccafcf17e 100644 --- a/src/libaudqt/libaudqt.h +++ b/src/libaudqt/libaudqt.h @@ -130,6 +130,11 @@ QLineEdit * file_entry_new (QWidget * parent, const char * title, String file_entry_get_uri (QLineEdit * entry); void file_entry_set_uri (QLineEdit * entry, const char * uri); +/* font-entry.cc */ +QLineEdit * font_entry_new (QWidget * parent, const char * font); +String font_entry_get_font (QLineEdit * entry); +void font_entry_set_font (QLineEdit * entry, const char * font); + /* prefs-builder.cc */ void prefs_populate (QBoxLayout * layout, ArrayRef widgets, const char * domain); diff --git a/src/libaudqt/meson.build b/src/libaudqt/meson.build index 0163204973..6aff2c913d 100644 --- a/src/libaudqt/meson.build +++ b/src/libaudqt/meson.build @@ -7,6 +7,7 @@ libaudqt_sources = [ 'equalizer-qt.cc', 'file-entry.cc', 'fileopener.cc', + 'font-entry.cc', 'infopopup-qt.cc', 'infowin-qt.cc', 'info-widget.cc', diff --git a/src/libaudqt/prefs-builder.cc b/src/libaudqt/prefs-builder.cc index 51ae4249fe..b7d66b981a 100644 --- a/src/libaudqt/prefs-builder.cc +++ b/src/libaudqt/prefs-builder.cc @@ -151,10 +151,13 @@ void prefs_populate (QBoxLayout * layout, ArrayRef widgets, c case PreferencesWidget::Entry: /* TODO: implement file chooser and font selector */ case PreferencesWidget::FileEntry: - case PreferencesWidget::FontButton: layout->addWidget (new StringWidget (& w, domain)); break; + case PreferencesWidget::FontButton: + layout->addWidget (new FontWidget (& w, domain)); + break; + case PreferencesWidget::RadioButton: { if (! radio_btn_group[w.child]) diff --git a/src/libaudqt/prefs-widget-qt.cc b/src/libaudqt/prefs-widget-qt.cc index 4c75feb754..6c65baf425 100644 --- a/src/libaudqt/prefs-widget-qt.cc +++ b/src/libaudqt/prefs-widget-qt.cc @@ -213,6 +213,31 @@ void StringWidget::update () m_lineedit->setText ((const char *) m_parent->cfg.get_string ()); } +/* font widget (audqt::FontEntry) */ +FontWidget::FontWidget (const PreferencesWidget * parent, const char * domain) : + HookableWidget (parent, domain), + m_lineedit (font_entry_new (this, nullptr)) +{ + auto layout = make_hbox (this); + + if (parent->label) + layout->addWidget (new QLabel (translate_str (parent->label, domain))); + + layout->addWidget (m_lineedit, 1); + + update (); + + QObject::connect (m_lineedit, & QLineEdit::textChanged, [this] (const QString & value) { + if (! m_updating) + m_parent->cfg.set_string (value.toUtf8 ()); + }); +} + +void FontWidget::update () +{ + m_lineedit->setText ((const char *) m_parent->cfg.get_string ()); +} + /* combo box widget (string or int) */ ComboBoxWidget::ComboBoxWidget (const PreferencesWidget * parent, const char * domain) : HookableWidget (parent, domain), diff --git a/src/libaudqt/prefs-widget.h b/src/libaudqt/prefs-widget.h index b4711466ab..ebbbdb262c 100644 --- a/src/libaudqt/prefs-widget.h +++ b/src/libaudqt/prefs-widget.h @@ -131,6 +131,15 @@ class StringWidget : public QWidget, HookableWidget { QLineEdit * m_lineedit; }; +/* font widget (audqt::FontEntry) */ +class FontWidget : public QWidget, HookableWidget { +public: + FontWidget (const PreferencesWidget * parent, const char * domain); +private: + void update (); + QLineEdit * m_lineedit; +}; + /* combo box (string or int) */ class ComboBoxWidget : public QWidget, HookableWidget { public: