Crossfire Server, Trunk
CREMessageItemModel.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 2022 the Crossfire Development Team
5  *
6  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
7  * welcome to redistribute it under certain conditions. For details, please
8  * see COPYING and LICENSE.
9  *
10  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
11  */
12 
13 #include <QtWidgets>
14 
15 #include "CREMessageItemModel.h"
16 
17 CREMessageItemModel::CREMessageItemModel(QObject* parent) : QAbstractItemModel(parent), myMessage(nullptr)
18 {
19 }
20 
22 {
23 }
24 
26 {
27  beginResetModel();
29  endResetModel();
30 }
31 
33 {
34  auto blue(myBlue), red(myRed);
35  myBlue.clear();
36  myRed.clear();
37 
38  int row = index.row();
39  if (row < 0 || row >= myMessage->rules().size())
40  return;
41 
42  MessageRule* rule = myMessage->rules()[row];
43 
44  foreach(QStringList pre, rule->preconditions())
45  {
46  if (pre.size() < 3)
47  continue;
48 
49  if (pre[0] != "token" && pre[0] != "npctoken")
50  continue;
51 
52  QStringList acceptable = pre;
53  acceptable.removeFirst();
54  acceptable.removeFirst();
55 
56  for (int c = 0; c < myMessage->rules().size(); c++)
57  {
59 
60  if (check == rule)
61  continue;
62 
63  bool match = false;
64  foreach(QStringList post, check->postconditions())
65  {
66  if (post.size() < 3)
67  continue;
68  if ((post[0] != "settoken" && post[0] != "setnpctoken") || post[1] != pre[1] || !acceptable.contains(post[2]))
69  continue;
70  match = true;
71  break;
72  }
73 
74  if (match)
75  myRed.insert(c);
76  }
77  }
78 
79  foreach(QStringList post, rule->postconditions())
80  {
81  if (post.size() < 3)
82  continue;
83 
84  if (post[0] != "settoken" && post[0] != "setnpctoken")
85  continue;
86 
87  for (int c = 0; c < myMessage->rules().size(); c++)
88  {
90 
91  if (check == rule)
92  continue;
93 
94  bool match = false;
95  foreach(QStringList pre, check->preconditions())
96  {
97  if (pre.size() < 3)
98  continue;
99  if ((pre[0] != "token" && pre[0] != "npctoken") || pre[1] != post[1])
100  continue;
101 
102  QStringList acceptable = pre;
103  acceptable.removeFirst();
104  acceptable.removeFirst();
105  if (!acceptable.contains(post[2]))
106  continue;
107 
108  match = true;
109  break;
110  }
111 
112  if (match)
113  myBlue.insert(c);
114  }
115  }
116 
117  for (int b : myBlue)
118  {
119  emit dataChanged(createIndex(b, 0), createIndex(b, 6));
120  blue.remove(b);
121  red.remove(b);
122  }
123  for (int r : myRed)
124  {
125  emit dataChanged(createIndex(r, 0), createIndex(r, 6));
126  blue.remove(r);
127  red.remove(r);
128  }
129 
130  for (int old : red + blue)
131  {
132  emit dataChanged(createIndex(old, 0), createIndex(old, 6));
133  }
134 }
135 
136 int CREMessageItemModel::columnCount(const QModelIndex& parent) const
137 {
138  if (parent.isValid())
139  return 0;
140  return 6;
141 }
142 
143 QModelIndex CREMessageItemModel::index(int row, int column, const QModelIndex& parent) const
144 {
145  if (parent.isValid())
146  return QModelIndex();
147  return createIndex(row, column);
148 }
149 
150 QModelIndex CREMessageItemModel::parent(const QModelIndex&) const
151 {
152  return QModelIndex();
153 }
154 
155 int CREMessageItemModel::rowCount(const QModelIndex& index) const
156 {
157  if (!myMessage || index.isValid())
158  return 0;
159 
160  return myMessage->rules().size();
161 }
162 
163 static QString toDisplay(const QList<QStringList>& list)
164 {
165  QStringList data;
166  foreach(QStringList item, list)
167  data.append(item.join(" "));
168  return data.join("\n");
169 }
170 
171 QVariant CREMessageItemModel::data(const QModelIndex& index, int role) const
172 {
173  if (myMessage == NULL || !index.isValid())
174  return QVariant();
175 
176  if (role == Qt::BackgroundColorRole)
177  {
178  if (myBlue.contains(index.row()))
179  return QVariant::fromValue(QBrush(Qt::blue));
180  if (myRed.contains(index.row()))
181  return QVariant::fromValue(QBrush(Qt::red));
182  return QVariant();
183  }
184 
185  if (role != Qt::DisplayRole && role != Qt::EditRole)
186  return QVariant();
187 
188  Q_ASSERT(index.row() < myMessage->rules().size());
189  const MessageRule* rule = myMessage->rules()[index.row()];
190 
191  switch(index.column())
192  {
193  case 0:
194  return role == Qt::DisplayRole ? QVariant::fromValue(rule->match().join("\n")) : QVariant::fromValue(rule->match());
195  case 1:
196  return role == Qt::DisplayRole ? QVariant::fromValue(toDisplay(rule->preconditions())) : QVariant::fromValue(rule->preconditions());
197  case 2:
198  return role == Qt::DisplayRole ? QVariant::fromValue(toDisplay(rule->replies())) : QVariant::fromValue(rule->replies());
199  case 3:
200  return role == Qt::DisplayRole ? QVariant::fromValue(rule->messages().join("\n")) : QVariant::fromValue(rule->messages());
201  case 4:
202  return role == Qt::DisplayRole ? QVariant::fromValue(toDisplay(rule->postconditions())) : QVariant::fromValue(rule->postconditions());
203  case 5:
204  return role == Qt::DisplayRole ? QVariant::fromValue(rule->include().join("\n")) : QVariant::fromValue(rule->include());
205  }
206 
207  return QVariant();;
208 }
209 
210 QVariant CREMessageItemModel::headerData(int section, Qt::Orientation orientation, int role) const
211 {
212  if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
213  return QVariant();
214 
215  switch(section)
216  {
217  case 0:
218  return tr("match");
219  case 1:
220  return tr("pre-conditions");
221  case 2:
222  return tr("player suggested replies");
223  case 3:
224  return tr("NPC messages");
225  case 4:
226  return tr("post-conditions");
227  case 5:
228  return tr("includes");
229  }
230 
231  return QVariant();
232 }
233 
234 Qt::ItemFlags CREMessageItemModel::flags(const QModelIndex& index) const
235 {
236  if (!index.isValid())
237  return 0;
238  return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
239 }
240 
241 bool CREMessageItemModel::setData(const QModelIndex& index, const QVariant& value, int role)
242 {
243  if (!index.isValid() || myMessage == nullptr || myMessage->rules().size() <= index.row())
244  return false;
245  if (role != Qt::EditRole)
246  return false;
247 
248  MessageRule* rule = myMessage->rules()[index.row()];
249 
250  switch (index.column())
251  {
252  case 0:
253  rule->setMatch(value.value<QStringList>());
254  break;
255  case 1:
256  rule->setPreconditions(value.value<QList<QStringList>>());
257  break;
258  case 2:
259  rule->setReplies(value.value<QList<QStringList>>());
260  break;
261  case 3:
262  rule->setMessages(value.value<QStringList>());
263  break;
264  case 4:
265  rule->setPostconditions(value.value<QList<QStringList>>());
266  break;
267  case 5:
268  rule->setInclude(value.value<QStringList>());
269  break;
270  default:
271  return false;
272  }
273 
274  myMessage->setModified(true);
275  emit dataChanged(index, index);
276 
277  return true;
278 }
279 
280 bool CREMessageItemModel::insertRows(int row, int count, const QModelIndex& parent)
281 {
282  if (parent.isValid())
283  return false;
284 
285  beginInsertRows(parent, row, row + count - 1);
286  while (count > 0)
287  {
288  myMessage->rules().insert(row, new MessageRule());
289  count--;
290  }
291  endInsertRows();
292  myMessage->setModified(true);
293 
294  return true;
295 }
296 
297 bool CREMessageItemModel::removeRows(int row, int count, const QModelIndex& parent)
298 {
299  if (parent.isValid())
300  return false;
301  if (row < 0 || row >= myMessage->rules().size())
302  return false;
303 
304  beginRemoveRows(parent, row, row + count);
305  while (count > 0 && row < myMessage->rules().size())
306  {
307  myMessage->rules().removeAt(row);
308  count--;
309  }
310  endRemoveRows();
311  myMessage->setModified(true);
312 
313  return true;
314 }
315 
316 void CREMessageItemModel::moveUpDown(int row, bool up)
317 {
318  if (!myMessage)
319  return;
320 
321  const int shift = up ? -1 : 1;
322  if (row < 0 || row >= myMessage->rules().size() || (row + shift) < 0 || (row + shift) >= myMessage->rules().size())
323  return;
324 
325  MessageRule* moved = myMessage->rules()[row];
326  myMessage->rules()[row] = myMessage->rules()[row + shift];
327  myMessage->rules()[row + shift] = moved;
328 
329  emit dataChanged(createIndex(up ? row - 1 : row, 0), createIndex(up ? row : row + 1, 6));
330  myMessage->setModified(true);
331 }
332 
334 {
335  if (!myMessage || row < 0 || row >= myMessage->rules().count())
336  return;
337 
338  beginInsertRows(QModelIndex(), row + 1, row + 1);
339  myMessage->rules().insert(row + 1, new MessageRule(*myMessage->rules()[row]));
340  endInsertRows();
341  myMessage->setModified(true);
342 }
CREMessageItemModel::index
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const override
Definition: CREMessageItemModel.cpp:143
CREMessageItemModel::insertRows
virtual bool insertRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
Definition: CREMessageItemModel.cpp:280
CREMessageItemModel::myRed
QSet< int > myRed
Definition: CREMessageItemModel.h:50
c
static event_registration c
Definition: citylife.cpp:425
CREMessageItemModel::data
virtual QVariant data(const QModelIndex &index, int role) const override
Definition: CREMessageItemModel.cpp:171
CREMessageItemModel::setMessage
void setMessage(MessageFile *message)
Definition: CREMessageItemModel.cpp:25
guildoracle.list
list
Definition: guildoracle.py:87
CREMessageItemModel::myMessage
MessageFile * myMessage
Definition: CREMessageItemModel.h:49
CREMessageItemModel::moveUpDown
void moveUpDown(int row, bool up)
Definition: CREMessageItemModel.cpp:316
CREMessageItemModel::~CREMessageItemModel
virtual ~CREMessageItemModel()
Definition: CREMessageItemModel.cpp:21
MessageFile
Definition: MessageFile.h:68
CREMessageItemModel::CREMessageItemModel
CREMessageItemModel(QObject *parent)
Definition: CREMessageItemModel.cpp:17
CREMessageItemModel::removeRows
virtual bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
Definition: CREMessageItemModel.cpp:297
CREMessageItemModel::columnCount
virtual int columnCount(const QModelIndex &parent) const override
Definition: CREMessageItemModel.cpp:136
Ice.b
b
Definition: Ice.py:48
navar-midane_time.data
data
Definition: navar-midane_time.py:11
CREMessageItemModel::rowCount
virtual int rowCount(const QModelIndex &parent) const override
Definition: CREMessageItemModel.cpp:155
disinfect.count
int count
Definition: disinfect.py:7
push.match
bool match
Definition: push.py:61
MessageFile::setModified
void setModified(bool modified=true)
Definition: MessageFile.cpp:394
toDisplay
static QString toDisplay(const QList< QStringList > &list)
Definition: CREMessageItemModel.cpp:163
CREMessageItemModel::flags
virtual Qt::ItemFlags flags(const QModelIndex &index) const override
Definition: CREMessageItemModel.cpp:234
MessageFile::rules
QList< MessageRule * > & rules()
Definition: MessageFile.cpp:266
diamondslots.message
string message
Definition: diamondslots.py:57
bigchest.check
check
Definition: bigchest.py:10
item
Definition: item.py:1
autojail.value
value
Definition: autojail.py:6
CREMessageItemModel::setSelectedRule
void setSelectedRule(const QModelIndex &index)
Definition: CREMessageItemModel.cpp:32
npc_dialog.index
int index
Definition: npc_dialog.py:102
CREMessageItemModel::headerData
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override
Definition: CREMessageItemModel.cpp:210
CREMessageItemModel::myBlue
QSet< int > myBlue
Definition: CREMessageItemModel.h:50
CREMessageItemModel::parent
virtual QModelIndex parent(const QModelIndex &index) const override
Definition: CREMessageItemModel.cpp:150
npc_dialog.rule
rule
Definition: npc_dialog.py:108
CREMessageItemModel::setData
virtual bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
Definition: CREMessageItemModel.cpp:241
CREMessageItemModel::duplicateRow
void duplicateRow(int row)
Definition: CREMessageItemModel.cpp:333
CREMessageItemModel.h
ring_occidental_mages.r
r
Definition: ring_occidental_mages.py:6
MessageRule
Definition: MessageFile.h:25