Skip to content

Commit bacad8c

Browse files
committedJul 6, 2017
[needs-docs] Show recently used fonts in submenu in font button
1 parent e95b65e commit bacad8c

File tree

5 files changed

+142
-31
lines changed

5 files changed

+142
-31
lines changed
 

‎python/core/qgsfontutils.sip

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,21 @@ class QgsFontUtils
187187
.. versionadded:: 2.16
188188
:rtype: str
189189
%End
190+
191+
static void addRecentFontFamily( const QString &family );
192+
%Docstring
193+
Adds a font ``family`` to the list of recently used font families.
194+
.. versionadded:: 3.0
195+
.. seealso:: recentFontFamilies()
196+
%End
197+
198+
static QStringList recentFontFamilies();
199+
%Docstring
200+
Returns a list of recently used font families.
201+
.. seealso:: addRecentFontFamily()
202+
.. versionadded:: 3.0
203+
:rtype: list of str
204+
%End
190205
};
191206

192207
/************************************************************************

‎src/core/qgsfontutils.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "qgsapplication.h"
1919
#include "qgslogger.h"
20+
#include "qgssettings.h"
2021

2122
#include <QApplication>
2223
#include <QFile>
@@ -506,3 +507,31 @@ QString QgsFontUtils::asCSS( const QFont &font, double pointToPixelScale )
506507

507508
return css;
508509
}
510+
511+
void QgsFontUtils::addRecentFontFamily( const QString &family )
512+
{
513+
if ( family.isEmpty() )
514+
{
515+
return;
516+
}
517+
518+
QgsSettings settings;
519+
QStringList recentFamilies = settings.value( QStringLiteral( "fonts/recent" ) ).toStringList();
520+
521+
//remove matching families
522+
recentFamilies.removeAll( family );
523+
524+
//then add to start of list
525+
recentFamilies.prepend( family );
526+
527+
//trim to 10 fonts
528+
recentFamilies = recentFamilies.mid( 0, 10 );
529+
530+
settings.setValue( QStringLiteral( "fonts/recent" ), recentFamilies );
531+
}
532+
533+
QStringList QgsFontUtils::recentFontFamilies()
534+
{
535+
QgsSettings settings;
536+
return settings.value( QStringLiteral( "fonts/recent" ) ).toStringList();
537+
}

‎src/core/qgsfontutils.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,20 @@ class CORE_EXPORT QgsFontUtils
165165
* \since QGIS 2.16
166166
*/
167167
static QString asCSS( const QFont &font, double pointToPixelMultiplier = 1.0 );
168+
169+
/**
170+
* Adds a font \a family to the list of recently used font families.
171+
* \since QGIS 3.0
172+
* \see recentFontFamilies()
173+
*/
174+
static void addRecentFontFamily( const QString &family );
175+
176+
/**
177+
* Returns a list of recently used font families.
178+
* \see addRecentFontFamily()
179+
* \since QGIS 3.0
180+
*/
181+
static QStringList recentFontFamilies();
168182
};
169183

170184
#endif // QGSFONTUTILS_H

‎src/gui/qgsfontbutton.cpp

Lines changed: 49 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ void QgsFontButton::showSettingsDialog()
7070
if ( dialog.exec() )
7171
{
7272
setTextFormat( dialog.format() );
73+
QgsFontUtils::addRecentFontFamily( mFormat.font().family() );
7374
}
7475
break;
7576
}
@@ -80,6 +81,7 @@ void QgsFontButton::showSettingsDialog()
8081
QFont newFont = QgsGuiUtils::getFont( ok, mFont, mDialogTitle );
8182
if ( ok )
8283
{
84+
QgsFontUtils::addRecentFontFamily( newFont.family() );
8385
setCurrentFont( newFont );
8486
}
8587
break;
@@ -141,9 +143,11 @@ void QgsFontButton::pasteFormat()
141143
if ( mMode == ModeTextRenderer && formatFromMimeData( QApplication::clipboard()->mimeData(), tempFormat ) )
142144
{
143145
setTextFormat( tempFormat );
146+
QgsFontUtils::addRecentFontFamily( mFormat.font().family() );
144147
}
145148
else if ( mMode == ModeQFont && fontFromMimeData( QApplication::clipboard()->mimeData(), font ) )
146149
{
150+
QgsFontUtils::addRecentFontFamily( font.family() );
147151
setCurrentFont( font );
148152
}
149153
}
@@ -280,10 +284,12 @@ void QgsFontButton::dropEvent( QDropEvent *e )
280284
if ( mMode == ModeTextRenderer && formatFromMimeData( e->mimeData(), format ) )
281285
{
282286
setTextFormat( format );
287+
QgsFontUtils::addRecentFontFamily( mFormat.font().family() );
283288
return;
284289
}
285290
else if ( mMode == ModeQFont && fontFromMimeData( e->mimeData(), font ) )
286291
{
292+
QgsFontUtils::addRecentFontFamily( font.family() );
287293
setCurrentFont( font );
288294
return;
289295
}
@@ -463,34 +469,6 @@ void QgsFontButton::prepareMenu()
463469
//menu is opened, otherwise color schemes like the recent color scheme grid are meaningless
464470
mMenu->clear();
465471

466-
#if 0 // too slow if many fonts...
467-
QMenu *fontMenu = new QMenu( mFormat.font().family(), mMenu );
468-
QFontDatabase db;
469-
Q_FOREACH ( const QString &family, db.families() )
470-
{
471-
QAction *fontAction = new QAction( family, fontMenu );
472-
QFont f = fontAction->font();
473-
f.setFamily( family );
474-
fontAction->setFont( f );
475-
fontAction->setToolTip( family );
476-
fontMenu->addAction( fontAction );
477-
if ( family == mFormat.font().family() )
478-
{
479-
fontAction->setCheckable( true );
480-
fontAction->setChecked( true );
481-
}
482-
auto setFont = [this, family]
483-
{
484-
QFont f = mFormat.font();
485-
f.setFamily( family );
486-
mFormat.setFont( f );
487-
updatePreview();
488-
emit changed();
489-
};
490-
connect( fontAction, &QAction::triggered, this, setFont );
491-
}
492-
mMenu->addMenu( fontMenu );
493-
#endif
494472

495473
QWidgetAction *sizeAction = new QWidgetAction( mMenu );
496474
QWidget *sizeWidget = new QWidget();
@@ -545,6 +523,49 @@ void QgsFontButton::prepareMenu()
545523
sizeWidget->setFocusPolicy( Qt::StrongFocus );
546524
mMenu->addAction( sizeAction );
547525

526+
QMenu *recentFontMenu = new QMenu( tr( "Recent fonts" ), mMenu );
527+
Q_FOREACH ( const QString &family, QgsFontUtils::recentFontFamilies() )
528+
{
529+
QAction *fontAction = new QAction( family, recentFontMenu );
530+
QFont f = fontAction->font();
531+
f.setFamily( family );
532+
fontAction->setFont( f );
533+
fontAction->setToolTip( family );
534+
recentFontMenu->addAction( fontAction );
535+
if ( ( mMode == ModeTextRenderer && family == mFormat.font().family() )
536+
|| ( mMode == ModeQFont && family == mFont.family() ) )
537+
{
538+
fontAction->setCheckable( true );
539+
fontAction->setChecked( true );
540+
}
541+
auto setFont = [this, family]
542+
{
543+
switch ( mMode )
544+
{
545+
case ModeTextRenderer:
546+
{
547+
QgsTextFormat newFormat = mFormat;
548+
QFont f = newFormat.font();
549+
f.setFamily( family );
550+
newFormat.setFont( f );
551+
setTextFormat( newFormat );
552+
QgsFontUtils::addRecentFontFamily( mFormat.font().family() );
553+
break;
554+
}
555+
case ModeQFont:
556+
{
557+
QFont font = mFont;
558+
font.setFamily( family );
559+
setCurrentFont( font );
560+
QgsFontUtils::addRecentFontFamily( family );
561+
break;
562+
}
563+
}
564+
};
565+
connect( fontAction, &QAction::triggered, this, setFont );
566+
}
567+
mMenu->addMenu( recentFontMenu );
568+
548569
QAction *configureAction = new QAction( tr( "Configure format..." ), this );
549570
mMenu->addAction( configureAction );
550571
connect( configureAction, &QAction::triggered, this, &QgsFontButton::showSettingsDialog );

‎tests/src/python/test_qgsfontutils.py

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,29 @@
1414
# This will get replaced with a git SHA1 when you do a git archive
1515
__revision__ = '$Format:%H$'
1616

17-
from qgis.core import QgsFontUtils
17+
from qgis.core import QgsFontUtils, QgsSettings
1818
from qgis.testing import (
1919
start_app,
2020
unittest
2121
)
22+
from qgis.PyQt.QtCore import QCoreApplication
2223
from utilities import (
2324
getTestFontFamily,
2425
loadTestFonts
2526
)
2627

27-
start_app()
28-
2928

3029
class TestQgsFontUtils(unittest.TestCase):
3130

3231
@classmethod
3332
def setUpClass(cls):
33+
QCoreApplication.setOrganizationName("QGIS_Test")
34+
QCoreApplication.setOrganizationDomain("QGIS_TestPyQgsFontUtils.com")
35+
QCoreApplication.setApplicationName("QGIS_TestPyQgsFontUtils")
36+
QgsSettings().clear()
37+
38+
start_app()
39+
3440
cls._family = getTestFontFamily()
3541
cls._has_style = QgsFontUtils.fontFamilyHasStyle
3642

@@ -88,6 +94,32 @@ def testToFromMimeData(self):
8894
msg = self._family + ' test font Bold Oblique at 14 pt not retrieved from mime data'
8995
self.assertTrue(res, msg)
9096

97+
def testRecentFonts(self):
98+
"""
99+
Test adding and retrieving recent fonts
100+
"""
101+
102+
# test empty list
103+
self.assertFalse(QgsFontUtils.recentFontFamilies())
104+
QgsFontUtils.addRecentFontFamily('Comic Sans FTW, suckers')
105+
self.assertEqual(QgsFontUtils.recentFontFamilies(), ['Comic Sans FTW, suckers'])
106+
QgsFontUtils.addRecentFontFamily('Arial')
107+
self.assertEqual(QgsFontUtils.recentFontFamilies(), ['Arial', 'Comic Sans FTW, suckers'])
108+
QgsFontUtils.addRecentFontFamily('Arial2')
109+
QgsFontUtils.addRecentFontFamily('Arial3')
110+
QgsFontUtils.addRecentFontFamily('Arial4')
111+
QgsFontUtils.addRecentFontFamily('Arial5')
112+
QgsFontUtils.addRecentFontFamily('Arial6')
113+
QgsFontUtils.addRecentFontFamily('Arial7')
114+
QgsFontUtils.addRecentFontFamily('Arial8')
115+
QgsFontUtils.addRecentFontFamily('Arial9')
116+
QgsFontUtils.addRecentFontFamily('Arial10')
117+
self.assertEqual(QgsFontUtils.recentFontFamilies(), ['Arial10', 'Arial9', 'Arial8', 'Arial7', 'Arial6', 'Arial5', 'Arial4', 'Arial3', 'Arial2', 'Arial'])
118+
QgsFontUtils.addRecentFontFamily('Arial9')
119+
self.assertEqual(QgsFontUtils.recentFontFamilies(), ['Arial9', 'Arial10', 'Arial8', 'Arial7', 'Arial6', 'Arial5', 'Arial4', 'Arial3', 'Arial2', 'Arial'])
120+
QgsFontUtils.addRecentFontFamily('Comic Sans FTW, suckers')
121+
self.assertEqual(QgsFontUtils.recentFontFamilies(), ['Comic Sans FTW, suckers', 'Arial9', 'Arial10', 'Arial8', 'Arial7', 'Arial6', 'Arial5', 'Arial4', 'Arial3', 'Arial2'])
122+
91123

92124
if __name__ == '__main__':
93125
unittest.main()

0 commit comments

Comments
 (0)
Please sign in to comment.