~librecad-dev/librecad/librecad

« back to all changes in this revision

Viewing changes to librecad/src/lib/engine/rs_blocklist.cpp

  • Committer: Scott Howard
  • Date: 2014-02-21 19:07:55 UTC
  • Revision ID: showard@debian.org-20140221190755-csjax9wb146hgdq4
first commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** This file is part of the LibreCAD project, a 2D CAD program
 
4
**
 
5
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
 
6
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
 
7
**
 
8
**
 
9
** This file may be distributed and/or modified under the terms of the
 
10
** GNU General Public License version 2 as published by the Free Software 
 
11
** Foundation and appearing in the file gpl-2.0.txt included in the
 
12
** packaging of this file.
 
13
**
 
14
** This program is distributed in the hope that it will be useful,
 
15
** but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
** GNU General Public License for more details.
 
18
** 
 
19
** You should have received a copy of the GNU General Public License
 
20
** along with this program; if not, write to the Free Software
 
21
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
22
**
 
23
** This copyright notice MUST APPEAR in all copies of the script!  
 
24
**
 
25
**********************************************************************/
 
26
 
 
27
 
 
28
#include "rs_debug.h"
 
29
#include "rs_blocklist.h"
 
30
#include "rs_block.h"
 
31
#include "rs_blocklistlistener.h"
 
32
 
 
33
#if QT_VERSION < 0x040400
 
34
#include "emu_qt44.h"
 
35
#endif
 
36
 
 
37
/**
 
38
 * Constructor.
 
39
 * 
 
40
 * @param owner true if this is the owner of the blocks added.
 
41
 *              If so, the blocks will be deleted when the block
 
42
 *              list is deleted.
 
43
 */
 
44
RS_BlockList::RS_BlockList(bool owner) {
 
45
    this->owner = owner;
 
46
    //blocks.setAutoDelete(owner);
 
47
    activeBlock = NULL;
 
48
        setModified(false);
 
49
}
 
50
 
 
51
 
 
52
/**
 
53
 * Removes all blocks in the blocklist.
 
54
 */
 
55
void RS_BlockList::clear() {
 
56
    blocks.clear();
 
57
    activeBlock = NULL;
 
58
        setModified(true);
 
59
}
 
60
 
 
61
 
 
62
/**
 
63
 * Activates the given block.
 
64
 * Listeners are notified.
 
65
 */
 
66
void RS_BlockList::activate(const QString& name) {
 
67
    RS_DEBUG->print("RS_BlockList::activateBlock");
 
68
 
 
69
    activate(find(name));
 
70
}
 
71
 
 
72
/**
 
73
 * Activates the given block.
 
74
 * Listeners are notified.
 
75
 */
 
76
void RS_BlockList::activate(RS_Block* block) {
 
77
    RS_DEBUG->print("RS_BlockList::activateBlock");
 
78
    activeBlock = block;
 
79
 
 
80
    /*
 
81
       for (unsigned i=0; i<blockListListeners.count(); ++i) {
 
82
           RS_BlockListListener* l = blockListListeners.at(i);
 
83
        if (l!=NULL) {
 
84
                l->blockActivated(activeBlock);
 
85
        }
 
86
       }
 
87
    */
 
88
}
 
89
 
 
90
 
 
91
/**
 
92
 * Adds a block to the block list. If a block with the same name
 
93
 * exists already, the given block will be deleted if the blocklist
 
94
 * owns the blocks.
 
95
 *
 
96
 * @param notify true if you want listeners to be notified.
 
97
 *
 
98
 * @return false: block already existed and was deleted.
 
99
 */
 
100
bool RS_BlockList::add(RS_Block* block, bool notify) {
 
101
    RS_DEBUG->print("RS_BlockList::add()");
 
102
 
 
103
    if (block==NULL) {
 
104
        return false;
 
105
    }
 
106
 
 
107
    // check if block already exists:
 
108
    RS_Block* b = find(block->getName());
 
109
    if (b==NULL) {
 
110
        blocks.append(block);
 
111
 
 
112
        if (notify) {
 
113
            addNotification();
 
114
        }
 
115
                setModified(true);
 
116
 
 
117
                return true;
 
118
    } else {
 
119
        if (owner) {
 
120
            delete block;
 
121
            block = NULL;
 
122
        }
 
123
                return false;
 
124
    }
 
125
 
 
126
}
 
127
 
 
128
 
 
129
 
 
130
/**
 
131
 * Notifies the listeners about blocks that were added. This can be
 
132
 * used after adding a lot of blocks without auto-update or simply
 
133
 * to force an update of GUI blocklists.
 
134
 */
 
135
void RS_BlockList::addNotification() {
 
136
    for (int i=0; i<blockListListeners.size(); ++i) {
 
137
        RS_BlockListListener* l = blockListListeners.at(i);
 
138
        l->blockAdded(NULL);
 
139
    }
 
140
}
 
141
 
 
142
 
 
143
 
 
144
/**
 
145
 * Removes a block from the list.
 
146
 * Listeners are notified after the block was removed from 
 
147
 * the list but before it gets deleted.
 
148
 */
 
149
void RS_BlockList::remove(RS_Block* block) {
 
150
    RS_DEBUG->print("RS_BlockList::removeBlock()");
 
151
 
 
152
    // here the block is removed from the list but not deleted
 
153
#if QT_VERSION < 0x040400
 
154
    emu_qt44_removeOne(blocks, block);
 
155
#else
 
156
    blocks.removeOne(block);
 
157
#endif
 
158
 
 
159
    for (int i=0; i<blockListListeners.size(); ++i) {
 
160
        RS_BlockListListener* l = blockListListeners.at(i);
 
161
        l->blockRemoved(block);
 
162
    }
 
163
                
 
164
        setModified(true);
 
165
 
 
166
    // / *
 
167
    // activate an other block if necessary:
 
168
    if (activeBlock==block) {
 
169
        //activate(blocks.first());
 
170
                activeBlock = NULL;
 
171
        }
 
172
    // * /
 
173
 
 
174
    // now it's save to delete the block
 
175
    if (owner) {
 
176
        delete block;
 
177
    }
 
178
}
 
179
 
 
180
 
 
181
 
 
182
/**
 
183
 * Tries to rename the given block to 'name'. Block names are unique in the
 
184
 * block list.
 
185
 *
 
186
 * @retval true block was successfully renamed.
 
187
 * @retval false block couldn't be renamed.
 
188
 */
 
189
bool RS_BlockList::rename(RS_Block* block, const QString& name) {
 
190
        if (block!=NULL) {
 
191
                if (find(name)==NULL) {
 
192
                        block->setName(name);
 
193
                        setModified(true);
 
194
                        return true;
 
195
                }
 
196
        }
 
197
 
 
198
        return false;
 
199
}
 
200
 
 
201
 
 
202
/**
 
203
 * Changes a block's attributes. The attributes of block 'block'
 
204
 * are copied from block 'source'.
 
205
 * Listeners are notified.
 
206
 */
 
207
/*
 
208
void RS_BlockList::editBlock(RS_Block* block, const RS_Block& source) {
 
209
        *block = source;
 
210
        
 
211
    for (unsigned i=0; i<blockListListeners.count(); ++i) {
 
212
                RS_BlockListListener* l = blockListListeners.at(i);
 
213
 
 
214
                l->blockEdited(block);
 
215
        }
 
216
}
 
217
*/
 
218
 
 
219
 
 
220
 
 
221
/**
 
222
 * @return Pointer to the block with the given name or
 
223
 * \p NULL if no such block was found.
 
224
 */
 
225
RS_Block* RS_BlockList::find(const QString& name) {
 
226
    //RS_DEBUG->print("RS_BlockList::find");
 
227
        RS_Block* ret = NULL;
 
228
// Todo : reduce this from O(N) to O(log(N)) complexity based on sorted list or hash
 
229
    for (int i=0; i<count(); ++i) {
 
230
        RS_Block* b = at(i);
 
231
        if (b->getName()==name) {
 
232
            ret=b;
 
233
                        break;
 
234
        }
 
235
    }
 
236
 
 
237
    return ret;
 
238
}
 
239
 
 
240
 
 
241
 
 
242
/**
 
243
 * Finds a new unique block name.
 
244
 *
 
245
 * @param suggestion Suggested name the new name will be based on.
 
246
 */
 
247
QString RS_BlockList::newName(const QString& suggestion) {
 
248
    QString name;
 
249
    for (int i=0; i<1e5; ++i) {
 
250
        name = QString("%1-%2").arg(suggestion).arg(i);
 
251
        if (find(name)==NULL) {
 
252
            return name;
 
253
        }
 
254
    }
 
255
 
 
256
    return "0";
 
257
}
 
258
 
 
259
 
 
260
 
 
261
/**
 
262
 * Switches on / off the given block. 
 
263
 * Listeners are notified.
 
264
 */
 
265
void RS_BlockList::toggle(const QString& name) {
 
266
    toggle(find(name));
 
267
}
 
268
 
 
269
 
 
270
 
 
271
/**
 
272
 * Switches on / off the given block. 
 
273
 * Listeners are notified.
 
274
 */
 
275
void RS_BlockList::toggle(RS_Block* block) {
 
276
    if (block==NULL) {
 
277
        return;
 
278
    }
 
279
 
 
280
    block->toggle();
 
281
    // TODO LordOfBikes: when block attributes are saved, activate this
 
282
    //setModified(true);
 
283
 
 
284
    // Notify listeners:
 
285
    for (int i=0; i<blockListListeners.size(); ++i) {
 
286
        RS_BlockListListener* l = blockListListeners.at(i);
 
287
 
 
288
        l->blockToggled(block);
 
289
    }
 
290
}
 
291
 
 
292
 
 
293
 
 
294
/**
 
295
 * Freezes or defreezes all blocks.
 
296
 *
 
297
 * @param freeze true: freeze, false: defreeze
 
298
 */
 
299
void RS_BlockList::freezeAll(bool freeze) {
 
300
 
 
301
    for (int l=0; l<count(); l++) {
 
302
        at(l)->freeze(freeze);
 
303
    }
 
304
    // TODO LordOfBikes: when block attributes are saved, activate this
 
305
    //setModified(true);
 
306
 
 
307
    for (int i=0; i<blockListListeners.size(); ++i) {
 
308
        RS_BlockListListener* l = blockListListeners.at(i);
 
309
        l->blockToggled(NULL);
 
310
    }
 
311
}
 
312
 
 
313
 
 
314
 
 
315
/**
 
316
 * Switches on / off the given block. 
 
317
 * Listeners are notified.
 
318
 */
 
319
/*
 
320
void RS_BlockList::toggleBlock(const QString& name) {
 
321
        RS_Block* block = findBlock(name);
 
322
        block->toggle();
 
323
        
 
324
    // Notify listeners:
 
325
    for (unsigned i=0; i<blockListListeners.count(); ++i) {
 
326
                RS_BlockListListener* l = blockListListeners.at(i);
 
327
 
 
328
                l->blockToggled(block);
 
329
        }
 
330
}
 
331
*/
 
332
 
 
333
 
 
334
/**
 
335
 * adds a BlockListListener to the list of listeners. Listeners
 
336
 * are notified when the block list changes.
 
337
 */
 
338
void RS_BlockList::addListener(RS_BlockListListener* listener) {
 
339
    blockListListeners.append(listener);
 
340
}
 
341
 
 
342
 
 
343
 
 
344
/**
 
345
 * removes a BlockListListener from the list of listeners. 
 
346
 */
 
347
void RS_BlockList::removeListener(RS_BlockListListener* listener) {
 
348
#if QT_VERSION < 0x040400
 
349
    emu_qt44_removeOne(blockListListeners, listener);
 
350
#else
 
351
    blockListListeners.removeOne(listener);
 
352
#endif
 
353
}
 
354
 
 
355
 
 
356
 
 
357
/**
 
358
 * Dumps the blocks to stdout.
 
359
 */
 
360
std::ostream& operator << (std::ostream& os, RS_BlockList& b) {
 
361
 
 
362
    os << "Blocklist: \n";
 
363
    for (int i=0; i<b.count(); ++i) {
 
364
        RS_Block* blk = b.at(i);
 
365
 
 
366
        os << *blk << "\n";
 
367
    }
 
368
 
 
369
    return os;
 
370
}
 
371