Warning, file /office/calligra/libs/widgets/KoResourcePopupAction.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  * Made by Tomislav Lukman (tomislav.lukman@ck.tel.hr)
0003  * Copyright (C) 2012 Jean-Nicolas Artaud <jeannicolasartaud@gmail.com>
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 "KoResourcePopupAction.h"
0022 
0023 #include "KoResourceServerAdapter.h"
0024 #include "KoResourceItemView.h"
0025 #include "KoResourceModel.h"
0026 #include "KoResourceItemDelegate.h"
0027 #include "KoResource.h"
0028 #include "KoCheckerBoardPainter.h"
0029 #include "KoShapeBackground.h"
0030 #include <KoAbstractGradient.h>
0031 #include <KoPattern.h>
0032 #include <KoGradientBackground.h>
0033 #include <KoPatternBackground.h>
0034 #include <KoImageCollection.h>
0035 
0036 #include <QMenu>
0037 #include <QHBoxLayout>
0038 #include <QHeaderView>
0039 #include <QPainter>
0040 #include <QGradient>
0041 #include <QToolButton>
0042 #include <QRect>
0043 #include <QWidgetAction>
0044 
0045 #include <utility>
0046 
0047 class KoResourcePopupAction::Private
0048 {
0049 public:
0050     Private() : resourceList(0), background(0), checkerPainter(4)
0051     {}
0052     QMenu *menu;
0053     KoResourceItemView *resourceList;
0054     QSharedPointer<KoShapeBackground> background;
0055     KoCheckerBoardPainter checkerPainter;
0056 };
0057 
0058 KoResourcePopupAction::KoResourcePopupAction(QSharedPointer<KoAbstractResourceServerAdapter>resourceAdapter, QObject *parent)
0059 :  QAction(parent)
0060 , d(new Private())
0061 {
0062     Q_ASSERT(resourceAdapter);
0063 
0064     d->menu = new QMenu();
0065     QWidget *widget = new QWidget();
0066     QWidgetAction *wdgAction = new QWidgetAction(this);
0067 
0068     d->resourceList = new KoResourceItemView(widget);
0069     d->resourceList->setModel(new KoResourceModel(resourceAdapter, widget));
0070     d->resourceList->setItemDelegate(new KoResourceItemDelegate(widget));
0071     KoResourceModel * resourceModel = qobject_cast<KoResourceModel*>(d->resourceList->model());
0072     if (resourceModel) {
0073         resourceModel->setColumnCount(1);
0074     }
0075 
0076     KoResource *resource = 0;
0077     if (resourceAdapter->resources().count() > 0) {
0078         resource = resourceAdapter->resources().at(0);
0079     }
0080 
0081     KoAbstractGradient *gradient = dynamic_cast<KoAbstractGradient*>(resource);
0082     KoPattern *pattern = dynamic_cast<KoPattern*>(resource);
0083     if (gradient) {
0084         QGradient *qg = gradient->toQGradient();
0085         qg->setCoordinateMode(QGradient::ObjectBoundingMode);
0086         d->background = QSharedPointer<KoShapeBackground>(new KoGradientBackground(qg));
0087     } else if (pattern) {
0088         KoImageCollection *collection = new KoImageCollection();
0089         d->background = QSharedPointer<KoShapeBackground>(new KoPatternBackground(collection));
0090         static_cast<KoPatternBackground*>(d->background.data())->setPattern(pattern->pattern());
0091     }
0092 
0093     QHBoxLayout *layout = new QHBoxLayout(widget);
0094     layout->addWidget(d->resourceList);
0095     widget->setLayout(layout);
0096 
0097     wdgAction->setDefaultWidget(widget);
0098     d->menu->addAction(wdgAction);
0099     setMenu(d->menu);
0100     new QHBoxLayout(d->menu);
0101     d->menu->layout()->addWidget(widget);
0102     d->menu->layout()->setMargin(0);
0103 
0104     connect(d->resourceList, SIGNAL(clicked(QModelIndex)), this, SLOT(indexChanged(QModelIndex)));
0105 
0106     updateIcon();
0107 }
0108 
0109 KoResourcePopupAction::~KoResourcePopupAction()
0110 {
0111     /* Removing the actions here make them be deleted together with their default widget.
0112      * This happens only if the actions are QWidgetAction, and we know they are since
0113      * the only ones added are in KoResourcePopupAction constructor. */
0114     int i = 0;
0115     while(!d->menu->actions().empty()) {
0116         d->menu->removeAction(d->menu->actions().at(i));
0117         ++i;
0118     }
0119 
0120     delete d->menu;
0121 
0122     delete d;
0123 }
0124 
0125 QSharedPointer<KoShapeBackground> KoResourcePopupAction::currentBackground() const
0126 {
0127     return d->background;
0128 }
0129 
0130 void KoResourcePopupAction::setCurrentBackground(QSharedPointer<KoShapeBackground>  background)
0131 {
0132     d->background = std::move(background);
0133 
0134     updateIcon();
0135 }
0136 
0137 
0138 void KoResourcePopupAction::indexChanged(const QModelIndex &modelIndex)
0139 {
0140     if (! modelIndex.isValid()) {
0141         return;
0142     }
0143 
0144     d->menu->hide();
0145 
0146     KoResource *resource = static_cast<KoResource*>(modelIndex.internalPointer());
0147     if(resource) {
0148         KoAbstractGradient *gradient = dynamic_cast<KoAbstractGradient*>(resource);
0149         KoPattern *pattern = dynamic_cast<KoPattern*>(resource);
0150         if (gradient) {
0151             QGradient *qg = gradient->toQGradient();
0152             qg->setCoordinateMode(QGradient::ObjectBoundingMode);
0153             d->background = QSharedPointer<KoShapeBackground>(new KoGradientBackground(qg));
0154         } else if (pattern) {
0155             KoImageCollection *collection = new KoImageCollection();
0156             d->background = QSharedPointer<KoShapeBackground>(new KoPatternBackground(collection));
0157             qSharedPointerDynamicCast<KoPatternBackground>(d->background)->setPattern(pattern->pattern());
0158         }
0159 
0160         emit resourceSelected(d->background);
0161 
0162         updateIcon();
0163     }
0164 }
0165 
0166 void KoResourcePopupAction::updateIcon()
0167 {
0168     QSize iconSize;
0169     QToolButton *toolButton = dynamic_cast<QToolButton*>(parentWidget());
0170     if (toolButton) {
0171         iconSize = QSize(toolButton->iconSize());
0172     } else {
0173         iconSize = QSize(16, 16);
0174     }
0175 
0176     // This must be a QImage, as drawing to a QPixmap outside the
0177     // UI thread will cause sporadic crashes.
0178     QImage pm = QImage(iconSize, QImage::Format_ARGB32_Premultiplied);
0179 
0180     pm.fill(Qt::transparent);
0181 
0182     QPainter p(&pm);
0183     QSharedPointer<KoGradientBackground> gradientBackground = qSharedPointerDynamicCast<KoGradientBackground>(d->background);
0184     QSharedPointer<KoPatternBackground> patternBackground = qSharedPointerDynamicCast<KoPatternBackground>(d->background);
0185 
0186     if (gradientBackground) {
0187         QRect innerRect(0, 0, iconSize.width(), iconSize.height());
0188         QLinearGradient paintGradient;
0189         paintGradient.setStops(gradientBackground->gradient()->stops());
0190         paintGradient.setStart(innerRect.topLeft());
0191         paintGradient.setFinalStop(innerRect.topRight());
0192 
0193         d->checkerPainter.paint(p, innerRect);
0194         p.fillRect(innerRect, QBrush(paintGradient));
0195     } else if (patternBackground) {
0196         d->checkerPainter.paint(p, QRect(QPoint(),iconSize));
0197         p.fillRect(0, 0, iconSize.width(), iconSize.height(), patternBackground->pattern());
0198     }
0199 
0200     p.end();
0201 
0202     setIcon(QIcon(QPixmap::fromImage(pm)));
0203 }