OSDN Git Service

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