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