OSDN Git Service

ショートカットキーのMac対応
[gefu/Gefu.git] / mainwindow.cpp
1 #include "copymoveworker.h"\r
2 #include "deleteworker.h"\r
3 #include "mainwindow.h"\r
4 #include "operationdialog.h"\r
5 #include "overwritedialog.h"\r
6 #include "renamemultidialog.h"\r
7 #include "renamesingledialog.h"\r
8 #include "renameworker.h"\r
9 #include "sortdialog.h"\r
10 #include "ui_mainwindow.h"\r
11 #include <QFileSystemModel>\r
12 #include <QDebug>\r
13 #include <QKeyEvent>\r
14 #include <QDesktopServices>\r
15 #include <QSettings>\r
16 #include <QFileDialog>\r
17 #include <QMessageBox>\r
18 #include <QProcess>\r
19 #include <QThread>\r
20 #include <QInputDialog>\r
21 \r
22 MainWindow::MainWindow(QWidget *parent) :\r
23     QMainWindow(parent),\r
24     ui(new Ui::MainWindow)\r
25 {\r
26     ui->setupUi(this);\r
27     ui->LPanel->setSide("Left");\r
28     ui->RPanel->setSide("Right");\r
29 \r
30     QSettings settings;\r
31     if (settings.value(IniKey_ShowHidden, false).toBool()) {\r
32         ui->view_Hidden->setChecked(true);\r
33     }\r
34     if (settings.value(IniKey_ShowSystem, false).toBool()) {\r
35         ui->view_System->setChecked(true);\r
36     }\r
37 \r
38     // メニューのシグナル/スロットを設定する\r
39     connect(ui->action_Command, SIGNAL(triggered()), this, SLOT(onActionCommand()));\r
40     connect(ui->action_Exec, SIGNAL(triggered()), this, SLOT(onActionExec()));\r
41     connect(ui->action_Open, SIGNAL(triggered()), this, SLOT(onActionOpen()));\r
42     connect(ui->action_Quit, SIGNAL(triggered()), this, SLOT(onActionQuit()));\r
43     connect(ui->action_Setting, SIGNAL(triggered()), this, SLOT(onActionSetting()));\r
44 \r
45     connect(ui->mark_All, SIGNAL(triggered()), this, SLOT(onMarkAll()));\r
46     connect(ui->mark_AllFiles, SIGNAL(triggered()), this, SLOT(onMarkAllFiles()));\r
47     connect(ui->mark_AllOff, SIGNAL(triggered()), this, SLOT(onMarkAllOff()));\r
48     connect(ui->mark_Invert, SIGNAL(triggered()), this, SLOT(onMarkInvert()));\r
49     connect(ui->mark_Toggle, SIGNAL(triggered()), this, SLOT(onMarkToggle()));\r
50 \r
51     connect(ui->move_Down, SIGNAL(triggered()), this, SLOT(onMoveCursorDown()));\r
52     connect(ui->move_Up, SIGNAL(triggered()), this, SLOT(onMoveCursorUp()));\r
53     connect(ui->move_Begin, SIGNAL(triggered()), this, SLOT(onMoveCursorBegin()));\r
54     connect(ui->move_End, SIGNAL(triggered()), this, SLOT(onMoveCursorEnd()));\r
55     connect(ui->move_Back, SIGNAL(triggered()), this, SLOT(onMoveBack()));\r
56     connect(ui->move_Forward, SIGNAL(triggered()), this, SLOT(onMoveForward()));\r
57     connect(ui->move_Home, SIGNAL(triggered()), this, SLOT(onMoveHome()));\r
58     connect(ui->move_Jump, SIGNAL(triggered()), this, SLOT(onMoveJump()));\r
59     connect(ui->move_Parent, SIGNAL(triggered()), this, SLOT(onMoveParent()));\r
60     connect(ui->move_Root, SIGNAL(triggered()), this, SLOT(onMoveRoot()));\r
61 \r
62     connect(ui->view_FromOther, SIGNAL(triggered()), this, SLOT(onViewFromOther()));\r
63     connect(ui->view_ToOther, SIGNAL(triggered()), this, SLOT(onViewToOther()));\r
64     connect(ui->view_Hidden, SIGNAL(triggered()), this, SLOT(onViewHidden()));\r
65     connect(ui->view_Sort, SIGNAL(triggered()), this, SLOT(onViewSort()));\r
66     connect(ui->view_Swap, SIGNAL(triggered()), this, SLOT(onViewSwap()));\r
67     connect(ui->view_System, SIGNAL(triggered()), this, SLOT(onViewSystem()));\r
68 \r
69     connect(ui->cmd_Copy, SIGNAL(triggered()), this, SLOT(onCmdCopy()));\r
70     connect(ui->cmd_Delete, SIGNAL(triggered()), this, SLOT(onCmdDelete()));\r
71     connect(ui->cmd_Move, SIGNAL(triggered()), this, SLOT(onCmdMove()));\r
72     connect(ui->cmd_NewFile, SIGNAL(triggered()), this, SLOT(onCmdNewFile()));\r
73     connect(ui->cmd_NewFolder, SIGNAL(triggered()), this, SLOT(onCmdNewFolder()));\r
74     connect(ui->cmd_Rename, SIGNAL(triggered()), this, SLOT(onCmdRename()));\r
75 \r
76     connect(ui->help_About, SIGNAL(triggered()), this, SLOT(onHelpAbout()));\r
77 \r
78     // ウィンドウタイトルを設定する\r
79     setWindowTitle(tr("げふぅ v%1").arg(VERSION_VALUE));\r
80     // ウィンドウアイコンを設定する\r
81     setWindowIcon(QIcon(":/images/Gefu.png"));\r
82 \r
83     // ウィンドウ初期サイズを設定する\r
84     resize(800, 600);\r
85 \r
86 \r
87     int sortBy, orderBy;\r
88     // 左ペインのソート初期値\r
89     QDir *dir;\r
90     dir = ui->LPanel->dir();\r
91     dir->setSorting(QDir::Name);  // 0\r
92 \r
93     sortBy = settings.value(IniKey_LeftSortBy, SortByName).toInt();\r
94     switch (sortBy) {\r
95     case SortByDate:    dir->setSorting(dir->sorting() | QDir::Time); break;\r
96     case SortBySize:    dir->setSorting(dir->sorting() | QDir::Size); break;\r
97     case SortByType:    dir->setSorting(dir->sorting() | QDir::Type); break;\r
98     default:            dir->setSorting(dir->sorting() | QDir::Name); break;\r
99     }\r
100 \r
101     // デフォルトだと文字列は昇順で、数値は降順…orz\r
102     orderBy = settings.value(IniKey_LeftOrderBy, OrderByDesc).toInt();\r
103     if (((sortBy == SortByName || sortBy == SortByType) && orderBy == OrderByDesc) ||\r
104         ((sortBy == SortByDate || sortBy == SortBySize) && orderBy == OrderByAsc))\r
105     {\r
106         dir->setSorting(dir->sorting() | QDir::Reversed);\r
107     }\r
108 \r
109     switch (settings.value(IniKey_LeftPutDirs, PutDirsFirst).toInt()) {\r
110     case PutDirsFirst:  dir->setSorting(dir->sorting() | QDir::DirsFirst); break;\r
111     case PutDirsLast:   dir->setSorting(dir->sorting() | QDir::DirsLast); break;\r
112     }\r
113 \r
114     if (settings.value(IniKey_LeftIgnoreCase, true).toBool()) {\r
115         dir->setSorting(dir->sorting() | QDir::IgnoreCase);\r
116     }\r
117 \r
118     // 右ペインのソート初期値\r
119     dir = ui->RPanel->dir();\r
120     dir->setSorting(QDir::Name);  // 0\r
121 \r
122     sortBy = settings.value(IniKey_RightSortBy, SortByName).toInt();\r
123     switch (sortBy) {\r
124     case SortByDate:    dir->setSorting(dir->sorting() | QDir::Time); break;\r
125     case SortBySize:    dir->setSorting(dir->sorting() | QDir::Size); break;\r
126     case SortByType:    dir->setSorting(dir->sorting() | QDir::Type); break;\r
127     default:            dir->setSorting(dir->sorting() | QDir::Name); break;\r
128     }\r
129 \r
130     // デフォルトだと文字列は昇順で、数値は降順…orz\r
131     orderBy = settings.value(IniKey_RightOrderBy, OrderByDesc).toInt();\r
132     if (((sortBy == SortByName || sortBy == SortByType) && orderBy == OrderByDesc) ||\r
133         ((sortBy == SortByDate || sortBy == SortBySize) && orderBy == OrderByAsc))\r
134     {\r
135         dir->setSorting(dir->sorting() | QDir::Reversed);\r
136     }\r
137 \r
138     switch (settings.value(IniKey_RightPutDirs, PutDirsFirst).toInt()) {\r
139     case PutDirsFirst:  dir->setSorting(dir->sorting() | QDir::DirsFirst); break;\r
140     case PutDirsLast:   dir->setSorting(dir->sorting() | QDir::DirsLast); break;\r
141     }\r
142 \r
143     if (settings.value(IniKey_RightIgnoreCase, true).toBool()) {\r
144         dir->setSorting(dir->sorting() | QDir::IgnoreCase);\r
145     }\r
146 \r
147     QString path;\r
148 \r
149     path = settings.value(IniKey_LeftDir, QDir::homePath()).toString();\r
150     ui->LPanel->setCurrentFolder(path);\r
151 \r
152     path = settings.value(IniKey_RightDir, QDir::homePath()).toString();\r
153     ui->RPanel->setCurrentFolder(path);\r
154 }\r
155 \r
156 MainWindow::~MainWindow()\r
157 {\r
158     QSettings settings;\r
159 \r
160     settings.setValue(IniKey_LeftDir, ui->LPanel->dir()->absolutePath());\r
161     settings.setValue(IniKey_RightDir, ui->RPanel->dir()->absolutePath());\r
162 \r
163     delete ui;\r
164 }\r
165 \r
166 void MainWindow::setStatusText(const QString &str)\r
167 {\r
168     ui->statusBar->showMessage(str);\r
169 }\r
170 \r
171 FolderPanel* MainWindow::activePanel()\r
172 {\r
173     if (ui->LPanel->fileTable()->hasFocus()) {\r
174         return ui->LPanel;\r
175     }\r
176     if (ui->RPanel->fileTable()->hasFocus()) {\r
177         return ui->RPanel;\r
178     }\r
179 \r
180     return NULL;\r
181 }\r
182 \r
183 FolderPanel* MainWindow::inactivePanel()\r
184 {\r
185     FolderPanel *fp = activePanel();\r
186     if (fp == ui->LPanel) {\r
187         return ui->RPanel;\r
188     }\r
189     if (fp == ui->RPanel) {\r
190         return ui->LPanel;\r
191     }\r
192 \r
193     return NULL;\r
194 }\r
195 \r
196 ///\r
197 /// \brief MainWindow::onActionCommand\r
198 ///\r
199 /// コマンドを実行します(X)\r
200 ///\r
201 void MainWindow::onActionCommand()\r
202 {\r
203     FolderPanel *fp = activePanel();\r
204     if (!fp) {\r
205         return;\r
206     }\r
207 \r
208     QString command = "";\r
209     for (int n = 0; n < fp->fileTable()->rowCount(); n++) {\r
210         if (fp->fileTable()->item(n, 0)->checkState() == Qt::Checked) {\r
211             QString path = fp->fileTable()->item(n, 1)->text();\r
212             path = fp->dir()->absoluteFilePath(path);\r
213             path = QDir::cleanPath(path);\r
214             path = QDir::toNativeSeparators(path);\r
215 \r
216             QFileInfo info(path);\r
217             if (info.isExecutable()) {\r
218                 command = "\"" + path + "\" " + command;\r
219             }\r
220             else {\r
221                 command += " \"" + path + "\"";\r
222             }\r
223         }\r
224     }\r
225 \r
226     if (command.isEmpty()) {\r
227         int row = fp->fileTable()->currentRow();\r
228         QString path = fp->fileTable()->item(row, 1)->text();\r
229         path = fp->dir()->absoluteFilePath(path);\r
230         path = QDir::cleanPath(path);\r
231         path = QDir::toNativeSeparators(path);\r
232 \r
233         command = "\"" + path + "\"";\r
234     }\r
235 \r
236     QInputDialog dlg(this);\r
237     dlg.setInputMode(QInputDialog::TextInput);\r
238     dlg.setLabelText(tr("コマンドを入力:"));\r
239     dlg.setWindowTitle(tr("コマンドを実行"));\r
240     dlg.setTextValue(command);\r
241     dlg.resize(500, 100);\r
242     int ret = dlg.exec();\r
243     command = dlg.textValue();\r
244     if (ret == QDialog::Accepted && !command.isEmpty()) {\r
245         QProcess process(this);\r
246         process.setWorkingDirectory(fp->dir()->absolutePath());\r
247         if (!process.startDetached(command)) {\r
248             QMessageBox::critical(\r
249                         this,\r
250                         tr("エラー"),\r
251                         tr("コマンドの実行に失敗しました。<br/>") + command);\r
252         }\r
253     }\r
254 }\r
255 \r
256 ///\r
257 /// \brief MainWindow::onActionExec\r
258 ///\r
259 /// アプリケーションで開きます(Shift + Enter)\r
260 ///\r
261 void MainWindow::onActionExec()\r
262 {\r
263     FolderPanel *fp = activePanel();\r
264     if (!fp) {\r
265         return;\r
266     }\r
267 \r
268     QStringList list = selectedItems(fp);\r
269     foreach (const QString &path, list) {\r
270         QDesktopServices::openUrl(QUrl("file:///" + QDir::toNativeSeparators(path)));\r
271     }\r
272 }\r
273 \r
274 ///\r
275 /// \brief MainWindow::onActionOpen\r
276 ///\r
277 /// フォルダを開きます(Enter)\r
278 ///\r
279 void MainWindow::onActionOpen()\r
280 {\r
281     FolderPanel *fp = activePanel();\r
282     if (!fp) {\r
283         return;\r
284     }\r
285 \r
286     int row = fp->fileTable()->currentRow();\r
287     QString path = fp->fileTable()->item(row, 1)->text();\r
288     path = fp->dir()->absoluteFilePath(path);\r
289     QFileInfo info(path);\r
290 \r
291     if (info.isDir()) {\r
292         fp->setCurrentFolder(path);\r
293     }\r
294 }\r
295 \r
296 ///\r
297 /// \brief MainWindow::onActionQuit\r
298 ///\r
299 /// アプリケーションを終了します(Q)\r
300 ///\r
301 void MainWindow::onActionQuit()\r
302 {\r
303     qApp->quit();\r
304 }\r
305 \r
306 ///\r
307 /// \brief MainWindow::onActionSetting\r
308 ///\r
309 /// 環境設定ダイアログを表示します(Z)\r
310 ///\r
311 void MainWindow::onActionSetting()\r
312 {\r
313     QMessageBox::information(this, tr("情報"), tr("環境設定機能は未実装です。"));\r
314 }\r
315 \r
316 ///\r
317 /// \brief MainWindow::on_mark_All_triggered\r
318 ///\r
319 /// すべてマークします(Shift + A)\r
320 ///\r
321 void MainWindow::onMarkAll()\r
322 {\r
323     FolderPanel *fp = activePanel();\r
324     if (fp == NULL) {\r
325         return;\r
326     }\r
327 \r
328     int row = 0;\r
329     if (fp->fileTable()->item(row, 1)->text() == "..") {\r
330         row++;\r
331     }\r
332 \r
333     fp->beginUpdate();\r
334     int curRow = fp->fileTable()->currentRow();\r
335     int rowCount = fp->fileTable()->rowCount();\r
336     for (; row < rowCount; row++) {\r
337         fp->fileTable()->item(row, 0)->setCheckState(Qt::Checked);\r
338     }\r
339     fp->fileTable()->setCurrentIndex(\r
340                 fp->fileTable()->model()->index(curRow, 1));\r
341     fp->endUpdate();\r
342 }\r
343 \r
344 ///\r
345 /// \brief MainWindow::onMarkAllFiles\r
346 ///\r
347 /// すべての「ファイル」をマークします(A)\r
348 ///\r
349 void MainWindow::onMarkAllFiles()\r
350 {\r
351     FolderPanel *fp = activePanel();\r
352     if (fp == NULL) {\r
353         return;\r
354     }\r
355 \r
356     int row = 0;\r
357     if (fp->fileTable()->item(row, 1)->text() == "..") {\r
358         row++;\r
359     }\r
360 \r
361     fp->beginUpdate();\r
362     int curRow = fp->fileTable()->currentRow();\r
363     int rowCount = fp->fileTable()->rowCount();\r
364     for (; row < rowCount; row++) {\r
365         QString path = fp->fileTable()->item(row, 1)->text();\r
366         path = fp->dir()->absoluteFilePath(path);\r
367 \r
368         QFileInfo info(path);\r
369         if (info.isDir()) {\r
370             fp->fileTable()->item(row, 0)->setCheckState(Qt::Unchecked);\r
371         }\r
372         else {\r
373            fp->fileTable()->item(row, 0)->setCheckState(Qt::Checked);\r
374         }\r
375     }\r
376     fp->fileTable()->setCurrentIndex(\r
377                 fp->fileTable()->model()->index(curRow, 1));\r
378     fp->endUpdate();\r
379 }\r
380 \r
381 ///\r
382 /// \brief MainWindow::onMarkAllOff\r
383 ///\r
384 /// すべてのマークを解除します(U)\r
385 ///\r
386 void MainWindow::onMarkAllOff()\r
387 {\r
388     FolderPanel *fp = activePanel();\r
389     if (fp == NULL) {\r
390         return;\r
391     }\r
392 \r
393     int row = 0;\r
394     if (fp->fileTable()->item(row, 1)->text() == "..") {\r
395         row++;\r
396     }\r
397 \r
398     fp->beginUpdate();\r
399     int curRow = fp->fileTable()->currentRow();\r
400     int rowCount = fp->fileTable()->rowCount();\r
401     for (; row < rowCount; row++) {\r
402         fp->fileTable()->item(row, 0)->setCheckState(Qt::Unchecked);\r
403     }\r
404     fp->fileTable()->setCurrentIndex(\r
405                 fp->fileTable()->model()->index(curRow, 1));\r
406     fp->endUpdate();\r
407 }\r
408 \r
409 ///\r
410 /// \brief MainWindow::onMarkInvert\r
411 ///\r
412 /// マークを反転します(I)\r
413 ///\r
414 void MainWindow::onMarkInvert()\r
415 {\r
416     FolderPanel *fp = activePanel();\r
417     if (fp == NULL) {\r
418         return;\r
419     }\r
420 \r
421     int row = 0;\r
422     if (fp->fileTable()->item(row, 1)->text() == "..") {\r
423         row++;\r
424     }\r
425 \r
426     fp->beginUpdate();\r
427     int curRow = fp->fileTable()->currentRow();\r
428     int rowCount = fp->fileTable()->rowCount();\r
429     for (; row < rowCount; row++) {\r
430         QTableWidgetItem *item = fp->fileTable()->item(row, 0);\r
431         if (item->checkState() == Qt::Checked) {\r
432             item->setCheckState(Qt::Unchecked);\r
433         }\r
434         else {\r
435             item->setCheckState(Qt::Checked);\r
436         }\r
437     }\r
438     fp->fileTable()->setCurrentIndex(\r
439                 fp->fileTable()->model()->index(curRow, 1));\r
440     fp->endUpdate();\r
441 }\r
442 \r
443 ///\r
444 /// \brief MainWindow::onMarkToggle\r
445 ///\r
446 /// マークを設定または解除します(Space)\r
447 ///\r
448 void MainWindow::onMarkToggle()\r
449 {\r
450     FolderPanel *fp = activePanel();\r
451     if (fp == NULL) {\r
452         return;\r
453     }\r
454 \r
455     int row = fp->fileTable()->currentRow();\r
456     QTableWidgetItem *item = fp->fileTable()->item(row, 0);\r
457     if (fp->fileTable()->item(row, 1)->text() != "..") {\r
458        if (item->checkState() == Qt::Checked) {\r
459             item->setCheckState(Qt::Unchecked);\r
460        }\r
461         else {\r
462             item->setCheckState(Qt::Checked);\r
463        }\r
464     }\r
465     // 最終行でなければ、次のアイテムに移動する\r
466     if (row < fp->fileTable()->rowCount() - 1) {\r
467         QModelIndex nextIndex = fp->fileTable()->model()->index(row + 1, 1);\r
468         fp->fileTable()->setCurrentIndex(nextIndex);\r
469     }\r
470 }\r
471 \r
472 ///\r
473 /// \brief MainWindow::onMoveCursorDown\r
474 ///\r
475 /// カーソルを下に移動します(J)\r
476 ///\r
477 void MainWindow::onMoveCursorDown()\r
478 {\r
479     FolderPanel *fp = activePanel();\r
480     if (fp == NULL) {\r
481         return;\r
482     }\r
483 \r
484     int row = fp->fileTable()->currentRow();\r
485     if (row < fp->fileTable()->rowCount() - 1) {\r
486         QModelIndex nextIndex = fp->fileTable()->model()->index(row + 1, 1);\r
487         fp->fileTable()->setCurrentIndex(nextIndex);\r
488     }\r
489 }\r
490 \r
491 ///\r
492 /// \brief MainWindow::onMoveCursorUp\r
493 ///\r
494 /// カーソルを上に移動します(K)\r
495 ///\r
496 void MainWindow::onMoveCursorUp()\r
497 {\r
498     FolderPanel *fp = activePanel();\r
499     if (fp == NULL) {\r
500         return;\r
501     }\r
502 \r
503     int row = fp->fileTable()->currentRow();\r
504     if (row > 0) {\r
505         QModelIndex nextIndex = fp->fileTable()->model()->index(row - 1, 1);\r
506         fp->fileTable()->setCurrentIndex(nextIndex);\r
507     }\r
508 }\r
509 \r
510 ///\r
511 /// \brief MainWindow::onMoveCursorBegin\r
512 ///\r
513 /// カーソルを先頭に移動します(G)\r
514 ///\r
515 void MainWindow::onMoveCursorBegin()\r
516 {\r
517     FolderPanel *fp = activePanel();\r
518     if (fp == NULL) {\r
519         return;\r
520     }\r
521 \r
522     QModelIndex nextIndex = fp->fileTable()->model()->index(0, 1);\r
523     fp->fileTable()->setCurrentIndex(nextIndex);\r
524 }\r
525 \r
526 ///\r
527 /// \brief MainWindow::onMoveCursorEnd\r
528 ///\r
529 /// カーソルを末尾に移動します(Shift + G)\r
530 void MainWindow::onMoveCursorEnd()\r
531 {\r
532     FolderPanel *fp = activePanel();\r
533     if (fp == NULL) {\r
534         return;\r
535     }\r
536 \r
537     int row = fp->fileTable()->rowCount() - 1;\r
538     QModelIndex nextIndex = fp->fileTable()->model()->index(row, 1);\r
539     fp->fileTable()->setCurrentIndex(nextIndex);\r
540 }\r
541 \r
542 ///\r
543 /// \brief MainWindow::onMoveBack\r
544 ///\r
545 /// 前の履歴に戻ります(Alt + ←)\r
546 ///\r
547 void MainWindow::onMoveBack()\r
548 {\r
549     QMessageBox::information(this, tr("情報"), tr("履歴機能は未実装です。"));\r
550 }\r
551 \r
552 ///\r
553 /// \brief MainWindow::onMoveForward\r
554 ///\r
555 /// 次の履歴に進みます(Alt + →)\r
556 ///\r
557 void MainWindow::onMoveForward()\r
558 {\r
559     QMessageBox::information(this, tr("情報"), tr("履歴機能は未実装です。"));\r
560 \r
561 }\r
562 \r
563 ///\r
564 /// \brief MainWindow::onMoveHome\r
565 ///\r
566 /// ホームフォルダに移動します(H)\r
567 ///\r
568 void MainWindow::onMoveHome()\r
569 {\r
570     FolderPanel *fp = activePanel();\r
571     if (fp == NULL) {\r
572         return;\r
573     }\r
574 \r
575     fp->setCurrentFolder(QDir::homePath());\r
576 }\r
577 \r
578 ///\r
579 /// \brief MainWindow::onMoveJump\r
580 ///\r
581 /// フォルダを選択して移動します(Shift + J)\r
582 void MainWindow::onMoveJump()\r
583 {\r
584     FolderPanel *fp = activePanel();\r
585     if (fp == NULL) {\r
586         return;\r
587     }\r
588 \r
589     QString path = QFileDialog::getExistingDirectory(\r
590                 this,\r
591                 tr("フォルダを選択"),\r
592                 fp->dir()->absolutePath());\r
593     if (!path.isEmpty()) {\r
594         fp->setCurrentFolder(path);\r
595     }\r
596 }\r
597 \r
598 ///\r
599 /// \brief MainWindow::onMoveOther\r
600 ///\r
601 /// キーボードフォーカスを他方のパネルに移動します(TAB)\r
602 ///\r
603 void MainWindow::onMoveOther()\r
604 {\r
605     FolderPanel *fp = this->inactivePanel();\r
606     if (fp) {\r
607         fp->fileTable()->setFocus();\r
608     }\r
609 }\r
610 \r
611 ///\r
612 /// \brief MainWindow::onMoveParent\r
613 ///\r
614 /// 親フォルダに移動します(Backspace)\r
615 ///\r
616 void MainWindow::onMoveParent()\r
617 {\r
618     FolderPanel *fp = activePanel();\r
619     if (fp == NULL) {\r
620         return;\r
621     }\r
622 \r
623     if (!fp->dir()->isRoot()) {\r
624         QString path = fp->dir()->absoluteFilePath("..");\r
625         fp->setCurrentFolder(path);\r
626     }\r
627 }\r
628 \r
629 ///\r
630 /// \brief MainWindow::onMoveRoot\r
631 ///\r
632 /// ルートフォルダに移動します()\r
633 void MainWindow::onMoveRoot()\r
634 {\r
635     FolderPanel *fp = activePanel();\r
636     if (fp == NULL) {\r
637         return;\r
638     }\r
639 \r
640     if (!fp->dir()->isRoot()) {\r
641         fp->setCurrentFolder(QDir::rootPath());\r
642     }\r
643 }\r
644 \r
645 ///\r
646 /// \brief MainWindow::onViewFromOther\r
647 ///\r
648 /// 隣のパネルと同じフォルダを表示します(O)\r
649 ///\r
650 void MainWindow::onViewFromOther()\r
651 {\r
652     FolderPanel *fp1 = activePanel();\r
653     FolderPanel *fp2 = inactivePanel();\r
654     if (fp1 == NULL || fp2 == NULL) {\r
655         return;\r
656     }\r
657 \r
658     fp1->setCurrentFolder(fp2->dir()->absolutePath());\r
659 }\r
660 \r
661 ///\r
662 /// \brief MainWindow::onViewToOther\r
663 ///\r
664 /// 隣のパネルに同じフォルダを表示します(Shift + O)\r
665 ///\r
666 void MainWindow::onViewToOther()\r
667 {\r
668     FolderPanel *fp1 = activePanel();\r
669     FolderPanel *fp2 = inactivePanel();\r
670     if (fp1 == NULL || fp2 == NULL) {\r
671         return;\r
672     }\r
673 \r
674     fp2->setCurrentFolder(fp1->dir()->absolutePath());\r
675 }\r
676 \r
677 ///\r
678 /// \brief MainWindow::onViewHidden\r
679 ///\r
680 /// 隠しファイルの表示/非表示を切り替えます(Shift + H)\r
681 ///\r
682 void MainWindow::onViewHidden()\r
683 {\r
684     QSettings settings;\r
685     bool checked = !settings.value(IniKey_ShowHidden, false).toBool();\r
686     settings.setValue(IniKey_ShowHidden, checked);\r
687     ui->view_Hidden->setChecked(checked);\r
688 #if 1\r
689     if (checked) {\r
690         ui->LPanel->dir()->setFilter(ui->LPanel->dir()->filter() | QDir::Hidden);\r
691         ui->RPanel->dir()->setFilter(ui->RPanel->dir()->filter() | QDir::Hidden);\r
692     }\r
693     else {\r
694         ui->LPanel->dir()->setFilter(ui->LPanel->dir()->filter() ^ QDir::Hidden);\r
695         ui->RPanel->dir()->setFilter(ui->RPanel->dir()->filter() ^ QDir::Hidden);\r
696     }\r
697 #endif\r
698     ui->LPanel->setCurrentFolder(ui->LPanel->dir()->absolutePath());\r
699     ui->RPanel->setCurrentFolder(ui->RPanel->dir()->absolutePath());\r
700 }\r
701 \r
702 void MainWindow::onViewSort()\r
703 {\r
704     FolderPanel *fp = activePanel();\r
705     if (!fp) {\r
706         return;\r
707     }\r
708 \r
709     QString iniSec;\r
710     SortDialog dlg(this);\r
711     if (fp == ui->LPanel) {\r
712         iniSec = IniSec_Left;\r
713     }\r
714     else {\r
715         iniSec = IniSec_Right;\r
716     }\r
717 \r
718     dlg.setRightOrLeft(iniSec);\r
719     if (dlg.exec() == QDialog::Accepted) {\r
720         QSettings settings;\r
721         QDir *dir = fp->dir();\r
722         dir->setSorting(QDir::Name);  // 0\r
723 \r
724         int sortBy = settings.value(iniSec + slash + IniKey_SortBy, 0).toInt();\r
725         switch (sortBy) {\r
726         case SortByDate:    dir->setSorting(dir->sorting() | QDir::Time); break;\r
727         case SortBySize:    dir->setSorting(dir->sorting() | QDir::Size); break;\r
728         case SortByType:    dir->setSorting(dir->sorting() | QDir::Type); break;\r
729         default:            dir->setSorting(dir->sorting() | QDir::Name); break;\r
730         }\r
731 \r
732         // デフォルトだと文字列は昇順で、数値は降順…orz\r
733         int orderBy = settings.value(iniSec + slash + IniKey_OrderBy, 0).toInt();\r
734         if (((sortBy == SortByName || sortBy == SortByType) && orderBy == OrderByDesc) ||\r
735             ((sortBy == SortByDate || sortBy == SortBySize) && orderBy == OrderByAsc))\r
736         {\r
737             dir->setSorting(dir->sorting() | QDir::Reversed);\r
738         }\r
739 \r
740         switch (settings.value(iniSec + slash + IniKey_PutDirs, 0).toInt()) {\r
741         case PutDirsFirst:  dir->setSorting(dir->sorting() | QDir::DirsFirst); break;\r
742         case PutDirsLast:   dir->setSorting(dir->sorting() | QDir::DirsLast); break;\r
743         }\r
744 \r
745         if (settings.value(iniSec + slash + IniKey_IgnoreCase, true).toBool()) {\r
746             dir->setSorting(dir->sorting() | QDir::IgnoreCase);\r
747         }\r
748 \r
749         fp->setCurrentFolder(fp->dir()->absolutePath());\r
750     }\r
751 }\r
752 \r
753 ///\r
754 /// \brief MainWindow::onViewSwap\r
755 ///\r
756 /// パネルの表示内容を交換します(W)\r
757 ///\r
758 void MainWindow::onViewSwap()\r
759 {\r
760     FolderPanel *fp1 = activePanel();\r
761     FolderPanel *fp2 = inactivePanel();\r
762     if (fp1 == NULL || fp2 == NULL) {\r
763         return;\r
764     }\r
765 \r
766     QString path1 = fp1->dir()->absolutePath();\r
767     QString path2 = fp2->dir()->absolutePath();\r
768 \r
769     fp1->setCurrentFolder(path2);\r
770     fp2->setCurrentFolder(path1);\r
771 }\r
772 \r
773 ///\r
774 /// \brief MainWindow::onViewSystem\r
775 ///\r
776 /// システムファイルの表示/非表示を切り替えます(Shift + H)\r
777 ///\r
778 void MainWindow::onViewSystem()\r
779 {\r
780     QSettings settings;\r
781     bool checked = !settings.value(IniKey_ShowSystem, false).toBool();\r
782     settings.setValue(IniKey_ShowSystem, checked);\r
783     ui->view_System->setChecked(checked);\r
784 #if 1\r
785     QDir *dirs[2];\r
786     dirs[0] = ui->LPanel->dir();\r
787     dirs[1] = ui->RPanel->dir();\r
788     for (int n = 0; n < 2; n++) {\r
789         if (checked) {\r
790             dirs[n]->setFilter(dirs[n]->filter() | QDir::System);\r
791         }\r
792         else {\r
793             dirs[n]->setFilter(dirs[n]->filter() ^ QDir::System);\r
794         }\r
795     }\r
796 #endif\r
797     ui->LPanel->setCurrentFolder(ui->LPanel->dir()->absolutePath());\r
798     ui->RPanel->setCurrentFolder(ui->RPanel->dir()->absolutePath());\r
799 }\r
800 \r
801 ///\r
802 /// \brief MainWindow::onCmdMove\r
803 ///\r
804 /// ファイルを移動します(Ctrl + M)\r
805 ///\r
806 void MainWindow::onCmdMove()\r
807 {\r
808     FolderPanel *fp = activePanel();\r
809     if (!fp) {\r
810         return;\r
811     }\r
812 \r
813     QStringList list = selectedItems(fp);\r
814     if (list.isEmpty()) {\r
815         return;\r
816     }\r
817 \r
818     CopyMoveWorker *worker = new CopyMoveWorker();\r
819     connect(worker, SIGNAL(askOverWrite(bool*,int*,int*,QString*,QString,QString)),\r
820             this, SLOT(onAskOverWrite(bool*,int*,int*,QString*,QString,QString)));\r
821     worker->setCopyList(&list);\r
822     worker->setTargetDir(inactivePanel()->dir()->absolutePath());\r
823     worker->setMoveMode(true);\r
824 \r
825     OperationDialog opDlg(this);\r
826     opDlg.setWindowTitle(tr("移動"));\r
827     opDlg.setWorker(worker);\r
828 \r
829     ui->LPanel->UninstallWatcher();\r
830     ui->RPanel->UninstallWatcher();\r
831     opDlg.exec();\r
832     ui->LPanel->setCurrentFolder(ui->LPanel->dir()->absolutePath());\r
833     ui->RPanel->setCurrentFolder(ui->RPanel->dir()->absolutePath());\r
834 \r
835 }\r
836 \r
837 ///\r
838 /// \brief MainWindow::onCmdCopy\r
839 ///\r
840 /// ファイルをコピーします(Ctrl + C)\r
841 ///\r
842 void MainWindow::onCmdCopy()\r
843 {\r
844     FolderPanel *fp = activePanel();\r
845     if (!fp) {\r
846         return;\r
847     }\r
848 \r
849     QStringList list = selectedItems(fp);\r
850     if (list.isEmpty()) {\r
851         return;\r
852     }\r
853 \r
854     CopyMoveWorker *worker = new CopyMoveWorker();\r
855     connect(worker, SIGNAL(askOverWrite(bool*,int*,int*,QString*,QString,QString)),\r
856             this, SLOT(onAskOverWrite(bool*,int*,int*,QString*,QString,QString)));\r
857     worker->setCopyList(&list);\r
858     worker->setTargetDir(inactivePanel()->dir()->absolutePath());\r
859     worker->setMoveMode(false);\r
860 \r
861     OperationDialog opDlg(this);\r
862     opDlg.setWindowTitle(tr("コピー"));\r
863     opDlg.setWorker(worker);\r
864 \r
865     ui->LPanel->UninstallWatcher();\r
866     ui->RPanel->UninstallWatcher();\r
867     opDlg.exec();\r
868     ui->LPanel->setCurrentFolder(ui->LPanel->dir()->absolutePath());\r
869     ui->RPanel->setCurrentFolder(ui->RPanel->dir()->absolutePath());\r
870 \r
871 }\r
872 \r
873 ///\r
874 /// \brief MainWindow::onAskOverWrite\r
875 /// \param bOk\r
876 /// \param prevCopyMethod\r
877 /// \param copyMethod\r
878 /// \param alias\r
879 /// \param srcPath\r
880 /// \param tgtPath\r
881 ///\r
882 /// 上書き処理の方法をユーザに問い合わせます\r
883 ///\r
884 void MainWindow::onAskOverWrite(bool *bOk, int *prevCopyMethod, int *copyMethod,\r
885                                 QString *alias, const QString srcPath,\r
886                                 const QString tgtPath)\r
887 {\r
888     OverWriteDialog dlg;\r
889     dlg.setCopyMethod(*prevCopyMethod);\r
890     dlg.setSameMethodChecked(*copyMethod != OverWriteDialog::Undefined);\r
891     dlg.setFileInfo(srcPath, tgtPath);\r
892     if (dlg.exec() == QDialog::Rejected) {\r
893         *bOk = false;\r
894     }\r
895     else {\r
896         *prevCopyMethod = dlg.copyMethod();\r
897         if (dlg.isSameMethodChecked()) {\r
898             *copyMethod = *prevCopyMethod;\r
899         }\r
900         *alias = dlg.alias();\r
901         *bOk = true;\r
902     }\r
903     CopyMoveWorker *worker = static_cast<CopyMoveWorker*>(sender());\r
904     worker->endAsking();\r
905 }\r
906 \r
907 ///\r
908 /// \brief MainWindow::onCmdDelete\r
909 ///\r
910 /// ファイルを削除します\r
911 ///\r
912 void MainWindow::onCmdDelete()\r
913 {\r
914     FolderPanel *fp = activePanel();\r
915     if (!fp) {\r
916         return;\r
917     }\r
918 \r
919     QStringList list = selectedItems(fp);\r
920     if (list.isEmpty()) {\r
921         return;\r
922     }\r
923 \r
924     QString msg;\r
925     if (list.size() == 1) {\r
926         msg = QFileInfo(list.at(0)).fileName();\r
927     }\r
928     else {\r
929         msg = tr("%1個のアイテム").arg(list.size());\r
930     }\r
931     int ret = QMessageBox::question(\r
932                 this,\r
933                 tr("確認"),\r
934                 msg + tr("を削除します<br/>よろしいですか?"));\r
935     if (ret == QMessageBox::Yes) {\r
936         DeleteWorker *worker = new DeleteWorker();\r
937         worker->setDeleteList(&list);\r
938 \r
939         OperationDialog opDlg(this);\r
940         opDlg.setWindowTitle(tr("削除"));\r
941         opDlg.setWorker(worker);\r
942 \r
943         ui->LPanel->UninstallWatcher();\r
944         ui->RPanel->UninstallWatcher();\r
945         opDlg.exec();\r
946         ui->LPanel->setCurrentFolder(ui->LPanel->dir()->absolutePath());\r
947         ui->RPanel->setCurrentFolder(ui->RPanel->dir()->absolutePath());\r
948     }\r
949 }\r
950 \r
951 ///\r
952 /// \brief MainWindow::onCmdNewFile\r
953 ///\r
954 /// ファイルを作成します\r
955 ///\r
956 void MainWindow::onCmdNewFile()\r
957 {\r
958     FolderPanel *fp = activePanel();\r
959     if (!fp) {\r
960         return;\r
961     }\r
962 \r
963     bool bOk;\r
964     QString name = QInputDialog::getText(\r
965                 this,\r
966                 tr("ファイルを作成"),\r
967                 tr("ファイル名"),\r
968                 QLineEdit::Normal,\r
969                 "",\r
970                 &bOk);\r
971     if (bOk && !name.isEmpty()) {\r
972         QFile file(fp->dir()->absoluteFilePath(name));\r
973         if (!file.open(QIODevice::WriteOnly)) {\r
974             QMessageBox::critical(this,\r
975                                   tr("エラー"),\r
976                                   tr("ファイルの作成に失敗しました。"));\r
977         }\r
978         else {\r
979             file.close();\r
980         }\r
981     }\r
982 }\r
983 \r
984 ///\r
985 /// \brief MainWindow::onCmdNewFolder\r
986 ///\r
987 /// フォルダを作成します\r
988 ///\r
989 void MainWindow::onCmdNewFolder()\r
990 {\r
991     FolderPanel *fp = activePanel();\r
992     if (!fp) {\r
993         return;\r
994     }\r
995 \r
996     bool bOk;\r
997     QString name = QInputDialog::getText(\r
998                 this,\r
999                 tr("フォルダを作成"),\r
1000                 tr("フォルダ名"),\r
1001                 QLineEdit::Normal,\r
1002                 "",\r
1003                 &bOk);\r
1004     if (bOk && !name.isEmpty()) {\r
1005         if (!fp->dir()->mkpath(name)) {\r
1006             QMessageBox::critical(this,\r
1007                                   tr("エラー"),\r
1008                                   tr("フォルダの作成に失敗しました。"));\r
1009         }\r
1010     }\r
1011 }\r
1012 \r
1013 ///\r
1014 /// \brief MainWindow::onCmdRename\r
1015 ///\r
1016 /// 名前を変更します\r
1017 ///\r
1018 void MainWindow::onCmdRename()\r
1019 {\r
1020     FolderPanel *fp = activePanel();\r
1021     if (!fp) {\r
1022         return;\r
1023     }\r
1024 \r
1025     QStringList list = selectedItems(fp);\r
1026     if (list.isEmpty()) {\r
1027         return;\r
1028     }\r
1029 \r
1030     IRenameDialog *dlg;\r
1031     if (list.size() == 1) {\r
1032         dlg = new RenameSingleDialog(this);\r
1033     }\r
1034     else {\r
1035         dlg = new RenameMultiDialog(this);\r
1036     }\r
1037     dlg->setWorkingDirectory(fp->dir()->absolutePath());\r
1038     dlg->setNames(list);\r
1039     int dlgResult = dlg->exec();\r
1040     if (dlgResult == QDialog::Accepted && !dlg->renameMap().isEmpty()) {\r
1041         RenameWorker *worker = new RenameWorker();\r
1042         worker->setRenameMap(&dlg->renameMap());\r
1043 \r
1044         OperationDialog opDlg(this);\r
1045         opDlg.setWindowTitle(tr("名前を変更"));\r
1046         opDlg.setWorker(worker);\r
1047 \r
1048         ui->LPanel->UninstallWatcher();\r
1049         ui->RPanel->UninstallWatcher();\r
1050         opDlg.exec();\r
1051         ui->LPanel->setCurrentFolder(ui->LPanel->dir()->absolutePath());\r
1052         ui->RPanel->setCurrentFolder(ui->RPanel->dir()->absolutePath());\r
1053     }\r
1054 }\r
1055 \r
1056 ///\r
1057 /// \brief MainWindow::onHelpAbout\r
1058 ///\r
1059 /// アプリケーションの概要を表示します(?)\r
1060 ///\r
1061 void MainWindow::onHelpAbout()\r
1062 {\r
1063     QMessageBox::about(\r
1064                 this,\r
1065                 tr("げふぅ について"),\r
1066                 tr("<h3>Gefu Ver%1</h3>").arg(VERSION_VALUE) +\r
1067                 tr("<center>Gefu is Experimental File Utility.<br/>"\r
1068                    "(げふぅは実験的なファイルユーティリティです)</center>"\r
1069                    "<p>Copyright 2014 @miyabi_satoh All rights reserved.</p>"));\r
1070 }\r
1071 \r
1072 ///\r
1073 /// \brief MainWindow::selectedItems\r
1074 /// \param fp フォルダパネルへのポインタ\r
1075 /// \return 選択アイテムのフルパスのリスト\r
1076 ///\r
1077 /// 選択アイテムのフルパスのリストを取得します\r
1078 ///\r
1079 QStringList MainWindow::selectedItems(FolderPanel *fp)\r
1080 {\r
1081     QStringList list;\r
1082     for (int n = 0; n < fp->fileTable()->rowCount(); n++) {\r
1083         if (fp->fileTable()->item(n, 0)->checkState() == Qt::Checked) {\r
1084             list << fp->dir()->absoluteFilePath(fp->fileTable()->item(n, 1)->text());\r
1085         }\r
1086     }\r
1087 \r
1088     if (list.isEmpty()) {\r
1089         int row = fp->fileTable()->currentRow();\r
1090         QString name = fp->fileTable()->item(row, 1)->text();\r
1091         if (name != "..") {\r
1092             list << fp->dir()->absoluteFilePath(name);\r
1093         }\r
1094     }\r
1095 \r
1096     return list;\r
1097 }\r
1098 \r
1099 ///\r
1100 /// \brief getMainWnd\r
1101 /// \return メインウィンドウのポインタ\r
1102 ///\r
1103 /// メインウィンドウを取得します\r
1104 ///\r
1105 MainWindow* getMainWnd()\r
1106 {\r
1107     foreach (QWidget *w, qApp->topLevelWidgets()) {\r
1108         if (w->objectName() == "MainWindow") {\r
1109             return static_cast<MainWindow*>(w);\r
1110         }\r
1111     }\r
1112     qDebug() << "MainWindow not found !?";\r
1113     return NULL;\r
1114 }\r