OSDN Git Service

ドロップ処理のテスト
[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 #include <QMimeData>\r
10 #include <QUrl>\r
11 #include <QMessageBox>\r
12 #ifdef Q_OS_WIN32\r
13     #include <windows.h>\r
14 #endif\r
15 \r
16 FileTableModel::FileTableModel(QObject *parent) :\r
17     QAbstractTableModel(parent),\r
18     m_dir(),\r
19     m_fileInfoList(),\r
20     m_checkStates(),\r
21     m_IconFactory(),\r
22     m_fsWatcher(NULL),\r
23     m_font(),\r
24     m_NormalBrush(),\r
25     m_NormalTextBrush(),\r
26     m_MarkBrush(),\r
27     m_MarkTextBrush(),\r
28     m_SystemBrush(),\r
29     m_HiddenBrush(),\r
30     m_ReadonlyBrush()\r
31 {\r
32 }\r
33 \r
34 bool FileTableModel::setPath(const QString &path)\r
35 {\r
36     if (!QFileInfo::exists(path)) {\r
37         qDebug() << "パスが存在しません";\r
38         qDebug() << path;\r
39         return false;\r
40     }\r
41     QFileInfo info(path);\r
42     if (!info.isDir()) {\r
43         qDebug() << "フォルダではありません";\r
44         qDebug() << path;\r
45         return false;\r
46     }\r
47 \r
48     beginResetModel();\r
49 \r
50     m_dir.setPath(path);\r
51     m_fileInfoList = m_dir.entryInfoList();\r
52     m_checkStates.clear();\r
53 \r
54     if (m_fileInfoList.isEmpty()) {\r
55         qDebug() << "ファイルリストを取得できません";\r
56         qDebug() << path;\r
57     }\r
58     else {\r
59         QFileInfoList::iterator it, itRoot = m_fileInfoList.end();\r
60         for (it = m_fileInfoList.begin(); it != m_fileInfoList.end(); ) {\r
61             if (it->fileName() == "..") {\r
62                 if (m_dir.isRoot()) {\r
63                    it = m_fileInfoList.erase(it);\r
64                     itRoot = m_fileInfoList.end();\r
65                     continue;\r
66                 }\r
67                 else {\r
68                     itRoot = it;\r
69                 }\r
70             }\r
71 #ifdef Q_OS_WIN32\r
72             if (!(filter() & QDir::System)){\r
73                 DWORD dwFlags = ::GetFileAttributes(\r
74                             it->absoluteFilePath().toStdWString().c_str());\r
75                 if (dwFlags != DWORD(-1) && it->fileName() != ".." &&\r
76                     ((dwFlags & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM))\r
77                 {\r
78                     qDebug() << it->fileName() << " is system file.";\r
79                     it = m_fileInfoList.erase(it);\r
80                     continue;\r
81                 }\r
82             }\r
83 #endif\r
84             it++;\r
85         }\r
86         // ソート方法によらず、".."は必ず先頭にする\r
87         if (itRoot != m_fileInfoList.begin() && itRoot != m_fileInfoList.end()) {\r
88             QFileInfo info(*itRoot);\r
89             m_fileInfoList.erase(itRoot);\r
90             m_fileInfoList.push_front(info);\r
91         }\r
92     }\r
93 \r
94     m_checkStates.resize(m_fileInfoList.size());\r
95     m_checkStates.fill(Qt::Unchecked);\r
96 \r
97     if (m_fsWatcher) {\r
98         delete m_fsWatcher;\r
99     }\r
100     m_fsWatcher = new QFileSystemWatcher(this);\r
101     m_fsWatcher->addPath(path);\r
102     connect(m_fsWatcher, SIGNAL(directoryChanged(QString)),\r
103 //            this, SLOT(refresh()));\r
104             this, SIGNAL(listUpdated()));\r
105 \r
106     endResetModel();\r
107 \r
108     emit rootChanged(m_dir.absolutePath());\r
109     stateChanged();\r
110 \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     stateChanged();\r
132 }\r
133 \r
134 void FileTableModel::setCheckStateAll(Qt::CheckState state)\r
135 {\r
136     beginResetModel();\r
137     m_checkStates.fill(state);\r
138     if (state == Qt::Checked && m_fileInfoList.size() > 1 &&\r
139         m_fileInfoList[0].fileName() == "..")\r
140     {\r
141         m_checkStates[0] = Qt::Unchecked;\r
142     }\r
143     endResetModel();\r
144 \r
145     stateChanged();\r
146 }\r
147 \r
148 \r
149 bool FileTableModel::isDir(const QModelIndex &index) const\r
150 {\r
151     return m_fileInfoList[index.row()].isDir();\r
152 }\r
153 \r
154 const QString FileTableModel::absoluteFilePath(const QModelIndex &index) const\r
155 {\r
156     return m_dir.absoluteFilePath(m_fileInfoList[index.row()].fileName());\r
157 }\r
158 \r
159 QFileInfo FileTableModel::fileInfo(const QModelIndex &index) const\r
160 {\r
161     return m_fileInfoList[index.row()];\r
162 }\r
163 \r
164 #define Brush(x, y, z)  QBrush((x).value((y), (z)).value<QColor>());\r
165 \r
166 \r
167 void FileTableModel::updateAppearance()\r
168 {\r
169     QSettings settings;\r
170     QPalette palette(QApplication::palette("QTableView"));\r
171 \r
172     m_font = settings.value(IniKey_ViewFont, QApplication::font()).value<QFont>();\r
173     m_NormalBrush = Brush(settings, IniKey_ViewColorBgNormal, palette.base());\r
174     m_NormalTextBrush = Brush(settings, IniKey_ViewColorFgNormal, palette.text());\r
175     m_MarkBrush = Brush(settings, IniKey_ViewColorBgMark, DefaultMarkBgColor);\r
176     m_MarkTextBrush = Brush(settings, IniKey_ViewColorFgMark, DefaultMarkFgColor);\r
177     m_SystemBrush = Brush(settings, IniKey_ViewColorFgSystem, DefaultSystemColor);\r
178     m_HiddenBrush = Brush(settings, IniKey_ViewColorFgHidden, DefaultHiddenColor);\r
179     m_ReadonlyBrush = Brush(settings, IniKey_ViewColorFgReadonly, DefaultReadonlyColor);\r
180 \r
181     beginResetModel();\r
182     endResetModel();\r
183 }\r
184 \r
185 //void FileTableModel::refresh()\r
186 //{\r
187 //    setPath(m_dir.absolutePath());\r
188 \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 //        TODO\r
355 //        flags |= Qt::ItemIsDragEnabled;\r
356         flags |= Qt::ItemIsDropEnabled;\r
357     }\r
358     return flags;\r
359 }\r
360 \r
361 bool FileTableModel::setData(const QModelIndex &index, const QVariant &value, int role)\r
362 {\r
363     if (!index.isValid()) {\r
364         return false;\r
365     }\r
366 \r
367     switch (role) {\r
368     case Qt::CheckStateRole:\r
369         if (index.column() == 0) {\r
370             m_checkStates[index.row()] = static_cast<Qt::CheckState>(value.toInt());\r
371             emit dataChanged(index, this->index(index.row(), 3));\r
372             stateChanged();\r
373             return true;\r
374         }\r
375         break;\r
376     }\r
377 \r
378     return false;\r
379 }\r
380 \r
381 Qt::DropActions FileTableModel::supportedDropActions() const\r
382 {\r
383     return Qt::CopyAction | Qt::MoveAction;\r
384 }\r
385 \r
386 QStringList FileTableModel::mimeTypes() const\r
387 {\r
388     QStringList types;\r
389 \r
390     types << "text/uri-list";\r
391 \r
392     return types;\r
393 }\r
394 \r
395 bool FileTableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)\r
396 {\r
397     Q_UNUSED(parent);\r
398 \r
399     qDebug() << action << row << column;\r
400 \r
401     if (action == Qt::IgnoreAction)\r
402         return true;\r
403 \r
404     if (!data->hasFormat("text/uri-list"))\r
405         return false;\r
406 \r
407     if (column > 0)\r
408         return false;\r
409 \r
410     QString msg;\r
411     msg = "ドロップを検知しました。<br/>";\r
412     foreach (const QUrl &url, data->urls()) {\r
413         msg += url.toLocalFile() + "<br/>";\r
414         qDebug() << url.toLocalFile();\r
415     }\r
416     QMessageBox::information(NULL, "info", msg);\r
417 \r
418     return true;\r
419 }\r