# HG changeset patch # User Chris Cannam # Date 1186763810 0 # Node ID 20097c32d15de042d7fffc93751ac948c3239836 # Parent 20028c6344947d770c0baf1213c9898a66577bf9 * 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 diff -r 20028c634494 -r 20097c32d15d base/TextAbbrev.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/base/TextAbbrev.cpp Fri Aug 10 16:36:50 2007 +0000 @@ -0,0 +1,264 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006-2007 Chris Cannam and QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "TextAbbrev.h" + +#include +#include + +QString +TextAbbrev::getDefaultEllipsis() +{ + return "..."; +} + +int +TextAbbrev::getFuzzLength(QString ellipsis) +{ + int len = ellipsis.length(); + if (len < 3) return len + 3; + else if (len > 5) return len + 5; + else return len * 2; +} + +int +TextAbbrev::getFuzzWidth(const QFontMetrics &metrics, QString ellipsis) +{ + int width = metrics.width(ellipsis); + return width * 2; +} + +QString +TextAbbrev::abbreviateTo(QString text, int characters, Policy policy, + QString ellipsis) +{ + switch (policy) { + + case ElideEnd: + case ElideEndAndCommonPrefixes: + text = text.left(characters) + ellipsis; + break; + + case ElideStart: + text = ellipsis + text.right(characters); + break; + + case ElideMiddle: + if (characters > 2) { + text = text.left(characters/2 + 1) + ellipsis + + text.right(characters - (characters/2 + 1)); + } else { + text = text.left(characters) + ellipsis; + } + break; + } + + return text; +} + +QString +TextAbbrev::abbreviate(QString text, int maxLength, Policy policy, bool fuzzy, + QString ellipsis) +{ + if (ellipsis == "") ellipsis = getDefaultEllipsis(); + int fl = (fuzzy ? getFuzzLength(ellipsis) : 0); + if (maxLength <= ellipsis.length()) maxLength = ellipsis.length() + 1; + if (text.length() <= maxLength + fl) return text; + + int truncated = maxLength - ellipsis.length(); + return abbreviateTo(text, truncated, policy, ellipsis); +} + +QString +TextAbbrev::abbreviate(QString text, + const QFontMetrics &metrics, int &maxWidth, + Policy policy, QString ellipsis) +{ + if (ellipsis == "") ellipsis = getDefaultEllipsis(); + + int tw = metrics.width(text); + + if (tw <= maxWidth) { + maxWidth = tw; + return text; + } + + int truncated = text.length(); + QString original = text; + + while (tw > maxWidth && truncated > 1) { + + truncated--; + + if (truncated > ellipsis.length()) { + text = abbreviateTo(original, truncated, policy, ellipsis); + } else { + break; + } + + tw = metrics.width(text); + } + + maxWidth = tw; + return text; +} + +QStringList +TextAbbrev::abbreviate(const QStringList &texts, int maxLength, + Policy policy, bool fuzzy, QString ellipsis) +{ + if (policy == ElideEndAndCommonPrefixes && + texts.size() > 1) { + + if (ellipsis == "") ellipsis = getDefaultEllipsis(); + int fl = (fuzzy ? getFuzzLength(ellipsis) : 0); + if (maxLength <= ellipsis.length()) maxLength = ellipsis.length() + 1; + + int maxOrigLength = 0; + for (int i = 0; i < texts.size(); ++i) { + int len = texts[i].length(); + if (len > maxOrigLength) maxOrigLength = len; + } + if (maxOrigLength <= maxLength + fl) return texts; + + return abbreviate(elidePrefixes + (texts, maxOrigLength - maxLength, ellipsis), + maxLength, ElideEnd, fuzzy, ellipsis); + } + + QStringList results; + for (int i = 0; i < texts.size(); ++i) { + results.push_back + (abbreviate(texts[i], maxLength, policy, fuzzy, ellipsis)); + } + return results; +} + +QStringList +TextAbbrev::abbreviate(const QStringList &texts, const QFontMetrics &metrics, + int &maxWidth, Policy policy, QString ellipsis) +{ + if (policy == ElideEndAndCommonPrefixes && + texts.size() > 1) { + + if (ellipsis == "") ellipsis = getDefaultEllipsis(); + + int maxOrigWidth = 0; + for (int i = 0; i < texts.size(); ++i) { + int w = metrics.width(texts[i]); + if (w > maxOrigWidth) maxOrigWidth = w; + } + + return abbreviate(elidePrefixes(texts, metrics, + maxOrigWidth - maxWidth, ellipsis), + metrics, maxWidth, ElideEnd, ellipsis); + } + + QStringList results; + int maxAbbrWidth = 0; + for (int i = 0; i < texts.size(); ++i) { + int width = maxWidth; + QString abbr = abbreviate(texts[i], metrics, width, policy, ellipsis); + if (width > maxAbbrWidth) maxAbbrWidth = width; + results.push_back(abbr); + } + maxWidth = maxAbbrWidth; + return results; +} + +QStringList +TextAbbrev::elidePrefixes(const QStringList &texts, + int targetReduction, + QString ellipsis) +{ + if (texts.empty()) return texts; + int plen = getPrefixLength(texts); + int fl = getFuzzLength(ellipsis); + if (plen < fl) return texts; + + QString prefix = texts[0].left(plen); + int truncated = plen; + if (plen >= targetReduction + fl) { + truncated = plen - targetReduction; + } else { + truncated = fl; + } + prefix = abbreviate(prefix, truncated, ElideEnd, false, ellipsis); + + QStringList results; + for (int i = 0; i < texts.size(); ++i) { + results.push_back + (prefix + texts[i].right(texts[i].length() - plen)); + } + return results; +} + +QStringList +TextAbbrev::elidePrefixes(const QStringList &texts, + const QFontMetrics &metrics, + int targetWidthReduction, + QString ellipsis) +{ + if (texts.empty()) return texts; + int plen = getPrefixLength(texts); + int fl = getFuzzLength(ellipsis); + if (plen < fl) return texts; + + QString prefix = texts[0].left(plen); + int pwid = metrics.width(prefix); + int twid = pwid - targetWidthReduction; + if (twid < metrics.width(ellipsis) * 2) twid = metrics.width(ellipsis) * 2; + prefix = abbreviate(prefix, metrics, twid, ElideEnd, ellipsis); + + QStringList results; + for (int i = 0; i < texts.size(); ++i) { + results.push_back + (prefix + texts[i].right(texts[i].length() - plen)); + } + return results; +} + +static bool +havePrefix(QString prefix, const QStringList &texts) +{ + for (int i = 1; i < texts.size(); ++i) { + if (!texts[i].startsWith(prefix)) return false; + } + return true; +} + +int +TextAbbrev::getPrefixLength(const QStringList &texts) +{ + QString reference = texts[0]; + + if (reference == "" || havePrefix(reference, texts)) { + return reference.length(); + } + + int candidate = reference.length(); + QString splitChars(";:,./#-!()$_+=[]{}\\"); + + while (--candidate > 1) { + if (splitChars.contains(reference[candidate])) { + if (havePrefix(reference.left(candidate - 1), texts)) { + break; + } + } + } + + return candidate; +} + diff -r 20028c634494 -r 20097c32d15d base/TextAbbrev.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/base/TextAbbrev.h Fri Aug 10 16:36:50 2007 +0000 @@ -0,0 +1,108 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006-2007 Chris Cannam and QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _TEXT_ABBREV_H_ +#define _TEXT_ABBREV_H_ + +#include +#include + +class QFontMetrics; + +class TextAbbrev +{ +public: + enum Policy { + ElideEnd, + ElideEndAndCommonPrefixes, + ElideStart, + ElideMiddle + }; + + /** + * Abbreviate the given text to the given maximum length + * (including ellipsis), using the given abbreviation policy. If + * fuzzy is true, the text will be left alone if it is "not much + * more than" the maximum length. + * + * If ellipsis is non-empty, it will be used to show elisions in + * preference to the default (which is "..."). + */ + static QString abbreviate(QString text, int maxLength, + Policy policy = ElideEnd, + bool fuzzy = true, + QString ellipsis = ""); + + /** + * Abbreviate the given text to the given maximum painted width, + * using the given abbreviation policy. maxWidth is also modified + * so as to return the painted width of the abbreviated text. + * + * If ellipsis is non-empty, it will be used to show elisions in + * preference to the default (which is tr("...")). + */ + static QString abbreviate(QString text, + const QFontMetrics &metrics, + int &maxWidth, + Policy policy = ElideEnd, + QString ellipsis = ""); + + /** + * Abbreviate all of the given texts to the given maximum length, + * using the given abbreviation policy. If fuzzy is true, texts + * that are "not much more than" the maximum length will be left + * alone. + * + * If ellipsis is non-empty, it will be used to show elisions in + * preference to the default (which is tr("...")). + */ + static QStringList abbreviate(const QStringList &texts, int maxLength, + Policy policy = ElideEndAndCommonPrefixes, + bool fuzzy = true, + QString ellipsis = ""); + + /** + * Abbreviate all of the given texts to the given maximum painted + * width, using the given abbreviation policy. maxWidth is also + * modified so as to return the maximum painted width of the + * abbreviated texts. + * + * If ellipsis is non-empty, it will be used to show elisions in + * preference to the default (which is tr("...")). + */ + static QStringList abbreviate(const QStringList &texts, + const QFontMetrics &metrics, + int &maxWidth, + Policy policy = ElideEndAndCommonPrefixes, + QString ellipsis = ""); + +protected: + static QString getDefaultEllipsis(); + static int getFuzzLength(QString ellipsis); + static int getFuzzWidth(const QFontMetrics &metrics, QString ellipsis); + static QString abbreviateTo(QString text, int characters, + Policy policy, QString ellipsis); + static QStringList elidePrefixes(const QStringList &texts, + int targetReduction, + QString ellipsis); + static QStringList elidePrefixes(const QStringList &texts, + const QFontMetrics &metrics, + int targetWidthReduction, + QString ellipsis); + static int getPrefixLength(const QStringList &texts); +}; + +#endif + diff -r 20028c634494 -r 20097c32d15d base/base.pro --- a/base/base.pro Thu Aug 09 16:29:29 2007 +0000 +++ b/base/base.pro Fri Aug 10 16:36:50 2007 +0000 @@ -37,6 +37,7 @@ Selection.h \ StorageAdviser.h \ TempDirectory.h \ + TextAbbrev.h \ Thread.h \ UnitDatabase.h \ Window.h \ @@ -62,6 +63,7 @@ Selection.cpp \ StorageAdviser.cpp \ TempDirectory.cpp \ + TextAbbrev.cpp \ Thread.cpp \ UnitDatabase.cpp \ XmlExportable.cpp