Warning, file /office/calligra/libs/widgets/KoPositionSelector.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2007 Thomas Zander <zander@kde.org>
0003  * Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Library General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Library General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Library General Public License
0016  * along with this library; see the file COPYING.LIB.  If not, write to
0017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019  */
0020 
0021 #include "KoPositionSelector.h"
0022 
0023 #include <QRadioButton>
0024 #include <QGridLayout>
0025 #include <QButtonGroup>
0026 #include <QPainter>
0027 #include <WidgetsDebug.h>
0028 #include <QStyleOption>
0029 
0030 #define GAP 0
0031 
0032 class Q_DECL_HIDDEN KoPositionSelector::Private
0033 {
0034 public:
0035     Private()
0036         : position(KoFlake::TopLeftCorner)
0037     {
0038         topLeft = createButton(KoFlake::TopLeftCorner);
0039         topLeft->setChecked(true);
0040         topRight = createButton(KoFlake::TopRightCorner);
0041         center = createButton(KoFlake::CenteredPosition);
0042         bottomRight = createButton(KoFlake::BottomRightCorner);
0043         bottomLeft = createButton(KoFlake::BottomLeftCorner);
0044     }
0045 
0046     QRadioButton *createButton(int id) {
0047         QRadioButton *b = new QRadioButton();
0048         buttonGroup.addButton(b, id);
0049         return b;
0050     }
0051 
0052     QRadioButton *topLeft, *topRight, *center, *bottomRight, *bottomLeft;
0053     QButtonGroup buttonGroup;
0054     KoFlake::Position position;
0055 };
0056 
0057 class RadioLayout : public QLayout {
0058 Q_OBJECT
0059 public:
0060     RadioLayout(QWidget *parent)
0061         : QLayout(parent)
0062     {
0063     }
0064 
0065     ~RadioLayout() override
0066     {
0067         foreach( const Item & item, items )
0068             delete item.child;
0069         items.clear();
0070     }
0071 
0072     void setGeometry (const QRect &geom) override {
0073         QSize prefSize = calcSizes();
0074 
0075         qreal columnWidth, rowHeight;
0076         if (geom.width() <= minimum.width())
0077             columnWidth = geom.width() / (qreal) maxCol;
0078         else
0079             columnWidth = prefSize.width() + GAP;
0080         if (geom.height() <= minimum.height())
0081             rowHeight = geom.height() / (qreal) maxRow;
0082         else
0083             rowHeight = prefSize.height() + GAP;
0084         // padding inside row and column so that radio button is centered
0085         QPoint padding( qRound(0.5 * (columnWidth - prefSize.width())), qRound(0.5 * (rowHeight - prefSize.height())));
0086         // offset so that all the radio button are centered within the widget
0087         qreal offsetX = 0.5 * (geom.width()- static_cast<qreal>(maxCol) * columnWidth);
0088         qreal offsetY = 0.5 * (geom.height() - static_cast<qreal>(maxRow) * rowHeight);
0089         QPoint offset( qRound(offsetX), qRound(offsetY));
0090         foreach(const Item & item, items) {
0091             QPoint point( qRound(item.column * columnWidth), qRound(item.row * rowHeight) );
0092             QRect rect(point + offset + padding + geom.topLeft(), prefSize);
0093             item.child->setGeometry(rect);
0094         }
0095     }
0096 
0097     QSize calcSizes() {
0098         QSize prefSize;
0099         maxRow = 0;
0100         maxCol = 0;
0101         foreach(const Item & item, items) {
0102             if(prefSize.isEmpty()) {
0103                 QAbstractButton *but = dynamic_cast<QAbstractButton*> (item.child->widget());
0104                 Q_ASSERT(but);
0105                 QStyleOptionButton opt;
0106                 opt.initFrom(but);
0107                 prefSize = QSize(but->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorWidth, &opt, but),
0108                         but->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorHeight, &opt, but));
0109             }
0110             maxRow = qMax(maxRow, item.row);
0111             maxCol = qMax(maxCol, item.column);
0112         }
0113         maxCol++; maxRow++; // due to being zero-based.
0114         preferred = QSize(maxCol * prefSize.width() + (maxCol-1) * GAP, maxRow * prefSize.height() + (maxRow-1) * GAP);
0115         minimum = QSize(maxCol * prefSize.width(), maxRow * prefSize.height());
0116         return prefSize;
0117     }
0118 
0119     QLayoutItem *itemAt (int index) const override {
0120         if( index < count() )
0121             return items.at(index).child;
0122         else
0123             return 0;
0124     }
0125 
0126     QLayoutItem *takeAt (int index) override {
0127         Q_ASSERT(index < count());
0128         Item item = items.takeAt(index);
0129         return item.child;
0130     }
0131 
0132     int count () const override {
0133         return items.count();
0134     }
0135 
0136     void addItem(QLayoutItem *) override {
0137         Q_ASSERT(0);
0138     }
0139 
0140     QSize sizeHint() const override {
0141         if(preferred.isEmpty())
0142             const_cast<RadioLayout*> (this)->calcSizes();
0143         return preferred;
0144     }
0145 
0146     QSize minimumSize() const override {
0147         if(minimum.isEmpty())
0148             const_cast<RadioLayout*> (this)->calcSizes();
0149         return minimum;
0150     }
0151 
0152     void addWidget(QRadioButton *widget, int row, int column) {
0153         addChildWidget(widget);
0154         Item newItem;
0155         newItem.child = new QWidgetItem(widget);
0156         newItem.row = row;
0157         newItem.column = column;
0158         items.append(newItem);
0159     }
0160 
0161 private:
0162     struct Item {
0163         QLayoutItem *child;
0164         int column;
0165         int row;
0166     };
0167     QList<Item> items;
0168     QSize preferred, minimum;
0169     int maxCol, maxRow;
0170 };
0171 
0172 KoPositionSelector::KoPositionSelector(QWidget *parent)
0173     : QWidget(parent),
0174     d(new Private())
0175 {
0176     setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
0177     RadioLayout *lay = new RadioLayout(this);
0178     lay->addWidget(d->topLeft, 0, 0);
0179     lay->addWidget(d->topRight, 0, 2);
0180     lay->addWidget(d->center, 1, 1);
0181     lay->addWidget(d->bottomRight, 2, 2);
0182     lay->addWidget(d->bottomLeft, 2, 0);
0183     setLayout(lay);
0184 
0185     connect(&d->buttonGroup, SIGNAL(buttonClicked(int)), this, SLOT(positionChanged(int)));
0186 }
0187 
0188 KoPositionSelector::~KoPositionSelector() {
0189     delete d;
0190 }
0191 
0192 KoFlake::Position KoPositionSelector::position() const {
0193     return d->position;
0194 }
0195 
0196 void KoPositionSelector::setPosition(KoFlake::Position position) {
0197     d->position = position;
0198     switch(d->position) {
0199         case KoFlake::TopLeftCorner:
0200             d->topLeft->setChecked(true);
0201             break;
0202         case KoFlake::TopRightCorner:
0203             d->topRight->setChecked(true);
0204             break;
0205         case KoFlake::CenteredPosition:
0206             d->center->setChecked(true);
0207             break;
0208         case KoFlake::BottomLeftCorner:
0209             d->bottomLeft->setChecked(true);
0210             break;
0211         case KoFlake::BottomRightCorner:
0212             d->bottomRight->setChecked(true);
0213             break;
0214     }
0215 }
0216 
0217 void KoPositionSelector::positionChanged(int position) {
0218     d->position = static_cast<KoFlake::Position> (position);
0219     emit positionSelected(d->position);
0220 }
0221 
0222 void KoPositionSelector::paintEvent (QPaintEvent *) {
0223     QPainter painter( this );
0224     QPen pen(Qt::black);
0225     int width;
0226     if (d->topLeft->width() %2 == 0)
0227         width = 2;
0228     else
0229         width = 3;
0230     pen.setWidth(width);
0231     painter.setPen(pen);
0232     painter.drawRect( QRect( d->topLeft->geometry().center(), d->bottomRight->geometry().center() ) );
0233     painter.end();
0234 }
0235 #include "KoPositionSelector.moc"