OSDN Git Service

It's 2011 now.
[qt-creator-jp/qt-creator-jp.git] / src / plugins / coreplugin / editormanager / openeditorsmodel.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 (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights.  These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #include "openeditorsmodel.h"
35 #include "ieditor.h"
36 #include "ifile.h"
37
38 #include <QtCore/QDir>
39 #include <QtGui/QIcon>
40
41 namespace Core {
42
43 struct OpenEditorsModelPrivate {
44     OpenEditorsModelPrivate();
45
46     const QIcon m_lockedIcon;
47     const QIcon m_unlockedIcon;
48
49     QList<OpenEditorsModel::Entry> m_editors;
50     QList<IEditor *> m_duplicateEditors;
51 };
52
53 OpenEditorsModelPrivate::OpenEditorsModelPrivate() :
54     m_lockedIcon(QLatin1String(":/core/images/locked.png")),
55     m_unlockedIcon(QLatin1String(":/core/images/unlocked.png"))
56 {
57 }
58
59 OpenEditorsModel::Entry::Entry() :
60     editor(0)
61 {
62 }
63
64 OpenEditorsModel::OpenEditorsModel(QObject *parent) :
65     QAbstractItemModel(parent), d(new OpenEditorsModelPrivate)
66 {
67 }
68
69 OpenEditorsModel::~OpenEditorsModel()
70 {
71 }
72
73 QIcon OpenEditorsModel::lockedIcon() const
74 {
75     return d->m_lockedIcon;
76 }
77
78 QIcon OpenEditorsModel::unlockedIcon() const
79 {
80     return d->m_unlockedIcon;
81 }
82
83 QString OpenEditorsModel::Entry::fileName() const {
84     return editor ? editor->file()->fileName() : m_fileName;
85 }
86
87 QString OpenEditorsModel::Entry::displayName() const {
88     return editor ? editor->displayName() : m_displayName;
89 }
90
91 QString OpenEditorsModel::Entry::id() const
92 {
93     return editor ? editor->id() : m_id;
94 }
95
96 int OpenEditorsModel::columnCount(const QModelIndex &parent) const
97 {
98     Q_UNUSED(parent)
99     return 2;
100 }
101
102 int OpenEditorsModel::rowCount(const QModelIndex &parent) const
103 {
104     if (!parent.isValid())
105         return d->m_editors.count();
106     return 0;
107 }
108
109 QList<IEditor *> OpenEditorsModel::editors() const
110 {
111     QList<IEditor *> result;
112     foreach (const Entry &entry, d->m_editors)
113         if (entry.editor)
114             result += entry.editor;
115     return result;
116 }
117
118 void OpenEditorsModel::addEditor(IEditor *editor, bool isDuplicate)
119 {
120     if (!editor)
121         return;
122
123     if (isDuplicate) {
124         d->m_duplicateEditors.append(editor);
125         return;
126     }
127
128     Entry entry;
129     entry.editor = editor;
130     addEntry(entry);
131 }
132
133 void OpenEditorsModel::addRestoredEditor(const QString &fileName, const QString &displayName, const QString &id)
134 {
135     Entry entry;
136     entry.m_fileName = fileName;
137     entry.m_displayName = displayName;
138     entry.m_id = id;
139     addEntry(entry);
140 }
141
142 QModelIndex OpenEditorsModel::firstRestoredEditor() const
143 {
144     for (int i = 0; i < d->m_editors.count(); ++i)
145         if (!d->m_editors.at(i).editor)
146             return createIndex(i, 0);
147     return QModelIndex();
148 }
149
150 void OpenEditorsModel::addEntry(const Entry &entry)
151 {
152     QString fileName = entry.fileName();
153
154     int previousIndex = findFileName(fileName);
155     if (previousIndex >= 0) {
156         if (entry.editor && d->m_editors.at(previousIndex).editor == 0) {
157             d->m_editors[previousIndex] = entry;
158             connect(entry.editor, SIGNAL(changed()), this, SLOT(itemChanged()));
159         }
160         return;
161     }
162
163     int index;
164     QString displayName = entry.displayName();
165     for (index = 0; index < d->m_editors.count(); ++index) {
166         if (displayName < d->m_editors.at(index).displayName())
167             break;
168     }
169
170     beginInsertRows(QModelIndex(), index, index);
171     d->m_editors.insert(index, entry);
172     if (entry.editor)
173         connect(entry.editor, SIGNAL(changed()), this, SLOT(itemChanged()));
174     endInsertRows();
175 }
176
177
178 int OpenEditorsModel::findEditor(IEditor *editor) const
179 {
180     for (int i = 0; i < d->m_editors.count(); ++i)
181         if (d->m_editors.at(i).editor == editor)
182             return i;
183     return -1;
184 }
185
186 int OpenEditorsModel::findFileName(const QString &filename) const
187 {
188     if (filename.isEmpty())
189         return -1;
190     for (int i = 0; i < d->m_editors.count(); ++i) {
191         if (d->m_editors.at(i).fileName() == filename)
192             return i;
193     }
194     return -1;
195 }
196
197 void OpenEditorsModel::removeEditor(IEditor *editor)
198 {
199     d->m_duplicateEditors.removeAll(editor);
200     int idx = findEditor(editor);
201     if (idx < 0)
202         return;
203     beginRemoveRows(QModelIndex(), idx, idx);
204     d->m_editors.removeAt(idx);
205     endRemoveRows();
206     disconnect(editor, SIGNAL(changed()), this, SLOT(itemChanged()));
207 }
208
209 void OpenEditorsModel::removeEditor(const QModelIndex &index)
210 {
211     int idx = index.row();
212     if (idx < 0)
213         return;
214     IEditor *editor= d->m_editors.at(idx).editor;
215     beginRemoveRows(QModelIndex(), idx, idx);
216     d->m_editors.removeAt(idx);
217     endRemoveRows();
218     if (editor)
219         disconnect(editor, SIGNAL(changed()), this, SLOT(itemChanged()));
220 }
221
222 void OpenEditorsModel::removeAllRestoredEditors()
223 {
224     for (int i = d->m_editors.count()-1; i >= 0; --i) {
225         if (!d->m_editors.at(i).editor) {
226             beginRemoveRows(QModelIndex(), i, i);
227             d->m_editors.removeAt(i);
228             endRemoveRows();
229         }
230     }
231 }
232
233 QList<OpenEditorsModel::Entry> OpenEditorsModel::restoredEditors() const
234 {
235     QList<Entry> result;
236     for (int i = d->m_editors.count()-1; i >= 0; --i) {
237         if (!d->m_editors.at(i).editor) {
238             result.append(d->m_editors.at(i));
239         }
240     }
241     return result;
242 }
243
244 bool OpenEditorsModel::isDuplicate(IEditor *editor) const
245 {
246     return editor && d->m_duplicateEditors.contains(editor);
247 }
248
249 IEditor *OpenEditorsModel::originalForDuplicate(IEditor *duplicate) const
250 {
251     IFile *file = duplicate->file();
252     foreach(const Entry &e, d->m_editors)
253         if (e.editor && e.editor->file() == file)
254             return e.editor;
255     return 0;
256 }
257
258 QList<IEditor *> OpenEditorsModel::duplicatesFor(IEditor *editor) const
259 {
260     QList<IEditor *> result;
261     IFile *file = editor->file();
262     foreach(IEditor *e, d->m_duplicateEditors)
263         if (e->file() == file)
264             result += e;
265     return result;
266 }
267
268 void OpenEditorsModel::makeOriginal(IEditor *duplicate)
269 {
270     Q_ASSERT(duplicate && isDuplicate(duplicate));
271     IEditor *original = originalForDuplicate(duplicate);
272     Q_ASSERT(original);
273     int i = findEditor(original);
274     d->m_editors[i].editor = duplicate;
275     d->m_duplicateEditors.removeOne(duplicate);
276     d->m_duplicateEditors.append(original);
277     disconnect(original, SIGNAL(changed()), this, SLOT(itemChanged()));
278     connect(duplicate, SIGNAL(changed()), this, SLOT(itemChanged()));
279 }
280
281 void OpenEditorsModel::emitDataChanged(IEditor *editor)
282 {
283     int idx = findEditor(editor);
284     if (idx < 0)
285         return;
286     QModelIndex mindex = index(idx, 0);
287     emit dataChanged(mindex, mindex);
288 }
289
290 QModelIndex OpenEditorsModel::index(int row, int column, const QModelIndex &parent) const
291 {
292     Q_UNUSED(parent)
293     if (column < 0 || column > 1 || row < 0 || row >= d->m_editors.count())
294         return QModelIndex();
295     return createIndex(row, column);
296 }
297
298 QVariant OpenEditorsModel::data(const QModelIndex &index, int role) const
299 {
300     if (!index.isValid() || (index.column() != 0 && role < Qt::UserRole))
301         return QVariant();
302     Entry e = d->m_editors.at(index.row());
303     switch (role) {
304     case Qt::DisplayRole:
305         return (e.editor && e.editor->file()->isModified())
306                 ? e.displayName() + QLatin1Char('*')
307                 : e.displayName();
308     case Qt::DecorationRole:
309         return (e.editor && e.editor->file()->isReadOnly())
310                 ? d->m_lockedIcon : QIcon();
311     case Qt::ToolTipRole:
312         return e.fileName().isEmpty()
313                 ? e.displayName()
314                 : QDir::toNativeSeparators(e.fileName());
315     case Qt::UserRole:
316         return qVariantFromValue(e.editor);
317     case Qt::UserRole + 1:
318         return e.fileName();
319     case Qt::UserRole + 2:
320         return e.editor ? e.editor->id() : e.id();
321     default:
322         return QVariant();
323     }
324     return QVariant();
325 }
326
327 QModelIndex OpenEditorsModel::indexOf(IEditor *editor) const
328 {
329     int idx = findEditor(originalForDuplicate(editor));
330     return createIndex(idx, 0);
331 }
332
333 QString OpenEditorsModel::displayNameForFile(IFile *file) const
334 {
335     for (int i = 0; i < d->m_editors.count(); ++i)
336         if (d->m_editors.at(i).editor && d->m_editors.at(i).editor->file() == file)
337             return d->m_editors.at(i).editor->displayName();
338     return QString();
339 }
340
341 void OpenEditorsModel::itemChanged()
342 {
343     emitDataChanged(qobject_cast<IEditor*>(sender()));
344 }
345
346 QList<OpenEditorsModel::Entry> OpenEditorsModel::entries() const
347 {
348     return d->m_editors;
349 }
350
351 IEditor *OpenEditorsModel::editorAt(int row) const
352 {
353     return d->m_editors.at(row).editor;
354 }
355
356 } // namespace Core