libs/flake
KoSelection.cppGo to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "KoSelection.h"
00025 #include "KoSelection_p.h"
00026 #include "KoShapeContainer.h"
00027 #include "KoShapeGroup.h"
00028 #include "KoPointerEvent.h"
00029
00030 #include <QPainter>
00031 #include <QTimer>
00032
00033 QRectF KoSelectionPrivate::sizeRect()
00034 {
00035 bool first = true;
00036 QRectF bb;
00037
00038 QMatrix invSelectionTransform = q->absoluteTransformation(0).inverted();
00039
00040 QRectF bound;
00041
00042 if (!selectedShapes.isEmpty()) {
00043 QList<KoShape*>::const_iterator it = selectedShapes.constBegin();
00044 for (; it != selectedShapes.constEnd(); ++it) {
00045 if (dynamic_cast<KoShapeGroup*>(*it))
00046 continue;
00047
00048 const QMatrix shapeTransform = (*it)->absoluteTransformation(0);
00049 const QRectF shapeRect(QRectF(QPointF(), (*it)->size()));
00050
00051 if (first) {
00052 bb = (shapeTransform * invSelectionTransform).mapRect(shapeRect);
00053 bound = shapeTransform.mapRect( shapeRect );
00054 first = false;
00055 } else {
00056 bb = bb.united((shapeTransform * invSelectionTransform).mapRect(shapeRect));
00057 bound = bound.united( shapeTransform.mapRect( shapeRect ) );
00058 }
00059 }
00060 }
00061
00062 globalBound = bound;
00063 return bb;
00064 }
00065
00066 void KoSelectionPrivate::requestSelectionChangedEvent()
00067 {
00068 if (eventTriggered)
00069 return;
00070 eventTriggered = true;
00071 QTimer::singleShot(0, q, SLOT(selectionChangedEvent()));
00072 }
00073
00074 void KoSelectionPrivate::selectionChangedEvent()
00075 {
00076 eventTriggered = false;
00077 q->setScale(1, 1);
00078 emit q->selectionChanged();
00079 }
00080
00081 void KoSelectionPrivate::selectGroupChildren(KoShapeGroup *group)
00082 {
00083 if (! group)
00084 return;
00085
00086 foreach(KoShape *shape, group->childShapes()) {
00087 if (selectedShapes.contains(shape))
00088 continue;
00089 selectedShapes << shape;
00090
00091 KoShapeGroup* childGroup = dynamic_cast<KoShapeGroup*>(shape);
00092 if (childGroup)
00093 selectGroupChildren(childGroup);
00094 }
00095 }
00096
00097 void KoSelectionPrivate::deselectGroupChildren(KoShapeGroup *group)
00098 {
00099 if (! group)
00100 return;
00101
00102 foreach(KoShape *shape, group->childShapes()) {
00103 if (selectedShapes.contains(shape))
00104 selectedShapes.removeAll(shape);
00105
00106 KoShapeGroup* childGroup = dynamic_cast<KoShapeGroup*>(shape);
00107 if (childGroup)
00108 deselectGroupChildren(childGroup);
00109 }
00110 }
00111
00113
00114 KoSelection::KoSelection()
00115 : KoShape(*(new KoSelectionPrivate(this)))
00116 {
00117 }
00118
00119 KoSelection::~KoSelection()
00120 {
00121 }
00122
00123 void KoSelection::paint(QPainter &painter, const KoViewConverter &converter)
00124 {
00125 Q_UNUSED(painter);
00126 Q_UNUSED(converter);
00127 }
00128
00129 void KoSelection::select(KoShape *shape, bool recursive)
00130 {
00131 Q_D(KoSelection);
00132 Q_ASSERT(shape != this);
00133 Q_ASSERT(shape);
00134 if (!shape->isSelectable() || !shape->isVisible(true))
00135 return;
00136
00137
00138 uint oldSelectionCount = d->selectedShapes.count();
00139
00140 if (!d->selectedShapes.contains(shape))
00141 d->selectedShapes << shape;
00142
00143
00144 KoShapeGroup* group = dynamic_cast<KoShapeGroup*>(shape);
00145 if (group)
00146 d->selectGroupChildren(group);
00147
00148 if (recursive) {
00149
00150 KoShapeContainer *parent = shape->parent();
00151 while (parent) {
00152 KoShapeGroup *parentGroup = dynamic_cast<KoShapeGroup*>(parent);
00153 if (! parentGroup) break;
00154 if (! d->selectedShapes.contains(parentGroup)) {
00155 d->selectedShapes << parentGroup;
00156 d->selectGroupChildren(parentGroup);
00157 }
00158 parent = parentGroup->parent();
00159 }
00160 }
00161
00162 if (d->selectedShapes.count() == 1) {
00163 setTransformation(shape->absoluteTransformation(0));
00164 updateSizeAndPosition();
00165 }
00166 else {
00167
00168 if( ! oldSelectionCount )
00169 d->globalBound = QRectF();
00170
00171 setTransformation(QMatrix());
00172
00173
00174
00175 uint newSelectionCount = d->selectedShapes.count();
00176 for( uint i = oldSelectionCount; i < newSelectionCount; ++i ) {
00177 KoShape * shape = d->selectedShapes[i];
00178 const QMatrix shapeTransform = shape->absoluteTransformation(0);
00179 const QRectF shapeRect(QRectF(QPointF(), shape->size()));
00180
00181 d->globalBound = d->globalBound.united( shapeTransform.mapRect( shapeRect ) );
00182 }
00183 setSize(d->globalBound.size());
00184 setPosition(d->globalBound.topLeft());
00185 }
00186
00187 d->requestSelectionChangedEvent();
00188 }
00189
00190 void KoSelection::deselect(KoShape *shape, bool recursive)
00191 {
00192 Q_D(KoSelection);
00193 if (! d->selectedShapes.contains(shape))
00194 return;
00195
00196 d->selectedShapes.removeAll(shape);
00197
00198 KoShapeGroup *group = dynamic_cast<KoShapeGroup*>(shape);
00199 if (recursive) {
00200
00201 KoShapeGroup *parentGroup = dynamic_cast<KoShapeGroup*>(shape->parent());
00202 while (parentGroup) {
00203 group = parentGroup;
00204 parentGroup = dynamic_cast<KoShapeGroup*>(parentGroup->parent());
00205 }
00206 }
00207 if (group)
00208 d->deselectGroupChildren(group);
00209
00210 if (count() == 1)
00211 setTransformation(firstSelectedShape()->absoluteTransformation(0));
00212
00213 updateSizeAndPosition();
00214
00215 d->requestSelectionChangedEvent();
00216 }
00217
00218 void KoSelection::deselectAll()
00219 {
00220 Q_D(KoSelection);
00221
00222 setTransformation(QMatrix());
00223
00224 if (d->selectedShapes.isEmpty())
00225 return;
00226 d->selectedShapes.clear();
00227 d->requestSelectionChangedEvent();
00228 }
00229
00230 int KoSelection::count() const
00231 {
00232 Q_D(const KoSelection);
00233 int count = 0;
00234 foreach(KoShape *shape, d->selectedShapes)
00235 if (dynamic_cast<KoShapeGroup*>(shape) == 0)
00236 ++count;
00237 return count;
00238 }
00239
00240 bool KoSelection::hitTest(const QPointF &position) const
00241 {
00242 Q_D(const KoSelection);
00243 if (count() > 1) {
00244 QRectF bb(boundingRect());
00245 return bb.contains(position);
00246 } else if (count() == 1)
00247 return (*d->selectedShapes.begin())->hitTest(position);
00248 else
00249 return false;
00250 }
00251 void KoSelection::updateSizeAndPosition()
00252 {
00253 Q_D(KoSelection);
00254 QRectF bb = d->sizeRect();
00255 QMatrix matrix = absoluteTransformation(0);
00256 setSize(bb.size());
00257 QPointF p = matrix.map(bb.topLeft() + matrix.inverted().map(position()));
00258 setPosition(p);
00259 }
00260
00261 QRectF KoSelection::boundingRect() const
00262 {
00263 return absoluteTransformation(0).mapRect(QRectF(QPointF(), size()));
00264 }
00265
00266 const QList<KoShape*> KoSelection::selectedShapes(KoFlake::SelectionType strip) const
00267 {
00268 Q_D(const KoSelection);
00269 QList<KoShape*> answer;
00270
00271 bool doStripping = strip == KoFlake::StrippedSelection;
00272 foreach(KoShape *shape, d->selectedShapes) {
00273 KoShapeContainer *container = shape->parent();
00274 if (strip != KoFlake::TopLevelSelection && dynamic_cast<KoShapeGroup*>(shape))
00275
00276
00277
00278 continue;
00279 bool add = true;
00280 while (doStripping && add && container) {
00281 if (dynamic_cast<KoShapeGroup*>(container) == 0 && d->selectedShapes.contains(container))
00282 add = false;
00283 container = container->parent();
00284 }
00285 if (strip == KoFlake::TopLevelSelection && container && d->selectedShapes.contains(container))
00286 add = false;
00287 if (add)
00288 answer << shape;
00289 }
00290 return answer;
00291 }
00292
00293 bool KoSelection::isSelected(const KoShape *shape) const
00294 {
00295 Q_D(const KoSelection);
00296 if (shape == this)
00297 return true;
00298
00299 foreach (KoShape *s, d->selectedShapes) {
00300 if (s == shape)
00301 return true;
00302 }
00303
00304 return false;
00305 }
00306
00307 KoShape *KoSelection::firstSelectedShape(KoFlake::SelectionType strip) const
00308 {
00309 QList<KoShape*> set = selectedShapes(strip);
00310 if (set.isEmpty())
00311 return 0;
00312 return *(set.begin());
00313 }
00314
00315 void KoSelection::setActiveLayer(KoShapeLayer* layer)
00316 {
00317 Q_D(KoSelection);
00318 d->activeLayer = layer;
00319 emit currentLayerChanged(layer);
00320 }
00321
00322 KoShapeLayer* KoSelection::activeLayer() const
00323 {
00324 Q_D(const KoSelection);
00325 return d->activeLayer;
00326 }
00327
00328 void KoSelection::saveOdf(KoShapeSavingContext &) const
00329 {
00330 }
00331
00332 bool KoSelection::loadOdf(const KoXmlElement &, KoShapeLoadingContext &)
00333 {
00334 return true;
00335 }
00336
00337 #include "KoSelection.moc"
|