OSDN Git Service

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