Subversion Repositories Scribus

Rev

Rev 21288 | Rev 22120 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4430 cbradney 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
3903 cbradney 7
/***************************************************************************
8
        copyright            : (C) 2005 by Craig Bradney
9
        email                : cbradney@zip.com.au
10
***************************************************************************/
11
 
12
/***************************************************************************
13
*                                                                         *
14
*   This program is free software; you can redistribute it and/or modify  *
15
*   it under the terms of the GNU General Public License as published by  *
16
*   the Free Software Foundation; either version 2 of the License, or     *
17
*   (at your option) any later version.                                   *
18
*                                                                         *
19
***************************************************************************/
20
 
15169 jghali 21
#include "sclimits.h"
4133 cbradney 22
#include "scribusdoc.h"
10223 cbradney 23
#include "selection.h"
13101 jghali 24
#include <QDebug>
3903 cbradney 25
 
4133 cbradney 26
Selection::Selection(QObject* parent)
27
        : QObject(parent),
11735 jghali 28
        m_isGUISelection(false),
29
        m_delaySignals(0),
30
        m_sigSelectionChanged(false),
31
        m_sigSelectionIsMultiple(false)
4133 cbradney 32
{
20691 craig 33
        m_groupX   = m_groupY   = m_groupW   = m_groupH   = 0;
34
        m_visualGX = m_visualGY = m_visualGW = m_visualGH = 0;
4133 cbradney 35
}
3903 cbradney 36
 
4133 cbradney 37
Selection::Selection(QObject* parent, bool guiSelection)
38
        : QObject(parent),
11735 jghali 39
        m_isGUISelection(guiSelection),
40
        m_delaySignals(0),
41
        m_sigSelectionChanged(false),
42
        m_sigSelectionIsMultiple(false)
3903 cbradney 43
{
20691 craig 44
        m_groupX   = m_groupY   = m_groupW   = m_groupH   = 0;
45
        m_visualGX = m_visualGY = m_visualGW = m_visualGH = 0;
3903 cbradney 46
}
47
 
4130 cbradney 48
Selection::Selection(const Selection& other) :
49
        QObject(other.parent()),
4133 cbradney 50
        m_SelList(other.m_SelList),
11736 jghali 51
        // We do not copy m_isGUISelection as :
52
        // 1) copy ctor is used for temporary selections
53
        // 2) having two GUI selections for same doc should really be avoided
54
        m_isGUISelection(false),
11735 jghali 55
        // We do not copy m_delaySignals as that can potentially
56
        // cause much trouble balancing delaySignalOff/On right
57
        m_delaySignals(0),
58
        m_sigSelectionChanged(other.m_sigSelectionChanged),
59
        m_sigSelectionIsMultiple(other.m_sigSelectionIsMultiple)
4130 cbradney 60
{
4352 cbradney 61
        if (m_isGUISelection && !m_SelList.isEmpty())
62
        {
63
                m_SelList[0]->connectToGUI();
64
                m_SelList[0]->emitAllToGUI();
65
                m_SelList[0]->setSelected(true);
16546 jghali 66
                emit selectionIsMultiple(m_SelList.count() > 1);
4352 cbradney 67
        }
20691 craig 68
        m_groupX = other.m_groupX;
69
        m_groupY = other.m_groupY;
70
        m_groupW = other.m_groupW;
71
        m_groupH = other.m_groupH;
72
        m_visualGX = other.m_visualGX;
73
        m_visualGY = other.m_visualGY;
74
        m_visualGW = other.m_visualGW;
75
        m_visualGH = other.m_visualGH;
4130 cbradney 76
}
3903 cbradney 77
 
4130 cbradney 78
Selection& Selection::operator=( const Selection &other )
79
{
80
        if (&other==this)
81
                return *this;
11729 jghali 82
        if (m_isGUISelection)
83
        {
84
                SelectionList::Iterator itend = m_SelList.end();
85
                for (SelectionList::Iterator it = m_SelList.begin(); it != itend; ++it)
86
                        (*it)->setSelected(false);
87
        }
4133 cbradney 88
        m_SelList=other.m_SelList;
11736 jghali 89
        // Do not copy m_isGUISelection for consistency with cpy ctor
90
        /* m_isGUISelection = other.m_isGUISelection; */
11735 jghali 91
        // We do not copy m_delaySignals as that can potentially
92
        // cause much trouble balancing delaySignalOff/On right
93
        m_sigSelectionChanged = other.m_sigSelectionChanged;
94
        m_sigSelectionIsMultiple = other.m_sigSelectionIsMultiple;
4352 cbradney 95
        if (m_isGUISelection && !m_SelList.isEmpty())
96
        {
97
                m_SelList[0]->connectToGUI();
98
                m_SelList[0]->emitAllToGUI();
99
                m_SelList[0]->setSelected(true);
16546 jghali 100
                emit selectionIsMultiple(m_SelList.count() > 1);
4352 cbradney 101
        }
4130 cbradney 102
        return *this;
103
}
104
 
11729 jghali 105
void Selection::copy(Selection& other, bool emptyOther)
8735 cbradney 106
{
107
        if (&other==this)
108
                return;
11729 jghali 109
        if (m_isGUISelection)
110
        {
111
                SelectionList::Iterator itend = m_SelList.end();
112
                for (SelectionList::Iterator it = m_SelList.begin(); it != itend; ++it)
113
                        (*it)->setSelected(false);
114
        }
8735 cbradney 115
        m_SelList=other.m_SelList;
116
        if (m_isGUISelection && !m_SelList.isEmpty())
11729 jghali 117
                m_sigSelectionIsMultiple = true;
8735 cbradney 118
        if (emptyOther)
119
                other.clear();
11729 jghali 120
        sendSignals();
8735 cbradney 121
}
122
 
3903 cbradney 123
Selection::~Selection()
124
{
125
}
126
 
4132 cbradney 127
bool Selection::clear()
3903 cbradney 128
{
4133 cbradney 129
        if (!m_SelList.isEmpty())
130
        {
131
                SelectionList::Iterator itend=m_SelList.end();
132
                SelectionList::Iterator it=m_SelList.begin();
133
                while (it!=itend)
3903 cbradney 134
                {
4133 cbradney 135
                        (*it)->isSingleSel=false;
136
                        if (m_isGUISelection)
11729 jghali 137
                        {
138
                                (*it)->setSelected(false);
3903 cbradney 139
                                (*it)->disconnectFromGUI();
11729 jghali 140
                        }
4133 cbradney 141
                        ++it;
3903 cbradney 142
                }
4133 cbradney 143
        }
144
        m_SelList.clear();
11729 jghali 145
        m_sigSelectionChanged = true;
146
        sendSignals();
4133 cbradney 147
        return true;
3903 cbradney 148
}
149
 
4132 cbradney 150
bool Selection::connectItemToGUI()
3903 cbradney 151
{
6593 fschmid 152
        bool ret = false;
4133 cbradney 153
        if (!m_isGUISelection || m_SelList.isEmpty())
6593 fschmid 154
                return ret;
16546 jghali 155
        if (m_SelList.count() == 1)
3903 cbradney 156
        {
8501 cbradney 157
                QPointer<PageItem> pi=m_SelList.first();
4132 cbradney 158
                //Quick check to see if the pointer is NULL, if its NULL, we should remove it from the list now
159
                if (pi.isNull())
3903 cbradney 160
                {
10455 cbradney 161
                        m_SelList.removeAll(pi);
6593 fschmid 162
                        return ret;
3903 cbradney 163
                }
6593 fschmid 164
                ret = pi->connectToGUI();
165
                pi->emitAllToGUI();
12125 jghali 166
                m_sigSelectionChanged = true;
4132 cbradney 167
        }
6593 fschmid 168
        else
169
        {
170
                ret = m_SelList.first()->connectToGUI();
171
                m_SelList.first()->emitAllToGUI();
12125 jghali 172
                m_sigSelectionChanged    = true;
173
                m_sigSelectionIsMultiple = true;
6593 fschmid 174
        }
12125 jghali 175
        sendSignals(false);
6593 fschmid 176
        return ret;
3903 cbradney 177
}
178
 
179
bool Selection::disconnectAllItemsFromGUI()
180
{
4133 cbradney 181
        if (!m_isGUISelection || m_SelList.isEmpty())
182
                return false;
183
        SelectionList::Iterator it2end=m_SelList.end();
184
        SelectionList::Iterator it2=m_SelList.begin();
185
        while (it2!=it2end)
4132 cbradney 186
        {
4133 cbradney 187
                (*it2)->disconnectFromGUI();
188
                ++it2;
4132 cbradney 189
        }
3903 cbradney 190
        return true;
191
}
192
 
4280 cbradney 193
bool Selection::addItem(PageItem *item, bool ignoreGUI)
3903 cbradney 194
{
195
        if (item==NULL)
196
                return false;
17388 jghali 197
        bool listWasEmpty = m_SelList.isEmpty();
4133 cbradney 198
        if (listWasEmpty || !m_SelList.contains(item))
3903 cbradney 199
        {
4133 cbradney 200
                m_SelList.append(item);
11729 jghali 201
                if (m_isGUISelection)
5859 tsoots 202
                {
11729 jghali 203
                        item->setSelected(true);
204
                        m_sigSelectionChanged = true;
205
                        m_sigSelectionIsMultiple = true;
5859 tsoots 206
                }
11729 jghali 207
                sendSignals();
4132 cbradney 208
                return true;
3903 cbradney 209
        }
210
        return false;
211
}
212
 
4632 cbradney 213
bool Selection::prependItem(PageItem *item, bool doEmit)
3903 cbradney 214
{
3934 cbradney 215
        if (item==NULL)
216
                return false;
4133 cbradney 217
        if (!m_SelList.contains(item))
3934 cbradney 218
        {
4133 cbradney 219
                if (m_isGUISelection && !m_SelList.isEmpty())
220
                        m_SelList[0]->disconnectFromGUI();
221
                m_SelList.prepend(item);
11729 jghali 222
                if (m_isGUISelection /*&& doEmit*/)
5859 tsoots 223
                {
11729 jghali 224
                        item->setSelected(true);
225
                        m_sigSelectionChanged = true;
226
                        m_sigSelectionIsMultiple = true;
16546 jghali 227
                }      
11729 jghali 228
                sendSignals();
4132 cbradney 229
                return true;
3934 cbradney 230
        }
3903 cbradney 231
        return false;
232
}
233
 
8266 avox 234
PageItem *Selection::itemAt_(int index)
3903 cbradney 235
{
8583 cbradney 236
        if (!m_SelList.isEmpty() && index<m_SelList.count())
4132 cbradney 237
        {
8501 cbradney 238
                QPointer<PageItem> pi=m_SelList[index];
4593 cbradney 239
                //If not NULL return it, otherwise remove from the list and return NULL
4132 cbradney 240
                if (!pi.isNull())
241
                        return pi;
9803 fschmid 242
//              SelectionList::Iterator it=m_SelList.at(index);
243
                m_SelList.removeAt(index);
4132 cbradney 244
        }
3903 cbradney 245
        return NULL;
246
}
3934 cbradney 247
 
18357 jghali 248
QList<PageItem*> Selection::items() const
249
{
250
        QList<PageItem*> selectedItems;
251
        for (int i = 0; i < m_SelList.count(); ++i)
252
        {
253
                QPointer<PageItem> pi = m_SelList.at(i);
254
                if (pi.isNull())
255
                        continue;
256
                selectedItems.append(pi.data());
257
        }
258
        return selectedItems;
259
}
260
 
4132 cbradney 261
bool Selection::removeFirst()
3934 cbradney 262
{
4133 cbradney 263
        if (!m_SelList.isEmpty())
3934 cbradney 264
        {
11729 jghali 265
                if (m_isGUISelection && m_SelList.first())
266
                        m_SelList.first()->setSelected(false);
4133 cbradney 267
                removeItem(m_SelList.first());
268
                if (m_SelList.isEmpty())
3934 cbradney 269
                        return true;
4133 cbradney 270
                if (m_isGUISelection)
11729 jghali 271
                        m_sigSelectionChanged = true;
272
                sendSignals();
3934 cbradney 273
        }
274
        return false;
275
}
276
 
4132 cbradney 277
bool Selection::removeItem(PageItem *item)
3934 cbradney 278
{
13101 jghali 279
    bool removeOk(false);
4133 cbradney 280
        if (!m_SelList.isEmpty() && m_SelList.contains(item))
4132 cbradney 281
        {
16118 fschmid 282
                removeOk=(m_SelList.removeAll(item)==1);
283
                if (removeOk)
3934 cbradney 284
                {
16118 fschmid 285
                        if (m_isGUISelection)
12166 jghali 286
                        {
16118 fschmid 287
                                item->setSelected(false);
288
                                item->disconnectFromGUI();
12166 jghali 289
                        }
16118 fschmid 290
                        item->isSingleSel = false;
3934 cbradney 291
                }
13101 jghali 292
 
15920 jghali 293
                if (m_isGUISelection)
5859 tsoots 294
                {
11729 jghali 295
                        m_sigSelectionChanged = true;
296
                        sendSignals();
5859 tsoots 297
                }
4132 cbradney 298
                return removeOk;
299
        }
13101 jghali 300
        return removeOk;
3934 cbradney 301
}
302
 
8583 cbradney 303
PageItem* Selection::takeItem(int itemIndex)
3934 cbradney 304
{
4133 cbradney 305
        if (!m_SelList.isEmpty() && itemIndex<m_SelList.count())
4132 cbradney 306
        {
11729 jghali 307
                PageItem *item =  m_SelList[itemIndex];
308
                bool removeOk  = (m_SelList.removeAll(item) == 1);
4132 cbradney 309
                if (removeOk)
3934 cbradney 310
                {
4132 cbradney 311
                        item->isSingleSel = false;
11729 jghali 312
                        if (m_isGUISelection)
3934 cbradney 313
                        {
11729 jghali 314
                                item->setSelected(false);
315
                                m_sigSelectionChanged = true;
316
                                if (itemIndex == 0)
4133 cbradney 317
                                        item->disconnectFromGUI();
3934 cbradney 318
                        }
11729 jghali 319
                        sendSignals();
4132 cbradney 320
                        return item;
3934 cbradney 321
                }
4132 cbradney 322
        }
3934 cbradney 323
        return NULL;
324
}
325
 
8266 avox 326
QStringList Selection::getSelectedItemsByName() const
3934 cbradney 327
{
328
        QStringList names;
8266 avox 329
        SelectionList::ConstIterator it=m_SelList.begin();
330
        SelectionList::ConstIterator itend=m_SelList.end();
3934 cbradney 331
        for ( ; it!=itend ; ++it)
332
                names.append((*it)->itemName());
333
        return names;
334
}
4049 cbradney 335
 
8266 avox 336
double Selection::width() const
6442 cbradney 337
{
338
        if (m_SelList.isEmpty())
339
                return 0.0;
15169 jghali 340
        double minX =  std::numeric_limits<double>::max();
341
        double maxX = -std::numeric_limits<double>::max();
8266 avox 342
        SelectionList::ConstIterator it=m_SelList.begin();
343
        SelectionList::ConstIterator itend=m_SelList.end();
6442 cbradney 344
        double x1=0.0,x2=0.0,y1=0.0,y2=0.0;
345
        for ( ; it!=itend ; ++it)
346
        {
347
                (*it)->getBoundingRect(&x1, &y1, &x2, &y2);
348
                if (x1<minX)
349
                        minX=x1;
350
                if (x2>maxX)
351
                        maxX=x2;
352
        }
353
        return maxX-minX;
354
}
355
 
8266 avox 356
double Selection::height() const
6442 cbradney 357
{
358
        if (m_SelList.isEmpty())
359
                return 0.0;
15169 jghali 360
        double minY =  std::numeric_limits<double>::max();
361
        double maxY = -std::numeric_limits<double>::max();
8266 avox 362
        SelectionList::ConstIterator it=m_SelList.begin();
363
        SelectionList::ConstIterator itend=m_SelList.end();
6442 cbradney 364
        double x1=0.0,x2=0.0,y1=0.0,y2=0.0;
365
        for ( ; it!=itend ; ++it)
366
        {
367
                (*it)->getBoundingRect(&x1, &y1, &x2, &y2);
368
                if (y1<minY)
369
                        minY=y1;
370
                if (y2>maxY)
371
                        maxY=y2;
372
        }
373
        return maxY-minY;
374
}
7575 cbradney 375
 
376
void Selection::setGroupRect()
377
{
378
        PageItem *currItem;
15169 jghali 379
        uint selectedItemCount = count();
380
        if (selectedItemCount == 0)
381
        {
20691 craig 382
                m_groupX   = m_groupY   = m_groupW   = m_groupH   = 0;
383
                m_visualGX = m_visualGY = m_visualGW = m_visualGH = 0;
15169 jghali 384
                return;
385
        }
386
        double minx  =  std::numeric_limits<double>::max();
387
        double miny  =  std::numeric_limits<double>::max();
388
        double maxx  = -std::numeric_limits<double>::max();
389
        double maxy  = -std::numeric_limits<double>::max();
390
        double vminx =  std::numeric_limits<double>::max();
391
        double vminy =  std::numeric_limits<double>::max();
392
        double vmaxx = -std::numeric_limits<double>::max();
393
        double vmaxy = -std::numeric_limits<double>::max();
394
 
7575 cbradney 395
        for (uint gc = 0; gc < selectedItemCount; ++gc)
396
        {
397
                currItem = itemAt(gc);
398
                if (currItem->rotation() != 0)
399
                {
21288 jghali 400
                        QRectF itRect(currItem->getBoundingRect());
21293 jghali 401
                        minx = qMin(minx, itRect.x());
402
                        miny = qMin(miny, itRect.y());
403
                        maxx = qMax(maxx, itRect.right());
404
                        maxy = qMax(maxy, itRect.bottom());
12463 pierre 405
 
406
                        // Same for visual
21288 jghali 407
                        QRectF itVisualRect(currItem->getVisualBoundingRect());
408
                        vminx = qMin(vminx, itVisualRect.x());
409
                        vminy = qMin(vminy, itVisualRect.y());
410
                        vmaxx = qMax(vmaxx, itVisualRect.right());
411
                        vmaxy = qMax(vmaxy, itVisualRect.bottom());
7575 cbradney 412
                }
413
                else
414
                {
8562 jghali 415
                        minx = qMin(minx, currItem->xPos());
416
                        miny = qMin(miny, currItem->yPos());
417
                        maxx = qMax(maxx, currItem->xPos() + currItem->width());
418
                        maxy = qMax(maxy, currItem->yPos() + currItem->height());
12463 pierre 419
 
420
                        vminx = qMin(vminx, currItem->visualXPos());
421
                        vminy = qMin(vminy, currItem->visualYPos());
422
                        vmaxx = qMax(vmaxx, currItem->visualXPos() + currItem->visualWidth());
423
                        vmaxy = qMax(vmaxy, currItem->visualYPos() + currItem->visualHeight());
7575 cbradney 424
                }
425
        }
20691 craig 426
        m_groupX = minx;
427
        m_groupY = miny;
428
        m_groupW = maxx - minx;
429
        m_groupH = maxy - miny;
12463 pierre 430
 
20691 craig 431
        m_visualGX = vminx;
432
        m_visualGY = vminy;
433
        m_visualGW = vmaxx - vminx;
434
        m_visualGH = vmaxy - vminy;
7575 cbradney 435
}
436
 
437
void Selection::getGroupRect(double *x, double *y, double *w, double *h)
438
{
13801 pierre 439
        setGroupRect();
20691 craig 440
        *x = m_groupX;
441
        *y = m_groupY;
442
        *w = m_groupW;
443
        *h = m_groupH;
7611 cbradney 444
}
7686 cbradney 445
 
13801 pierre 446
QRectF Selection::getGroupRect()
447
{
448
        double x, y, w, h;
449
        getGroupRect(&x, &y, &w, &h);
450
        return QRectF(x,y,w,h);
451
}
452
 
12463 pierre 453
void Selection::getVisualGroupRect(double * x, double * y, double * w, double * h)
454
{
13801 pierre 455
        setGroupRect();
20691 craig 456
        *x = m_visualGX;
457
        *y = m_visualGY;
458
        *w = m_visualGW;
459
        *h = m_visualGH;
12463 pierre 460
}
461
 
13801 pierre 462
QRectF Selection::getVisualGroupRect()
463
{
464
        double x, y, w, h;
465
        getGroupRect(&x, &y, &w, &h);
466
        return QRectF(x,y,w,h);
467
}
468
 
8266 avox 469
bool Selection::itemsAreSameType() const
7686 cbradney 470
{
471
        //CB Putting count=1 before isempty test as its probably the most likely, given our view code.
472
        if (m_SelList.count()==1)
473
                return true;
474
        if (m_SelList.isEmpty())
475
                return false;
8266 avox 476
        SelectionList::ConstIterator it=m_SelList.begin();
477
        SelectionList::ConstIterator itend=m_SelList.end();
478
        PageItem::ItemType itemType = (*it)->itemType();
7686 cbradney 479
        for ( ; it!=itend ; ++it)
480
        {
16105 fschmid 481
                if ((*it)->isGroup())           // ignore GroupControl items
9057 fschmid 482
                        continue;
8266 avox 483
                if ((*it)->itemType() != itemType)
7686 cbradney 484
                        return false;
485
        }
486
        return true;
487
}
11729 jghali 488
 
14296 jghali 489
int Selection::objectsLayer(void) const
490
{
491
        if (m_SelList.isEmpty())
492
                return -1;
493
        int layerID = m_SelList.at(0)->LayerID;
494
        for (int i = 1; i < m_SelList.count(); ++i)
495
        {
496
                if (m_SelList.at(i)->LayerID != layerID)
497
                {
498
                        layerID = -1;
499
                        break;
500
                }
501
        }
502
        return layerID;
503
}
504
 
17092 jghali 505
bool Selection::objectsHaveSameParent(void) const
506
{
507
        int selectedItemCount = m_SelList.count();
508
        if (selectedItemCount <= 1)
509
                return true;
510
 
511
        bool haveSameParent = true;
512
        const PageItem *firstItem = itemAt(0);
513
        for (int a = 1; a < selectedItemCount; ++a)
514
        {
515
                if (itemAt(a)->Parent != firstItem->Parent)
516
                {
517
                        haveSameParent = false;
518
                        break;
519
                }
520
        }
521
        return haveSameParent;
522
}
523
 
11729 jghali 524
bool Selection::signalsDelayed(void)
525
{
526
        return (m_isGUISelection && (m_delaySignals > 0));
527
}
528
 
529
void Selection::delaySignalsOn(void)
530
{
531
        ++m_delaySignals;
532
}
533
 
534
void Selection::delaySignalsOff(void)
535
{
536
        --m_delaySignals;
537
        if (m_delaySignals <= 0)
538
                sendSignals();
539
}
540
 
12125 jghali 541
void Selection::sendSignals(bool guiConnect)
11729 jghali 542
{
543
        if (m_isGUISelection && (m_delaySignals <= 0))
544
        {
15169 jghali 545
                setGroupRect();
15318 jghali 546
                // JG - We should probably add an m_sigSelectionChanged here
547
                // to avoid multiple connectItemToGUI() if sendSignals() is called 
548
                // several times successively (but does that happen?)
549
                if (guiConnect /*&& m_sigSelectionChanged*/)
12125 jghali 550
                        connectItemToGUI();
11729 jghali 551
                if (m_sigSelectionChanged)
552
                        emit selectionChanged();
553
                if (m_sigSelectionIsMultiple)
16546 jghali 554
                        emit selectionIsMultiple(m_SelList.count() > 1);
11729 jghali 555
                m_sigSelectionChanged = false;
556
                m_sigSelectionIsMultiple = false;
557
        }
558
}
12463 pierre 559
 
13101 jghali 560