stereotypecontroller.cpp 7.79 KB
Newer Older
Jochen Becher's avatar
Jochen Becher committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
/***************************************************************************
**
** Copyright (C) 2015 Jochen Becher
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "stereotypecontroller.h"

#include "stereotypeicon.h"
#include "shapepaintvisitor.h"
#include "toolbar.h"

#include "qmt/infrastructure/qmtassert.h"
#include "qmt/style/style.h"

#include <QHash>
#include <QPainter>
#include <QIcon>
#include <QPair>

#include <algorithm>

namespace qmt {

49
class StereotypeController::StereotypeControllerPrivate
Jochen Becher's avatar
Jochen Becher committed
50
{
51
public:
Jochen Becher's avatar
Jochen Becher committed
52 53 54 55
    StereotypeControllerPrivate()
    {
    }

56 57 58
    QHash<QPair<StereotypeIcon::Element, QString>, QString> m_stereotypeToIconIdMap;
    QHash<QString, StereotypeIcon> m_iconIdToStereotypeIconsMap;
    QList<Toolbar> m_toolbars;
Jochen Becher's avatar
Jochen Becher committed
59 60 61 62 63 64 65 66 67 68 69 70 71
};

StereotypeController::StereotypeController(QObject *parent) :
    QObject(parent),
    d(new StereotypeControllerPrivate)
{
}

StereotypeController::~StereotypeController()
{
    delete d;
}

72
QList<StereotypeIcon> StereotypeController::stereotypeIcons() const
Jochen Becher's avatar
Jochen Becher committed
73
{
74
    return d->m_iconIdToStereotypeIconsMap.values();
Jochen Becher's avatar
Jochen Becher committed
75 76
}

77
QList<Toolbar> StereotypeController::toolbars() const
Jochen Becher's avatar
Jochen Becher committed
78
{
79
    return d->m_toolbars;
Jochen Becher's avatar
Jochen Becher committed
80 81
}

82
QList<QString> StereotypeController::knownStereotypes(StereotypeIcon::Element stereotypeElement) const
Jochen Becher's avatar
Jochen Becher committed
83 84
{
    QSet<QString> stereotypes;
85
    foreach (const StereotypeIcon &icon, d->m_iconIdToStereotypeIconsMap.values()) {
86 87
        if (icon.elements().isEmpty() || icon.elements().contains(stereotypeElement)) {
            stereotypes += icon.stereotypes();
Jochen Becher's avatar
Jochen Becher committed
88 89 90 91 92 93 94 95 96 97
        }
    }
    QList<QString> list = stereotypes.toList();
    std::sort(list.begin(), list.end());
    return list;
}

QString StereotypeController::findStereotypeIconId(StereotypeIcon::Element element, const QList<QString> &stereotypes) const
{
    foreach (const QString &stereotype, stereotypes) {
98 99
        if (d->m_stereotypeToIconIdMap.contains(qMakePair(element, stereotype))) {
            return d->m_stereotypeToIconIdMap.value(qMakePair(element, stereotype));
100 101
        } else if (d->m_stereotypeToIconIdMap.contains(qMakePair(StereotypeIcon::ElementAny, stereotype))) {
            return d->m_stereotypeToIconIdMap.value(qMakePair(StereotypeIcon::ElementAny, stereotype));
Jochen Becher's avatar
Jochen Becher committed
102 103 104 105 106
        }
    }
    return QString();
}

107
QList<QString> StereotypeController::filterStereotypesByIconId(const QString &stereotypeIconId, const QList<QString> &stereotypes) const
Jochen Becher's avatar
Jochen Becher committed
108
{
109
    if (!d->m_iconIdToStereotypeIconsMap.contains(stereotypeIconId)) {
Jochen Becher's avatar
Jochen Becher committed
110 111
        return stereotypes;
    }
112
    QList<QString> filteredStereotypes = stereotypes;
113
    foreach (const QString &stereotype, d->m_iconIdToStereotypeIconsMap.value(stereotypeIconId).stereotypes()) {
114
        filteredStereotypes.removeAll(stereotype);
Jochen Becher's avatar
Jochen Becher committed
115
    }
116
    return filteredStereotypes;
Jochen Becher's avatar
Jochen Becher committed
117 118
}

119
StereotypeIcon StereotypeController::findStereotypeIcon(const QString &stereotypeIconId)
Jochen Becher's avatar
Jochen Becher committed
120
{
121 122
    QMT_CHECK(d->m_iconIdToStereotypeIconsMap.contains(stereotypeIconId));
    return d->m_iconIdToStereotypeIconsMap.value(stereotypeIconId);
Jochen Becher's avatar
Jochen Becher committed
123 124
}

125
QIcon StereotypeController::createIcon(StereotypeIcon::Element element, const QList<QString> &stereotypes, const QString &defaultIconPath,
Jochen Becher's avatar
Jochen Becher committed
126 127
                                       const Style *style, const QSize &size, const QMarginsF &margins)
{
128
    // TODO implement cache with key build from element, stereotypes, defaultIconPath, style, size and margins
Jochen Becher's avatar
Jochen Becher committed
129 130 131
    // TODO implement unique id for style which can be used as key
    // TODO fix rendering of icon which negativ extension of bounding box (e.g. stereotype "component")
    QIcon icon;
132 133 134
    QString stereotypeIconId = findStereotypeIconId(element, stereotypes);
    if (!stereotypeIconId.isEmpty()) {
        StereotypeIcon stereotypeIcon = findStereotypeIcon(stereotypeIconId);
Jochen Becher's avatar
Jochen Becher committed
135 136 137

        qreal width = size.width() - margins.left() - margins.right();
        qreal height = size.height() - margins.top() - margins.bottom();
138 139
        qreal ratioWidth = height * stereotypeIcon.width() / stereotypeIcon.height();
        qreal ratioHeight = width * stereotypeIcon.height() / stereotypeIcon.width();
140 141 142 143
        if (ratioWidth > width) {
            height = ratioHeight;
        } else if (ratioHeight > height) {
            width = ratioWidth;
Jochen Becher's avatar
Jochen Becher committed
144
        }
145 146 147
        QSizeF shapeSize(width, height);

        ShapeSizeVisitor sizeVisitor(QPointF(0.0, 0.0),
148
                                           QSizeF(stereotypeIcon.width(), stereotypeIcon.height()),
149
                                           shapeSize, shapeSize);
150 151
        stereotypeIcon.iconShape().visitShapes(&sizeVisitor);
        QRectF iconBoundingRect = sizeVisitor.boundingRect();
152
        QPixmap pixmap(iconBoundingRect.width() + margins.left() + margins.right(), iconBoundingRect.height() + margins.top() + margins.bottom());
Jochen Becher's avatar
Jochen Becher committed
153 154 155
        pixmap.fill(Qt::transparent);
        QPainter painter(&pixmap);
        painter.setBrush(Qt::NoBrush);
156
        painter.translate(-iconBoundingRect.topLeft() + QPointF(margins.left(), margins.top()));
157
        QPen linePen = style->linePen();
158 159
        linePen.setWidthF(2.0);
        painter.setPen(linePen);
160
        painter.setBrush(style->fillBrush());
Jochen Becher's avatar
Jochen Becher committed
161
        ShapePaintVisitor visitor(&painter, QPointF(0.0, 0.0),
162
                                       QSizeF(stereotypeIcon.width(), stereotypeIcon.height()),
163
                                       shapeSize, shapeSize);
164
        stereotypeIcon.iconShape().visitShapes(&visitor);
165 166 167 168 169 170

        QPixmap iconPixmap(size);
        iconPixmap.fill(Qt::transparent);
        QPainter iconPainter(&iconPixmap);
        iconPainter.drawPixmap((iconPixmap.width() - pixmap.width()) / 2, (iconPixmap.width() - pixmap.height()) / 2, pixmap);
        icon = QIcon(iconPixmap);
Jochen Becher's avatar
Jochen Becher committed
171
    }
172 173
    if (icon.isNull() && !defaultIconPath.isEmpty()) {
        icon = QIcon(defaultIconPath);
Jochen Becher's avatar
Jochen Becher committed
174 175 176 177 178
    }
    return icon;

}

179
void StereotypeController::addStereotypeIcon(const StereotypeIcon &stereotypeIcon)
Jochen Becher's avatar
Jochen Becher committed
180
{
181 182
    if (stereotypeIcon.elements().isEmpty()) {
        foreach (const QString &stereotype, stereotypeIcon.stereotypes()) {
183
            d->m_stereotypeToIconIdMap.insert(qMakePair(StereotypeIcon::ElementAny, stereotype), stereotypeIcon.id());
Jochen Becher's avatar
Jochen Becher committed
184 185
        }
    } else {
186 187 188
        foreach (StereotypeIcon::Element element, stereotypeIcon.elements()) {
            foreach (const QString &stereotype, stereotypeIcon.stereotypes()) {
                d->m_stereotypeToIconIdMap.insert(qMakePair(element, stereotype), stereotypeIcon.id());
Jochen Becher's avatar
Jochen Becher committed
189 190 191
            }
        }
    }
192
    d->m_iconIdToStereotypeIconsMap.insert(stereotypeIcon.id(), stereotypeIcon);
Jochen Becher's avatar
Jochen Becher committed
193 194 195 196
}

void StereotypeController::addToolbar(const Toolbar &toolbar)
{
197
    d->m_toolbars.append(toolbar);
Jochen Becher's avatar
Jochen Becher committed
198 199 200
}

} // namespace qmt