OSDN Git Service

Ver0.08pre
[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 \r
153 bool FileTableModel::isDir(const QModelIndex &index) const\r
154 {\r
155     return m_fileInfoList[index.row()].isDir();\r
156 }\r
157 \r
158 const QString FileTableModel::absoluteFilePath(const QModelIndex &index) const\r
159 {\r
160     if (!index.isValid()) {\r
161         qDebug() << "index is invalid.";\r
162         return QString();\r
163     }\r
164     return m_dir.absoluteFilePath(m_fileInfoList[index.row()].fileName());\r
165 }\r
166 \r
167 QFileInfo FileTableModel::fileInfo(const QModelIndex &index) const\r
168 {\r
169     return m_fileInfoList[index.row()];\r
170 }\r
171 \r
172 void FileTableModel::updateAppearance()\r
173 {\r
174     QSettings settings;\r
175     QPalette palette(QApplication::palette("QTableView"));\r
176 \r
177     m_font = settings.value(IniKey_ViewFont).value<QFont>();\r
178     m_NormalBrush = QBrush(settings.value(IniKey_ViewColorBgNormal).value<QColor>());\r
179     m_NormalTextBrush = QBrush(settings.value(IniKey_ViewColorFgNormal).value<QColor>());\r
180     m_MarkBrush = QBrush(settings.value(IniKey_ViewColorBgMark).value<QColor>());\r
181     m_MarkTextBrush = QBrush(settings.value(IniKey_ViewColorFgMark).value<QColor>());\r
182     m_SystemBrush = QBrush(settings.value(IniKey_ViewColorFgSystem).value<QColor>());\r
183     m_HiddenBrush = QBrush(settings.value(IniKey_ViewColorFgHidden).value<QColor>());\r
184     m_ReadonlyBrush = QBrush(settings.value(IniKey_ViewColorFgReadonly).value<QColor>());\r
185     m_ReadonlyBrush = QBrush(settings.value(IniKey_ViewColorFgReadonly).value<QColor>());\r
186 \r
187     beginResetModel();\r
188     endResetModel();\r
189 }\r
190 \r
191 void FileTableModel::stateChanged()\r
192 {\r
193     int numFolder = 0;\r
194     int numFile = 0;\r
195     quint64 totalSize = 0;\r
196     for (int n = 0; n < m_checkStates.size(); n++) {\r
197         if (m_checkStates[n] == Qt::Checked) {\r
198             if (m_fileInfoList[n].isDir()) {\r
199                 numFolder++;\r
200             }\r
201             else {\r
202                 numFile++;\r
203                 totalSize += m_fileInfoList[n].size();\r
204             }\r
205         }\r
206     }\r
207 \r
208     emit stateChanged(numFolder, numFile, totalSize);\r
209 }\r
210 \r
211 QFileInfoList FileTableModel::checkedItems() const\r
212 {\r
213     QFileInfoList list;\r
214     for (int n = 0; n < m_checkStates.size(); n++) {\r
215         if (m_fileInfoList[n].fileName() != ".." &&\r
216             m_checkStates[n] == Qt::Checked)\r
217         {\r
218             list.append(m_fileInfoList[n]);\r
219         }\r
220     }\r
221     return list;\r
222 }\r
223 \r
224 int FileTableModel::rowCount(const QModelIndex &parent) const\r
225 {\r
226     Q_UNUSED(parent);\r
227     return m_fileInfoList.size();\r
228 }\r
229 \r
230 int FileTableModel::columnCount(const QModelIndex &parent) const\r
231 {\r
232     Q_UNUSED(parent);\r
233     return 4;\r
234 }\r
235 \r
236 QVariant FileTableModel::data(const QModelIndex &index, int role) const\r
237 {\r
238     if (!index.isValid()) {\r
239         return QVariant();\r
240     }\r
241 \r
242     const QFileInfo &info = m_fileInfoList.at(index.row());\r
243     int checked = m_checkStates.at(index.row());\r
244 \r
245     switch (role) {\r
246     case Qt::DisplayRole:\r
247         switch (index.column()) {\r
248         case 0: // チェックボックス\r
249             return QString("");\r
250         case 1: // ファイル名\r
251             return info.fileName();\r
252         case 2: // サイズ\r
253             if (info.isDir()) {\r
254                 return QString("<DIR>");\r
255             }\r
256             else {\r
257                 return FilesizeToString(info.size());\r
258             }\r
259             break;\r
260         case 3:\r
261             return info.lastModified().toString("yy/MM/dd hh:mm");\r
262         }\r
263         break;\r
264 \r
265     case Qt::DecorationRole:\r
266         if (index.column() == 1) {\r
267             if (info.fileName() == "..") {\r
268                 return QIcon(":/images/Up.png");\r
269             }\r
270             else {\r
271                 // infoを使うと、正しいアイコンが取れない場合がある…なぜ?\r
272                 return m_IconFactory.icon(QFileInfo(info.absoluteFilePath()));\r
273             }\r
274         }\r
275         break;\r
276 \r
277     case Qt::FontRole:\r
278         return m_font;\r
279 \r
280     case Qt::TextAlignmentRole:\r
281         switch (index.column()) {\r
282         case 0:\r
283         case 1:\r
284             return Qt::AlignLeft + Qt::AlignVCenter;\r
285         case 2:\r
286         case 3:\r
287             return Qt::AlignRight + Qt::AlignVCenter;\r
288         }\r
289         break;\r
290 \r
291     case Qt::BackgroundRole:\r
292         if (checked) {\r
293             return m_MarkBrush;\r
294         }\r
295         return m_NormalBrush;\r
296 \r
297     case Qt::ForegroundRole:\r
298         if (checked) {\r
299             return m_MarkTextBrush;\r
300         }\r
301 #ifdef Q_OS_WIN32\r
302         {\r
303             DWORD dwFlags = ::GetFileAttributes(\r
304                         info.absoluteFilePath().toStdWString().c_str());\r
305             if (dwFlags != DWORD(-1) && (dwFlags & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM)\r
306             {\r
307                 return m_SystemBrush;\r
308             }\r
309         }\r
310 #endif\r
311         if (info.isHidden() && info.fileName() != "..") {\r
312             return m_HiddenBrush;\r
313         }\r
314         if (!info.isWritable()) {\r
315             return m_ReadonlyBrush;\r
316         }\r
317         return m_NormalTextBrush;\r
318 \r
319     case Qt::CheckStateRole:\r
320         if (index.column() == 0 && info.fileName() != "..") {\r
321             return checked;\r
322         }\r
323         break;\r
324     }\r
325 \r
326     return QVariant();\r
327 }\r
328 \r
329 QVariant FileTableModel::headerData(int section, Qt::Orientation orientation, int role) const\r
330 {\r
331     if (role == Qt::DisplayRole) {\r
332         if (orientation == Qt::Horizontal) {\r
333             switch (section) {\r
334             case 0: return QString("");\r
335             case 1: return tr("名前");\r
336             case 2: return tr("サイズ");\r
337             case 3: return tr("更新日時");\r
338             }\r
339         }\r
340     }\r
341     return QVariant();\r
342 }\r
343 \r
344 Qt::ItemFlags FileTableModel::flags(const QModelIndex &index) const\r
345 {\r
346     Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;\r
347     if (!index.isValid()) {\r
348         flags |= Qt::ItemIsDropEnabled;\r
349     }\r
350     else if (m_fileInfoList[index.row()].fileName() != "..") {\r
351         if (index.column() == 0) {\r
352             flags |= Qt::ItemIsUserCheckable;\r
353         }\r
354         flags |= Qt::ItemIsDropEnabled;\r
355     }\r
356     return flags;\r
357 }\r
358 \r
359 bool FileTableModel::setData(const QModelIndex &index, const QVariant &value, int role)\r
360 {\r
361     if (!index.isValid()) {\r
362         return false;\r
363     }\r
364 \r
365     switch (role) {\r
366     case Qt::CheckStateRole:\r
367         if (index.column() == 0) {\r
368             m_checkStates[index.row()] = static_cast<Qt::CheckState>(value.toInt());\r
369             emit dataChanged(index, this->index(index.row(), 3));\r
370             stateChanged();\r
371             return true;\r
372         }\r
373         break;\r
374     }\r
375 \r
376     return false;\r
377 }\r
378 \r
379 Qt::DropActions FileTableModel::supportedDropActions() const\r
380 {\r
381     return Qt::CopyAction | Qt::MoveAction;\r
382 }\r
383 \r
384 QStringList FileTableModel::mimeTypes() const\r
385 {\r
386     QStringList types;\r
387 \r
388     types << "text/uri-list";\r
389 \r
390     return types;\r
391 }\r