OSDN Git Service

Ver0.13
[gefu/Gefu.git] / folderview.cpp
1 #include "common.h"
2 #include "folderview.h"
3
4 #include <QDebug>
5 #include <QHeaderView>
6 #include <QKeyEvent>
7 #include <QSettings>
8 #include <QMimeData>
9 #include <QApplication>
10 #include <QDrag>
11 #include <QMenu>
12
13 QString FilesizeToString(quint64 size)
14 {
15     if (size >= 1024 * 1024 * 1024) {
16         return QString("%1GB").arg(int(10 * size / (1024 * 1024 * 1024)) / 10);
17     }
18     if (size >= 1024 * 1024) {
19         return QString("%1MB").arg(int(10 * size / (1024 * 1024)) / 10);
20     }
21     if (size >= 1024) {
22         return QString("%1KB").arg(int(10 * size / (1024)) / 10);
23     }
24     return QString("%1B").arg(size);
25 }
26
27 FolderView::FolderView(QWidget *parent) :
28     QTableView(parent),
29     m_model(),
30     m_dragStartPos(),
31     m_dragging(false)
32 {
33     setModel(&m_model);
34     connect(&m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(dataChanged(QModelIndex,QModelIndex)));
35
36     setDragEnabled(true);
37     setAcceptDrops(true);
38     setDropIndicatorShown(true);
39
40     setContextMenuPolicy(Qt::DefaultContextMenu);
41 }
42
43 QString FolderView::side() const
44 {
45     if (this->objectName() == "folderView1") {
46         return QString("Left");
47     }
48     else {
49         Q_ASSERT(this->objectName() == "folderView2");
50         return QString("Right");
51     }
52 }
53
54 void FolderView::initialize()
55 {
56     qDebug() << side() << "initialize";
57
58     setColumnWidth(0, 30);
59
60     QHeaderView *header;
61     // 列のリサイズモードを設定する
62     header = horizontalHeader();
63     header->setSectionResizeMode(QHeaderView::ResizeToContents);
64     header->setSectionResizeMode(0, QHeaderView::Fixed);
65     header->setSectionResizeMode(1, QHeaderView::Stretch);
66
67     // 前回終了時のパスを開く
68     QSettings settings;
69     setPath(settings.value(side() + slash + IniKey_Dir).toString(), true);
70
71     // 色とフォントを設定する
72     updateAppearance();
73 }
74
75 void FolderView::updateAppearance()
76 {
77     qDebug() << side() << "updateAppearance";
78     m_model.updateAppearance();
79
80     QSettings settings;
81     QPalette pal = palette();
82     pal.setColor(QPalette::Base, settings.value(IniKey_ViewColorBgNormal).value<QColor>());
83     setPalette(pal);
84
85     // 行の高さを設定する
86     QHeaderView *header = verticalHeader();
87     header->setDefaultSectionSize(QFontMetrics(m_model.font()).height() * 1.5);
88 }
89
90 void FolderView::refresh()
91 {
92     qDebug() << side() << "refresh";
93
94     int row = currentIndex().row();
95
96     setPath(m_model.absolutePath(), false);
97
98     if (row < 0) {
99         row = 0;
100     }
101     else if (row >= m_model.rowCount()) {
102         row = m_model.rowCount() - 1;
103     }
104     setCurrentIndex(m_model.index(row, 0));
105     selectRow(row);
106 }
107
108 void FolderView::searchItem(const QString &text)
109 {
110     qDebug() << "FolderView::searchItem" << text;
111
112     for (int row = 0; row < m_model.rowCount(); row++) {
113         QModelIndex index = m_model.index(row, 0);
114         QString name = m_model.fileInfo(index).fileName().toLower();
115         if (name.indexOf(text.toLower()) != -1) {
116             setCurrentIndex(index);
117             emit itemFound();
118             return;
119         }
120     }
121
122     emit itemNotFound();
123 }
124
125 void FolderView::searchNext(const QString &text)
126 {
127     qDebug() << "FolderView::searchNext" << text;
128
129     for (int row = currentIndex().row() + 1; row < m_model.rowCount(); row++) {
130         QModelIndex index = m_model.index(row, 0);
131         QString name = m_model.fileInfo(index).fileName().toLower();
132         if (name.indexOf(text.toLower()) != -1) {
133             setCurrentIndex(index);
134             emit itemFound();
135             return;
136         }
137     }
138
139     emit itemNotFound();
140 }
141
142 void FolderView::searchPrev(const QString &text)
143 {
144     qDebug() << side() << "searchPrev" << text;
145
146     for (int row = currentIndex().row() - 1; row >= 0; row--) {
147         QModelIndex index = m_model.index(row, 0);
148         QString name = m_model.fileInfo(index).fileName().toLower();
149         if (name.indexOf(text.toLower()) != -1) {
150             setCurrentIndex(index);
151             emit itemFound();
152             return;
153         }
154     }
155
156     emit itemNotFound();
157 }
158
159 void FolderView::setCheckStateAll(bool checked)
160 {
161     qDebug() << side() << "markAll();";
162
163     QModelIndex current = currentIndex();
164
165     setUpdatesEnabled(false);
166     m_model.setCheckStateAll(checked ? Qt::Checked : Qt::Unchecked);
167     setUpdatesEnabled(true);
168
169     setCurrentIndex(current);
170 }
171
172 void FolderView::setCheckStateAllFiles()
173 {
174     qDebug() << side() << "markAllFiles();";
175
176     QModelIndex current = currentIndex();
177
178     setUpdatesEnabled(false);
179     for (int n = 0; n < m_model.rowCount(); n++) {
180         QModelIndex index = m_model.index(n, 0);
181         QFileInfo info = m_model.fileInfo(index);
182         if (info.isDir()) {
183             m_model.setCheckState(index, Qt::Unchecked);
184         }
185         else {
186             m_model.setCheckState(index, Qt::Checked);
187         }
188     }
189     setUpdatesEnabled(true);
190
191     setCurrentIndex(current);
192 }
193
194 void FolderView::invertCheckState()
195 {
196     qDebug() << side() << "invertCheckState();";
197
198     QModelIndex current = currentIndex();
199
200     setUpdatesEnabled(false);
201     for (int n = 0; n < m_model.rowCount(); n++) {
202         QModelIndex index = m_model.index(n, 0);
203         if (m_model.checkState(index) == Qt::Checked) {
204             m_model.setCheckState(index, Qt::Unchecked);
205         }
206         else {
207             m_model.setCheckState(index, Qt::Checked);
208         }
209     }
210     setUpdatesEnabled(true);
211
212     setCurrentIndex(current);
213 }
214
215 void FolderView::toggleCheckState(const QModelIndex &index)
216 {
217     QFileInfo info = m_model.fileInfo(index);
218     if (info.fileName() != "..") {
219         if (m_model.checkState(index) == Qt::Checked) {
220             m_model.setCheckState(index, Qt::Unchecked);
221         }
222         else {
223             m_model.setCheckState(index, Qt::Checked);
224         }
225     }
226     // 最終行でなければ、次のアイテムに移動する
227     if (index.row() == m_model.rowCount() - 1) {
228         setCurrentIndex(index);
229     }
230     else if (index.row() < m_model.rowCount() - 1) {
231         setCurrentIndex(m_model.index(index.row() + 1, 1));
232     }
233 }
234
235 bool FolderView::historyBack()
236 {
237     if (!m_history.isBegin()) {
238         setPath(m_history.back(), false);
239         return true;
240     }
241     return false;
242 }
243
244 bool FolderView::historyForward()
245 {
246     if (!m_history.isEnd()) {
247         setPath(m_history.forward(), false);
248         return true;
249     }
250     return false;
251 }
252
253 QFileInfo FolderView::currentItem() const
254 {
255     qDebug() << "FolderView::currentItem";
256
257     Q_ASSERT(currentIndex().isValid());
258
259     return m_model.fileInfo(currentIndex());
260 }
261
262 QFileInfoList FolderView::checkedItems() const
263 {
264     qDebug() << side() << "checkedItems()";
265
266     return m_model.checkedItems();
267 }
268
269 QFileInfoList FolderView::selectedItems() const
270 {
271     qDebug() << side() << "selectedItems";
272
273     // マークされているアイテムを取得する
274     QFileInfoList list = m_model.checkedItems();
275
276     // 一つもマークされていなければ、カーソル位置のアイテムを取得する
277     if (list.isEmpty()) {
278         list << currentItem();
279     }
280
281     return list;
282 }
283
284 void FolderView::setPath(const QString &path, bool addHistory)
285 {
286     qDebug() << side() << "setPath" << path << addHistory;
287
288     Q_ASSERT(QFileInfo(path).isDir());
289
290     emit retrieveStarted(path);
291
292     setUpdatesEnabled(false);
293     m_model.setPath(path);
294     setCurrentIndex(m_model.index(0, 0));
295     setUpdatesEnabled(true);
296
297     if (addHistory) {
298         m_history.add(path);
299     }
300
301     emit retrieveFinished();
302 }
303
304 void FolderView::setFilter(QDir::Filters filter, bool enable)
305 {
306     qDebug() << side() << "setFilter" << enable;
307
308     if (enable) {
309         m_model.setFilter(m_model.filter() | filter);
310     }
311     else {
312         m_model.setFilter(m_model.filter() ^ filter);
313     }
314 }
315
316 void FolderView::setHistoryIndexAt(int index)
317 {
318     m_history.setAt(index);
319     setPath(m_history.current(), false);
320 }
321
322 void FolderView::setNameFilters(const QStringList &list)
323 {
324     m_model.setNameFilters(list);
325     refresh();
326 }
327
328 void FolderView::setSorting(QDir::SortFlags flags)
329 {
330     m_model.setSorting(flags);
331     refresh();
332 }
333
334 void FolderView::keyPressEvent(QKeyEvent *event)
335 {
336     qDebug() << side() << "keyPressEvent";
337
338     emit keyPressed(event);
339
340     if (!event->isAccepted()) {
341         QTableView::keyPressEvent(event);
342     }
343     else {
344         qDebug() << "KeyEvent accepted.";
345     }
346 }
347
348 void FolderView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
349 {
350     emit dataChanged();
351
352     QTableView::dataChanged(topLeft, bottomRight, roles);
353 }
354
355 void FolderView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
356 {
357     emit currentChanged(m_model.fileInfo(current));
358
359     QTableView::currentChanged(current, previous);
360 }
361
362 void FolderView::mousePressEvent(QMouseEvent *event)
363 {
364     if ((event->buttons() & Qt::LeftButton) || (event->buttons() & Qt::RightButton))
365     {
366         m_dragStartPos = event->pos();
367     }
368
369     QTableView::mousePressEvent(event);
370 }
371
372 void FolderView::mouseMoveEvent(QMouseEvent *event)
373 {
374     if (!(event->buttons() & Qt::LeftButton) &&
375             !(event->buttons() & Qt::RightButton))
376     {
377         QTableView::mouseMoveEvent(event);
378         return;
379     }
380     if ((event->pos() - m_dragStartPos).manhattanLength()
381             < QApplication::startDragDistance())
382     {
383         QTableView::mouseMoveEvent(event);
384         return;
385     }
386
387     QFileInfoList list = selectedItems();
388     if (list.isEmpty()) {
389         QTableView::mousePressEvent(event);
390         return;
391     }
392
393     QList<QUrl> urls;
394     foreach (const QFileInfo &info, list) {
395         urls << QUrl::fromLocalFile(info.absoluteFilePath());
396     }
397
398     QDrag *drag = new QDrag(this);
399     QMimeData *mimeData = new QMimeData;
400     mimeData->setUrls(urls);
401     drag->setMimeData(mimeData);
402
403     m_dragging = true;
404     if (event->buttons() & Qt::RightButton) {
405         drag->exec(Qt::CopyAction | Qt::MoveAction);
406     }
407     else {
408         drag->exec(Qt::CopyAction);
409     }
410     m_dragging = false;
411 }
412
413 void FolderView::dragEnterEvent(QDragEnterEvent *event)
414 {
415     if (event->mimeData()->hasUrls()) {
416         event->acceptProposedAction();
417         return;
418     }
419
420     QTableView::dragEnterEvent(event);
421 }
422
423 void FolderView::dropEvent(QDropEvent *event)
424 {
425     qDebug() << side() << "dropEvent();";
426
427     if (m_dragging) {
428         event->ignore();
429         return;
430     }
431
432     QFileInfoList list;
433     foreach (const QUrl &url, event->mimeData()->urls()) {
434         QString path = QFileInfo(url.toLocalFile()).canonicalFilePath();
435         if (!path.isEmpty()) {
436             list << path;
437         }
438         else {
439             qDebug() << "path is empty." << url;
440         }
441     }
442
443     if (list.isEmpty()) {
444         event->ignore();
445         return;
446     }
447
448     event->acceptProposedAction();
449
450     emit dropAccepted(list);
451 }
452
453
454 void FolderView::contextMenuEvent(QContextMenuEvent *event)
455 {
456     qDebug() << side() << "contextMenuEvent();";
457
458     emit requestContextMenu(event);
459 }