OSDN Git Service

Ver0.12
[gefu/Gefu.git] / mainwindow.cpp
index 35549b2..108d547 100644 (file)
-#include "copymoveworker.h"\r
-#include "deleteworker.h"\r
+#include "common.h"\r
+#include "version.h"\r
 #include "mainwindow.h"\r
+#include "preferencedialog.h"\r
+#include "folderview.h"\r
+#include "searchbox.h"\r
+#include "locationbox.h"\r
+#include "ui_mainwindow.h"\r
+#include "copymoveworker.h"\r
 #include "operationdialog.h"\r
 #include "overwritedialog.h"\r
-#include "renamemultidialog.h"\r
-#include "renamesingledialog.h"\r
+#include "deleteworker.h"\r
 #include "renameworker.h"\r
-#include "ui_mainwindow.h"\r
-#include <QFileSystemModel>\r
+#include "renamesingledialog.h"\r
+#include "renamemultidialog.h"\r
+#include "historydialog.h"\r
+#include "sortdialog.h"\r
+\r
+#include <QCheckBox>\r
+#include <QCloseEvent>\r
 #include <QDebug>\r
-#include <QKeyEvent>\r
-#include <QDesktopServices>\r
-#include <QSettings>\r
-#include <QFileDialog>\r
+#include <QDesktopWidget>\r
 #include <QMessageBox>\r
-#include <QProcess>\r
-#include <QThread>\r
+#include <QSettings>\r
+#include <QNetworkAccessManager>\r
+#include <QNetworkReply>\r
 #include <QInputDialog>\r
+#include <QProcess>\r
+#include <QDesktopServices>\r
+#include <QClipboard>\r
+#include <QFileDialog>\r
+\r
+MainWindow* getMainWnd()\r
+{\r
+    foreach (QWidget *w, qApp->topLevelWidgets()) {\r
+        if (w->objectName() == "MainWindow") {\r
+            return static_cast<MainWindow*>(w);\r
+        }\r
+    }\r
+    qDebug() << "MainWindow not found !?";\r
+    return NULL;\r
+}\r
 \r
 MainWindow::MainWindow(QWidget *parent) :\r
     QMainWindow(parent),\r
-    ui(new Ui::MainWindow)\r
+    ui(new Ui::MainWindow),\r
+    m_focusedView(NULL),\r
+    m_overwriteDialog(NULL)\r
 {\r
     ui->setupUi(this);\r
 \r
+    m_overwriteDialog = new OverWriteDialog(this);\r
+\r
+    initActionConnections();\r
+    connect(qApp, SIGNAL(focusChanged(QWidget*,QWidget*)), this, SLOT(focusChange(QWidget*,QWidget*)));\r
+    connect(ui->textView, SIGNAL(viewFinished(QWidget*)), this, SLOT(viewFinish(QWidget*)));\r
+\r
+    // テキストビューアは初期状態で非表示\r
+    ui->textView->setVisible(false);\r
+\r
+    for (int i = 1; i <= 2; i++) {\r
+        LocationBox *locationBox = findChild<LocationBox*>(QString("locationBox%1").arg(i));\r
+        Q_CHECK_PTR(locationBox);\r
+\r
+        FolderView *folderView = findChild<FolderView*>(QString("folderView%1").arg(i));\r
+        Q_CHECK_PTR(folderView);\r
+\r
+        SearchBox *searchBox = findChild<SearchBox*>(QString("searchBox%1").arg(i));\r
+        Q_CHECK_PTR(searchBox);\r
+\r
+        // シグナル&スロット\r
+        connect(folderView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(open(QModelIndex)));\r
+        connect(folderView, SIGNAL(dataChanged()), this, SLOT(dataChange()));\r
+        connect(folderView, SIGNAL(dropAccepted(QFileInfoList)), this, SLOT(dropAccept(QFileInfoList)));\r
+        connect(folderView, SIGNAL(currentChanged(QFileInfo)), this, SLOT(currentChange(QFileInfo)));\r
+        connect(folderView, SIGNAL(itemFound()), this, SLOT(itemFound()));\r
+        connect(folderView, SIGNAL(itemNotFound()), this, SLOT(itemNotFound()));\r
+        connect(folderView, SIGNAL(keyPressed(QKeyEvent*)), this, SLOT(keyPress(QKeyEvent*)));\r
+        connect(folderView, SIGNAL(retrieveFinished()), this, SLOT(retrieveFinish()));\r
+        connect(folderView, SIGNAL(retrieveStarted(QString)), this, SLOT(retrieveStart(QString)));\r
+        connect(folderView, SIGNAL(requestContextMenu(QContextMenuEvent*)), this, SLOT(showContextMenu(QContextMenuEvent*)));\r
+        connect(searchBox, SIGNAL(textEdited(QString)), this, SLOT(searchItem(QString)));\r
+        connect(searchBox, SIGNAL(returnPressed()), this, SLOT(returnPressInSearchBox()));\r
+\r
+        // 検索ボックスは初期状態で非表示\r
+        searchBox->setVisible(false);\r
+\r
+        // ロケーションボックスを初期化する\r
+        locationBox->initialize();\r
+\r
+        // フィルタを初期化する\r
+        setNameFilters(folderView);\r
+\r
+        // ソートを初期化する\r
+        setSorting(folderView);\r
+\r
+        // フォルダビューを初期化する\r
+        folderView->initialize();\r
+    }\r
+\r
+    QSettings settings;\r
+    // メニュー項目の状態を初期化する\r
+    ui->view_Hidden->setChecked(settings.value(IniKey_ShowHidden).toBool());\r
+    ui->view_System->setChecked(settings.value(IniKey_ShowSystem).toBool());\r
+    ui->action_OpenEditor->setEnabled(!settings.value(IniKey_EditorPath).toString().isEmpty());\r
+    ui->action_OpenTerminal->setEnabled(!settings.value(IniKey_TerminalPath).toString().isEmpty());\r
+\r
+    // 追加のショートカットキーを設定する\r
+    QList<QKeySequence> shortcuts;\r
+    shortcuts = ui->action_Open->shortcuts();\r
+    shortcuts.append(QKeySequence("M"));\r
+    ui->action_Open->setShortcuts(shortcuts);\r
+\r
+    shortcuts = ui->action_Exec->shortcuts();\r
+    shortcuts.append(QKeySequence("Shift+M"));\r
+    ui->action_Exec->setShortcuts(shortcuts);\r
+\r
+    // MacだとShift+の形で認識されてしまうもの\r
+    shortcuts = ui->view_FontSizeUp->shortcuts();\r
+    shortcuts.append(QKeySequence("Shift++"));\r
+    ui->view_FontSizeUp->setShortcuts(shortcuts);\r
+\r
+    shortcuts = ui->view_Filter->shortcuts();\r
+    shortcuts.append(QKeySequence("Shift+*"));\r
+    ui->view_Filter->setShortcuts(shortcuts);\r
+\r
+    shortcuts = ui->action_OpenTerminal->shortcuts();\r
+    shortcuts.append(QKeySequence("Shift+>"));\r
+    ui->action_OpenTerminal->setShortcuts(shortcuts);\r
+\r
+    shortcuts = ui->help_About->shortcuts();\r
+    shortcuts.append(QKeySequence("Shift+?"));\r
+    ui->help_About->setShortcuts(shortcuts);\r
+\r
+    // ウィンドウタイトルを設定する\r
+    setWindowTitle(tr("げふぅ v%1").arg(VERSION_VALUE));\r
+\r
+    // ウィンドウアイコンを設定する\r
+#if defined(Q_OS_MAC)\r
+    setWindowIcon(QIcon(":/images/Gefu.icns"));\r
+#else\r
+    setWindowIcon(QIcon(":/images/Gefu.png"));\r
+#endif\r
+\r
+    //>>>>> ウィンドウサイズと位置を設定する\r
+    QString strValue;\r
+    QPoint point = this->geometry().topLeft();\r
+    QSize size = this->geometry().size();\r
+    //>>>> 前回の位置・サイズ・状態を復元する\r
+    if (!settings.value(IniKey_WindowGeometry, "").toString().isEmpty()) {\r
+        restoreGeometry(settings.value(IniKey_WindowGeometry).toByteArray());\r
+        restoreState(settings.value(iniKey_WindowState).toByteArray());\r
+    }\r
+    //>>>> INIファイルの設定から復元する\r
+    //>>> サイズ\r
+    strValue = settings.value(IniKey_BootSizeSpec).toString();\r
+    if (strValue == "sizeAbsolute") {\r
+        size = settings.value(IniKey_BootSizeAbs).toSize();\r
+    }\r
+    else if (strValue == "sizeRelative") {\r
+        size = settings.value(IniKey_BootSizeRel).toSize();\r
+        size.setWidth(size.width() * QApplication::desktop()->width() / 100.0);\r
+        size.setHeight(size.height() * QApplication::desktop()->height() / 100.0);\r
+    }\r
+    else if (strValue == "sizeLast") {\r
+        size = this->geometry().size();\r
+    }\r
+    //>>> 位置\r
+    strValue = settings.value(IniKey_BootPosSpec).toString();\r
+    if (strValue == "posAbsolute") {\r
+        point = settings.value(IniKey_BootPosAbs).toPoint();\r
+    }\r
+    else if (strValue == "posRelative") {\r
+        point = settings.value(IniKey_BootPosRel).toPoint();\r
+        point.setX(point.x() * QApplication::desktop()->width() / 100.0);\r
+        point.setY(point.y() * QApplication::desktop()->height() / 100.0);\r
+    }\r
+    else if (strValue == "posLast") {\r
+        point = this->geometry().topLeft();\r
+    }\r
+    else {\r
+        point.setX((QApplication::desktop()->width() - size.width()) / 2);\r
+        point.setY((QApplication::desktop()->height() - size.height()) / 2);\r
+    }\r
+    this->setGeometry(QRect(point, size));\r
+\r
+    // 最新バージョンをチェックする\r
+    if (settings.value(IniKey_CheckUpdates).toBool()) {\r
+        checkUpdate(true);\r
+    }\r
+\r
+    ui->folderView1->refresh();\r
+    ui->folderView2->refresh();\r
+}\r
+\r
+MainWindow::~MainWindow()\r
+{\r
+    delete ui;\r
+}\r
+\r
+FolderView* MainWindow::otherSideView(const FolderView *view) const\r
+{\r
+    qDebug() << "MainWindow::otherSideView()" << view->objectName();\r
+\r
+    if (view == ui->folderView1) {\r
+        return ui->folderView2;\r
+    }\r
+\r
+    Q_ASSERT(view == ui->folderView2);\r
+    return ui->folderView1;\r
+}\r
+\r
+void MainWindow::focusChange(QWidget *old, QWidget *now)\r
+{\r
+    Q_UNUSED(old);\r
+    qDebug() << "MainWindow::focusChange";\r
+\r
+    if (now == ui->folderView1 || now == ui->folderView2) {\r
+        ui->statusBar->showMessage(folderView()->currentItem().absoluteFilePath());\r
+    }\r
+\r
+    if (old == ui->searchBox1 || old == ui->searchBox2) {\r
+        old->setVisible(false);\r
+    }\r
+\r
+    updateActions();\r
+}\r
+\r
+void MainWindow::executeCommand()\r
+{\r
+    qDebug() << "MainWindow::executeCommand";\r
+\r
+    FolderView *v = folderView();\r
+    Q_ASSERT(v);\r
+\r
+    QFileInfoList list = v->selectedItems();\r
+    QString command = QString::null;\r
+    foreach (const QFileInfo &info, list) {\r
+#ifdef Q_OS_MAC\r
+        QString path = info.absoluteFilePath();\r
+#else\r
+        QString path = info.fileName();\r
+#endif\r
+        if (info.isExecutable()) {\r
+            command = QQ(path) + " " + command;\r
+        }\r
+        else {\r
+            command += " " + QQ(path);\r
+        }\r
+    }\r
+\r
+    QInputDialog dlg(this);\r
+    dlg.setInputMode(QInputDialog::TextInput);\r
+    dlg.setWindowTitle(tr("コマンドを実行"));\r
+    dlg.setLabelText(tr("コマンド:"));\r
+    dlg.setTextValue(command);\r
+    dlg.resize(width() * 0.8, dlg.height());\r
+\r
+    int ret = dlg.exec();\r
+    command = dlg.textValue();\r
+    if (ret == QDialog::Accepted && !command.isEmpty()) {\r
+        startProcess(command, v->dir(), tr("コマンドの実行に失敗しました。"));\r
+    }\r
+}\r
+\r
+void MainWindow::historyBack()\r
+{\r
+    qDebug() << "MainWindow::historyBack();";\r
+\r
+    if (folderView()->historyBack()) {\r
+        updateActions();\r
+    }\r
+}\r
+\r
+void MainWindow::historyForward()\r
+{\r
+    qDebug() << "MainWindow::historyForward();";\r
+\r
+    if (folderView()->historyForward()) {\r
+        updateActions();\r
+    }\r
+}\r
+\r
+void MainWindow::itemFound()\r
+{\r
+    qDebug() << "MainWindow::itemFound";\r
+\r
+    SearchBox *box = searchBox(static_cast<FolderView*>(sender()));\r
+    QPalette pal = box->palette();\r
+    pal.setColor(QPalette::Text, QPalette().text().color());\r
+    box->setPalette(pal);\r
+}\r
+\r
+void MainWindow::itemNotFound()\r
+{\r
+    qDebug() << "MainWindow::itemNotFound";\r
+\r
+    SearchBox *box = searchBox(static_cast<FolderView*>(sender()));\r
+    QPalette pal = box->palette();\r
+    pal.setColor(QPalette::Text, Qt::red);\r
+    box->setPalette(pal);\r
+}\r
+\r
+void MainWindow::markAll()\r
+{\r
+    qDebug() << "MainWindow::markAll();";\r
+\r
+    folderView()->setCheckStateAll(true);\r
+}\r
+\r
+void MainWindow::markAllFiles()\r
+{\r
+    qDebug() << "MainWindow::markAllFiles();";\r
+\r
+    folderView()->setCheckStateAllFiles();\r
+}\r
+\r
+void MainWindow::markAllOff()\r
+{\r
+    qDebug() << "MainWindow::markAllOff();";\r
+\r
+    folderView()->setCheckStateAll(false);\r
+}\r
+\r
+void MainWindow::markInvert()\r
+{\r
+    qDebug() << "MainWindow::markInvert();";\r
+\r
+    folderView()->invertCheckState();\r
+}\r
+\r
+void MainWindow::markToggle()\r
+{\r
+    qDebug() << "MainWindow::markToggle();";\r
+\r
+    folderView()->toggleCheckState(folderView()->currentIndex());\r
+}\r
+\r
+void MainWindow::moveItems()\r
+{\r
+    qDebug() << "MainWindow::moveItems";\r
+\r
+    FolderView *v = folderView();\r
+    QFileInfoList list = v->selectedItems();\r
+    if (list.isEmpty()) {\r
+        return;\r
+    }\r
+\r
+    QSettings settings;\r
+    if (settings.value(IniKey_ConfirmCopy).toBool()) {\r
+        if (QMessageBox::question(this, tr("確認"), tr("移動を実行しますか?"))\r
+            != QMessageBox::Yes)\r
+        {\r
+            return;\r
+        }\r
+    }\r
+\r
+    // 上書き確認ダイアログを初期化する\r
+    m_overwriteDialog->reset();\r
+\r
+    // ワーカースレッドを作成する\r
+    FolderView *other = otherSideView(v);\r
+    CopyMoveWorker *worker = new CopyMoveWorker();\r
+    connect(worker, SIGNAL(askOverWrite(QString*,QString*,QString,QString)),\r
+            this, SLOT(askOverWrite(QString*,QString*,QString,QString)));\r
+    worker->setCopyList(&list);\r
+    worker->setTargetDir(other->dir());\r
+    worker->setMoveMode(true);\r
+\r
+    // 進捗ダイアログを表示して、処理を開始する\r
+    OperationDialog opDlg(this);\r
+    opDlg.setWindowTitle(tr("移動"));\r
+    opDlg.setWorker(worker);\r
+    opDlg.setAutoClose(settings.value(IniKey_AutoCloseCopy).toBool());\r
+\r
+    opDlg.exec();\r
+\r
+    settings.setValue(IniKey_AutoCloseCopy, opDlg.autoClose());\r
+\r
+    // 念のため、リフレッシュ\r
+    ui->folderView1->refresh();\r
+    ui->folderView2->refresh();\r
+}\r
+\r
+void MainWindow::keyPress(QKeyEvent *event)\r
+{\r
+    QString ksq = KeyEventToSequence(event);\r
+    if (ksq == "") {\r
+        event->ignore();\r
+        return;\r
+    }\r
+\r
+    qDebug() << "MainWindow::keyPress" << ksq;\r
+\r
+    foreach (QObject *obj, children()) {\r
+        QAction *action = qobject_cast<QAction*>(obj);\r
+        if (!action) {\r
+            continue;\r
+        }\r
+\r
+        foreach (const QKeySequence &k, action->shortcuts()) {\r
+            if (ksq == k.toString()) {\r
+                if (action->isEnabled()) {\r
+                    if (action->isCheckable()) {\r
+                        action->setChecked(!action->isChecked());\r
+                    }\r
+                    else {\r
+                        emit action->triggered();\r
+                    }\r
+                    qDebug() << "emit" << action->objectName();\r
+                }\r
+                event->accept();\r
+                return;\r
+            }\r
+        }\r
+    }\r
+\r
+    if (ksq == "Left" || ksq == "Right") {\r
+        FolderView *view = static_cast<FolderView*>(sender());\r
+        if (view->side() == ksq) {\r
+            setPathToParent();\r
+        }\r
+        else {\r
+            otherSideView(view)->setFocus();\r
+        }\r
+        event->accept();\r
+        return;\r
+    }\r
+\r
+    event->ignore();\r
+}\r
+\r
+void MainWindow::returnPressInSearchBox()\r
+{\r
+    qDebug() << "MainWindow::returnPressInSearchBox";\r
+\r
+    if (QApplication::keyboardModifiers() & Qt::ShiftModifier) {\r
+        emit ui->action_SearchPrev->triggered();\r
+    }\r
+    else {\r
+        emit ui->action_SearchNext->triggered();\r
+    }\r
+}\r
+\r
+void MainWindow::chooseFolder()\r
+{\r
+    qDebug() << "MainWindow::chooseFolder();";\r
+\r
+    QString path = QFileDialog::getExistingDirectory(\r
+                this, tr("フォルダを選択"), folderView()->dir());\r
+    if (!path.isEmpty()) {\r
+        folderView()->setPath(path, true);\r
+        updateActions();\r
+    }\r
+}\r
+\r
+void MainWindow::copyFilenameToClipboard()\r
+{\r
+    qDebug() << "MainWindow::copyFilenameToClipboard();";\r
+\r
+    QClipboard *clipboard = QApplication::clipboard();\r
+    clipboard->setText(folderView()->currentItem().fileName());\r
+}\r
+\r
+void MainWindow::copyFullpathTpClipboard()\r
+{\r
+    qDebug() << "MainWindow::copyFullpathTpClipboard();";\r
+\r
+    QClipboard *clipboard = QApplication::clipboard();\r
+    clipboard->setText(folderView()->currentItem().absoluteFilePath());\r
+}\r
+\r
+void MainWindow::askOverWrite(QString *copyMethod,\r
+                              QString *alias,\r
+                              const QString &srcPath,\r
+                              const QString &tgtPath)\r
+{\r
+    qDebug() << "MainWindow::askOverWrite();";\r
+\r
+    CopyMoveWorker *worker = static_cast<CopyMoveWorker*>(sender());\r
+    if (!m_overwriteDialog->isKeepSetting() ||\r
+        m_overwriteDialog->copyMethod() == "rbRename")\r
+    {\r
+        m_overwriteDialog->setFileInfo(srcPath, tgtPath);\r
+        if (m_overwriteDialog->exec() == QDialog::Rejected) {\r
+            worker->requestStop();\r
+        }\r
+    }\r
+    *copyMethod = m_overwriteDialog->copyMethod();\r
+    *alias = m_overwriteDialog->alias();\r
+\r
+    worker->endAsking();\r
+}\r
+\r
+void MainWindow::currentChange(const QFileInfo &info)\r
+{\r
+    qDebug() << "MainWindow::currentChange();";\r
+\r
+    ui->statusBar->showMessage(info.absoluteFilePath());\r
+    if (info.isDir()) {\r
+        ui->action_Open->setIcon(QIcon(":/images/Open.png"));\r
+        ui->action_Open->setText(tr("開く"));\r
+        ui->action_Open->setToolTip(tr("開く"));\r
+    }\r
+    else {\r
+        ui->action_Open->setIcon(QIcon(":/images/Search text.png"));\r
+        ui->action_Open->setText(tr("テキストビューアで開く"));\r
+        ui->action_Open->setToolTip(tr("テキストビューアで開く"));\r
+        ui->action_Open->setEnabled(true);\r
+\r
+        QSettings settings;\r
+        if (!settings.value(IniKey_ViewerForceOpen).toBool()) {\r
+            QStringList list = settings.value(IniKey_ViewerIgnoreExt).toString().split(",");\r
+            foreach (const QString &ext, list) {\r
+                if (ext.toLower() == info.suffix().toLower()) {\r
+                    ui->action_Open->setEnabled(false);\r
+                    break;\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+}\r
+\r
+void MainWindow::dataChange()\r
+{\r
+    qDebug() << "MainWindow::dataChange();";\r
+\r
+    FolderView *view = static_cast<FolderView*>(sender());\r
+    QFileInfoList list = view->checkedItems();\r
+    if (list.isEmpty()) {\r
+        showNameFilters(view);\r
+    }\r
+    else {\r
+        int numFolders = 0;\r
+        int numFiles = 0;\r
+        quint64 size = 0;\r
+        foreach (const QFileInfo &info, list) {\r
+            if (info.isDir()) {\r
+                numFolders++;\r
+            }\r
+            else {\r
+                numFiles++;\r
+                size += info.size();\r
+            }\r
+        }\r
+\r
+        QString msg = QString::null;\r
+        if (numFolders > 0) {\r
+            msg += tr("%1個のフォルダ ").arg(numFolders);\r
+        }\r
+        if (numFiles > 0) {\r
+            msg += tr("%1個のファイル ").arg(numFiles);\r
+        }\r
+\r
+        if (!msg.isEmpty()) {\r
+            msg += tr("を選択 合計%1").arg(FilesizeToString(size));\r
+        }\r
+\r
+        filterLabel(view)->setText(msg);\r
+    }\r
+}\r
+\r
+void MainWindow::dropAccept(const QFileInfoList &list)\r
+{\r
+    copyItems(list, static_cast<FolderView*>(sender())->dir());\r
+}\r
+\r
+void MainWindow::copyItems(const QFileInfoList &list, const QString &tgtDir)\r
+{\r
+    QSettings settings;\r
+    if (settings.value(IniKey_ConfirmCopy).toBool()) {\r
+        if (QMessageBox::question(this, tr("確認"), tr("コピーを実行しますか?"))\r
+            != QMessageBox::Yes)\r
+        {\r
+            return;\r
+        }\r
+    }\r
+\r
+    // 上書き確認ダイアログを初期化する\r
+    m_overwriteDialog->reset();\r
+\r
+    // ワーカースレッドを作成する\r
+    CopyMoveWorker *worker = new CopyMoveWorker();\r
+    connect(worker, SIGNAL(askOverWrite(QString*,QString*,QString,QString)),\r
+            this, SLOT(askOverWrite(QString*,QString*,QString,QString)));\r
+    worker->setCopyList(&list);\r
+    worker->setTargetDir(tgtDir);\r
+    worker->setMoveMode(false);\r
+\r
+    // 進捗ダイアログを表示して、処理を開始する\r
+    OperationDialog opDlg(this);\r
+    opDlg.setWindowTitle(tr("コピー"));\r
+    opDlg.setWorker(worker);\r
+    opDlg.setAutoClose(settings.value(IniKey_AutoCloseCopy).toBool());\r
+\r
+    opDlg.exec();\r
+\r
+    settings.setValue(IniKey_AutoCloseCopy, opDlg.autoClose());\r
+\r
+    // 念のため、リフレッシュ\r
+    ui->folderView1->refresh();\r
+    ui->folderView2->refresh();\r
+}\r
+\r
+void MainWindow::copyItems()\r
+{\r
+    qDebug() << "MainWindow::copyItems";\r
+\r
+    FolderView *v = folderView();\r
+    QFileInfoList list = v->selectedItems();\r
+    if (list.isEmpty()) {\r
+        return;\r
+    }\r
+\r
+    FolderView *other = otherSideView(v);\r
+    copyItems(list, other->dir());\r
+#if 0\r
+    QSettings settings;\r
+    if (settings.value(IniKey_ConfirmCopy).toBool()) {\r
+        if (QMessageBox::question(this, tr("確認"), tr("コピーを実行しますか?"))\r
+            != QMessageBox::Yes)\r
+        {\r
+            return;\r
+        }\r
+    }\r
+\r
+    // 上書き確認ダイアログを初期化する\r
+    m_overwriteDialog->reset();\r
+\r
+    // ワーカースレッドを作成する\r
+    FolderView *other = otherSideView(v);\r
+    CopyMoveWorker *worker = new CopyMoveWorker();\r
+    connect(worker, SIGNAL(askOverWrite(QString*,QString*,QString,QString)),\r
+            this, SLOT(askOverWrite(QString*,QString*,QString,QString)));\r
+    worker->setCopyList(&list);\r
+    worker->setTargetDir(other->dir());\r
+    worker->setMoveMode(false);\r
+\r
+    // 進捗ダイアログを表示して、処理を開始する\r
+    OperationDialog opDlg(this);\r
+    opDlg.setWindowTitle(tr("コピー"));\r
+    opDlg.setWorker(worker);\r
+    opDlg.setAutoClose(settings.value(IniKey_AutoCloseCopy).toBool());\r
+\r
+    opDlg.exec();\r
+\r
+    settings.setValue(IniKey_AutoCloseCopy, opDlg.autoClose());\r
+\r
+    // 念のため、リフレッシュ\r
+    ui->folderView1->refresh();\r
+    ui->folderView2->refresh();\r
+#endif\r
+}\r
+\r
+void MainWindow::createFile()\r
+{\r
+    qDebug() << "MainWindow::createFile";\r
+\r
+    bool bOk;\r
+    QString name = QInputDialog::getText(\r
+                this, tr("ファイルを作成"), tr("ファイル名:"),\r
+                QLineEdit::Normal, "", &bOk);\r
+    if (!bOk || name.isEmpty()) {\r
+        return;\r
+    }\r
+\r
+    QDir dir(folderView()->dir());\r
+    QFile file(dir.absoluteFilePath(name));\r
+    if (!file.open(QIODevice::WriteOnly)) {\r
+        QMessageBox::critical(\r
+                    this, tr("エラー"),\r
+                    tr("ファイルの作成に失敗しました。"));\r
+    }\r
+    else {\r
+        file.close();\r
+\r
+        QSettings settings;\r
+        if (settings.value(IniKey_OpenAfterCreateFile).toBool()) {\r
+            openEditor(dir.absoluteFilePath(name));\r
+        }\r
+    }\r
+}\r
+\r
+void MainWindow::createFolder()\r
+{\r
+    qDebug() << "MainWindow::createFolder";\r
+\r
+    bool bOk;\r
+    QString name = QInputDialog::getText(\r
+                this, tr("フォルダを作成"), tr("フォルダ名:"),\r
+                QLineEdit::Normal, "", &bOk);\r
+    if (!bOk || name.isEmpty()) {\r
+        return;\r
+    }\r
+\r
+    QDir dir(folderView()->dir());\r
+    if (!dir.mkpath(name)) {\r
+        QMessageBox::critical(\r
+                    this, tr("エラー"),\r
+                    tr("フォルダの作成に失敗しました。"));\r
+    }\r
+    else {\r
+        QSettings settings;\r
+        if (settings.value(IniKey_MoveAfterCreateFolder).toBool()) {\r
+            folderView()->setPath(dir.absoluteFilePath(name), true);\r
+            updateActions();\r
+        }\r
+    }\r
+}\r
+\r
+void MainWindow::deleteItems()\r
+{\r
+    qDebug() << "MainWindow::deleteItems";\r
+\r
+    FolderView *v = folderView();\r
+    QFileInfoList list = v->selectedItems();\r
+    if (list.isEmpty()) {\r
+        return;\r
+    }\r
+\r
+    QSettings settings;\r
+    if (settings.value(IniKey_ConfirmDelete).toBool()) {\r
+        QString msg;\r
+        if (list.size() == 1) {\r
+            msg = list[0].fileName();\r
+        }\r
+        else {\r
+            msg = tr("%1個のアイテム").arg(list.size());\r
+        }\r
+        int ret = QMessageBox::question(\r
+                    this, tr("確認"),\r
+                    msg + tr("を削除しますか?"));\r
+        if (ret != QMessageBox::Yes) {\r
+            return;\r
+        }\r
+    }\r
+\r
+    DeleteWorker *worker = new DeleteWorker();\r
+    worker->setDeleteList(&list);\r
+\r
+    OperationDialog opDlg(this);\r
+    opDlg.setWindowTitle(tr("削除"));\r
+    opDlg.setWorker(worker);\r
+    opDlg.setAutoClose(settings.value(IniKey_AutoCloseDelete).toBool());\r
+\r
+    opDlg.exec();\r
+\r
+    settings.setValue(IniKey_AutoCloseDelete, opDlg.autoClose());\r
+\r
+    // 念のため、リフレッシュ\r
+    ui->folderView1->refresh();\r
+    ui->folderView2->refresh();\r
+}\r
+\r
+void MainWindow::open(const QModelIndex &index)\r
+{\r
+    Q_UNUSED(index);\r
+    qDebug() << "MainWindow::open";\r
+\r
+    FolderView *v = folderView();\r
+    Q_ASSERT(v);\r
+\r
+    QFileInfo info = v->currentItem();\r
+    if (info.isDir()) {\r
+        v->setPath(info.absoluteFilePath(), true);\r
+        updateActions();\r
+        return;\r
+    }\r
+\r
+    QSettings settings;\r
+    if (!settings.value(IniKey_ViewerForceOpen).toBool()) {\r
+        QStringList list = settings.value(IniKey_ViewerIgnoreExt).toString().split(",");\r
+        foreach (const QString &ext, list) {\r
+            if (ext.toLower() == info.suffix().toLower()) {\r
+                shellExecute();\r
+                return;\r
+            }\r
+        }\r
+    }\r
+\r
+    setUpdatesEnabled(false);\r
+\r
+    foreach (QObject *obj, this->children()) {\r
+        QAction *action = qobject_cast<QAction*>(obj);\r
+        if (action) {\r
+            if (action->objectName() == "help_About" ||\r
+                action->objectName() == "check_Update" ||\r
+                action->objectName() == "copy_Fullpath" ||\r
+                action->objectName() == "copy_Filename" ||\r
+                action->objectName() == "action_Quit" ||\r
+                action->objectName() == "action_Setting")\r
+            {\r
+                continue;\r
+            }\r
+            action->setEnabled(false);\r
+        }\r
+    }\r
+\r
+    m_focusedView = folderView();\r
+    ui->splitter->setVisible(false);\r
+    ui->textView->setVisible(true);\r
+    ui->textView->setFocus();\r
+\r
+    setUpdatesEnabled(true);\r
+\r
+    QFile file(info.absoluteFilePath());\r
+    if (file.open(QIODevice::ReadOnly)) {\r
+        ui->textView->setSource(file.readAll());\r
+    }\r
+}\r
+\r
+void MainWindow::openEditor(const QString &path)\r
+{\r
+    qDebug() << "MainWindow::openEditor";\r
+\r
+    QSettings settings;\r
+    QString exe = settings.value(IniKey_EditorPath).toString();\r
+    if (exe.isEmpty()) {\r
+        QMessageBox::critical(\r
+                    this, tr("エラー"),\r
+                    tr("外部エディタのパスが未定義です。"));\r
+        return;\r
+    }\r
+\r
+    FolderView *v = folderView();\r
+    Q_ASSERT(v);\r
+\r
+    QFileInfoList list;\r
+    if (path.isEmpty()) {\r
+        list = v->selectedItems();\r
+    }\r
+    else {\r
+        list << path;\r
+    }\r
+\r
+    foreach (const QFileInfo &info, list) {\r
+        QString opt = settings.value(IniKey_EditorOption).toString();\r
+        replaceVars(opt, info);\r
+\r
+#ifdef Q_OS_MAC\r
+        QString command = "open -a " + exe + " " + opt;\r
+#else\r
+        QString command = QQ(exe) + " " + opt;\r
+#endif\r
+        if (!startProcess(command, info.absolutePath(), tr("外部エディタの起動に失敗しました。"))) {\r
+            break;\r
+        }\r
+    }\r
+}\r
+\r
+void MainWindow::openTerminal()\r
+{\r
+    qDebug() << "MainWindow::openTerminal";\r
+\r
+    QSettings settings;\r
+    QString exe = settings.value(IniKey_TerminalPath).toString();\r
+    if (exe.isEmpty()) {\r
+        QMessageBox::critical(\r
+                    this, tr("エラー"),\r
+                    tr("ターミナルのパスが未定義です。"));\r
+        return;\r
+    }\r
+\r
+    FolderView *v = folderView();\r
+    Q_ASSERT(v);\r
+\r
+    foreach (const QFileInfo &info, v->selectedItems()) {\r
+        QString opt = settings.value(IniKey_TerminalOption).toString();\r
+        replaceVars(opt, info);\r
+\r
+#ifdef Q_OS_MAC\r
+        QString command = "open -a " + QQ(exe) + " --args " + opt;\r
+#else\r
+        QString command = QQ(exe) + " " + opt;\r
+#endif\r
+        if (!startProcess(command, info.absolutePath(), tr("ターミナルの起動に失敗しました。"))) {\r
+            break;\r
+        }\r
+    }\r
+}\r
+\r
+void MainWindow::refresh()\r
+{\r
+    qDebug() << "MainWindow::refresh();";\r
+\r
+    folderView()->refresh();\r
+    updateActions();\r
+}\r
+\r
+void MainWindow::renameItems()\r
+{\r
+    qDebug() << "MainWindow::renameItems";\r
+\r
+    FolderView *v = folderView();\r
+\r
+    QFileInfoList list = v->selectedItems();\r
+    if (list.isEmpty()) {\r
+        return;\r
+    }\r
+\r
+    IRenameDialog *dlg;\r
+    if (list.size() == 1) {\r
+        dlg = new RenameSingleDialog(this);\r
+    }\r
+    else {\r
+        dlg = new RenameMultiDialog(this);\r
+    }\r
+    dlg->setWorkingDirectory(v->dir());\r
+    dlg->setNames(list);\r
+    int dlgResult = dlg->exec();\r
+    if (dlgResult != QDialog::Accepted || dlg->renameMap().isEmpty()) {\r
+        return;\r
+    }\r
+\r
     QSettings settings;\r
-    bool checked = settings.value("Common/ShowHidden", false).toBool();\r
-    ui->view_Hidden->setChecked(checked);\r
-\r
-    // メニューのシグナル/スロットを設定する\r
-    connect(ui->action_Command, SIGNAL(triggered()), this, SLOT(onActionCommand()));\r
-    connect(ui->action_Exec, SIGNAL(triggered()), this, SLOT(onActionExec()));\r
-    connect(ui->action_Open, SIGNAL(triggered()), this, SLOT(onActionOpen()));\r
-    connect(ui->action_Quit, SIGNAL(triggered()), this, SLOT(onActionQuit()));\r
-    connect(ui->action_Setting, SIGNAL(triggered()), this, SLOT(onActionSetting()));\r
-\r
-    connect(ui->mark_All, SIGNAL(triggered()), this, SLOT(onMarkAll()));\r
-    connect(ui->mark_AllFiles, SIGNAL(triggered()), this, SLOT(onMarkAllFiles()));\r
-    connect(ui->mark_AllOff, SIGNAL(triggered()), this, SLOT(onMarkAllOff()));\r
-    connect(ui->mark_Invert, SIGNAL(triggered()), this, SLOT(onMarkInvert()));\r
-    connect(ui->mark_Toggle, SIGNAL(triggered()), this, SLOT(onMarkToggle()));\r
-\r
-    connect(ui->move_Down, SIGNAL(triggered()), this, SLOT(onMoveCursorDown()));\r
-    connect(ui->move_Up, SIGNAL(triggered()), this, SLOT(onMoveCursorUp()));\r
-    connect(ui->move_Begin, SIGNAL(triggered()), this, SLOT(onMoveCursorBegin()));\r
-    connect(ui->move_End, SIGNAL(triggered()), this, SLOT(onMoveCursorEnd()));\r
-    connect(ui->move_Back, SIGNAL(triggered()), this, SLOT(onMoveBack()));\r
-    connect(ui->move_Forward, SIGNAL(triggered()), this, SLOT(onMoveForward()));\r
-    connect(ui->move_Home, SIGNAL(triggered()), this, SLOT(onMoveHome()));\r
-    connect(ui->move_Jump, SIGNAL(triggered()), this, SLOT(onMoveJump()));\r
-    connect(ui->move_Parent, SIGNAL(triggered()), this, SLOT(onMoveParent()));\r
-    connect(ui->move_Root, SIGNAL(triggered()), this, SLOT(onMoveRoot()));\r
-\r
-    connect(ui->view_FromOther, SIGNAL(triggered()), this, SLOT(onViewFromOther()));\r
-    connect(ui->view_ToOther, SIGNAL(triggered()), this, SLOT(onViewToOther()));\r
-    connect(ui->view_Hidden, SIGNAL(triggered()), this, SLOT(onViewHidden()));\r
-    connect(ui->view_Swap, SIGNAL(triggered()), this, SLOT(onViewSwap()));\r
-\r
-    connect(ui->cmd_Copy, SIGNAL(triggered()), this, SLOT(onCmdCopy()));\r
-    connect(ui->cmd_Delete, SIGNAL(triggered()), this, SLOT(onCmdDelete()));\r
-    connect(ui->cmd_Move, SIGNAL(triggered()), this, SLOT(onCmdMove()));\r
-    connect(ui->cmd_NewFile, SIGNAL(triggered()), this, SLOT(onCmdNewFile()));\r
-    connect(ui->cmd_NewFolder, SIGNAL(triggered()), this, SLOT(onCmdNewFolder()));\r
-    connect(ui->cmd_Rename, SIGNAL(triggered()), this, SLOT(onCmdRename()));\r
-\r
-    connect(ui->help_About, SIGNAL(triggered()), this, SLOT(onHelpAbout()));\r
-\r
-    // ウィンドウタイトルを設定する\r
-    setWindowTitle(tr("げふぅ v0.00"));\r
-    // ウィンドウアイコンを設定する\r
-    setWindowIcon(QIcon(":/images/Gefu.png"));\r
+    if (settings.value(IniKey_ConfirmRename).toBool()) {\r
+        int ret = QMessageBox::question(this, tr("確認"),\r
+                                        tr("名前の変更を実行しますか?"));\r
+        if (ret != QMessageBox::Yes) {\r
+            return;\r
+        }\r
+    }\r
 \r
-    // ウィンドウ初期サイズを設定する\r
-    resize(800, 600);\r
+    RenameWorker *worker = new RenameWorker();\r
+    worker->setRenameMap(&dlg->renameMap());\r
 \r
-    QString path;\r
+    OperationDialog opDlg(this);\r
+    opDlg.setWindowTitle(tr("名前を変更"));\r
+    opDlg.setWorker(worker);\r
+    opDlg.setAutoClose(settings.value(IniKey_AutoCloseRename).toBool());\r
 \r
-    path = settings.value("Left/dir", QDir::homePath()).toString();\r
-    ui->folderPanel_L->setCurrentFolder(path);\r
+    opDlg.exec();\r
 \r
-    path = settings.value("Right/dir", QDir::homePath()).toString();\r
-    ui->folderPanel_R->setCurrentFolder(path);\r
+    settings.setValue(IniKey_AutoCloseRename, opDlg.autoClose());\r
 }\r
 \r
-MainWindow::~MainWindow()\r
+void MainWindow::retrieveFinish()\r
 {\r
-    QSettings settings;\r
-\r
-    settings.setValue("Left/dir", ui->folderPanel_L->dir()->absolutePath());\r
-    settings.setValue("Right/dir", ui->folderPanel_R->dir()->absolutePath());\r
+    qDebug() << "MainWindow::retrieveFinish();";\r
 \r
-    delete ui;\r
+    ui->statusBar->showMessage(tr("レディ"), 5000);\r
 }\r
 \r
-void MainWindow::setStatusText(const QString &str)\r
+void MainWindow::retrieveStart(const QString &path)\r
 {\r
-    ui->statusBar->showMessage(str);\r
-}\r
+    qDebug() << "MainWindow::retrieveStart();" << path;\r
 \r
-FolderPanel* MainWindow::activePanel()\r
-{\r
-    if (ui->folderPanel_L->fileTable()->hasFocus()) {\r
-        return ui->folderPanel_L;\r
+    ui->statusBar->showMessage(tr("ファイルリストを取得しています..."));\r
+    if (sender() == ui->folderView1) {\r
+        ui->locationBox1->setText(path);\r
     }\r
-    if (ui->folderPanel_R->fileTable()->hasFocus()) {\r
-        return ui->folderPanel_R;\r
+    else {\r
+        Q_ASSERT(sender() == ui->folderView2);\r
+        ui->locationBox2->setText(path);\r
     }\r
-\r
-    return NULL;\r
 }\r
 \r
-FolderPanel* MainWindow::inactivePanel()\r
+void MainWindow::shellExecute()\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (fp == ui->folderPanel_L) {\r
-        return ui->folderPanel_R;\r
-    }\r
-    if (fp == ui->folderPanel_R) {\r
-        return ui->folderPanel_L;\r
-    }\r
+    qDebug() << "MainWindow::shellExecute";\r
 \r
-    return NULL;\r
+    FolderView *v = folderView();\r
+    Q_ASSERT(v);\r
+\r
+    QFileInfoList list = v->selectedItems();\r
+    foreach (const QFileInfo &info, list) {\r
+        QString path = QDir::toNativeSeparators(info.absoluteFilePath());\r
+        QDesktopServices::openUrl(QUrl("file:///" + path));\r
+    }\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onActionCommand\r
-///\r
-/// コマンドを実行します(X)\r
-///\r
-void MainWindow::onActionCommand()\r
+void MainWindow::showFilterDialog()\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (!fp) {\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::showFilterDialog();";\r
 \r
-    QString command = "";\r
-    for (int n = 0; n < fp->fileTable()->rowCount(); n++) {\r
-        if (fp->fileTable()->item(n, 0)->checkState() == Qt::Checked) {\r
-            QString path = fp->fileTable()->item(n, 1)->text();\r
-            path = fp->dir()->absoluteFilePath(path);\r
-            path = QDir::cleanPath(path);\r
-            path = QDir::toNativeSeparators(path);\r
+    QString filters = folderView()->nameFilters().join(" ");\r
 \r
-            QFileInfo info(path);\r
-            if (info.isExecutable()) {\r
-                command = "\"" + path + "\" " + command;\r
-            }\r
-            else {\r
-                command += " \"" + path + "\"";\r
-            }\r
-        }\r
+    QInputDialog dlg(this);\r
+    dlg.setInputMode(QInputDialog::TextInput);\r
+    dlg.setWindowTitle(tr("フィルタを設定"));\r
+    dlg.setLabelText(tr("フィルタ:"));\r
+    dlg.setTextValue(filters);\r
+    dlg.resize(width() * 0.8, dlg.height());\r
+\r
+    if (dlg.exec() == QDialog::Accepted) {\r
+        setNameFilters(folderView(), dlg.textValue());\r
     }\r
+}\r
+\r
+void MainWindow::showHistoryDialog()\r
+{\r
+    qDebug() << "MainWindow::showHistoryDialog();";\r
 \r
-    if (command.isEmpty()) {\r
-        int row = fp->fileTable()->currentRow();\r
-        QString path = fp->fileTable()->item(row, 1)->text();\r
-        path = fp->dir()->absoluteFilePath(path);\r
-        path = QDir::cleanPath(path);\r
-        path = QDir::toNativeSeparators(path);\r
+    FolderView *v = folderView();\r
+    FolderView *vOther = otherSideView(v);\r
 \r
-        command = "\"" + path + "\"";\r
+    HistoryDialog dlg(this);\r
+    if (v->side() == "Left") {\r
+        dlg.setDefaultLeft(true);\r
+        dlg.setHistory(v->history(), vOther->history());\r
+    }\r
+    else {\r
+        dlg.setDefaultLeft(false);\r
+        dlg.setHistory(vOther->history(), v->history());\r
     }\r
 \r
-    QInputDialog dlg(this);\r
-    dlg.setInputMode(QInputDialog::TextInput);\r
-    dlg.setLabelText(tr("コマンドを入力:"));\r
-    dlg.setWindowTitle(tr("コマンドを実行"));\r
-    dlg.setTextValue(command);\r
-    dlg.resize(500, 100);\r
-    int ret = dlg.exec();\r
-    command = dlg.textValue();\r
-    if (ret == QDialog::Accepted && !command.isEmpty()) {\r
-        QProcess process(this);\r
-        process.setWorkingDirectory(fp->dir()->absolutePath());\r
-        if (!process.startDetached(command)) {\r
-            QMessageBox::critical(\r
-                        this,\r
-                        tr("エラー"),\r
-                        tr("コマンドの実行に失敗しました。<br/>") + command);\r
+    if (dlg.exec() == QDialog::Accepted) {\r
+        if (v->side() == dlg.selectedSide()) {\r
+            v->setHistoryIndexAt(dlg.selectedIndex());\r
         }\r
+        else {\r
+            v->setPath(vOther->history()->at(dlg.selectedIndex()), true);\r
+        }\r
+        updateActions();\r
     }\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onActionExec\r
-///\r
-/// アプリケーションで開きます(Shift + Enter)\r
-///\r
-void MainWindow::onActionExec()\r
+void MainWindow::showSortDialog()\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (!fp) {\r
+    qDebug() << "MainWindow::showSortDialog();";\r
+\r
+    SortDialog dlg(this);\r
+    dlg.setRightOrLeft(folderView()->side());\r
+\r
+    if (dlg.exec() != QDialog::Accepted) {\r
         return;\r
     }\r
 \r
-    QStringList list = selectedItems(fp);\r
-    foreach (const QString &path, list) {\r
-        QDesktopServices::openUrl(QUrl("file:///" + QDir::toNativeSeparators(path)));\r
-    }\r
+    setSorting(folderView());\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onActionOpen\r
-///\r
-/// フォルダを開きます(Enter)\r
-///\r
-void MainWindow::onActionOpen()\r
+void MainWindow::swapView()\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (!fp) {\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::swapView();";\r
 \r
-    int row = fp->fileTable()->currentRow();\r
-    QString path = fp->fileTable()->item(row, 1)->text();\r
-    path = fp->dir()->absoluteFilePath(path);\r
-    QFileInfo info(path);\r
+    QString dir1 = ui->folderView1->dir();\r
+    QString dir2 = ui->folderView2->dir();\r
 \r
-    if (info.isDir()) {\r
-        fp->setCurrentFolder(path);\r
-    }\r
-}\r
+    ui->folderView1->setPath(dir2, true);\r
+    ui->folderView2->setPath(dir1, true);\r
 \r
-///\r
-/// \brief MainWindow::onActionQuit\r
-///\r
-/// アプリケーションを終了します(Q)\r
-///\r
-void MainWindow::onActionQuit()\r
-{\r
-    qApp->quit();\r
+    updateActions();\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onActionSetting\r
-///\r
-/// 環境設定ダイアログを表示します(Z)\r
-///\r
-void MainWindow::onActionSetting()\r
+void MainWindow::setSorting(FolderView *view)\r
 {\r
-    QMessageBox::information(this, tr("情報"), tr("環境設定機能は未実装です。"));\r
-}\r
+    qDebug() << "MainWindow::setSorting();" << view->objectName();\r
 \r
-///\r
-/// \brief MainWindow::on_mark_All_triggered\r
-///\r
-/// すべてマークします(Shift + A)\r
-///\r
-void MainWindow::onMarkAll()\r
-{\r
-    FolderPanel *fp = activePanel();\r
-    if (fp == NULL) {\r
-        return;\r
-    }\r
+    QSettings settings;\r
+    QDir::SortFlags flags;\r
 \r
-    int row = 0;\r
-    if (fp->fileTable()->item(row, 1)->text() == "..") {\r
-        row++;\r
+    int sortBy = settings.value(view->side() + slash + IniKey_SortBy).toInt();\r
+    switch (sortBy) {\r
+    case SortByDate:    flags |= QDir::Time; break;\r
+    case SortBySize:    flags |= QDir::Size; break;\r
+    case SortByType:    flags |= QDir::Type; break;\r
+    default:            flags |= QDir::Name; break;\r
     }\r
 \r
-    fp->beginUpdate();\r
-    int curRow = fp->fileTable()->currentRow();\r
-    int rowCount = fp->fileTable()->rowCount();\r
-    for (; row < rowCount; row++) {\r
-        fp->fileTable()->item(row, 0)->setCheckState(Qt::Checked);\r
+    // デフォルトだと文字列は昇順で、数値は降順…orz\r
+    int orderBy = settings.value(view->side() + slash + IniKey_OrderBy).toInt();\r
+    if (((sortBy == SortByName || sortBy == SortByType) && orderBy == OrderByDesc) ||\r
+        ((sortBy == SortByDate || sortBy == SortBySize) && orderBy == OrderByAsc))\r
+    {\r
+        flags |= QDir::Reversed;\r
     }\r
-    fp->fileTable()->setCurrentIndex(\r
-                fp->fileTable()->model()->index(curRow, 1));\r
-    fp->endUpdate();\r
-}\r
 \r
-///\r
-/// \brief MainWindow::onMarkAllFiles\r
-///\r
-/// すべての「ファイル」をマークします(A)\r
-///\r
-void MainWindow::onMarkAllFiles()\r
-{\r
-    FolderPanel *fp = activePanel();\r
-    if (fp == NULL) {\r
-        return;\r
+    switch (settings.value(view->side() + slash + IniKey_PutDirs).toInt()) {\r
+    case PutDirsFirst:  flags |= QDir::DirsFirst; break;\r
+    case PutDirsLast:   flags |= QDir::DirsLast; break;\r
     }\r
 \r
-    int row = 0;\r
-    if (fp->fileTable()->item(row, 1)->text() == "..") {\r
-        row++;\r
+    if (settings.value(view->side() + slash + IniKey_IgnoreCase).toBool()) {\r
+        flags |= QDir::IgnoreCase;\r
     }\r
 \r
-    fp->beginUpdate();\r
-    int curRow = fp->fileTable()->currentRow();\r
-    int rowCount = fp->fileTable()->rowCount();\r
-    for (; row < rowCount; row++) {\r
-        QString path = fp->fileTable()->item(row, 1)->text();\r
-        path = fp->dir()->absoluteFilePath(path);\r
+    view->setSorting(flags);\r
+}\r
 \r
-        QFileInfo info(path);\r
-        if (info.isDir()) {\r
-            fp->fileTable()->item(row, 0)->setCheckState(Qt::Unchecked);\r
-        }\r
-        else {\r
-           fp->fileTable()->item(row, 0)->setCheckState(Qt::Checked);\r
-        }\r
-    }\r
-    fp->fileTable()->setCurrentIndex(\r
-                fp->fileTable()->model()->index(curRow, 1));\r
-    fp->endUpdate();\r
+void MainWindow::showNameFilters(FolderView *view)\r
+{\r
+    filterLabel(view)->setText(tr("フィルタ:") + view->nameFilters().join(" "));\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onMarkAllOff\r
-///\r
-/// すべてのマークを解除します(U)\r
-///\r
-void MainWindow::onMarkAllOff()\r
+void MainWindow::searchItem(const QString &text)\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (fp == NULL) {\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::searchItem" << text;\r
 \r
-    int row = 0;\r
-    if (fp->fileTable()->item(row, 1)->text() == "..") {\r
-        row++;\r
+    FolderView *v;\r
+    SearchBox *box;\r
+    if (ui->searchBox1->hasFocus()) {\r
+        v = ui->folderView1;\r
+        box = ui->searchBox1;\r
+    }\r
+    else {\r
+        Q_ASSERT(ui->searchBox2->hasFocus());\r
+        v = ui->folderView2;\r
+        box = ui->searchBox2;\r
     }\r
 \r
-    fp->beginUpdate();\r
-    int curRow = fp->fileTable()->currentRow();\r
-    int rowCount = fp->fileTable()->rowCount();\r
-    for (; row < rowCount; row++) {\r
-        fp->fileTable()->item(row, 0)->setCheckState(Qt::Unchecked);\r
+    if (text.right(1) == "/") {\r
+        box->setText(text.left(text.length() - 1));\r
+        ui->action_Search->setChecked(false);\r
+        return;\r
     }\r
-    fp->fileTable()->setCurrentIndex(\r
-                fp->fileTable()->model()->index(curRow, 1));\r
-    fp->endUpdate();\r
+\r
+    v->searchItem(box->text());\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onMarkInvert\r
-///\r
-/// マークを反転します(I)\r
-///\r
-void MainWindow::onMarkInvert()\r
+void MainWindow::searchNext()\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (fp == NULL) {\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::searchNext";\r
 \r
-    int row = 0;\r
-    if (fp->fileTable()->item(row, 1)->text() == "..") {\r
-        row++;\r
-    }\r
+    FolderView *v = folderView();\r
+    SearchBox *box = searchBox(v);\r
+    v->searchNext(box->text());\r
+}\r
 \r
-    fp->beginUpdate();\r
-    int curRow = fp->fileTable()->currentRow();\r
-    int rowCount = fp->fileTable()->rowCount();\r
-    for (; row < rowCount; row++) {\r
-        QTableWidgetItem *item = fp->fileTable()->item(row, 0);\r
-        if (item->checkState() == Qt::Checked) {\r
-            item->setCheckState(Qt::Unchecked);\r
-        }\r
-        else {\r
-            item->setCheckState(Qt::Checked);\r
-        }\r
-    }\r
-    fp->fileTable()->setCurrentIndex(\r
-                fp->fileTable()->model()->index(curRow, 1));\r
-    fp->endUpdate();\r
+void MainWindow::searchPrev()\r
+{\r
+    qDebug() << "MainWindow::searchPrev";\r
+\r
+    FolderView *v = folderView();\r
+    SearchBox *box = searchBox(v);\r
+    v->searchPrev(box->text());\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onMarkToggle\r
-///\r
-/// マークを設定または解除します(Space)\r
-///\r
-void MainWindow::onMarkToggle()\r
+void MainWindow::setCursorToBegin()\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (fp == NULL) {\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::setCursorToBegin();";\r
 \r
-    int row = fp->fileTable()->currentRow();\r
-    QTableWidgetItem *item = fp->fileTable()->item(row, 0);\r
-    if (fp->fileTable()->item(row, 1)->text() != "..") {\r
-       if (item->checkState() == Qt::Checked) {\r
-            item->setCheckState(Qt::Unchecked);\r
-       }\r
-        else {\r
-            item->setCheckState(Qt::Checked);\r
-       }\r
-    }\r
-    // 最終行でなければ、次のアイテムに移動する\r
-    if (row < fp->fileTable()->rowCount() - 1) {\r
-        QModelIndex nextIndex = fp->fileTable()->model()->index(row + 1, 1);\r
-        fp->fileTable()->setCurrentIndex(nextIndex);\r
-    }\r
+    FolderView *v = folderView();\r
+    int row = 0;\r
+    v->setCurrentIndex(v->model()->index(row, 0));\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onMoveCursorDown\r
-///\r
-/// カーソルを下に移動します(J)\r
-///\r
-void MainWindow::onMoveCursorDown()\r
+void MainWindow::cursorDown()\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (fp == NULL) {\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::cursorDown();";\r
 \r
-    int row = fp->fileTable()->currentRow();\r
-    if (row < fp->fileTable()->rowCount() - 1) {\r
-        QModelIndex nextIndex = fp->fileTable()->model()->index(row + 1, 1);\r
-        fp->fileTable()->setCurrentIndex(nextIndex);\r
+    FolderView *v = folderView();\r
+    int row = v->currentIndex().row() + 1;\r
+    if (row < v->model()->rowCount()) {\r
+        v->setCurrentIndex(v->model()->index(row, 0));\r
     }\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onMoveCursorUp\r
-///\r
-/// カーソルを上に移動します(K)\r
-///\r
-void MainWindow::onMoveCursorUp()\r
+void MainWindow::cursorUp()\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (fp == NULL) {\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::cursorUp();";\r
 \r
-    int row = fp->fileTable()->currentRow();\r
-    if (row > 0) {\r
-        QModelIndex nextIndex = fp->fileTable()->model()->index(row - 1, 1);\r
-        fp->fileTable()->setCurrentIndex(nextIndex);\r
+    FolderView *v = folderView();\r
+    int row = v->currentIndex().row() - 1;\r
+    if (row >= 0) {\r
+        v->setCurrentIndex(v->model()->index(row, 0));\r
     }\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onMoveCursorBegin\r
-///\r
-/// カーソルを先頭に移動します(G)\r
-///\r
-void MainWindow::onMoveCursorBegin()\r
+void MainWindow::setCursorToEnd()\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (fp == NULL) {\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::setCursorToEnd();";\r
 \r
-    QModelIndex nextIndex = fp->fileTable()->model()->index(0, 1);\r
-    fp->fileTable()->setCurrentIndex(nextIndex);\r
+    FolderView *v = folderView();\r
+    int row = v->model()->rowCount() - 1;\r
+    v->setCurrentIndex(v->model()->index(row, 0));\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onMoveCursorEnd\r
-///\r
-/// カーソルを末尾に移動します(Shift + G)\r
-void MainWindow::onMoveCursorEnd()\r
+void MainWindow::setFontSizeDown()\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (fp == NULL) {\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::setFontSizeDown();";\r
+\r
+    QSettings settings;\r
+\r
+    QFont font = settings.value(IniKey_ViewFont).value<QFont>();\r
+    font.setPointSize(font.pointSize() - 1);\r
+    settings.setValue(IniKey_ViewFont, font);\r
 \r
-    int row = fp->fileTable()->rowCount() - 1;\r
-    QModelIndex nextIndex = fp->fileTable()->model()->index(row, 1);\r
-    fp->fileTable()->setCurrentIndex(nextIndex);\r
+    ui->folderView1->updateAppearance();\r
+    ui->folderView2->updateAppearance();\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onMoveBack\r
-///\r
-/// 前の履歴に戻ります(Alt + ←)\r
-///\r
-void MainWindow::onMoveBack()\r
+void MainWindow::setFontSizeUp()\r
 {\r
-    QMessageBox::information(this, tr("情報"), tr("履歴機能は未実装です。"));\r
+    qDebug() << "MainWindow::setFontSizeUp();";\r
+\r
+    QSettings settings;\r
+\r
+    QFont font = settings.value(IniKey_ViewFont).value<QFont>();\r
+    font.setPointSize(font.pointSize() + 1);\r
+    settings.setValue(IniKey_ViewFont, font);\r
+\r
+    ui->folderView1->updateAppearance();\r
+    ui->folderView2->updateAppearance();\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onMoveForward\r
-///\r
-/// 次の履歴に進みます(Alt + →)\r
-///\r
-void MainWindow::onMoveForward()\r
+void MainWindow::setPathFromOther()\r
 {\r
-    QMessageBox::information(this, tr("情報"), tr("履歴機能は未実装です。"));\r
+    qDebug() << "MainWindow::setPathFromOther();";\r
 \r
+    FolderView *view = folderView();\r
+    FolderView *other = otherSideView(view);\r
+\r
+    view->setPath(other->dir(), true);\r
+    updateActions();\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onMoveHome\r
-///\r
-/// ホームフォルダに移動します(H)\r
-///\r
-void MainWindow::onMoveHome()\r
+void MainWindow::setPathToHome()\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (fp == NULL) {\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::setPathToHome();";\r
 \r
-    fp->setCurrentFolder(QDir::homePath());\r
+    folderView()->setPath(QDir::homePath(), true);\r
+    updateActions();\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onMoveJump\r
-///\r
-/// フォルダを選択して移動します(Shift + J)\r
-void MainWindow::onMoveJump()\r
+void MainWindow::setPathToOther()\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (fp == NULL) {\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::setPathToOther();";\r
 \r
-    QString path = QFileDialog::getExistingDirectory(\r
-                this,\r
-                tr("フォルダを選択"),\r
-                fp->dir()->absolutePath());\r
-    if (!path.isEmpty()) {\r
-        fp->setCurrentFolder(path);\r
-    }\r
+    FolderView *view = folderView();\r
+    FolderView *other = otherSideView(view);\r
+\r
+    other->setPath(view->dir(), true);\r
+    updateActions();\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onMoveOther\r
-///\r
-/// キーボードフォーカスを他方のパネルに移動します(TAB)\r
-///\r
-void MainWindow::onMoveOther()\r
+void MainWindow::setPathToParent()\r
 {\r
-    FolderPanel *fp = this->inactivePanel();\r
-    if (fp) {\r
-        fp->fileTable()->setFocus();\r
+    qDebug() << "MainWindow::setPathToParent();";\r
+\r
+    QDir dir(folderView()->dir());\r
+    if (!dir.isRoot()) {\r
+        dir.cdUp();\r
+        folderView()->setPath(dir.absolutePath(), true);\r
+        updateActions();\r
     }\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onMoveParent\r
-///\r
-/// 親フォルダに移動します(Backspace)\r
-///\r
-void MainWindow::onMoveParent()\r
+void MainWindow::setPathToRoot()\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (fp == NULL) {\r
-        return;\r
+    qDebug() << "MainWindow::setPathToRoot();";\r
+\r
+    folderView()->setPath(QDir::rootPath(), true);\r
+    updateActions();\r
+}\r
+\r
+void MainWindow::toggleSearchBox(bool checked)\r
+{\r
+    qDebug() << "MainWindow::toggleSearchBox" << checked;\r
+\r
+    FolderView *v;\r
+    SearchBox *box;\r
+\r
+    if (checked) {\r
+        v = folderView();\r
+        if (v == ui->folderView1) {\r
+            box = ui->searchBox1;\r
+        }\r
+        else {\r
+            Q_ASSERT(v == ui->folderView2);\r
+            box = ui->searchBox2;\r
+        }\r
+\r
+        box->setVisible(true);\r
+        box->setFocus();\r
+        box->selectAll();\r
     }\r
+    else {\r
+        if (ui->searchBox1->isVisible()) {\r
+            box = ui->searchBox1;\r
+            v = ui->folderView1;\r
+        }\r
+        else {\r
+            Q_ASSERT(ui->searchBox2->isVisible());\r
+            box = ui->searchBox2;\r
+            v = ui->folderView2;\r
+        }\r
 \r
-    if (!fp->dir()->isRoot()) {\r
-        QString path = fp->dir()->absoluteFilePath("..");\r
-        fp->setCurrentFolder(path);\r
+        if (box->hasFocus()) {\r
+            v->setFocus();\r
+        }\r
+        box->setVisible(false);\r
     }\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onMoveRoot\r
-///\r
-/// ルートフォルダに移動します()\r
-void MainWindow::onMoveRoot()\r
+void MainWindow::openRequest(const QFileInfo &info)\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (fp == NULL) {\r
-        return;\r
-    }\r
+    m_focusedView = QApplication::focusWidget();\r
 \r
-    if (!fp->dir()->isRoot()) {\r
-        fp->setCurrentFolder(QDir::rootPath());\r
+    QFile file(info.absoluteFilePath());\r
+    if (file.open(QIODevice::ReadOnly)) {\r
+        ui->splitter->setVisible(false);\r
+        ui->textView->setVisible(true);\r
+        ui->textView->setFocus();\r
+        ui->textView->setSource(file.readAll());\r
+    }\r
+    else {\r
+        QMessageBox::critical(\r
+                    this, tr("エラー"),\r
+                    tr("ファイルの読み込みに失敗しました。"));\r
     }\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onViewFromOther\r
-///\r
-/// 隣のパネルと同じフォルダを表示します(O)\r
-///\r
-void MainWindow::onViewFromOther()\r
+void MainWindow::showPreferenceDialog()\r
 {\r
-    FolderPanel *fp1 = activePanel();\r
-    FolderPanel *fp2 = inactivePanel();\r
-    if (fp1 == NULL || fp2 == NULL) {\r
-        return;\r
+    qDebug() << "MainWindow::showPreferenceDialog";\r
+\r
+    PreferenceDialog dlg(this);\r
+    if (dlg.exec() == QDialog::Accepted) {\r
+        ui->locationBox1->updateAppearance();\r
+        ui->locationBox2->updateAppearance();\r
+        ui->folderView1->updateAppearance();\r
+        ui->folderView2->updateAppearance();\r
+        ui->textView->updateAppearance();\r
+\r
+        updateActions();\r
     }\r
+}\r
+\r
+void MainWindow::toggleShowHiddenFiles(bool checked)\r
+{\r
+    qDebug() << "MainWindow::toggleShowHiddenFiles" << checked;\r
 \r
-    fp1->setCurrentFolder(fp2->dir()->absolutePath());\r
+    ui->folderView1->setFilter(QDir::Hidden, checked);\r
+    ui->folderView1->refresh();\r
+\r
+    ui->folderView2->setFilter(QDir::Hidden, checked);\r
+    ui->folderView2->refresh();\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onViewToOther\r
-///\r
-/// 隣のパネルに同じフォルダを表示します(Shift + O)\r
-///\r
-void MainWindow::onViewToOther()\r
+void MainWindow::toggleShowSystemFiles(bool checked)\r
 {\r
-    FolderPanel *fp1 = activePanel();\r
-    FolderPanel *fp2 = inactivePanel();\r
-    if (fp1 == NULL || fp2 == NULL) {\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::toggleShowSystemFiles" << checked;\r
+\r
+    ui->folderView1->setFilter(QDir::System, checked);\r
+    ui->folderView1->refresh();\r
 \r
-    fp2->setCurrentFolder(fp1->dir()->absolutePath());\r
+    ui->folderView2->setFilter(QDir::System, checked);\r
+    ui->folderView2->refresh();\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onViewHidden\r
-///\r
-/// 隠しファイルの表示/非表示を切り替えます(Shift + H)\r
-void MainWindow::onViewHidden()\r
+void MainWindow::showContextMenu(QContextMenuEvent *event)\r
 {\r
-    QSettings settings;\r
-    bool checked = !settings.value("Common/ShowHidden", false).toBool();\r
-    settings.setValue("Common/ShowHidden", checked);\r
+    qDebug() << "MainWindow::showContextMenu();";\r
 \r
-    if (checked) {\r
-        ui->folderPanel_L->dir()->setFilter(ui->folderPanel_L->dir()->filter() | QDir::Hidden);\r
-        ui->folderPanel_R->dir()->setFilter(ui->folderPanel_R->dir()->filter() | QDir::Hidden);\r
+    FolderView *view = static_cast<FolderView*>(sender());\r
+    QModelIndex index = view->indexAt(event->pos());\r
+\r
+    QMenu menu(this);\r
+    if (index.isValid()) {\r
+        menu.addAction(ui->action_Open);\r
+        menu.addAction(ui->action_Exec);\r
+        menu.addAction(ui->action_OpenEditor);\r
+        menu.addAction(ui->action_OpenTerminal);\r
+        menu.addSeparator();\r
+        menu.addAction(ui->copy_Filename);\r
+        menu.addAction(ui->copy_Fullpath);\r
     }\r
     else {\r
-        ui->folderPanel_L->dir()->setFilter(ui->folderPanel_L->dir()->filter() ^ QDir::Hidden);\r
-        ui->folderPanel_R->dir()->setFilter(ui->folderPanel_R->dir()->filter() ^ QDir::Hidden);\r
+        menu.addAction(ui->move_Back);\r
+        menu.addAction(ui->move_Forward);\r
+        menu.addSeparator();\r
+        menu.addAction(ui->move_Parent);\r
+        menu.addAction(ui->move_Home);\r
+        menu.addAction(ui->move_Root);\r
+        menu.addAction(ui->move_Jump);\r
     }\r
 \r
-    ui->folderPanel_L->setCurrentFolder(ui->folderPanel_L->dir()->absolutePath());\r
-    ui->folderPanel_R->setCurrentFolder(ui->folderPanel_R->dir()->absolutePath());\r
+    menu.exec(event->globalPos());\r
+\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onViewSwap\r
-///\r
-/// パネルの表示内容を交換します(W)\r
-///\r
-void MainWindow::onViewSwap()\r
+void MainWindow::checkUpdate(bool silent)\r
 {\r
-    FolderPanel *fp1 = activePanel();\r
-    FolderPanel *fp2 = inactivePanel();\r
-    if (fp1 == NULL || fp2 == NULL) {\r
-        return;\r
+    qDebug() << "MainWindow::checkUpdate()" << silent;\r
+\r
+    QNetworkAccessManager *manager = new QNetworkAccessManager(this);\r
+\r
+    if (silent) {\r
+        connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(checkUpdateFinishedSilent(QNetworkReply*)));\r
+    }\r
+    else {\r
+        connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(checkUpdateFinished(QNetworkReply*)));\r
     }\r
+#ifdef Q_OS_WIN\r
+    manager->get(QNetworkRequest(QUrl("http://miyabi.rakusaba.jp/wp-content/uploads/gefu_latest_win.html")));\r
+#elif defined(Q_OS_MAC)\r
+    manager->get(QNetworkRequest(QUrl("http://miyabi.rakusaba.jp/wp-content/uploads/gefu_latest_mac.html")));\r
+#endif\r
+}\r
 \r
-    QString path1 = fp1->dir()->absolutePath();\r
-    QString path2 = fp2->dir()->absolutePath();\r
+void MainWindow::checkUpdateFinishedSilent(QNetworkReply *reply)\r
+{\r
+    qDebug() << "MainWindow::checkUpdateFinishedSilent";\r
 \r
-    fp1->setCurrentFolder(path2);\r
-    fp2->setCurrentFolder(path1);\r
+    checkUpdateFinished(reply, true);\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onCmdMove\r
-///\r
-/// ファイルを移動します(Ctrl + M)\r
-///\r
-void MainWindow::onCmdMove()\r
+void MainWindow::checkUpdateFinished(QNetworkReply *reply, bool silent)\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (!fp) {\r
-        return;\r
+    qDebug() << "MainWindow::checkUpdateFinished" << silent;\r
+\r
+    if (reply->error() == QNetworkReply::NoError) {\r
+        QString str = reply->readAll();\r
+        str = str.split(QRegExp("[\r\n]"), QString::SkipEmptyParts).at(0);\r
+        QRegExp rx("Gefu([0-9]+)");\r
+        rx.indexIn(str);\r
+        QString version = rx.cap(1);\r
+        if (version.toInt() > VERSION_VALUE * 100) {\r
+            QMessageBox::information(\r
+                        this, tr("情報"),\r
+                        tr("最新のバージョンが存在します。<br/>") +\r
+                        tr("<a href='%1'>こちらからダウンロードしてください。</a>").arg(str));\r
+        }\r
+        else if (!silent) {\r
+            QMessageBox::information(\r
+                        this, tr("情報"),\r
+                        tr("お使いのバージョンは最新です。"));\r
+        }\r
     }\r
-\r
-    QStringList list = selectedItems(fp);\r
-    if (list.isEmpty()) {\r
-        return;\r
+    else if (!silent){\r
+        QMessageBox::critical(\r
+                    this, tr("エラー"),\r
+                    tr("最新バージョンのチェックに失敗しました。<br/>") +\r
+                    reply->errorString());\r
     }\r
+}\r
 \r
-    CopyMoveWorker *worker = new CopyMoveWorker();\r
-    connect(worker, SIGNAL(askOverWrite(bool*,int*,int*,QString*,QString,QString)),\r
-            this, SLOT(onAskOverWrite(bool*,int*,int*,QString*,QString,QString)));\r
-    worker->setCopyList(&list);\r
-    worker->setTargetDir(inactivePanel()->dir()->absolutePath());\r
-    worker->setMoveMode(true);\r
+void MainWindow::viewFinish(QWidget *sender)\r
+{\r
+    qDebug() << "MainWindow::viewFinish();" << sender->objectName();\r
 \r
-    OperationDialog opDlg(this);\r
-    opDlg.setWindowTitle(tr("移動"));\r
-    opDlg.setWorker(worker);\r
+    sender->setVisible(false);\r
+    ui->splitter->setVisible(true);\r
+    m_focusedView->setFocus();\r
+}\r
 \r
-    ui->folderPanel_L->UninstallWatcher();\r
-    ui->folderPanel_R->UninstallWatcher();\r
-    opDlg.exec();\r
-    ui->folderPanel_L->setCurrentFolder(ui->folderPanel_L->dir()->absolutePath());\r
-    ui->folderPanel_R->setCurrentFolder(ui->folderPanel_R->dir()->absolutePath());\r
 \r
+void MainWindow::initActionConnections()\r
+{\r
+    qDebug() << "MainWindow::initActionConnections";\r
+\r
+    connect(ui->action_Command, SIGNAL(triggered()), this, SLOT(executeCommand()));\r
+    connect(ui->action_Exec, SIGNAL(triggered()), this, SLOT(shellExecute()));\r
+    connect(ui->action_Open, SIGNAL(triggered()), this, SLOT(open()));\r
+    connect(ui->action_OpenEditor, SIGNAL(triggered()), this, SLOT(openEditor()));\r
+    connect(ui->action_OpenTerminal, SIGNAL(triggered()), this, SLOT(openTerminal()));\r
+    connect(ui->action_Quit, SIGNAL(triggered()), this, SLOT(close()));\r
+    connect(ui->action_Search, SIGNAL(toggled(bool)), this, SLOT(toggleSearchBox(bool)));\r
+    connect(ui->action_SearchNext, SIGNAL(triggered()), this, SLOT(searchNext()));\r
+    connect(ui->action_SearchPrev, SIGNAL(triggered()), this, SLOT(searchPrev()));\r
+    connect(ui->action_Setting, SIGNAL(triggered()), this, SLOT(showPreferenceDialog()));\r
+    connect(ui->check_Update, SIGNAL(triggered()), this, SLOT(checkUpdate()));\r
+    connect(ui->cmd_Copy, SIGNAL(triggered()), this, SLOT(copyItems()));\r
+    connect(ui->cmd_Delete, SIGNAL(triggered()), this, SLOT(deleteItems()));\r
+    connect(ui->cmd_Move, SIGNAL(triggered()), this, SLOT(moveItems()));\r
+    connect(ui->cmd_NewFile, SIGNAL(triggered()), this, SLOT(createFile()));\r
+    connect(ui->cmd_NewFolder, SIGNAL(triggered()), this, SLOT(createFolder()));\r
+    connect(ui->cmd_Rename, SIGNAL(triggered()), this, SLOT(renameItems()));\r
+    connect(ui->copy_Filename, SIGNAL(triggered()), this, SLOT(copyFilenameToClipboard()));\r
+    connect(ui->copy_Fullpath, SIGNAL(triggered()), this, SLOT(copyFullpathTpClipboard()));\r
+    connect(ui->help_About, SIGNAL(triggered()), this, SLOT(about()));\r
+    connect(ui->mark_All, SIGNAL(triggered()), this, SLOT(markAll()));\r
+    connect(ui->mark_AllFiles, SIGNAL(triggered()), this, SLOT(markAllFiles()));\r
+    connect(ui->mark_AllOff, SIGNAL(triggered()), this, SLOT(markAllOff()));\r
+    connect(ui->mark_Invert, SIGNAL(triggered()), this, SLOT(markInvert()));\r
+    connect(ui->mark_Toggle, SIGNAL(triggered()), this, SLOT(markToggle()));\r
+    connect(ui->move_Back, SIGNAL(triggered()), this, SLOT(historyBack()));\r
+    connect(ui->move_Begin, SIGNAL(triggered()), this, SLOT(setCursorToBegin()));\r
+    connect(ui->move_Down, SIGNAL(triggered()), this, SLOT(cursorDown()));\r
+    connect(ui->move_End, SIGNAL(triggered()), this, SLOT(setCursorToEnd()));\r
+    connect(ui->move_Forward, SIGNAL(triggered()), this, SLOT(historyForward()));\r
+    connect(ui->move_History, SIGNAL(triggered()), this, SLOT(showHistoryDialog()));\r
+    connect(ui->move_Home, SIGNAL(triggered()), this, SLOT(setPathToHome()));\r
+    connect(ui->move_Jump, SIGNAL(triggered()), this, SLOT(chooseFolder()));\r
+    connect(ui->move_Parent, SIGNAL(triggered()), this, SLOT(setPathToParent()));\r
+    connect(ui->move_Root, SIGNAL(triggered()), this, SLOT(setPathToRoot()));\r
+    connect(ui->move_Up, SIGNAL(triggered()), this, SLOT(cursorUp()));\r
+    connect(ui->view_Filter, SIGNAL(triggered()), this, SLOT(showFilterDialog()));\r
+    connect(ui->view_FontSizeDown, SIGNAL(triggered()), this, SLOT(setFontSizeDown()));\r
+    connect(ui->view_FontSizeUp, SIGNAL(triggered()), this, SLOT(setFontSizeUp()));\r
+    connect(ui->view_FromOther, SIGNAL(triggered()), this, SLOT(setPathFromOther()));\r
+    connect(ui->view_Hidden, SIGNAL(toggled(bool)), this, SLOT(toggleShowHiddenFiles(bool)));\r
+    connect(ui->view_Refresh, SIGNAL(triggered()), this, SLOT(refresh()));\r
+    connect(ui->view_Sort, SIGNAL(triggered()), this, SLOT(showSortDialog()));\r
+    connect(ui->view_Swap, SIGNAL(triggered()), this, SLOT(swapView()));\r
+    connect(ui->view_System, SIGNAL(toggled(bool)), this, SLOT(toggleShowSystemFiles(bool)));\r
+    connect(ui->view_ToOther, SIGNAL(triggered()), this, SLOT(setPathToOther()));\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onCmdCopy\r
-///\r
-/// ファイルをコピーします(Ctrl + C)\r
-///\r
-void MainWindow::onCmdCopy()\r
+FolderView *MainWindow::folderView() const\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (!fp) {\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::folderView";\r
 \r
-    QStringList list = selectedItems(fp);\r
-    if (list.isEmpty()) {\r
-        return;\r
+    QWidget *w = qApp->focusWidget();\r
+    if (w == ui->folderView1 || w == ui->searchBox1 || w == ui->locationBox1) {\r
+        return ui->folderView1;\r
+    }\r
+    if (w == ui->folderView2 || w == ui->searchBox2 || w == ui->locationBox2) {\r
+        return ui->folderView2;\r
     }\r
 \r
-    CopyMoveWorker *worker = new CopyMoveWorker();\r
-    connect(worker, SIGNAL(askOverWrite(bool*,int*,int*,QString*,QString,QString)),\r
-            this, SLOT(onAskOverWrite(bool*,int*,int*,QString*,QString,QString)));\r
-    worker->setCopyList(&list);\r
-    worker->setTargetDir(inactivePanel()->dir()->absolutePath());\r
-    worker->setMoveMode(false);\r
+    qDebug() << w->objectName();\r
+    return NULL;\r
+}\r
 \r
-    OperationDialog opDlg(this);\r
-    opDlg.setWindowTitle(tr("コピー"));\r
-    opDlg.setWorker(worker);\r
+void MainWindow::replaceVars(QString &str, const QFileInfo info)\r
+{\r
+    qDebug() << "MainWindow::replaceVars" << str;\r
 \r
-    ui->folderPanel_L->UninstallWatcher();\r
-    ui->folderPanel_R->UninstallWatcher();\r
-    opDlg.exec();\r
-    ui->folderPanel_L->setCurrentFolder(ui->folderPanel_L->dir()->absolutePath());\r
-    ui->folderPanel_R->setCurrentFolder(ui->folderPanel_R->dir()->absolutePath());\r
-\r
-}\r
-\r
-///\r
-/// \brief MainWindow::onAskOverWrite\r
-/// \param bOk\r
-/// \param prevCopyMethod\r
-/// \param copyMethod\r
-/// \param alias\r
-/// \param srcPath\r
-/// \param tgtPath\r
-///\r
-/// 上書き処理の方法をユーザに問い合わせます\r
-///\r
-void MainWindow::onAskOverWrite(bool *bOk, int *prevCopyMethod, int *copyMethod,\r
-                                QString *alias, const QString srcPath,\r
-                                const QString tgtPath)\r
-{\r
-    OverWriteDialog dlg;\r
-    dlg.setCopyMethod(*prevCopyMethod);\r
-    dlg.setSameMethodChecked(*copyMethod != OverWriteDialog::Undefined);\r
-    dlg.setFileInfo(srcPath, tgtPath);\r
-    if (dlg.exec() == QDialog::Rejected) {\r
-        *bOk = false;\r
+    str.replace("$B", info.completeBaseName());\r
+    str.replace("$E", info.suffix());\r
+    str.replace("$F", info.fileName());\r
+    if (info.isDir()) {\r
+        str.replace("$D", info.absoluteFilePath());\r
     }\r
     else {\r
-        *prevCopyMethod = dlg.copyMethod();\r
-        if (dlg.isSameMethodChecked()) {\r
-            *copyMethod = *prevCopyMethod;\r
-        }\r
-        *alias = dlg.alias();\r
-        *bOk = true;\r
+        str.replace("$D", info.absolutePath());\r
     }\r
-    CopyMoveWorker *worker = static_cast<CopyMoveWorker*>(sender());\r
-    worker->endAsking();\r
+    str.replace("$P", info.absoluteFilePath());\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onCmdDelete\r
-///\r
-/// ファイルを削除します\r
-///\r
-void MainWindow::onCmdDelete()\r
+SearchBox *MainWindow::searchBox(FolderView *view) const\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (!fp) {\r
-        return;\r
-    }\r
-\r
-    QStringList list = selectedItems(fp);\r
-    if (list.isEmpty()) {\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::searchBox()" << view->objectName();\r
 \r
-    QString msg;\r
-    if (list.size() == 1) {\r
-        msg = QFileInfo(list.at(0)).fileName();\r
+    if (view == ui->folderView1) {\r
+        return ui->searchBox1;\r
     }\r
     else {\r
-        msg = tr("%1個のアイテム").arg(list.size());\r
-    }\r
-    int ret = QMessageBox::question(\r
-                this,\r
-                tr("確認"),\r
-                msg + tr("を削除します<br/>よろしいですか?"));\r
-    if (ret == QMessageBox::Yes) {\r
-        DeleteWorker *worker = new DeleteWorker();\r
-        worker->setDeleteList(&list);\r
-\r
-        OperationDialog opDlg(this);\r
-        opDlg.setWindowTitle(tr("削除"));\r
-        opDlg.setWorker(worker);\r
-\r
-        ui->folderPanel_L->UninstallWatcher();\r
-        ui->folderPanel_R->UninstallWatcher();\r
-        opDlg.exec();\r
-        ui->folderPanel_L->setCurrentFolder(ui->folderPanel_L->dir()->absolutePath());\r
-        ui->folderPanel_R->setCurrentFolder(ui->folderPanel_R->dir()->absolutePath());\r
+        Q_ASSERT(view == ui->folderView2);\r
+        return ui->searchBox2;\r
     }\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onCmdNewFile\r
-///\r
-/// ファイルを作成します\r
-///\r
-void MainWindow::onCmdNewFile()\r
+bool MainWindow::startProcess(const QString &cmd, const QString &workDir, const QString &errMsg)\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (!fp) {\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::startProcess" << cmd << workDir << errMsg;\r
 \r
-    bool bOk;\r
-    QString name = QInputDialog::getText(\r
-                this,\r
-                tr("ファイルを作成"),\r
-                tr("ファイル名"),\r
-                QLineEdit::Normal,\r
-                "",\r
-                &bOk);\r
-    if (bOk && !name.isEmpty()) {\r
-        QFile file(fp->dir()->absoluteFilePath(name));\r
-        if (!file.open(QIODevice::WriteOnly)) {\r
-            QMessageBox::critical(this,\r
-                                  tr("エラー"),\r
-                                  tr("ファイルの作成に失敗しました。"));\r
-        }\r
-        else {\r
-            file.close();\r
-        }\r
+    QProcess process(this);\r
+    process.setWorkingDirectory(workDir);\r
+    if (!process.startDetached(cmd)) {\r
+        QMessageBox::critical(this, tr("エラー"), errMsg + "<br/>" + cmd);\r
+        return false;\r
     }\r
+    return true;\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onCmdNewFolder\r
-///\r
-/// フォルダを作成します\r
-///\r
-void MainWindow::onCmdNewFolder()\r
+void MainWindow::updateActions()\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (!fp) {\r
-        return;\r
+    qDebug() << "MainWindow::updateActions";\r
+\r
+    if (ui->textView->hasFocus()) {\r
+        // テキストビューア時\r
+        setEnabledAllActions(false);\r
+        ui->action_Quit->setEnabled(true);\r
+        ui->action_Setting->setEnabled(true);\r
+        ui->check_Update->setEnabled(true);\r
+        ui->copy_Filename->setEnabled(true);\r
+        ui->copy_Fullpath->setEnabled(true);\r
+        ui->help_About->setEnabled(true);\r
+    }\r
+    else if (ui->searchBox1->hasFocus() || ui->searchBox2->hasFocus()) {\r
+        // ファイル検索時\r
+        setEnabledAllActions(false);\r
+        ui->action_Search->setEnabled(true);\r
+        ui->action_SearchNext->setEnabled(true);\r
+        ui->action_SearchPrev->setEnabled(true);\r
+        ui->help_About->setEnabled(true);\r
+        ui->action_Quit->setEnabled(true);\r
+    }\r
+    else if (ui->folderView1->hasFocus() || ui->folderView2->hasFocus()) {\r
+        // 通常時\r
+        setEnabledAllActions(true);\r
+        ui->action_SearchNext->setEnabled(false);\r
+        ui->action_SearchPrev->setEnabled(false);\r
+\r
+        ui->move_Back->setEnabled(!folderView()->history()->isBegin());\r
+        ui->move_Forward->setEnabled(!folderView()->history()->isEnd());\r
+\r
+        QSettings settings;\r
+        ui->action_OpenEditor->setEnabled(!settings.value(IniKey_EditorPath).toString().isEmpty());\r
+        ui->action_OpenTerminal->setEnabled(!settings.value(IniKey_TerminalPath).toString().isEmpty());\r
     }\r
+}\r
 \r
-    bool bOk;\r
-    QString name = QInputDialog::getText(\r
-                this,\r
-                tr("フォルダを作成"),\r
-                tr("フォルダ名"),\r
-                QLineEdit::Normal,\r
-                "",\r
-                &bOk);\r
-    if (bOk && !name.isEmpty()) {\r
-        if (!fp->dir()->mkpath(name)) {\r
-            QMessageBox::critical(this,\r
-                                  tr("エラー"),\r
-                                  tr("フォルダの作成に失敗しました。"));\r
+void MainWindow::setEnabledAllActions(bool enable)\r
+{\r
+    qDebug() << "MainWindow::setEnabledAllActions();" << enable;\r
+    foreach (QObject *obj, children()) {\r
+        QAction *action = qobject_cast<QAction*>(obj);\r
+        if (action) {\r
+            action->setEnabled(enable);\r
         }\r
     }\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onCmdRename\r
-///\r
-/// 名前を変更します\r
-///\r
-void MainWindow::onCmdRename()\r
+void MainWindow::setNameFilters(FolderView *view, const QString &filters)\r
 {\r
-    FolderPanel *fp = activePanel();\r
-    if (!fp) {\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::setNameFilters();" << view->objectName() << filters;\r
 \r
-    QStringList list = selectedItems(fp);\r
+    QStringList list = filters.split(" ", QString::SkipEmptyParts);\r
     if (list.isEmpty()) {\r
-        return;\r
+        list << "*";\r
     }\r
+    view->setNameFilters(list);\r
+    showNameFilters(view);\r
+}\r
 \r
-    IRenameDialog *dlg;\r
-    if (list.size() == 1) {\r
-        dlg = new RenameSingleDialog(this);\r
+QLabel *MainWindow::filterLabel(const FolderView *view) const\r
+{\r
+    qDebug() << "MainWindow::filterLabel()" << view->objectName();\r
+    if (view == ui->folderView1) {\r
+        return ui->filterLabel1;\r
     }\r
     else {\r
-        dlg = new RenameMultiDialog(this);\r
-    }\r
-    dlg->setWorkingDirectory(fp->dir()->absolutePath());\r
-    dlg->setNames(list);\r
-    int dlgResult = dlg->exec();\r
-    if (dlgResult == QDialog::Accepted && !dlg->renameMap().isEmpty()) {\r
-        RenameWorker *worker = new RenameWorker();\r
-        worker->setRenameMap(&dlg->renameMap());\r
-\r
-        OperationDialog opDlg(this);\r
-        opDlg.setWindowTitle(tr("名前を変更"));\r
-        opDlg.setWorker(worker);\r
-\r
-        ui->folderPanel_L->UninstallWatcher();\r
-        ui->folderPanel_R->UninstallWatcher();\r
-        opDlg.exec();\r
-        ui->folderPanel_L->setCurrentFolder(ui->folderPanel_L->dir()->absolutePath());\r
-        ui->folderPanel_R->setCurrentFolder(ui->folderPanel_R->dir()->absolutePath());\r
+        Q_ASSERT(view == ui->folderView2);\r
+        return ui->filterLabel2;\r
     }\r
 }\r
 \r
-///\r
-/// \brief MainWindow::onHelpAbout\r
-///\r
-/// アプリケーションの概要を表示します(?)\r
-///\r
-void MainWindow::onHelpAbout()\r
+void MainWindow::about()\r
 {\r
     QMessageBox::about(\r
                 this,\r
                 tr("げふぅ について"),\r
                 tr("<h3>Gefu Ver%1</h3>").arg(VERSION_VALUE) +\r
-                tr("<center>Gefu is Experimental File Utility.<br/>"\r
-                   "(げふぅは実験的なファイルユーティリティです)</center>"\r
-                   "<p>Copyright 2014 @miyabi_satoh All rights reserved.</p>"));\r
+                tr("<center>Gefu is an Experimental File Utility.<br/>"\r
+                   "<small>(げふぅは実験的なファイルユーティリティです)</small></center>"\r
+                   "<p>最新版の情報は<a href='https://sourceforge.jp/projects/gefu/'>プロジェクトサイト</a>で公開しています。</p>"\r
+                   "<p><small>Copyright 2014 @miyabi_satoh All rights reserved.</small></p>"));\r
 }\r
 \r
-///\r
-/// \brief MainWindow::selectedItems\r
-/// \param fp フォルダパネルへのポインタ\r
-/// \return 選択アイテムのフルパスのリスト\r
-///\r
-/// 選択アイテムのフルパスのリストを取得します\r
-///\r
-QStringList MainWindow::selectedItems(FolderPanel *fp)\r
+void MainWindow::closeEvent(QCloseEvent *event)\r
 {\r
-    QStringList list;\r
-    for (int n = 0; n < fp->fileTable()->rowCount(); n++) {\r
-        if (fp->fileTable()->item(n, 0)->checkState() == Qt::Checked) {\r
-            list << fp->dir()->absoluteFilePath(fp->fileTable()->item(n, 1)->text());\r
-        }\r
-    }\r
+    QSettings settings;\r
 \r
-    if (list.isEmpty()) {\r
-        int row = fp->fileTable()->currentRow();\r
-        QString name = fp->fileTable()->item(row, 1)->text();\r
-        if (name != "..") {\r
-            list << fp->dir()->absoluteFilePath(name);\r
+    if (settings.value(IniKey_ConfirmExit).toBool()) {\r
+        QMessageBox msgBox;\r
+        QCheckBox *checkBox = new QCheckBox();\r
+        checkBox->setText(tr("次回以降は確認しない"));\r
+        msgBox.setCheckBox(checkBox);\r
+        msgBox.setText(tr("終了しますか?"));\r
+        msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);\r
+        msgBox.setIcon(QMessageBox::Question);\r
+\r
+        if (msgBox.exec() == QMessageBox::No) {\r
+            event->ignore();\r
+            return;\r
         }\r
+        settings.setValue(IniKey_ConfirmExit, !checkBox->isChecked());\r
     }\r
 \r
-    return list;\r
+    settings.setValue(QString("Left/") + IniKey_Dir, ui->folderView1->dir());\r
+    settings.setValue(QString("Right/") + IniKey_Dir, ui->folderView2->dir());\r
+    settings.setValue(IniKey_ShowHidden, ui->view_Hidden->isChecked());\r
+    settings.setValue(IniKey_ShowSystem, ui->view_System->isChecked());\r
+    settings.setValue(IniKey_WindowGeometry, saveGeometry());\r
+    settings.setValue(iniKey_WindowState, saveState());\r
+    QMainWindow::closeEvent(event);\r
 }\r
 \r
-///\r
-/// \brief getMainWnd\r
-/// \return メインウィンドウのポインタ\r
-///\r
-/// メインウィンドウを取得します\r
-///\r
-MainWindow* getMainWnd()\r
+\r
+void MainWindow::keyPressEvent(QKeyEvent *event)\r
 {\r
-    foreach (QWidget *w, qApp->topLevelWidgets()) {\r
-        if (w->objectName() == "MainWindow") {\r
-            return static_cast<MainWindow*>(w);\r
-        }\r
-    }\r
-    qDebug() << "MainWindow not found !?";\r
-    return NULL;\r
+    QString ksq = KeyEventToSequence(event);\r
+    qDebug() << ksq << " @MainWindow";\r
+\r
+    QMainWindow::keyPressEvent(event);\r
 }\r