1 /*-
2 * Copyright (c) 2016 Marcel Kaiser. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25 #include <QVBoxLayout>
26
27 #include "list.h"
28 #include "desktopfile.h"
29 #include "qt-helper/qt-helper.h"
30
List(dsbautostart_t * as,QWidget * parent)31 List::List(dsbautostart_t *as, QWidget *parent)
32 : QWidget(parent) {
33
34 list = new ListWidget(parent);
35 list->setMouseTracking(true);
36 this->as = as;
37
38 QVBoxLayout *vbox = new QVBoxLayout;
39 vbox->addWidget(list);
40 setLayout(vbox);
41 list->setToolTip(QString(tr("Double click to edit.\n" \
42 "Use checkbox to activate/deactivate a command.\n" \
43 "Use Drag & Drop to add desktop files.")));
44 if ((ascp = dsbautostart_copy(as)) == NULL) {
45 if (dsbautostart_error()) {
46 qh_err(this, EXIT_FAILURE, "%s",
47 dsbautostart_strerror());
48 }
49 }
50 for (entry_t *entry = as->entry; entry != NULL; entry = entry->next)
51 addItem(entry);
52 _modified = false;
53 connect(list, SIGNAL(itemChanged(QListWidgetItem *)), this,
54 SLOT(catchItemChanged(QListWidgetItem *)));
55 connect(list, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this,
56 SLOT(catchDoubleClicked(QListWidgetItem *)));
57 connect(list, SIGNAL(itemDroped(QStringList &)), this,
58 SLOT(addDesktopFiles(QStringList &)));
59 connect(list, SIGNAL(deleteKeyPressed()), this, SLOT(delItem()));
60 }
61
62 bool
modified()63 List::modified()
64 {
65 return (_modified);
66 }
67
68 void
unsetModified()69 List::unsetModified()
70 {
71 dsbautostart_free(ascp);
72 if ((ascp = dsbautostart_copy(as)) == NULL) {
73 if (dsbautostart_error()) {
74 qh_err(this, EXIT_FAILURE, "%s",
75 dsbautostart_strerror());
76 }
77 }
78 _modified = false;
79 }
80
81 void
newItem()82 List::newItem()
83 {
84 entry_t *entry = dsbautostart_add_entry(as, "", true);
85
86 if (entry == NULL)
87 qh_errx(this, EXIT_FAILURE, "%s", dsbautostart_strerror());
88 QListWidgetItem *item = List::addItem(entry);
89 list->editItem(item);
90 compare();
91 }
92
93 QListWidgetItem *
addItem(entry_t * entry)94 List::addItem(entry_t *entry)
95 {
96 QListWidgetItem *item = new QListWidgetItem(entry->cmd);
97 item->setFlags(Qt::ItemIsEditable | Qt::ItemIsUserCheckable |
98 Qt::ItemIsSelectable | Qt::ItemIsEnabled);
99 item->setCheckState(entry->active ? Qt::Checked : Qt::Unchecked);
100 item->setData(Qt::UserRole, qVariantFromValue((void *)entry));
101 list->addItem(item);
102 items.append(item);
103
104 return (item);
105 }
106
107 void
catchItemChanged(QListWidgetItem * item)108 List::catchItemChanged(QListWidgetItem *item)
109 {
110 updateItem(item);
111 compare();
112 }
113
114 void
catchDoubleClicked(QListWidgetItem * item)115 List::catchDoubleClicked(QListWidgetItem *item)
116 {
117 list->editItem(item);
118 list->setCurrentItem(item, QItemSelectionModel::Deselect);
119 }
120
121 void
delItem()122 List::delItem()
123 {
124 entry_t *entry;
125 QListWidgetItem *item = list->currentItem();
126
127 if (item == 0)
128 return;
129 entry = (entry_t *)item->data(Qt::UserRole).value<void *>();
130 if (dsbautostart_del_entry(as, entry) == NULL)
131 qh_errx(this, EXIT_FAILURE, "%s", dsbautostart_strerror());
132 list->removeItemWidget(item);
133 items.removeOne(item);
134 delete item;
135 compare();
136 }
137
138 void
moveItemUp()139 List::moveItemUp()
140 {
141 int row;
142 entry_t *entry;
143 QListWidgetItem *item = list->currentItem();
144
145 if (item == 0)
146 return;
147 entry = (entry_t *)item->data(Qt::UserRole).value<void *>();
148 if (dsbautostart_entry_move_up(as, entry) == NULL)
149 qh_errx(this, EXIT_FAILURE, "%s", dsbautostart_strerror());
150 row = list->currentRow();
151 if (row == 0)
152 return;
153 list->takeItem(row);
154 list->insertItem(--row, item);
155 list->setCurrentRow(row);
156 compare();
157 }
158
159 void
moveItemDown()160 List::moveItemDown()
161 {
162 int row;
163 entry_t *entry;
164 QListWidgetItem *item = list->currentItem();
165
166 if (item == 0)
167 return;
168 entry = (entry_t *)item->data(Qt::UserRole).value<void *>();
169 if (dsbautostart_entry_move_down(as, entry) == NULL)
170 qh_errx(this, EXIT_FAILURE, "%s", dsbautostart_strerror());
171 row = list->currentRow();
172
173 if (list->count() - 1 == row)
174 return;
175 list->takeItem(row);
176 list->insertItem(++row, item);
177 list->setCurrentRow(row);
178 compare();
179 }
180
181 void
updateItem(QListWidgetItem * item)182 List::updateItem(QListWidgetItem *item)
183 {
184 bool cbstate = item->checkState() == Qt::Unchecked ? false : true;
185 entry_t *entry;
186
187 entry = (entry_t *)item->data(Qt::UserRole).value<void *>();
188 if (dsbautostart_set(as, entry, item->text().toUtf8().constData(),
189 cbstate) == -1)
190 qh_errx(this, EXIT_FAILURE, "%s", dsbautostart_strerror());
191 compare();
192 }
193
194 void
update()195 List::update()
196 {
197 for (int i = 0; i < items.size(); i++)
198 updateItem(items.at(i));
199 }
200
201 void
undo()202 List::undo()
203 {
204 dsbautostart_undo(as);
205 list->clear();
206 items.clear();
207 for (entry_t *entry = as->entry; entry != NULL; entry = entry->next)
208 addItem(entry);
209 compare();
210 }
211
212 void
redo()213 List::redo()
214 {
215 dsbautostart_redo(as);
216 list->clear();
217 items.clear();
218 for (entry_t *entry = as->entry; entry != NULL; entry = entry->next)
219 addItem(entry);
220 compare();
221 }
222
223 bool
canUndo()224 List::canUndo()
225 {
226 return (dsbautostart_can_undo(as));
227 }
228
229 bool
canRedo()230 List::canRedo()
231 {
232
233 return (dsbautostart_can_redo(as));
234 }
235
236 void
compare()237 List::compare()
238 {
239 if (!dsbautostart_cmp(ascp, as)) {
240 emit listModified(true);
241 _modified = true;
242 } else {
243 _modified = false;
244 emit listModified(false);
245 }
246 }
247
248 void
addDesktopFiles(QStringList & list)249 List::addDesktopFiles(QStringList &list)
250 {
251 entry_t *entry;
252
253 for (QString s : list) {
254 DesktopFile df(s);
255 if (df.read() == -1)
256 continue;
257 entry = dsbautostart_add_entry(as, df.cmd.toLocal8Bit().data(), true);
258 if (entry == NULL) {
259 qh_errx(this, EXIT_FAILURE, "%s",
260 dsbautostart_strerror());
261 }
262 List::addItem(entry);
263 }
264 compare();
265 }
266