OSDN Git Service

Ver0.12
[gefu/Gefu.git] / filetablemodel.cpp
1 #include "common.h"\r
2 #include "filetablemodel.h"\r
3 \r
4 #include <QDateTime>\r
5 #include <QDebug>\r
6 #include <QApplication>\r
7 #include <QSettings>\r
8 #include <QPalette>\r
9 #ifdef Q_OS_WIN32\r
10     #include <windows.h>\r
11 #endif\r
12 \r
13 FileTableModel::FileTableModel(QObject *parent) :\r
14     QAbstractTableModel(parent),\r
15     m_dir(),\r
16     m_fileInfoList(),\r
17     m_checkStates(),\r
18     m_IconFactory(),\r
19     m_fsWatcher(NULL),\r
20     m_font(),\r
21     m_NormalBrush(),\r
22     m_NormalTextBrush(),\r
23     m_MarkBrush(),\r
24     m_MarkTextBrush(),\r
25     m_SystemBrush(),\r
26     m_HiddenBrush(),\r
27     m_ReadonlyBrush()\r
28 {\r
29     // デフォルトフィルタを設定する\r
30     setFilter(QDir::NoDot | QDir::AllDirs | QDir::Files);\r
31 }\r
32 \r
33 bool FileTableModel::setPath(const QString &path)\r
34 {\r
35     if (!QFileInfo::exists(path)) {\r
36         qDebug() << "パスが存在しません";\r
37         qDebug() << path;\r
38         return false;\r
39     }\r
40     QFileInfo info(path);\r
41     if (!info.isDir()) {\r
42         qDebug() << "フォルダではありません";\r
43         qDebug() << path;\r
44         return false;\r
45     }\r
46 \r
47     beginResetModel();\r
48 \r
49     m_dir.setPath(path);\r
50     m_fileInfoList = m_dir.entryInfoList();\r
51     m_checkStates.clear();\r
52 \r
53     if (m_fileInfoList.isEmpty()) {\r
54         qDebug() << "ファイルリストを取得できません";\r
55         qDebug() << path;\r
56     }\r
57     else {\r
58         QFileInfoList::iterator it;\r
59         for (it = m_fileInfoList.begin(); it != m_fileInfoList.end(); ) {\r
60 #ifdef Q_OS_WIN32\r
61             if (!(filter() & QDir::System)){\r
62                 DWORD dwFlags = ::GetFileAttributes(\r
63                             it->absoluteFilePath().toStdWString().c_str());\r
64                 if (dwFlags != DWORD(-1) && it->fileName() != ".." &&\r
65                     ((dwFlags & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM))\r
66                 {\r
67                     qDebug() << it->fileName() << " is system file.";\r
68                     it = m_fileInfoList.erase(it);\r
69                     continue;\r
70                 }\r
71             }\r
72 #endif\r
73             if (it->fileName() == "..") {\r
74                 if (m_dir.isRoot()) {\r
75                     qDebug() << m_dir.absolutePath() << " is root.";\r
76                     it = m_fileInfoList.erase(it);\r
77                     continue;\r
78                 }\r
79             }\r
80             it++;\r
81         }\r
82         // ソート方法によらず、".."は必ず先頭にする\r
83         QFileInfoList::iterator itRoot = m_fileInfoList.end();\r
84         for (it = m_fileInfoList.begin(); it != m_fileInfoList.end(); it++) {\r
85             if (it->fileName() == "..") {\r
86                 itRoot = it;\r
87                 break;\r
88             }\r
89         }\r
90         if (itRoot != m_fileInfoList.end()) {\r
91             QFileInfo info(*itRoot);\r
92             m_fileInfoList.erase(itRoot);\r
93             m_fileInfoList.push_front(info);\r
94         }\r
95     }\r
96 \r
97     m_checkStates.resize(m_fileInfoList.size());\r
98     m_checkStates.fill(Qt::Unchecked);\r
99 \r
100     if (m_fsWatcher) {\r
101         delete m_fsWatcher;\r
102     }\r
103     m_fsWatcher = new QFileSystemWatcher(this);\r
104     m_fsWatcher->addPath(path);\r
105     connect(m_fsWatcher, SIGNAL(directoryChanged(QString)),\r
106             this, SLOT(directoryChange(QString)));\r
107 \r
108     endResetModel();\r
109 \r
110     emit dataChanged(QModelIndex(), QModelIndex());\r
111     return !m_fileInfoList.isEmpty();\r
112 }\r
113 \r
114 Qt::CheckState FileTableModel::checkState(const QModelIndex &index) const\r
115 {\r
116     return m_checkStates[index.row()];\r
117 }\r
118 \r
119 void FileTableModel::setCheckState(const QModelIndex &index, Qt::CheckState state)\r
120 {\r
121     beginResetModel();\r
122     m_checkStates[index.row()] = state;\r
123     if (state == Qt::Checked && index.row() == 0 &&\r
124         m_fileInfoList[0].fileName() == "..")\r
125     {\r
126         m_checkStates[0] = Qt::Unchecked;\r
127     }\r
128     endResetModel();;\r
129     emit dataChanged(index, this->index(index.row(), 3));\r
130 }\r
131 \r
132 void FileTableModel::setCheckStateAll(Qt::CheckState state)\r
133 {\r
134     beginResetModel();\r
135     m_checkStates.fill(state);\r
136     if (state == Qt::Checked && m_fileInfoList.size() > 1 &&\r
137         m_fileInfoList[0].fileName() == "..")\r
138     {\r
139         m_checkStates[0] = Qt::Unchecked;\r
140     }\r
141     endResetModel();\r
142     emit dataChanged(QModelIndex(), QModelIndex());\r
143 }\r
144 \r
145 QFileInfo FileTableModel::fileInfo(const QModelIndex &index) const\r
146 {\r
147     if (!index.isValid()) {\r
148         qDebug() << "fileInfo() : index is invalid.";\r
149         return QFileInfo();\r
150     }\r
151     return m_fileInfoList[index.row()];\r
152 }\r
153 \r
154 void FileTableModel::updateAppearance()\r
155 {\r
156     QSettings settings;\r
157     QPalette palette(QApplication::palette("QTableView"));\r
158 \r
159     m_font = settings.value(IniKey_ViewFont).value<QFont>();\r
160     m_NormalBrush = QBrush(settings.value(IniKey_ViewColorBgNormal).value<QColor>());\r
161     m_NormalTextBrush = QBrush(settings.value(IniKey_ViewColorFgNormal).value<QColor>());\r
162     m_MarkBrush = QBrush(settings.value(IniKey_ViewColorBgMark).value<QColor>());\r
163     m_MarkTextBrush = QBrush(settings.value(IniKey_ViewColorFgMark).value<QColor>());\r
164     m_SystemBrush = QBrush(settings.value(IniKey_ViewColorFgSystem).value<QColor>());\r
165     m_HiddenBrush = QBrush(settings.value(IniKey_ViewColorFgHidden).value<QColor>());\r
166     m_ReadonlyBrush = QBrush(settings.value(IniKey_ViewColorFgReadonly).value<QColor>());\r
167     m_ReadonlyBrush = QBrush(settings.value(IniKey_ViewColorFgReadonly).value<QColor>());\r
168 \r
169     beginResetModel();\r
170     endResetModel();\r
171 }\r
172 \r
173 void FileTableModel::directoryChange(const QString &path)\r
174 {\r
175     qDebug() << "FileTableModel::directoryChange";\r
176 \r
177     setPath(path);\r
178 }\r
179 \r
180 QFileInfoList FileTableModel::checkedItems() const\r
181 {\r
182     QFileInfoList list;\r
183     for (int n = 0; n < m_checkStates.size(); n++) {\r
184         if (m_fileInfoList[n].fileName() != ".." &&\r
185             m_checkStates[n] == Qt::Checked)\r
186         {\r
187             list.append(m_fileInfoList[n]);\r
188         }\r
189     }\r
190     return list;\r
191 }\r
192 \r
193 int FileTableModel::rowCount(const QModelIndex &parent) const\r
194 {\r
195     Q_UNUSED(parent);\r
196     return m_fileInfoList.size();\r
197 }\r
198 \r
199 int FileTableModel::columnCount(const QModelIndex &parent) const\r
200 {\r
201     Q_UNUSED(parent);\r
202     return 5;\r
203 }\r
204 \r
205 QVariant FileTableModel::data(const QModelIndex &index, int role) const\r
206 {\r
207     if (!index.isValid()) {\r
208         return QVariant();\r
209     }\r
210 \r
211     const QFileInfo &info = m_fileInfoList.at(index.row());\r
212     int checked = m_checkStates.at(index.row());\r
213 \r
214     switch (role) {\r
215     case Qt::DisplayRole:\r
216         switch (index.column()) {\r
217         case 0: // チェックボックス\r
218             return QString("");\r
219         case 1: // ファイル名\r
220             if (info.isDir()) {\r
221                 return info.fileName();\r
222             }\r
223             if (info.fileName().left(1) == ".") {   // "."で始まるファイル\r
224                 int pos = info.fileName().lastIndexOf(".");\r
225                 if (pos == 0) {\r
226                     return info.fileName();\r
227                 }\r
228             }\r
229             return info.completeBaseName();\r
230 \r
231         case 2: // 拡張子\r
232             if (info.isDir()) {\r
233                 return QString();\r
234             }\r
235             if (info.fileName().left(1) == ".") {   // "."で始まるファイル\r
236                 int pos = info.fileName().lastIndexOf(".");\r
237                 if (pos == 0) {\r
238                     return QString();\r
239                 }\r
240             }\r
241             return info.suffix();\r
242 \r
243         case 3: // サイズ\r
244             if (info.isDir()) {\r
245                 return QString("<DIR>");\r
246             }\r
247             else {\r
248                 return FilesizeToString(info.size());\r
249             }\r
250             break;\r
251 \r
252         case 4: // 更新日時\r
253             return info.lastModified().toString("yy/MM/dd hh:mm");\r
254         }\r
255         break;\r
256 \r
257     case Qt::DecorationRole:\r
258         if (index.column() == 1) {\r
259             if (info.fileName() == "..") {\r
260                 return QIcon(":/images/Up.png");\r
261             }\r
262             else {\r
263                 // infoを使うと、正しいアイコンが取れない場合がある…なぜ?\r
264                 return m_IconFactory.icon(QFileInfo(info.absoluteFilePath()));\r
265             }\r
266         }\r
267         break;\r
268 \r
269     case Qt::FontRole:\r
270         return m_font;\r
271 \r
272     case Qt::TextAlignmentRole:\r
273         switch (index.column()) {\r
274         case 3:\r
275         case 4:\r
276             return Qt::AlignRight + Qt::AlignVCenter;\r
277         default:\r
278             return Qt::AlignLeft + Qt::AlignVCenter;\r
279         }\r
280         break;\r
281 \r
282     case Qt::BackgroundRole:\r
283         if (checked) {\r
284             return m_MarkBrush;\r
285         }\r
286         return m_NormalBrush;\r
287 \r
288     case Qt::ForegroundRole:\r
289         if (checked) {\r
290             return m_MarkTextBrush;\r
291         }\r
292 #ifdef Q_OS_WIN32\r
293         {\r
294             DWORD dwFlags = ::GetFileAttributes(\r
295                         info.absoluteFilePath().toStdWString().c_str());\r
296             if (dwFlags != DWORD(-1) && (dwFlags & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM)\r
297             {\r
298                 return m_SystemBrush;\r
299             }\r
300         }\r
301 #endif\r
302         if (info.isHidden() && info.fileName() != "..") {\r
303             return m_HiddenBrush;\r
304         }\r
305         if (!info.isWritable()) {\r
306             return m_ReadonlyBrush;\r
307         }\r
308         return m_NormalTextBrush;\r
309 \r
310     case Qt::CheckStateRole:\r
311         if (index.column() == 0 && info.fileName() != "..") {\r
312             return checked;\r
313         }\r
314         break;\r
315     }\r
316 \r
317     return QVariant();\r
318 }\r
319 \r
320 QVariant FileTableModel::headerData(int section, Qt::Orientation orientation, int role) const\r
321 {\r
322     if (role == Qt::DisplayRole) {\r
323         if (orientation == Qt::Horizontal) {\r
324             switch (section) {\r
325             case 0: return QString("");\r
326             case 1: return tr("名前");\r
327             case 2: return tr("拡張子");\r
328             case 3: return tr("サイズ");\r
329             case 4: return tr("更新日時");\r
330             }\r
331         }\r
332     }\r
333     return QVariant();\r
334 }\r
335 \r
336 Qt::ItemFlags FileTableModel::flags(const QModelIndex &index) const\r
337 {\r
338     Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;\r
339     if (!index.isValid()) {\r
340         flags |= Qt::ItemIsDropEnabled;\r
341     }\r
342     else if (m_fileInfoList[index.row()].fileName() != "..") {\r
343         if (index.column() == 0) {\r
344             flags |= Qt::ItemIsUserCheckable;\r
345         }\r
346         flags |= Qt::ItemIsDropEnabled;\r
347     }\r
348     return flags;\r
349 }\r
350 \r
351 bool FileTableModel::setData(const QModelIndex &index, const QVariant &value, int role)\r
352 {\r
353     if (!index.isValid()) {\r
354         return false;\r
355     }\r
356 \r
357     switch (role) {\r
358     case Qt::CheckStateRole:\r
359         if (index.column() == 0) {\r
360             m_checkStates[index.row()] = static_cast<Qt::CheckState>(value.toInt());\r
361             emit dataChanged(index, this->index(index.row(), 3));\r
362             return true;\r
363         }\r
364         break;\r
365     }\r
366 \r
367     return false;\r
368 }\r
369 \r
370 Qt::DropActions FileTableModel::supportedDropActions() const\r
371 {\r
372     return Qt::CopyAction | Qt::MoveAction;\r
373 }\r
374 \r
375 QStringList FileTableModel::mimeTypes() const\r
376 {\r
377     QStringList types;\r
378 \r
379     types << "text/uri-list";\r
380 \r
381     return types;\r
382 }\r