1 /*
2 SPDX-FileCopyrightText: 2009 Joris Guisson <joris.guisson@gmail.com>
3 SPDX-License-Identifier: GPL-2.0-or-later
4 */
5
6 #include <KLocalizedString>
7 #include <QComboBox>
8
9 #include "shutdowntorrentmodel.h"
10 #include <interfaces/coreinterface.h>
11 #include <torrent/queuemanager.h>
12
13 namespace kt
14 {
ShutdownTorrentModel(CoreInterface * core,QObject * parent)15 ShutdownTorrentModel::ShutdownTorrentModel(CoreInterface *core, QObject *parent)
16 : QAbstractTableModel(parent)
17 , qman(core->getQueueManager())
18 {
19 for (kt::QueueManager::iterator i = qman->begin(); i != qman->end(); i++) {
20 TriggerItem cond;
21 cond.checked = false;
22 cond.tc = *i;
23 cond.trigger = DOWNLOADING_COMPLETED;
24 conds.append(cond);
25 }
26
27 connect(core, &CoreInterface::torrentAdded, this, &ShutdownTorrentModel::torrentAdded);
28 connect(core, &CoreInterface::torrentRemoved, this, &ShutdownTorrentModel::torrentRemoved);
29 }
30
~ShutdownTorrentModel()31 ShutdownTorrentModel::~ShutdownTorrentModel()
32 {
33 }
34
torrentAdded(bt::TorrentInterface * tc)35 void ShutdownTorrentModel::torrentAdded(bt::TorrentInterface *tc)
36 {
37 TriggerItem cond;
38 cond.checked = false;
39 cond.tc = tc;
40 cond.trigger = DOWNLOADING_COMPLETED;
41 conds.append(cond);
42 insertRow(conds.count() - 1);
43 }
44
torrentRemoved(bt::TorrentInterface * tc)45 void ShutdownTorrentModel::torrentRemoved(bt::TorrentInterface *tc)
46 {
47 int idx = 0;
48 for (const TriggerItem &c : qAsConst(conds)) {
49 if (c.tc == tc) {
50 removeRow(idx);
51 break;
52 }
53 idx++;
54 }
55 }
56
data(const QModelIndex & index,int role) const57 QVariant ShutdownTorrentModel::data(const QModelIndex &index, int role) const
58 {
59 if (!index.isValid() || index.row() < 0 || index.row() >= conds.count())
60 return QVariant();
61
62 if (role == Qt::CheckStateRole) {
63 if (index.column() != 0)
64 return QVariant();
65
66 return conds.at(index.row()).checked ? Qt::Checked : Qt::Unchecked;
67 } else if (role == Qt::DisplayRole) {
68 const TriggerItem &cond = conds.at(index.row());
69 switch (index.column()) {
70 case 0:
71 return cond.tc->getDisplayName();
72 case 1:
73 if (cond.trigger == DOWNLOADING_COMPLETED)
74 return i18n("Downloading finishes");
75 else
76 return i18n("Seeding finishes");
77 default:
78 return QVariant();
79 }
80 } else if (role == Qt::EditRole) {
81 if (index.column() == 1)
82 return conds.at(index.row()).trigger;
83 }
84
85 return QVariant();
86 }
87
columnCount(const QModelIndex & parent) const88 int ShutdownTorrentModel::columnCount(const QModelIndex &parent) const
89 {
90 return parent.isValid() ? 0 : 2;
91 }
92
rowCount(const QModelIndex & parent) const93 int ShutdownTorrentModel::rowCount(const QModelIndex &parent) const
94 {
95 return parent.isValid() ? 0 : qman->count();
96 }
97
setData(const QModelIndex & index,const QVariant & value,int role)98 bool ShutdownTorrentModel::setData(const QModelIndex &index, const QVariant &value, int role)
99 {
100 if (!index.isValid() || index.row() < 0 || index.row() >= conds.count())
101 return false;
102
103 if (role == Qt::CheckStateRole) {
104 TriggerItem &cond = conds[index.row()];
105 Qt::CheckState checked = static_cast<Qt::CheckState>(value.toInt());
106 cond.checked = checked == Qt::Checked;
107 Q_EMIT dataChanged(index, index);
108 return true;
109 } else if (role == Qt::EditRole) {
110 int v = value.toInt();
111 if (v < 0 || v > 1)
112 return false;
113
114 Trigger trigger = (Trigger)v;
115 TriggerItem &cond = conds[index.row()];
116 cond.trigger = trigger;
117 Q_EMIT dataChanged(index, index);
118 return true;
119 }
120 return false;
121 }
122
headerData(int section,Qt::Orientation orientation,int role) const123 QVariant ShutdownTorrentModel::headerData(int section, Qt::Orientation orientation, int role) const
124 {
125 if (role != Qt::DisplayRole || orientation != Qt::Horizontal)
126 return QVariant();
127
128 switch (section) {
129 case 0:
130 return i18n("Torrent");
131 case 1:
132 return i18n("Event");
133 default:
134 return QVariant();
135 }
136 }
137
insertRows(int row,int count,const QModelIndex & parent)138 bool ShutdownTorrentModel::insertRows(int row, int count, const QModelIndex &parent)
139 {
140 Q_UNUSED(parent);
141 beginInsertRows(QModelIndex(), row, row + count - 1);
142 endInsertRows();
143 return true;
144 }
145
removeRows(int row,int count,const QModelIndex & parent)146 bool ShutdownTorrentModel::removeRows(int row, int count, const QModelIndex &parent)
147 {
148 Q_UNUSED(parent);
149 beginRemoveRows(QModelIndex(), row, row + count - 1);
150 for (int i = 0; i < count; i++) {
151 conds.takeAt(row);
152 }
153 endRemoveRows();
154 return true;
155 }
156
flags(const QModelIndex & index) const157 Qt::ItemFlags ShutdownTorrentModel::flags(const QModelIndex &index) const
158 {
159 if (!index.isValid() || index.row() < 0 || index.row() >= conds.count())
160 return {};
161
162 Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
163 if (index.column() == 0)
164 flags |= Qt::ItemIsUserCheckable;
165
166 if (index.column() == 1)
167 flags |= Qt::ItemIsEditable;
168
169 return flags;
170 }
171
applyRules(Action action,kt::ShutdownRuleSet * rules)172 void ShutdownTorrentModel::applyRules(Action action, kt::ShutdownRuleSet *rules)
173 {
174 rules->clear();
175 for (const TriggerItem &c : qAsConst(conds)) {
176 if (c.checked)
177 rules->addRule(action, SPECIFIC_TORRENT, c.trigger, c.tc);
178 }
179 }
180
addRule(const kt::ShutdownRule & rule)181 void ShutdownTorrentModel::addRule(const kt::ShutdownRule &rule)
182 {
183 QList<TriggerItem>::iterator i = conds.begin();
184 while (i != conds.end()) {
185 TriggerItem &c = *i;
186 if (c.tc == rule.tc) {
187 c.checked = true;
188 c.trigger = rule.trigger;
189 break;
190 }
191 i++;
192 }
193 }
194
195 //////////////////////////////////////////////////////
196
ShutdownTorrentDelegate(QObject * parent)197 ShutdownTorrentDelegate::ShutdownTorrentDelegate(QObject *parent)
198 : QStyledItemDelegate(parent)
199 {
200 }
201
~ShutdownTorrentDelegate()202 ShutdownTorrentDelegate::~ShutdownTorrentDelegate()
203 {
204 }
205
createEditor(QWidget * parent,const QStyleOptionViewItem & option,const QModelIndex & index) const206 QWidget *ShutdownTorrentDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
207 {
208 Q_UNUSED(option);
209 Q_UNUSED(index);
210 QComboBox *cb = new QComboBox(parent);
211 cb->addItem(i18n("Downloading finishes"));
212 cb->addItem(i18n("Seeding finishes"));
213 return cb;
214 }
215
setEditorData(QWidget * editor,const QModelIndex & index) const216 void ShutdownTorrentDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
217 {
218 int value = index.model()->data(index, Qt::EditRole).toInt();
219 QComboBox *cb = static_cast<QComboBox *>(editor);
220 cb->setCurrentIndex(value);
221 }
222
setModelData(QWidget * editor,QAbstractItemModel * model,const QModelIndex & index) const223 void ShutdownTorrentDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
224 {
225 QComboBox *cb = static_cast<QComboBox *>(editor);
226 int value = cb->currentIndex();
227 model->setData(index, value, Qt::EditRole);
228 }
229
sizeHint(const QStyleOptionViewItem & option,const QModelIndex & index) const230 QSize ShutdownTorrentDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
231 {
232 Q_UNUSED(option);
233 Q_UNUSED(index);
234 QComboBox tmp;
235 return tmp.sizeHint();
236 }
237
updateEditorGeometry(QWidget * editor,const QStyleOptionViewItem & option,const QModelIndex & index) const238 void ShutdownTorrentDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
239 {
240 Q_UNUSED(index);
241 QRect r = option.rect;
242 if (option.rect.height() < editor->sizeHint().height())
243 r.setHeight(editor->sizeHint().height());
244 editor->setGeometry(r);
245 }
246
247 }
248