OSDN Git Service

Update license.
[qt-creator-jp/qt-creator-jp.git] / src / libs / utils / environmentmodel.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
8 **
9 **
10 ** GNU Lesser General Public License Usage
11 **
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 **
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 **
23 ** Other Usage
24 **
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **************************************************************************/
32
33 #include "environmentmodel.h"
34
35 #include <utils/environment.h>
36
37 #include <QtGui/QFont>
38
39 namespace Utils {
40
41 namespace Internal {
42
43 class EnvironmentModelPrivate
44 {
45 public:
46     void updateResultEnvironment()
47     {
48         m_resultEnvironment = m_baseEnvironment;
49         m_resultEnvironment.modify(m_items);
50         // Add removed variables again and mark them as "<UNSET>" so
51         // that the user can actually see those removals:
52         foreach (const Utils::EnvironmentItem &item, m_items) {
53             if (item.unset) {
54                 m_resultEnvironment.set(item.name, EnvironmentModel::tr("<UNSET>"));
55             }
56         }
57     }
58
59     int findInChanges(const QString &name) const
60     {
61         for (int i=0; i<m_items.size(); ++i)
62             if (m_items.at(i).name == name)
63                 return i;
64         return -1;
65     }
66
67     int findInResultInsertPosition(const QString &name) const
68     {
69         Utils::Environment::const_iterator it;
70         int i = 0;
71         for (it = m_resultEnvironment.constBegin(); it != m_resultEnvironment.constEnd(); ++it, ++i)
72             if (m_resultEnvironment.key(it) > name)
73                 return i;
74         return m_resultEnvironment.size();
75     }
76
77     int findInResult(const QString &name) const
78     {
79         Utils::Environment::const_iterator it;
80         int i = 0;
81         for (it = m_resultEnvironment.constBegin(); it != m_resultEnvironment.constEnd(); ++it, ++i)
82             if (m_resultEnvironment.key(it) == name)
83                 return i;
84         return -1;
85     }
86
87     Utils::Environment m_baseEnvironment;
88     Utils::Environment m_resultEnvironment;
89     QList<Utils::EnvironmentItem> m_items;
90 };
91
92 } // namespace Internal
93
94 EnvironmentModel::EnvironmentModel(QObject *parent) :
95     QAbstractTableModel(parent),
96     m_d(new Internal::EnvironmentModelPrivate)
97 { }
98
99 EnvironmentModel::~EnvironmentModel()
100 {
101     delete m_d;
102 }
103
104 QString EnvironmentModel::indexToVariable(const QModelIndex &index) const
105 {
106     return m_d->m_resultEnvironment.key(m_d->m_resultEnvironment.constBegin() + index.row());
107 }
108
109 void EnvironmentModel::setBaseEnvironment(const Utils::Environment &env)
110 {
111     if (m_d->m_baseEnvironment == env)
112         return;
113     beginResetModel();
114     m_d->m_baseEnvironment = env;
115     m_d->updateResultEnvironment();
116     endResetModel();
117 }
118
119 int EnvironmentModel::rowCount(const QModelIndex &parent) const
120 {
121     if (parent.isValid())
122         return 0;
123
124     return m_d->m_resultEnvironment.size();
125 }
126 int EnvironmentModel::columnCount(const QModelIndex &parent) const
127 {
128     if (parent.isValid())
129         return 0;
130
131     return 2;
132 }
133
134 bool EnvironmentModel::changes(const QString &name) const
135 {
136     return m_d->findInChanges(name) >= 0;
137 }
138
139 QVariant EnvironmentModel::data(const QModelIndex &index, int role) const
140 {
141     if (!index.isValid())
142         return QVariant();
143
144     if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::ToolTipRole) {
145         if (index.column() == 0) {
146             return m_d->m_resultEnvironment.key(m_d->m_resultEnvironment.constBegin() + index.row());
147         } else if (index.column() == 1) {
148             // Do not return "<UNSET>" when editing a previously unset variable:
149             if (role == Qt::EditRole) {
150                 int pos = m_d->findInChanges(indexToVariable(index));
151                 if (pos >= 0)
152                     return m_d->m_items.at(pos).value;
153             }
154             return m_d->m_resultEnvironment.value(m_d->m_resultEnvironment.constBegin() + index.row());
155         }
156     }
157     if (role == Qt::FontRole) {
158         // check whether this environment variable exists in m_d->m_items
159         if (changes(m_d->m_resultEnvironment.key(m_d->m_resultEnvironment.constBegin() + index.row()))) {
160             QFont f;
161             f.setBold(true);
162             return QVariant(f);
163         }
164         return QFont();
165     }
166     return QVariant();
167 }
168
169 Qt::ItemFlags EnvironmentModel::flags(const QModelIndex &index) const
170 {
171     Q_UNUSED(index)
172     return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
173 }
174
175 QVariant EnvironmentModel::headerData(int section, Qt::Orientation orientation, int role) const
176 {
177     if (orientation == Qt::Vertical || role != Qt::DisplayRole)
178         return QVariant();
179     return section == 0 ? tr("Variable") : tr("Value");
180 }
181
182 /// *****************
183 /// Utility functions
184 /// *****************
185 QModelIndex EnvironmentModel::variableToIndex(const QString &name) const
186 {
187     int row = m_d->findInResult(name);
188     if (row == -1)
189         return QModelIndex();
190     return index(row, 0);
191 }
192
193 bool EnvironmentModel::setData(const QModelIndex &index, const QVariant &value, int role)
194 {
195     if (!index.isValid() || role != Qt::EditRole)
196         return false;
197
198     // ignore changes to already set values:
199     if (data(index, role) == value)
200         return true;
201
202     const QString oldName = data(this->index(index.row(), 0, QModelIndex())).toString();
203     const QString oldValue = data(this->index(index.row(), 1, QModelIndex())).toString();
204     int changesPos = m_d->findInChanges(oldName);
205
206     if (index.column() == 0) {
207         //fail if a variable with the same name already exists
208 #if defined(Q_OS_WIN)
209         const QString &newName = value.toString().toUpper();
210 #else
211         const QString &newName = value.toString();
212 #endif
213         // Does the new name exist already?
214         if (m_d->m_resultEnvironment.hasKey(newName))
215             return false;
216
217         Utils::EnvironmentItem newVariable(newName, oldValue);
218
219         if (changesPos != -1)
220             resetVariable(oldName); // restore the original base variable again
221
222         QModelIndex newIndex = addVariable(newVariable); // add the new variable
223         emit focusIndex(newIndex.sibling(newIndex.row(), 1)); // hint to focus on the value
224         return true;
225     } else if (index.column() == 1) {
226         // We are changing an existing value:
227         const QString stringValue = value.toString();
228         if (changesPos != -1) {
229             // We have already changed this value
230             if (stringValue == m_d->m_baseEnvironment.value(oldName)) {
231                 // ... and now went back to the base value
232                 m_d->m_items.removeAt(changesPos);
233             } else {
234                 // ... and changed it again
235                 m_d->m_items[changesPos].value = stringValue;
236                 m_d->m_items[changesPos].unset = false;
237             }
238         } else {
239             // Add a new change item:
240             m_d->m_items.append(Utils::EnvironmentItem(oldName, stringValue));
241         }
242         m_d->updateResultEnvironment();
243         emit dataChanged(index, index);
244         emit userChangesChanged();
245         return true;
246     }
247     return false;
248 }
249
250 QModelIndex EnvironmentModel::addVariable()
251 {
252     //: Name when inserting a new variable
253     return addVariable(Utils::EnvironmentItem(tr("<VARIABLE>"),
254                                               //: Value when inserting a new variable
255                                               tr("<VALUE>")));
256 }
257
258 QModelIndex EnvironmentModel::addVariable(const Utils::EnvironmentItem &item)
259 {
260
261     // Return existing index if the name is already in the result set:
262     int pos = m_d->findInResult(item.name);
263     if (pos >= 0 && pos < m_d->m_resultEnvironment.size())
264         return index(pos, 0, QModelIndex());
265
266     int insertPos = m_d->findInResultInsertPosition(item.name);
267     int changePos = m_d->findInChanges(item.name);
268     if (m_d->m_baseEnvironment.hasKey(item.name)) {
269         // We previously unset this!
270         Q_ASSERT(changePos >= 0);
271         // Do not insert a line here as we listed the variable as <UNSET> before!
272         Q_ASSERT(m_d->m_items.at(changePos).name == item.name);
273         Q_ASSERT(m_d->m_items.at(changePos).unset);
274         Q_ASSERT(m_d->m_items.at(changePos).value.isEmpty());
275         m_d->m_items[changePos] = item;
276         emit dataChanged(index(insertPos, 0, QModelIndex()), index(insertPos, 1, QModelIndex()));
277     } else {
278         // We add something that is not in the base environment
279         // Insert a new line!
280         beginInsertRows(QModelIndex(), insertPos, insertPos);
281         Q_ASSERT(changePos < 0);
282         m_d->m_items.append(item);
283         m_d->updateResultEnvironment();
284         endInsertRows();
285     }
286     emit userChangesChanged();
287     return index(insertPos, 0, QModelIndex());
288 }
289
290 void EnvironmentModel::resetVariable(const QString &name)
291 {
292     int rowInChanges = m_d->findInChanges(name);
293     if (rowInChanges < 0)
294         return;
295
296     int rowInResult = m_d->findInResult(name);
297     if (rowInResult < 0)
298         return;
299
300     if (m_d->m_baseEnvironment.hasKey(name)) {
301         m_d->m_items.removeAt(rowInChanges);
302         m_d->updateResultEnvironment();
303         emit dataChanged(index(rowInResult, 0, QModelIndex()), index(rowInResult, 1, QModelIndex()));
304         emit userChangesChanged();
305     } else {
306         // Remove the line completely!
307         beginRemoveRows(QModelIndex(), rowInResult, rowInResult);
308         m_d->m_items.removeAt(rowInChanges);
309         m_d->updateResultEnvironment();
310         endRemoveRows();
311         emit userChangesChanged();
312     }
313 }
314
315 void EnvironmentModel::unsetVariable(const QString &name)
316 {
317     // This does not change the number of rows as we will display a <UNSET>
318     // in place of the original variable!
319     int row = m_d->findInResult(name);
320     if (row < 0)
321         return;
322
323     // look in m_d->m_items for the variable
324     int pos = m_d->findInChanges(name);
325     if (pos != -1) {
326         m_d->m_items[pos].unset = true;
327         m_d->m_items[pos].value.clear();
328         m_d->updateResultEnvironment();
329         emit dataChanged(index(row, 0, QModelIndex()), index(row, 1, QModelIndex()));
330         emit userChangesChanged();
331         return;
332     }
333     Utils::EnvironmentItem item(name, QString());
334     item.unset = true;
335     m_d->m_items.append(item);
336     m_d->updateResultEnvironment();
337     emit dataChanged(index(row, 0, QModelIndex()), index(row, 1, QModelIndex()));
338     emit userChangesChanged();
339 }
340
341 bool EnvironmentModel::canUnset(const QString &name)
342 {
343     int pos = m_d->findInChanges(name);
344     if (pos != -1)
345         return m_d->m_items.at(pos).unset;
346     else
347         return false;
348 }
349
350 bool EnvironmentModel::canReset(const QString &name)
351 {
352     return m_d->m_baseEnvironment.hasKey(name);
353 }
354
355 QList<Utils::EnvironmentItem> EnvironmentModel::userChanges() const
356 {
357     return m_d->m_items;
358 }
359
360 void EnvironmentModel::setUserChanges(QList<Utils::EnvironmentItem> list)
361 {
362     // We assume nobody is reordering the items here.
363     if (list == m_d->m_items)
364         return;
365     beginResetModel();
366     m_d->m_items = list;
367     m_d->updateResultEnvironment();
368     endResetModel();
369 }
370
371 } // namespace Utils