OSDN Git Service

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