VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/objects/UIRichTextString.cpp@ 98103

Last change on this file since 98103 was 98103, checked in by vboxsync, 21 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
  • Property svn:mergeinfo set to (toggle deleted branches)
    /branches/VBox-3.0/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserItemMachine.cpp58652,​70973
    /branches/VBox-3.2/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserItemMachine.cpp66309,​66318
    /branches/VBox-4.0/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserItemMachine.cpp70873
    /branches/VBox-4.1/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserItemMachine.cpp74233
    /branches/VBox-4.2/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElement.cpp91503-91504,​91506-91508,​91510,​91514-91515,​91521
    /branches/VBox-4.3/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElement.cpp91223
    /branches/VBox-4.3/trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElement.cpp91223
    /branches/dsen/gui/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserItemMachine.cpp79076-79078,​79089,​79109-79110,​79112-79113,​79127-79130,​79134,​79141,​79151,​79155,​79157-79159,​79193,​79197
    /branches/dsen/gui2/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElement.cpp79562-79569,​79572-79573,​79578,​79581-79582,​79590-79591,​79598-79599,​79602-79603,​79605-79606,​79632,​79635,​79637,​79644
    /branches/dsen/gui3/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElement.cpp79645-79692
    /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserItemMachine.cpp79225,​79271
File size: 8.0 KB
Line 
1/* $Id: UIRichTextString.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIRichTextString class implementation.
4 */
5
6/*
7 * Copyright (C) 2015-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* Qt includes: */
29#include <QApplication>
30#include <QPalette>
31#include <QRegExp>
32
33/* GUI includes: */
34#include "UIRichTextString.h"
35
36/* Other VBox includes: */
37#include "iprt/assert.h"
38
39
40const QString UIRichTextString::s_strAny = QString("[\\s\\S]*");
41const QMap<UIRichTextString::Type, QString> UIRichTextString::s_patterns = populatePatterns();
42const QMap<UIRichTextString::Type, bool> UIRichTextString::s_doPatternHasMeta = populatePatternHasMeta();
43
44UIRichTextString::UIRichTextString(Type enmType /* = Type_None */)
45 : m_enmType(enmType)
46 , m_strString(QString())
47 , m_strStringMeta(QString())
48{
49}
50
51UIRichTextString::UIRichTextString(const QString &strString, Type enmType /* = Type_None */, const QString &strStringMeta /* = QString() */)
52 : m_enmType(enmType)
53 , m_strString(strString)
54 , m_strStringMeta(strStringMeta)
55{
56 //printf("Creating new UIRichTextString with string=\"%s\" and string-meta=\"%s\"\n",
57 // m_strString.toUtf8().constData(), m_strStringMeta.toUtf8().constData());
58 parse();
59}
60
61UIRichTextString::~UIRichTextString()
62{
63 /* Erase the map: */
64 qDeleteAll(m_strings.begin(), m_strings.end());
65 m_strings.clear();
66}
67
68QString UIRichTextString::toString() const
69{
70 /* Add own string first: */
71 QString strString = m_strString;
72
73 /* Add all the strings of children finally: */
74 foreach (const int &iPosition, m_strings.keys())
75 strString.insert(iPosition, m_strings.value(iPosition)->toString());
76
77 /* Return result: */
78 return strString;
79}
80
81QVector<QTextLayout::FormatRange> UIRichTextString::formatRanges(int iShift /* = 0 */) const
82{
83 /* Prepare format range list: */
84 QVector<QTextLayout::FormatRange> ranges;
85
86 /* Add own format range first: */
87 QTextLayout::FormatRange range;
88 range.start = iShift;
89 range.length = toString().size();
90 range.format = textCharFormat(m_enmType);
91 /* Enable anchor if present: */
92 if (!m_strAnchor.isNull())
93 {
94 range.format.setAnchorHref(m_strAnchor);
95 /* Highlight anchor if hovered: */
96 if (range.format.anchorHref() == m_strHoveredAnchor)
97 range.format.setForeground(qApp->palette().color(QPalette::Link));
98 }
99 ranges.append(range);
100
101 /* Add all the format ranges of children finally: */
102 foreach (const int &iPosition, m_strings.keys())
103 ranges.append(m_strings.value(iPosition)->formatRanges(iShift + iPosition));
104
105 /* Return result: */
106 return ranges;
107}
108
109void UIRichTextString::setHoveredAnchor(const QString &strHoveredAnchor)
110{
111 /* Define own hovered anchor first: */
112 m_strHoveredAnchor = strHoveredAnchor;
113
114 /* Propagate hovered anchor to children finally: */
115 foreach (const int &iPosition, m_strings.keys())
116 m_strings.value(iPosition)->setHoveredAnchor(m_strHoveredAnchor);
117}
118
119void UIRichTextString::parse()
120{
121 /* Assign the meta to anchor directly for now,
122 * will do a separate parsing when there will
123 * be more than one type of meta: */
124 if (!m_strStringMeta.isNull())
125 m_strAnchor = m_strStringMeta;
126
127 /* Parse the passed QString with all the known patterns: */
128 foreach (const Type &enmPattern, s_patterns.keys())
129 {
130 /* Get the current pattern: */
131 const QString strPattern = s_patterns.value(enmPattern);
132
133 /* Recursively parse the string: */
134 int iMaxLevel = 0;
135 do
136 {
137 /* Search for the maximum level of the current pattern: */
138 iMaxLevel = searchForMaxLevel(m_strString, strPattern, strPattern);
139 //printf(" Maximum level for the pattern \"%s\" is %d.\n",
140 // strPattern.toUtf8().constData(), iMaxLevel);
141 /* If current pattern of at least level 1 is found: */
142 if (iMaxLevel > 0)
143 {
144 /* Compose full pattern of the corresponding level: */
145 const QString strFullPattern = composeFullPattern(strPattern, strPattern, iMaxLevel);
146 //printf(" Full pattern: %s\n", strFullPattern.toUtf8().constData());
147 QRegExp regExp(strFullPattern);
148 regExp.setMinimal(true);
149 const int iPosition = regExp.indexIn(m_strString);
150 AssertReturnVoid(iPosition != -1);
151 if (iPosition != -1)
152 {
153 /* Cut the found string: */
154 m_strString.remove(iPosition, regExp.cap(0).size());
155 /* And paste that string as our child: */
156 const bool fPatterHasMeta = s_doPatternHasMeta.value(enmPattern);
157 const QString strSubString = !fPatterHasMeta ? regExp.cap(1) : regExp.cap(2);
158 const QString strSubMeta = !fPatterHasMeta ? QString() : regExp.cap(1);
159 m_strings.insert(iPosition, new UIRichTextString(strSubString, enmPattern, strSubMeta));
160 }
161 }
162 }
163 while (iMaxLevel > 0);
164 }
165}
166
167/* static */
168QMap<UIRichTextString::Type, QString> UIRichTextString::populatePatterns()
169{
170 QMap<Type, QString> patterns;
171 patterns.insert(Type_Anchor, QString("<a href=([^>]+)>(%1)</a>"));
172 patterns.insert(Type_Bold, QString("<b>(%1)</b>"));
173 patterns.insert(Type_Italic, QString("<i>(%1)</i>"));
174 return patterns;
175}
176
177/* static */
178QMap<UIRichTextString::Type, bool> UIRichTextString::populatePatternHasMeta()
179{
180 QMap<Type, bool> patternHasMeta;
181 patternHasMeta.insert(Type_Anchor, true);
182 patternHasMeta.insert(Type_Bold, false);
183 patternHasMeta.insert(Type_Italic, false);
184 return patternHasMeta;
185}
186
187/* static */
188int UIRichTextString::searchForMaxLevel(const QString &strString, const QString &strPattern,
189 const QString &strCurrentPattern, int iCurrentLevel /* = 0 */)
190{
191 QRegExp regExp(strCurrentPattern.arg(s_strAny));
192 regExp.setMinimal(true);
193 if (regExp.indexIn(strString) != -1)
194 return searchForMaxLevel(strString, strPattern,
195 strCurrentPattern.arg(s_strAny + strPattern + s_strAny),
196 iCurrentLevel + 1);
197 return iCurrentLevel;
198}
199
200/* static */
201QString UIRichTextString::composeFullPattern(const QString &strPattern,
202 const QString &strCurrentPattern, int iCurrentLevel)
203{
204 if (iCurrentLevel > 1)
205 return composeFullPattern(strPattern,
206 strCurrentPattern.arg(s_strAny + strPattern + s_strAny),
207 iCurrentLevel - 1);
208 return strCurrentPattern.arg(s_strAny);
209}
210
211/* static */
212QTextCharFormat UIRichTextString::textCharFormat(Type enmType)
213{
214 QTextCharFormat format;
215 switch (enmType)
216 {
217 case Type_Anchor:
218 {
219 format.setAnchor(true);
220 break;
221 }
222 case Type_Bold:
223 {
224 QFont font = format.font();
225 font.setBold(true);
226 format.setFont(font);
227 break;
228 }
229 case Type_Italic:
230 {
231 QFont font = format.font();
232 font.setItalic(true);
233 format.setFont(font);
234 break;
235 }
236
237 case Type_None: break; /* Shut up MSC */
238 }
239 return format;
240}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette