]> Shamusworld >> Repos - architektonas/blob - src/base/rs_blocklist.cpp
fd5dbf59db5296058c1899ddbbe7d8e0912ce862
[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         RS_Block * ret = NULL;
238
239         for(uint i=0; i<count(); ++i)
240         {
241                 RS_Block * b = at(i);
242
243                 if (b->getName() == name)
244                 {
245                         ret = b;
246                         break;
247                 }
248         }
249
250         return ret;
251 }
252
253 /**
254  * Finds a new unique block name.
255  *
256  * @param suggestion Suggested name the new name will be based on.
257  */
258 QString RS_BlockList::newName(const QString & suggestion)
259 {
260         QString name;
261
262         for(int i=0; i<1e5; ++i)
263         {
264                 name = QString("%1-%2").arg(suggestion).arg(i);
265
266                 if (find(name) == NULL)
267                         return name;
268         }
269
270         return "0";
271 }
272
273 /**
274  * Switches on / off the given block.
275  * Listeners are notified.
276  */
277 void RS_BlockList::toggle(const QString & name)
278 {
279         toggle(find(name));
280 }
281
282 /**
283  * Switches on / off the given block.
284  * Listeners are notified.
285  */
286 void RS_BlockList::toggle(RS_Block * block)
287 {
288         if (block == NULL)
289                 return;
290
291         block->toggle();
292
293         // Notify listeners:
294         for(int i=0; i<blockListListeners.count(); ++i)
295         {
296                 RS_BlockListListener * l = blockListListeners.at(i);
297
298                 l->blockToggled(block);
299         }
300 }
301
302 /**
303  * Freezes or defreezes all blocks.
304  *
305  * @param freeze true: freeze, false: defreeze
306  */
307 void RS_BlockList::freezeAll(bool freeze)
308 {
309         for(uint l=0; l<count(); l++)
310                 at(l)->freeze(freeze);
311
312         for(int i=0; i<blockListListeners.count(); ++i)
313         {
314                 RS_BlockListListener * l = blockListListeners.at(i);
315                 l->blockToggled(NULL);
316         }
317 }
318
319 /**
320  * Switches on / off the given block.
321  * Listeners are notified.
322  */
323 /*
324 void RS_BlockList::toggleBlock(const QString& name) {
325         RS_Block* block = findBlock(name);
326         block->toggle();
327
328     // Notify listeners:
329         for (uint i=0; i<blockListListeners.count(); ++i) {
330                 RS_BlockListListener* l = blockListListeners.at(i);
331
332                 l->blockToggled(block);
333         }
334 }
335 */
336
337 /**
338  * adds a BlockListListener to the list of listeners. Listeners
339  * are notified when the block list changes.
340  */
341 void RS_BlockList::addListener(RS_BlockListListener * listener)
342 {
343         blockListListeners.append(listener);
344 }
345
346 /**
347  * removes a BlockListListener from the list of listeners.
348  */
349 void RS_BlockList::removeListener(RS_BlockListListener * listener)
350 {
351 //      blockListListeners.remove(listener);
352         blockListListeners.removeAll(listener);
353 }
354
355 /**
356  * Sets the layer lists modified status to 'm'.
357  */
358 void RS_BlockList::setModified(bool m)
359 {
360         modified = m;
361 }
362
363 /**
364  * @retval true The layer list has been modified.
365  * @retval false The layer list has not been modified.
366  */
367 /*virtual*/ bool RS_BlockList::isModified() const
368 {
369         return modified;
370 }
371
372 /**
373  * Dumps the blocks to stdout.
374  */
375 std::ostream & operator<<(std::ostream & os, RS_BlockList & b)
376 {
377         os << "Blocklist: \n";
378
379         for(uint i=0; i<b.count(); ++i)
380         {
381                 RS_Block * blk = b.at(i);
382
383                 os << *blk << "\n";
384         }
385
386         return os;
387 }
388