svgui  1.9
TextAbbrev.cpp
Go to the documentation of this file.
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
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:
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
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 
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 // SVDEBUG << "TextAbbrev::getPrefixLength: prefix length is " << candidate << endl;
265 // for (int i = 0; i < texts.size(); ++i) {
266 // cerr << texts[i].left(candidate) << "|" << texts[i].right(texts[i].length() - candidate) << endl;
267 // }
268 
269  return candidate;
270 }
271 
static int getFuzzLength(QString ellipsis)
Definition: TextAbbrev.cpp:30
static QString getDefaultEllipsis()
Definition: TextAbbrev.cpp:24
static QString abbreviateTo(QString text, int characters, Policy policy, QString ellipsis)
Definition: TextAbbrev.cpp:46
static QString abbreviate(QString text, int maxLength, Policy policy=ElideEnd, bool fuzzy=true, QString ellipsis="")
Abbreviate the given text to the given maximum length (including ellipsis), using the given abbreviat...
Definition: TextAbbrev.cpp:74
static QStringList elidePrefixes(const QStringList &texts, int targetReduction, QString ellipsis)
Definition: TextAbbrev.cpp:184
static int getPrefixLength(const QStringList &texts)
Definition: TextAbbrev.cpp:245
static bool havePrefix(QString prefix, const QStringList &texts)
Definition: TextAbbrev.cpp:236
static int getFuzzWidth(const QFontMetrics &metrics, QString ellipsis)
Definition: TextAbbrev.cpp:39