Mercurial > hg > svcore
comparison base/TextAbbrev.cpp @ 286:20097c32d15d
* Better abbreviation modes for layer names in pane (and input model combo
of plugin parameter dialog)
* Avoid crash when loading SV file containing model derived from nonexistent
model (shouldn't happen of course, but see bug #1771769)
* Remember last-used input model in plugin parameter dialog
* Don't override a layer colour loaded from a session file with the generated
default colour when attaching it to a view
author | Chris Cannam |
---|---|
date | Fri, 10 Aug 2007 16:36:50 +0000 |
parents | |
children | 2c1e57ad86e7 |
comparison
equal
deleted
inserted
replaced
285:20028c634494 | 286:20097c32d15d |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 This file copyright 2006-2007 Chris Cannam and QMUL. | |
8 | |
9 This program is free software; you can redistribute it and/or | |
10 modify it under the terms of the GNU General Public License as | |
11 published by the Free Software Foundation; either version 2 of the | |
12 License, or (at your option) any later version. See the file | |
13 COPYING included with this distribution for more information. | |
14 */ | |
15 | |
16 #include "TextAbbrev.h" | |
17 | |
18 #include <QFontMetrics> | |
19 #include <QApplication> | |
20 | |
21 QString | |
22 TextAbbrev::getDefaultEllipsis() | |
23 { | |
24 return "..."; | |
25 } | |
26 | |
27 int | |
28 TextAbbrev::getFuzzLength(QString ellipsis) | |
29 { | |
30 int len = ellipsis.length(); | |
31 if (len < 3) return len + 3; | |
32 else if (len > 5) return len + 5; | |
33 else return len * 2; | |
34 } | |
35 | |
36 int | |
37 TextAbbrev::getFuzzWidth(const QFontMetrics &metrics, QString ellipsis) | |
38 { | |
39 int width = metrics.width(ellipsis); | |
40 return width * 2; | |
41 } | |
42 | |
43 QString | |
44 TextAbbrev::abbreviateTo(QString text, int characters, Policy policy, | |
45 QString ellipsis) | |
46 { | |
47 switch (policy) { | |
48 | |
49 case ElideEnd: | |
50 case ElideEndAndCommonPrefixes: | |
51 text = text.left(characters) + ellipsis; | |
52 break; | |
53 | |
54 case ElideStart: | |
55 text = ellipsis + text.right(characters); | |
56 break; | |
57 | |
58 case ElideMiddle: | |
59 if (characters > 2) { | |
60 text = text.left(characters/2 + 1) + ellipsis | |
61 + text.right(characters - (characters/2 + 1)); | |
62 } else { | |
63 text = text.left(characters) + ellipsis; | |
64 } | |
65 break; | |
66 } | |
67 | |
68 return text; | |
69 } | |
70 | |
71 QString | |
72 TextAbbrev::abbreviate(QString text, int maxLength, Policy policy, bool fuzzy, | |
73 QString ellipsis) | |
74 { | |
75 if (ellipsis == "") ellipsis = getDefaultEllipsis(); | |
76 int fl = (fuzzy ? getFuzzLength(ellipsis) : 0); | |
77 if (maxLength <= ellipsis.length()) maxLength = ellipsis.length() + 1; | |
78 if (text.length() <= maxLength + fl) return text; | |
79 | |
80 int truncated = maxLength - ellipsis.length(); | |
81 return abbreviateTo(text, truncated, policy, ellipsis); | |
82 } | |
83 | |
84 QString | |
85 TextAbbrev::abbreviate(QString text, | |
86 const QFontMetrics &metrics, int &maxWidth, | |
87 Policy policy, QString ellipsis) | |
88 { | |
89 if (ellipsis == "") ellipsis = getDefaultEllipsis(); | |
90 | |
91 int tw = metrics.width(text); | |
92 | |
93 if (tw <= maxWidth) { | |
94 maxWidth = tw; | |
95 return text; | |
96 } | |
97 | |
98 int truncated = text.length(); | |
99 QString original = text; | |
100 | |
101 while (tw > maxWidth && truncated > 1) { | |
102 | |
103 truncated--; | |
104 | |
105 if (truncated > ellipsis.length()) { | |
106 text = abbreviateTo(original, truncated, policy, ellipsis); | |
107 } else { | |
108 break; | |
109 } | |
110 | |
111 tw = metrics.width(text); | |
112 } | |
113 | |
114 maxWidth = tw; | |
115 return text; | |
116 } | |
117 | |
118 QStringList | |
119 TextAbbrev::abbreviate(const QStringList &texts, int maxLength, | |
120 Policy policy, bool fuzzy, QString ellipsis) | |
121 { | |
122 if (policy == ElideEndAndCommonPrefixes && | |
123 texts.size() > 1) { | |
124 | |
125 if (ellipsis == "") ellipsis = getDefaultEllipsis(); | |
126 int fl = (fuzzy ? getFuzzLength(ellipsis) : 0); | |
127 if (maxLength <= ellipsis.length()) maxLength = ellipsis.length() + 1; | |
128 | |
129 int maxOrigLength = 0; | |
130 for (int i = 0; i < texts.size(); ++i) { | |
131 int len = texts[i].length(); | |
132 if (len > maxOrigLength) maxOrigLength = len; | |
133 } | |
134 if (maxOrigLength <= maxLength + fl) return texts; | |
135 | |
136 return abbreviate(elidePrefixes | |
137 (texts, maxOrigLength - maxLength, ellipsis), | |
138 maxLength, ElideEnd, fuzzy, ellipsis); | |
139 } | |
140 | |
141 QStringList results; | |
142 for (int i = 0; i < texts.size(); ++i) { | |
143 results.push_back | |
144 (abbreviate(texts[i], maxLength, policy, fuzzy, ellipsis)); | |
145 } | |
146 return results; | |
147 } | |
148 | |
149 QStringList | |
150 TextAbbrev::abbreviate(const QStringList &texts, const QFontMetrics &metrics, | |
151 int &maxWidth, Policy policy, QString ellipsis) | |
152 { | |
153 if (policy == ElideEndAndCommonPrefixes && | |
154 texts.size() > 1) { | |
155 | |
156 if (ellipsis == "") ellipsis = getDefaultEllipsis(); | |
157 | |
158 int maxOrigWidth = 0; | |
159 for (int i = 0; i < texts.size(); ++i) { | |
160 int w = metrics.width(texts[i]); | |
161 if (w > maxOrigWidth) maxOrigWidth = w; | |
162 } | |
163 | |
164 return abbreviate(elidePrefixes(texts, metrics, | |
165 maxOrigWidth - maxWidth, ellipsis), | |
166 metrics, maxWidth, ElideEnd, ellipsis); | |
167 } | |
168 | |
169 QStringList results; | |
170 int maxAbbrWidth = 0; | |
171 for (int i = 0; i < texts.size(); ++i) { | |
172 int width = maxWidth; | |
173 QString abbr = abbreviate(texts[i], metrics, width, policy, ellipsis); | |
174 if (width > maxAbbrWidth) maxAbbrWidth = width; | |
175 results.push_back(abbr); | |
176 } | |
177 maxWidth = maxAbbrWidth; | |
178 return results; | |
179 } | |
180 | |
181 QStringList | |
182 TextAbbrev::elidePrefixes(const QStringList &texts, | |
183 int targetReduction, | |
184 QString ellipsis) | |
185 { | |
186 if (texts.empty()) return texts; | |
187 int plen = getPrefixLength(texts); | |
188 int fl = getFuzzLength(ellipsis); | |
189 if (plen < fl) return texts; | |
190 | |
191 QString prefix = texts[0].left(plen); | |
192 int truncated = plen; | |
193 if (plen >= targetReduction + fl) { | |
194 truncated = plen - targetReduction; | |
195 } else { | |
196 truncated = fl; | |
197 } | |
198 prefix = abbreviate(prefix, truncated, ElideEnd, false, ellipsis); | |
199 | |
200 QStringList results; | |
201 for (int i = 0; i < texts.size(); ++i) { | |
202 results.push_back | |
203 (prefix + texts[i].right(texts[i].length() - plen)); | |
204 } | |
205 return results; | |
206 } | |
207 | |
208 QStringList | |
209 TextAbbrev::elidePrefixes(const QStringList &texts, | |
210 const QFontMetrics &metrics, | |
211 int targetWidthReduction, | |
212 QString ellipsis) | |
213 { | |
214 if (texts.empty()) return texts; | |
215 int plen = getPrefixLength(texts); | |
216 int fl = getFuzzLength(ellipsis); | |
217 if (plen < fl) return texts; | |
218 | |
219 QString prefix = texts[0].left(plen); | |
220 int pwid = metrics.width(prefix); | |
221 int twid = pwid - targetWidthReduction; | |
222 if (twid < metrics.width(ellipsis) * 2) twid = metrics.width(ellipsis) * 2; | |
223 prefix = abbreviate(prefix, metrics, twid, ElideEnd, ellipsis); | |
224 | |
225 QStringList results; | |
226 for (int i = 0; i < texts.size(); ++i) { | |
227 results.push_back | |
228 (prefix + texts[i].right(texts[i].length() - plen)); | |
229 } | |
230 return results; | |
231 } | |
232 | |
233 static bool | |
234 havePrefix(QString prefix, const QStringList &texts) | |
235 { | |
236 for (int i = 1; i < texts.size(); ++i) { | |
237 if (!texts[i].startsWith(prefix)) return false; | |
238 } | |
239 return true; | |
240 } | |
241 | |
242 int | |
243 TextAbbrev::getPrefixLength(const QStringList &texts) | |
244 { | |
245 QString reference = texts[0]; | |
246 | |
247 if (reference == "" || havePrefix(reference, texts)) { | |
248 return reference.length(); | |
249 } | |
250 | |
251 int candidate = reference.length(); | |
252 QString splitChars(";:,./#-!()$_+=[]{}\\"); | |
253 | |
254 while (--candidate > 1) { | |
255 if (splitChars.contains(reference[candidate])) { | |
256 if (havePrefix(reference.left(candidate - 1), texts)) { | |
257 break; | |
258 } | |
259 } | |
260 } | |
261 | |
262 return candidate; | |
263 } | |
264 |