]> Shamusworld >> Repos - architektonas/blob - src/layerwidget.cpp
Whitespace changes. :-P
[architektonas] / src / layerwidget.cpp
1 //
2 // layerwidget.cpp: Layer add/remove/use widget
3 //
4 // Part of the Architektonas Project
5 // (C) 2011 Underground Software
6 // See the README and GPLv3 files for licensing and warranty information
7 //
8 // JLH = James Hammons <jlhamm@acm.org>
9 //
10 // WHO  WHEN        WHAT
11 // ---  ----------  ------------------------------------------------------------
12 // JLH  07/11/2013  Created this file
13 //
14
15 #include "layerwidget.h"
16 #include "global.h"
17 #include "layeritemwidget.h"
18
19 LayerWidget::LayerWidget(void): QWidget(),
20         addLayer(new QToolButton), removeLayer(new QToolButton),
21         editLayer(new QToolButton), layerUp(new QToolButton),
22         layerDown(new QToolButton), list(new QListWidget)
23 {
24         QListWidgetItem * qlwi = new QListWidgetItem(list);
25         LayerItemWidget * liw = new LayerItemWidget("Background", false, false, qlwi);
26         list->setItemWidget(qlwi, liw);
27
28         addLayer->setIcon(QIcon(":/res/layer-add.png"));
29         removeLayer->setIcon(QIcon(":/res/layer-delete.png"));
30         editLayer->setIcon(QIcon(":/res/layer-edit.png"));
31         layerUp->setIcon(QIcon(":/res/layer-up.png"));
32         layerDown->setIcon(QIcon(":/res/layer-down.png"));
33
34         addLayer->setToolTip(tr("Add layer"));
35         removeLayer->setToolTip(tr("Remove layer"));
36         editLayer->setToolTip(tr("Edit layer"));
37         layerUp->setToolTip(tr("Move layer up"));
38         layerDown->setToolTip(tr("Move layer down"));
39
40         QHBoxLayout * hbox1 = new QHBoxLayout;
41         hbox1->addWidget(addLayer);
42         hbox1->addWidget(removeLayer);
43         hbox1->addWidget(editLayer);
44         hbox1->addWidget(layerUp);
45         hbox1->addWidget(layerDown);
46         hbox1->addStretch();
47
48         QVBoxLayout * mainLayout = new QVBoxLayout;
49         mainLayout->addWidget(list);
50         mainLayout->addLayout(hbox1);
51
52         setLayout(mainLayout);
53
54         connect(list, SIGNAL(currentRowChanged(int)), this, SLOT(HandleLayerSelected(int)));
55         connect(list, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(HandleDblClick(QListWidgetItem *)));
56         connect(addLayer, SIGNAL(clicked()), this, SLOT(AddLayer()));
57         connect(removeLayer, SIGNAL(clicked()), this, SLOT(DeleteLayer()));
58         connect(editLayer, SIGNAL(clicked()), this, SLOT(EditLayer()));
59         connect(layerUp, SIGNAL(clicked()), this, SLOT(MoveLayerUp()));
60         connect(layerDown, SIGNAL(clicked()), this, SLOT(MoveLayerDown()));
61
62         connect(liw, SIGNAL(HideToggled(QListWidgetItem *, bool)), this, SLOT(HandleHideToggle(QListWidgetItem *, bool)));
63         connect(liw, SIGNAL(LockToggled(QListWidgetItem *, bool)), this, SLOT(HandleLockToggle(QListWidgetItem *, bool)));
64
65         list->setCurrentRow(0);
66
67         // We set global variables here, since we are 'in charge' of them (mostly)
68         Global::activeLayer = 0;
69         Global::numLayers = 1;
70         Global::layerHidden.clear();
71         Global::layerLocked.clear();
72         Global::layerName.clear();
73         Global::layerHidden.push_back(false);
74         Global::layerLocked.push_back(false);
75         Global::layerName.push_back("Background");
76 }
77
78 LayerWidget::~LayerWidget()
79 {
80 }
81
82 void LayerWidget::Reload(void)
83 {
84         list->clear();
85
86         for(int i=0; i<Global::numLayers; i++)
87         {
88                 QListWidgetItem * qlwi = new QListWidgetItem();
89                 LayerItemWidget * liw = new LayerItemWidget(Global::layerName[i].c_str(), Global::layerHidden[i], Global::layerLocked[i], qlwi);
90                 list->insertItem(0, qlwi);
91                 list->setItemWidget(qlwi, liw);
92
93                 // Set up SIGNAL/SLOTs for this LayerItemWidget
94                 connect(liw, SIGNAL(HideToggled(QListWidgetItem *, bool)), this, SLOT(HandleHideToggle(QListWidgetItem *, bool)));
95                 connect(liw, SIGNAL(LockToggled(QListWidgetItem *, bool)), this, SLOT(HandleLockToggle(QListWidgetItem *, bool)));
96         }
97
98         int layer = (Global::numLayers - Global::activeLayer) - 1;
99         list->setCurrentRow(layer, QItemSelectionModel::SelectCurrent);
100         SetButtonStates();
101 }
102
103 void LayerWidget::HandleLayerSelected(int currentRow)
104 {
105         // If LayerWidget is empty, bail out
106         if (currentRow == -1)
107                 return;
108
109         // This is numbered opposite of how it's presented. In other words, the
110         // bottom of the list is 0, and items above it count upwards. So like this:
111         //
112         // (2) Layer #2
113         // (1) Layer #1
114         // (0) Background
115         //
116         // which is the opposite of the internal numbering.
117         Global::activeLayer = (Global::numLayers - currentRow) - 1;
118
119         // Set button states to sane values
120         SetButtonStates();
121 }
122
123 //
124 // What happens here is that for every QListWidgetItem we make, we connect it
125 // to these handlers. But we only have to worry about that when adding and
126 // moving a layer. However, when toggling states, we need to toggle the global
127 // state variables too.
128 //
129 void LayerWidget::HandleHideToggle(QListWidgetItem * qlwi, bool state)
130 {
131         int currentRow = list->row(qlwi);
132         int layer = (Global::numLayers - currentRow) - 1;
133         std::vector<bool>::iterator i = Global::layerHidden.begin() + layer;
134         (*i) = state;
135 //printf("Item #%i, new hide state is %s\n", currentRow, (state ? "ON" : "off"));
136 //printf("LayerWidget: New hide state of layer %i is %s.\n", layer, (state ? "ON" : "off"));
137         // We do this last, because otherwise the Document would get the wrong state
138         emit LayerToggled();
139 }
140
141 void LayerWidget::HandleLockToggle(QListWidgetItem * qlwi, bool state)
142 {
143         int currentRow = list->row(qlwi);
144         int layer = (Global::numLayers - currentRow) - 1;
145         std::vector<bool>::iterator i = Global::layerLocked.begin() + layer;
146         (*i) = state;
147 //      printf("Item #%i, new lock state is %s\n", list->row(qlwi), (state ? "ON" : "off"));
148 }
149
150 void LayerWidget::HandleDblClick(QListWidgetItem * /*qlwi*/)
151 {
152         EditLayer();
153 }
154
155 void LayerWidget::AddLayer(void)
156 {
157         // We always stick the newest layer at the top of the list (visually, the
158         // top of the list is the end, the bottom is the beginning)...
159         int count = list->count();
160         QString text = QString("Layer #%1").arg(count);
161         QListWidgetItem * qlwi = new QListWidgetItem();
162         LayerItemWidget * liw = new LayerItemWidget(text, false, false, qlwi);
163         list->insertItem(0, qlwi);
164         list->setItemWidget(qlwi, liw);
165
166         // Set up SIGNAL/SLOTs for this LayerItemWidget
167         connect(liw, SIGNAL(HideToggled(QListWidgetItem *, bool)), this, SLOT(HandleHideToggle(QListWidgetItem *, bool)));
168         connect(liw, SIGNAL(LockToggled(QListWidgetItem *, bool)), this, SLOT(HandleLockToggle(QListWidgetItem *, bool)));
169
170         SetButtonStates();
171
172         // Fix up the global state
173         Global::layerHidden.push_back(false);
174         Global::layerLocked.push_back(false);
175         Global::layerName.push_back(text.toUtf8().data());
176         Global::numLayers++;
177 }
178
179 void LayerWidget::DeleteLayer(void)
180 {
181         int numItems = list->count();
182
183         if (numItems == 1)
184                 return;
185
186         // N.B.: This *must* go before the item removal because that causes
187         //       HandleLayerSelected() to be fired off which causes the numbers to
188         //       be off. You have been warned!
189         // Tell the DrawingView to delete this layer in its Container:
190         emit LayerDeleted(Global::activeLayer);
191
192         int currentRow = list->currentRow();
193         QListWidgetItem * qlwi = list->currentItem();
194         list->removeItemWidget(qlwi);
195         delete qlwi;
196
197         SetButtonStates();
198
199         // Fix up the global state
200         int layer = (Global::numLayers - currentRow) - 1;
201         Global::layerHidden.erase(Global::layerHidden.begin() + layer);
202         Global::layerLocked.erase(Global::layerLocked.begin() + layer);
203         Global::layerName.erase(Global::layerName.begin() + layer);
204         Global::numLayers--;
205
206         // If we're deleting from the top of the list, we have to decrement the
207         // active layer # by 1 (since we count upward from the bottom of the list).
208         if (currentRow == 0)
209                 Global::activeLayer--;
210 }
211
212 void LayerWidget::EditLayer(void)
213 {
214         // Get the LayerItemWidget so we can edit it (its name, anyway)...
215         QListWidgetItem * qlwi = list->currentItem();
216         LayerItemWidget * li = (LayerItemWidget *)list->itemWidget(qlwi);
217         QString s = li->name->text();
218
219         bool ok;
220         QString result = QInputDialog::getText(this, tr("Edit Layer Name"), tr("Layer Name:"), QLineEdit::Normal, s, &ok);
221
222         if (ok && !result.isEmpty())
223         {
224                 li->name->setText(result);
225
226                 // We don't reverse the layer # here, like elsewhere, because we're
227                 // using the layer # directly instead of having to translate it from
228                 // the widget.
229                 std::vector<std::string>::iterator i = Global::layerName.begin() + Global::activeLayer;
230                 (*i) = result.toUtf8().data();
231         }
232 }
233
234 void LayerWidget::MoveLayerUp(void)
235 {
236         // Get information out of the LayerItemWidget (& get it from the list!)
237         int currentRow = list->currentRow();
238         QListWidgetItem * qlwi = list->currentItem();
239         LayerItemWidget * li = (LayerItemWidget *)list->itemWidget(qlwi);
240         QString s = li->name->text();
241         bool visible = li->invisible->isChecked();
242         bool editible = li->locked->isChecked();
243
244         // We have to make a new LayerItemWidget because it destroys the old one!
245         list->takeItem(currentRow);
246         list->insertItem(currentRow - 1, qlwi);
247         li = new LayerItemWidget(s, visible, editible, qlwi);
248         list->setItemWidget(qlwi, li);
249         list->setCurrentItem(qlwi);
250
251         // Set up SIGNAL/SLOTs for this LayerItemWidget
252         connect(li, SIGNAL(HideToggled(QListWidgetItem *, bool)), this, SLOT(HandleHideToggle(QListWidgetItem *, bool)));
253         connect(li, SIGNAL(LockToggled(QListWidgetItem *, bool)), this, SLOT(HandleLockToggle(QListWidgetItem *, bool)));
254
255         // Fix up the global state...
256         // N.B.: Because we handle the button states correctly, we should never
257         //       have a situation where the reference in the vector is bad.
258         int layer = (Global::numLayers - currentRow) - 1;
259         bool old = Global::layerHidden[layer];
260         Global::layerHidden[layer] = Global::layerHidden[layer + 1];
261         Global::layerHidden[layer + 1] = old;
262         old = Global::layerLocked[layer];
263         Global::layerLocked[layer] = Global::layerLocked[layer + 1];
264         Global::layerLocked[layer + 1] = old;
265         std::string oldStr = Global::layerName[layer];
266         Global::layerName[layer] = Global::layerName[layer + 1];
267         Global::layerName[layer + 1] = oldStr;
268         // We also have to tell the document to shuffle its layers too
269         emit LayersSwapped(layer, layer + 1);
270 }
271
272 void LayerWidget::MoveLayerDown(void)
273 {
274         // Get information out of the LayerItemWidget (& get it from the list!)
275         int currentRow = list->currentRow();
276         QListWidgetItem * qlwi = list->currentItem();
277         LayerItemWidget * li = (LayerItemWidget *)list->itemWidget(qlwi);
278         QString s = li->name->text();
279         bool visible = li->invisible->isChecked();
280         bool editible = li->locked->isChecked();
281
282         // We have to make a new LayerItemWidget because it destroys the old one!
283         list->takeItem(currentRow);
284         list->insertItem(currentRow + 1, qlwi);
285         li = new LayerItemWidget(s, visible, editible, qlwi);
286         list->setItemWidget(qlwi, li);
287         list->setCurrentItem(qlwi);
288
289         // Set up SIGNAL/SLOTs for this LayerItemWidget
290         connect(li, SIGNAL(HideToggled(QListWidgetItem *, bool)), this, SLOT(HandleHideToggle(QListWidgetItem *, bool)));
291         connect(li, SIGNAL(LockToggled(QListWidgetItem *, bool)), this, SLOT(HandleLockToggle(QListWidgetItem *, bool)));
292
293         // Fix up the global state...
294         // N.B.: Because we handle the button states correctly, we should never
295         //       have a situation where the reference in the vector is bad.
296         int layer = (Global::numLayers - currentRow) - 1;
297         bool old = Global::layerHidden[layer];
298         Global::layerHidden[layer] = Global::layerHidden[layer - 1];
299         Global::layerHidden[layer - 1] = old;
300         old = Global::layerLocked[layer];
301         Global::layerLocked[layer] = Global::layerLocked[layer - 1];
302         Global::layerLocked[layer - 1] = old;
303         std::string oldStr = Global::layerName[layer];
304         Global::layerName[layer] = Global::layerName[layer - 1];
305         Global::layerName[layer - 1] = oldStr;
306         // We also have to tell the document to shuffle its layers too
307         emit LayersSwapped(layer, layer - 1);
308 }
309
310 //
311 // Set button states in this widget to sane values
312 //
313 void LayerWidget::SetButtonStates(void)
314 {
315         int numItems = list->count();
316         int currentRow = list->currentRow();
317
318         layerDown->setEnabled(currentRow == (numItems - 1) ? false : true);
319         layerUp->setEnabled(currentRow == 0 ? false : true);
320         removeLayer->setEnabled(numItems == 1 ? false : true);
321 }