]> Shamusworld >> Repos - architektonas/blob - src/base/rs_blocklist.cpp
GPL compliance check...
[architektonas] / src / base / rs_blocklist.cpp
1 // rs_blocklist.cpp
2 //
3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // Portions copyright (C) 2001-2003 RibbonSoft
7 // Copyright (C) 2010 Underground Software
8 // See the README and GPLv2 files for licensing and warranty information
9 //
10 // JLH = James L. Hammons <jlhamm@acm.org>
11 //
12 // Who  When        What
13 // ---  ----------  -----------------------------------------------------------
14 // JLH  05/28/2010  Added this text. :-)
15 //
16
17 #include "rs_blocklist.h"
18
19 /**
20  * Constructor.
21  *
22  * @param owner true if this is the owner of the blocks added.
23  *              If so, the blocks will be deleted when the block
24  *              list is deleted.
25  */
26 RS_BlockList::RS_BlockList(bool owner)
27 {
28         this->owner = owner;
29         //blocks.setAutoDelete(owner);
30 //OK, this is good. We don't have to fuck with this shit.
31 //      blocks.setAutoDelete(false);
32 //      blockListListeners.setAutoDelete(false);
33         activeBlock = NULL;
34         setModified(false);
35 }
36
37 /*virtual*/ RS_BlockList::~RS_BlockList()
38 {
39 }
40
41 /**
42  * Removes all blocks in the blocklist.
43  */
44 void RS_BlockList::clear()
45 {
46         blocks.clear();
47         setModified(true);
48 }
49
50 /**
51  * @return Number of blocks available.
52  */
53 uint RS_BlockList::count()
54 {
55         return blocks.count();
56 }
57
58 /**
59  * @return Block at given position or NULL if i is out of range.
60  */
61 RS_Block * RS_BlockList::at(uint i)
62 {
63         return blocks.at(i);
64 }
65
66 /**
67  * Activates the given block.
68  * Listeners are notified.
69  */
70 void RS_BlockList::activate(const QString & name)
71 {
72         RS_DEBUG->print("RS_BlockList::activateBlock");
73
74         activate(find(name));
75 }
76
77 /**
78  * Activates the given block.
79  * Listeners are notified.
80  */
81 void RS_BlockList::activate(RS_Block * block)
82 {
83         RS_DEBUG->print("RS_BlockList::activateBlock");
84         activeBlock = block;
85
86         /*
87                 for (uint i=0; i<blockListListeners.count(); ++i) {
88                         RS_BlockListListener* l = blockListListeners.at(i);
89                 if (l!=NULL) {
90                         l->blockActivated(activeBlock);
91                 }
92                 }
93         */
94 }
95
96 //! @return The active block of NULL if no block is activated.
97 RS_Block * RS_BlockList::getActive()
98 {
99         return activeBlock;
100 }
101
102 /**
103  * Adds a block to the block list. If a block with the same name
104  * exists already, the given block will be deleted if the blocklist
105  * owns the blocks.
106  *
107  * @param notify true if you want listeners to be notified.
108  *
109  * @return false: block already existed and was deleted.
110  */
111 bool RS_BlockList::add(RS_Block * block, bool notify)
112 {
113         RS_DEBUG->print("RS_BlockList::add()");
114
115         if (block == NULL)
116                 return false;
117
118         // check if block already exists:
119         RS_Block * b = find(block->getName());
120
121         if (b == NULL)
122         {
123                 blocks.append(block);
124
125                 if (notify)
126                         addNotification();
127
128                 setModified(true);
129
130                 return true;
131         }
132         else
133         {
134                 if (owner)
135                 {
136                         delete block;
137                         block = NULL;
138                 }
139
140                 return false;
141         }
142 }
143
144 /**
145  * Notifies the listeners about blocks that were added. This can be
146  * used after adding a lot of blocks without auto-update or simply
147  * to force an update of GUI blocklists.
148  */
149 void RS_BlockList::addNotification()
150 {
151         for(int i=0; i<blockListListeners.count(); ++i)
152         {
153                 RS_BlockListListener * l = blockListListeners.at(i);
154                 l->blockAdded(NULL);
155         }
156 }
157
158 /**
159  * Removes a block from the list.
160  * Listeners are notified after the block was removed from
161  * the list but before it gets deleted.
162  */
163 void RS_BlockList::remove(RS_Block * block)
164 {
165         RS_DEBUG->print("RS_BlockList::removeBlock()");
166
167         // here the block is removed from the list but not deleted
168 //      blocks.remove(block);
169         blocks.removeAll(block);
170
171         for(int i=0; i<blockListListeners.count(); ++i)
172         {
173                 RS_BlockListListener * l = blockListListeners.at(i);
174                 l->blockRemoved(block);
175         }
176
177         setModified(true);
178
179         // / *
180         // activate an other block if necessary:
181         if (activeBlock == block)
182         {
183                 //activate(blocks.first());
184                 activeBlock = NULL;
185         }
186         // * /
187
188         // now it's safe to delete the block
189         if (owner)
190                 delete block;
191 }
192
193 /**
194  * Tries to rename the given block to 'name'. Block names are unique in the
195  * block list.
196  *
197  * @retval true block was successfully renamed.
198  * @retval false block couldn't be renamed.
199  */
200 bool RS_BlockList::rename(RS_Block * block, const QString & name)
201 {
202         if (block != NULL)
203         {
204                 if (find(name) == NULL)
205                 {
206                         block->setName(name);
207                         setModified(true);
208                         return true;
209                 }
210         }
211
212         return false;
213 }
214
215 /**
216  * Changes a block's attributes. The attributes of block 'block'
217  * are copied from block 'source'.
218  * Listeners are notified.
219  */
220 /*
221 void RS_BlockList::editBlock(RS_Block* block, const RS_Block& source) {
222         *block = source;
223
224         for (uint i=0; i<blockListListeners.count(); ++i) {
225                 RS_BlockListListener* l = blockListListeners.at(i);
226
227                 l->blockEdited(block);
228         }
229 }
230 */
231
232 /**
233  * @return Pointer to the block with the given name or
234  * \p NULL if no such block was found.
235  */
236 RS_Block * RS_BlockList::find(const QString & name)
237 {
238         //RS_DEBUG->print("RS_BlockList::find");
239
240         for(uint i=0; i<count(); i++)
241         {
242                 RS_Block * b = at(i);
243
244                 if (b->getName() == name)
245                         return b;
246         }
247
248         return NULL;
249 }
250
251 /**
252  * Finds a new unique block name.
253  *
254  * @param suggestion Suggested name the new name will be based on.
255  */
256 QString RS_BlockList::newName(const QString & suggestion)
257 {
258         QString name;
259
260         for(int i=0; i<1e5; ++i)
261         {
262                 name = QString("%1-%2").arg(suggestion).arg(i);
263
264                 if (find(name) == NULL)
265                         return name;
266         }
267
268         return "0";
269 }
270
271 /**
272  * Switches on / off the given block.
273  * Listeners are notified.
274  */
275 void RS_BlockList::toggle(const QString & name)
276 {
277         toggle(find(name));
278 }
279
280 /**
281  * Switches on / off the given block.
282  * Listeners are notified.
283  */
284 void RS_BlockList::toggle(RS_Block * block)
285 {
286         if (block == NULL)
287                 return;
288
289         block->toggle();
290
291         // Notify listeners:
292         for(int i=0; i<blockListListeners.count(); ++i)
293         {
294                 RS_BlockListListener * l = blockListListeners.at(i);
295
296                 l->blockToggled(block);
297         }
298 }
299
300 /**
301  * Freezes or defreezes all blocks.
302  *
303  * @param freeze true: freeze, false: defreeze
304  */
305 void RS_BlockList::freezeAll(bool freeze)
306 {
307         for(uint l=0; l<count(); l++)
308                 at(l)->freeze(freeze);
309
310         for(int i=0; i<blockListListeners.count(); ++i)
311         {
312                 RS_BlockListListener * l = blockListListeners.at(i);
313                 l->blockToggled(NULL);
314         }
315 }
316
317 /**
318  * Switches on / off the given block.
319  * Listeners are notified.
320  */
321 /*
322 void RS_BlockList::toggleBlock(const QString& name) {
323         RS_Block* block = findBlock(name);
324         block->toggle();
325
326     // Notify listeners:
327         for (uint i=0; i<blockListListeners.count(); ++i) {
328                 RS_BlockListListener* l = blockListListeners.at(i);
329
330                 l->blockToggled(block);
331         }
332 }
333 */
334
335 /**
336  * adds a BlockListListener to the list of listeners. Listeners
337  * are notified when the block list changes.
338  */
339 void RS_BlockList::addListener(RS_BlockListListener * listener)
340 {
341         blockListListeners.append(listener);
342 }
343
344 /**
345  * removes a BlockListListener from the list of listeners.
346  */
347 void RS_BlockList::removeListener(RS_BlockListListener * listener)
348 {
349 //      blockListListeners.remove(listener);
350         blockListListeners.removeAll(listener);
351 }
352
353 /**
354  * Sets the layer lists modified status to 'm'.
355  */
356 void RS_BlockList::setModified(bool m)
357 {
358         modified = m;
359 }
360
361 /**
362  * @retval true The layer list has been modified.
363  * @retval false The layer list has not been modified.
364  */
365 /*virtual*/ bool RS_BlockList::isModified() const
366 {
367         return modified;
368 }
369
370 /**
371  * Dumps the blocks to stdout.
372  */
373 std::ostream & operator<<(std::ostream & os, RS_BlockList & b)
374 {
375         os << "Blocklist: \n";
376
377         for(uint i=0; i<b.count(); ++i)
378         {
379                 RS_Block * blk = b.at(i);
380
381                 os << *blk << "\n";
382         }
383
384         return os;
385 }
386