OSDN Git Service

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