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