Mercurial > hg > svgui
comparison widgets/TextAbbrev.cpp @ 376:e1a9e478b7f2
* juggle some files around in order to free audioio, base, and system libraries
from dependency on QtGui
author | Chris Cannam |
---|---|
date | Wed, 12 Mar 2008 17:42:56 +0000 |
parents | |
children | 1fe7951a61e8 |
comparison
equal
deleted
inserted
replaced
375:daaf1c435d98 | 376:e1a9e478b7f2 |
---|---|
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 #include <iostream> | |
22 | |
23 QString | |
24 TextAbbrev::getDefaultEllipsis() | |
25 { | |
26 return "..."; | |
27 } | |
28 | |
29 int | |
30 TextAbbrev::getFuzzLength(QString ellipsis) | |
31 { | |
32 int len = ellipsis.length(); | |
33 if (len < 3) return len + 3; | |
34 else if (len > 5) return len + 5; | |
35 else return len * 2; | |
36 } | |
37 | |
38 int | |
39 TextAbbrev::getFuzzWidth(const QFontMetrics &metrics, QString ellipsis) | |
40 { | |
41 int width = metrics.width(ellipsis); | |
42 return width * 2; | |
43 } | |
44 | |
45 QString | |
46 TextAbbrev::abbreviateTo(QString text, int characters, Policy policy, | |
47 QString ellipsis) | |
48 { | |
49 switch (policy) { | |
50 | |
51 case ElideEnd: | |
52 case ElideEndAndCommonPrefixes: | |
53 text = text.left(characters) + ellipsis; | |
54 break; | |
55 | |
56 case ElideStart: | |
57 text = ellipsis + text.right(characters); | |
58 break; | |
59 | |
60 case ElideMiddle: | |
61 if (characters > 2) { | |
62 text = text.left(characters/2 + 1) + ellipsis | |
63 + text.right(characters - (characters/2 + 1)); | |
64 } else { | |
65 text = text.left(characters) + ellipsis; | |
66 } | |
67 break; | |
68 } | |
69 | |
70 return text; | |
71 } | |
72 | |
73 QString | |
74 TextAbbrev::abbreviate(QString text, int maxLength, Policy policy, bool fuzzy, | |
75 QString ellipsis) | |
76 { | |
77 if (ellipsis == "") ellipsis = getDefaultEllipsis(); | |
78 int fl = (fuzzy ? getFuzzLength(ellipsis) : 0); | |
79 if (maxLength <= ellipsis.length()) maxLength = ellipsis.length() + 1; | |
80 if (text.length() <= maxLength + fl) return text; | |
81 | |
82 int truncated = maxLength - ellipsis.length(); | |
83 return abbreviateTo(text, truncated, policy, ellipsis); | |
84 } | |
85 | |
86 QString | |
87 TextAbbrev::abbreviate(QString text, | |
88 const QFontMetrics &metrics, int &maxWidth, | |
89 Policy policy, QString ellipsis) | |
90 { | |
91 if (ellipsis == "") ellipsis = getDefaultEllipsis(); | |
92 | |
93 int tw = metrics.width(text); | |
94 | |
95 if (tw <= maxWidth) { | |
96 maxWidth = tw; | |
97 return text; | |
98 } | |
99 | |
100 int truncated = text.length(); | |
101 QString original = text; | |
102 | |
103 while (tw > maxWidth && truncated > 1) { | |
104 | |
105 truncated--; | |
106 | |
107 if (truncated > ellipsis.length()) { | |
108 text = abbreviateTo(original, truncated, policy, ellipsis); | |
109 } else { | |
110 break; | |
111 } | |
112 | |
113 tw = metrics.width(text); | |
114 } | |
115 | |
116 maxWidth = tw; | |
117 return text; | |
118 } | |
119 | |
120 QStringList | |
121 TextAbbrev::abbreviate(const QStringList &texts, int maxLength, | |
122 Policy policy, bool fuzzy, QString ellipsis) | |
123 { | |
124 if (policy == ElideEndAndCommonPrefixes && | |
125 texts.size() > 1) { | |
126 | |
127 if (ellipsis == "") ellipsis = getDefaultEllipsis(); | |
128 int fl = (fuzzy ? getFuzzLength(ellipsis) : 0); | |
129 if (maxLength <= ellipsis.length()) maxLength = ellipsis.length() + 1; | |
130 | |
131 int maxOrigLength = 0; | |
132 for (int i = 0; i < texts.size(); ++i) { | |
133 int len = texts[i].length(); | |
134 if (len > maxOrigLength) maxOrigLength = len; | |
135 } | |
136 if (maxOrigLength <= maxLength + fl) return texts; | |
137 | |
138 return abbreviate(elidePrefixes | |
139 (texts, maxOrigLength - maxLength, ellipsis), | |
140 maxLength, ElideEnd, fuzzy, ellipsis); | |
141 } | |
142 | |
143 QStringList results; | |
144 for (int i = 0; i < texts.size(); ++i) { | |
145 results.push_back | |
146 (abbreviate(texts[i], maxLength, policy, fuzzy, ellipsis)); | |
147 } | |
148 return results; | |
149 } | |
150 | |
151 QStringList | |
152 TextAbbrev::abbreviate(const QStringList &texts, const QFontMetrics &metrics, | |
153 int &maxWidth, Policy policy, QString ellipsis) | |
154 { | |
155 if (policy == ElideEndAndCommonPrefixes && | |
156 texts.size() > 1) { | |
157 | |
158 if (ellipsis == "") ellipsis = getDefaultEllipsis(); | |
159 | |
160 int maxOrigWidth = 0; | |
161 for (int i = 0; i < texts.size(); ++i) { | |
162 int w = metrics.width(texts[i]); | |
163 if (w > maxOrigWidth) maxOrigWidth = w; | |
164 } | |
165 | |
166 return abbreviate(elidePrefixes(texts, metrics, | |
167 maxOrigWidth - maxWidth, ellipsis), | |
168 metrics, maxWidth, ElideEnd, ellipsis); | |
169 } | |
170 | |
171 QStringList results; | |
172 int maxAbbrWidth = 0; | |
173 for (int i = 0; i < texts.size(); ++i) { | |
174 int width = maxWidth; | |
175 QString abbr = abbreviate(texts[i], metrics, width, policy, ellipsis); | |
176 if (width > maxAbbrWidth) maxAbbrWidth = width; | |
177 results.push_back(abbr); | |
178 } | |
179 maxWidth = maxAbbrWidth; | |
180 return results; | |
181 } | |
182 | |
183 QStringList | |
184 TextAbbrev::elidePrefixes(const QStringList &texts, | |
185 int targetReduction, | |
186 QString ellipsis) | |
187 { | |
188 if (texts.empty()) return texts; | |
189 int plen = getPrefixLength(texts); | |
190 int fl = getFuzzLength(ellipsis); | |
191 if (plen < fl) return texts; | |
192 | |
193 QString prefix = texts[0].left(plen); | |
194 int truncated = plen; | |
195 if (plen >= targetReduction + fl) { | |
196 truncated = plen - targetReduction; | |
197 } else { | |
198 truncated = fl; | |
199 } | |
200 prefix = abbreviate(prefix, truncated, ElideEnd, false, ellipsis); | |
201 | |
202 QStringList results; | |
203 for (int i = 0; i < texts.size(); ++i) { | |
204 results.push_back | |
205 (prefix + texts[i].right(texts[i].length() - plen)); | |
206 } | |
207 return results; | |
208 } | |
209 | |
210 QStringList | |
211 TextAbbrev::elidePrefixes(const QStringList &texts, | |
212 const QFontMetrics &metrics, | |
213 int targetWidthReduction, | |
214 QString ellipsis) | |
215 { | |
216 if (texts.empty()) return texts; | |
217 int plen = getPrefixLength(texts); | |
218 int fl = getFuzzLength(ellipsis); | |
219 if (plen < fl) return texts; | |
220 | |
221 QString prefix = texts[0].left(plen); | |
222 int pwid = metrics.width(prefix); | |
223 int twid = pwid - targetWidthReduction; | |
224 if (twid < metrics.width(ellipsis) * 2) twid = metrics.width(ellipsis) * 2; | |
225 prefix = abbreviate(prefix, metrics, twid, ElideEnd, ellipsis); | |
226 | |
227 QStringList results; | |
228 for (int i = 0; i < texts.size(); ++i) { | |
229 results.push_back | |
230 (prefix + texts[i].right(texts[i].length() - plen)); | |
231 } | |
232 return results; | |
233 } | |
234 | |
235 static bool | |
236 havePrefix(QString prefix, const QStringList &texts) | |
237 { | |
238 for (int i = 1; i < texts.size(); ++i) { | |
239 if (!texts[i].startsWith(prefix)) return false; | |
240 } | |
241 return true; | |
242 } | |
243 | |
244 int | |
245 TextAbbrev::getPrefixLength(const QStringList &texts) | |
246 { | |
247 QString reference = texts[0]; | |
248 | |
249 if (reference == "" || havePrefix(reference, texts)) { | |
250 return reference.length(); | |
251 } | |
252 | |
253 int candidate = reference.length(); | |
254 QString splitChars(";:,./#-!()$_+=[]{}\\"); | |
255 | |
256 while (--candidate > 1) { | |
257 if (splitChars.contains(reference[candidate])) { | |
258 if (havePrefix(reference.left(candidate), texts)) { | |
259 break; | |
260 } | |
261 } | |
262 } | |
263 | |
264 // std::cerr << "TextAbbrev::getPrefixLength: prefix length is " << candidate << std::endl; | |
265 // for (int i = 0; i < texts.size(); ++i) { | |
266 // std::cerr << texts[i].left(candidate).toStdString() << "|" << texts[i].right(texts[i].length() - candidate).toStdString() << std::endl; | |
267 // } | |
268 | |
269 return candidate; | |
270 } | |
271 |