OSDN Git Service

高速化の試み
[gefu/Gefu.git] / mainwindow.cpp
index 108d547..c6b44a0 100644 (file)
@@ -1,11 +1,8 @@
-#include "common.h"\r
+#include "global.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 "foldermodel.h"\r
+#include "folderpanel.h"\r
 #include "copymoveworker.h"\r
 #include "operationdialog.h"\r
 #include "overwritedialog.h"\r
 #include "renamemultidialog.h"\r
 #include "historydialog.h"\r
 #include "sortdialog.h"\r
+#include "simpletextview.h"\r
+#include "simpleimageview.h"\r
+#include "bookmarkdialog.h"\r
+#include "preferences.h"\r
+#include "mainwindow.h"\r
+#include "ui_mainwindow.h"\r
 \r
 #include <QCheckBox>\r
 #include <QCloseEvent>\r
 #include <QDebug>\r
-#include <QDesktopWidget>\r
 #include <QMessageBox>\r
-#include <QSettings>\r
+#include <QMimeData>\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
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::MainWindow\r
+/// \param parent   親ウィジェット\r
+///\r
+/// コンストラクタ\r
+///\r
 MainWindow::MainWindow(QWidget *parent) :\r
     QMainWindow(parent),\r
     ui(new Ui::MainWindow),\r
-    m_focusedView(NULL),\r
-    m_overwriteDialog(NULL)\r
+    m_overwriteDialog(this),\r
+    m_viewMode(ModeBasic),\r
+    m_prevMode(ModeBasic),\r
+    m_actions()\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
+    connect(qApp, SIGNAL(focusChanged(QWidget*,QWidget*)), this, SLOT(app_focusChange(QWidget*,QWidget*)));\r
+\r
+    // ステータスバーにウィジェットを設定する\r
+    QLabel *label = new QLabel(this);\r
+    label->setAlignment(Qt::AlignRight);\r
+    label->setObjectName("Right");\r
+    ui->statusBar->addPermanentWidget(label, 0);\r
+\r
+    // アプリケーション情報を初期化する\r
+    qApp->setApplicationName("Gefu");\r
+    qApp->setApplicationVersion(QString("%1").arg(VERSION_VALUE));\r
+    qApp->setOrganizationDomain("sourceforge.jp");\r
+    qApp->setOrganizationName("gefu");\r
+    qApp->setWindowIcon(QIcon("://images/file-manager.png"));\r
+\r
+    // 古い設定ファイルを削除する\r
+#ifdef Q_OS_MAC\r
+    QSettings::setDefaultFormat(QSettings::IniFormat);\r
+    QSettings settings(this);\r
+    if (QFileInfo::exists(settings.fileName())) {\r
+        QFile(settings.fileName()).remove();\r
+        QDir().rmdir(QFileInfo(settings.fileName()).absolutePath());\r
     }\r
+#endif\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
+    ui->LPanel->setModel(new FolderModel(this));\r
+    ui->RPanel->setModel(new FolderModel(this));\r
+    setActiveModel(ui->LPanel->model());\r
 \r
-    shortcuts = ui->action_OpenTerminal->shortcuts();\r
-    shortcuts.append(QKeySequence("Shift+>"));\r
-    ui->action_OpenTerminal->setShortcuts(shortcuts);\r
+    // パネルを初期化する\r
+    ui->LPanel->initialize(this);\r
+    ui->RPanel->initialize(this);\r
+    ui->FPanel->initialize(this);\r
+    ui->FPanel->setVisible(false);\r
 \r
-    shortcuts = ui->help_About->shortcuts();\r
-    shortcuts.append(QKeySequence("Shift+?"));\r
-    ui->help_About->setShortcuts(shortcuts);\r
+    // モデルを初期化する\r
+    Preferences prefs(this);\r
+    prefs.restoreModel("Left", ui->LPanel->model());\r
+    prefs.restoreModel("Right", ui->RPanel->model());\r
 \r
-    // ã\82¦ã\82£ã\83³ã\83\89ã\82¦ã\82¿ã\82¤ã\83\88ã\83«ã\82\92設å®\9aする\r
-    setWindowTitle(tr("げふぅ v%1").arg(VERSION_VALUE));\r
+    // ã\82¢ã\82¯ã\82·ã\83§ã\83³ã\82\92å\88\9dæ\9c\9få\8c\96する\r
+    initActions();\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
+    initBookmarkMenu();\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
+    setWindowTitle(tr("げふぅ Ver%1").arg(VERSION_VALUE));\r
+    setWindowIcon(QIcon("://images/file-manager.png"));\r
+    prefs.restoreWindow(this);\r
 \r
     // 最新バージョンをチェックする\r
-    if (settings.value(IniKey_CheckUpdates).toBool()) {\r
-        checkUpdate(true);\r
+    if (prefs.isCheckUpdate()) {\r
+        onCheckUpdate(true);\r
     }\r
 \r
-    ui->folderView1->refresh();\r
-    ui->folderView2->refresh();\r
+    ui->LPanel->updateAppearance(prefs);\r
+    ui->LPanel->model()->updateAppearance(prefs);\r
+    ui->RPanel->updateAppearance(prefs);\r
+    ui->RPanel->model()->updateAppearance(prefs);\r
 }\r
 \r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::~MainWindow\r
+///\r
+/// デストラクタ\r
+///\r
 MainWindow::~MainWindow()\r
 {\r
     delete ui;\r
 }\r
 \r
-FolderView* MainWindow::otherSideView(const FolderView *view) const\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::app_focusChange\r
+/// \param old  フォーカスを失うウィジェット\r
+/// \param now  フォーカスを得るウィジェット\r
+///\r
+/// フォーカス変更時の処理\r
+///\r
+void MainWindow::app_focusChange(QWidget *old, QWidget *now)\r
 {\r
-    qDebug() << "MainWindow::otherSideView()" << view->objectName();\r
+    qDebug() << "MainWindow::app_focusChange()";\r
+    if (old) qDebug() << "  old is" << old->objectName();\r
+    if (now) qDebug() << "  now is" << now->objectName();\r
+\r
+    // フォルダビューがフォーカスを得た場合\r
+    if (now && (now->objectName() == "folderView" ||\r
+                now->objectName() == "thumbnailView"))\r
+    {\r
+        connect(focusItemView()->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),\r
+                this, SLOT(view_currentChanged(QModelIndex,QModelIndex)));\r
+        FolderModel *m = static_cast<FolderModel*>(focusItemView()->model());\r
+        setActiveModel(m);\r
+        ui->statusBar->showMessage(m->filePath(focusItemView()->currentIndex()));\r
+    }\r
 \r
-    if (view == ui->folderView1) {\r
-        return ui->folderView2;\r
+    // 検索ボックスがフォーカスを失った場合\r
+    if (old && old->objectName() == "searchBox") {\r
+        // 検索モード終了\r
+        ui->toggle_Search->setChecked(false);\r
     }\r
 \r
-    Q_ASSERT(view == ui->folderView2);\r
-    return ui->folderView1;\r
+    // アクションの有効/無効を設定する\r
+    if (now) {\r
+        updateActions();\r
+    }\r
 }\r
 \r
-void MainWindow::focusChange(QWidget *old, QWidget *now)\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::model_PreReset\r
+///\r
+/// FolderModelリセット前の処理\r
+///\r
+void MainWindow::model_PreReset()\r
 {\r
-    Q_UNUSED(old);\r
-    qDebug() << "MainWindow::focusChange";\r
+    qDebug() << "MainWindow::model_PreReset()";\r
 \r
-    if (now == ui->folderView1 || now == ui->folderView2) {\r
-        ui->statusBar->showMessage(folderView()->currentItem().absoluteFilePath());\r
-    }\r
+    ui->statusBar->showMessage(tr("ファイルリストを取得しています..."));\r
+}\r
 \r
-    if (old == ui->searchBox1 || old == ui->searchBox2) {\r
-        old->setVisible(false);\r
-    }\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::model_PostReset\r
+///\r
+/// FolderModelリセット後の処理\r
+///\r
+void MainWindow::model_PostReset()\r
+{\r
+    qDebug() << "MainWindow::model_PostReset()";\r
 \r
-    updateActions();\r
+    FolderModel *m = static_cast<FolderModel*>(sender());\r
+    if (!m->error().isEmpty()) {\r
+        ui->statusBar->showMessage(m->error());\r
+    }\r
+    else {\r
+        ui->statusBar->showMessage(tr("レディ"));\r
+    }\r
 }\r
 \r
-void MainWindow::executeCommand()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onRunCommand\r
+///\r
+/// 入力されたコマンドを実行します。\r
+///\r
+void MainWindow::onRunCommand()\r
 {\r
-    qDebug() << "MainWindow::executeCommand";\r
-\r
-    FolderView *v = folderView();\r
-    Q_ASSERT(v);\r
+    qDebug() << "MainWindow::onRunCommand";\r
 \r
-    QFileInfoList list = v->selectedItems();\r
+    QFileInfoList list = selectedItems();\r
     QString command = QString::null;\r
     foreach (const QFileInfo &info, list) {\r
 #ifdef Q_OS_MAC\r
@@ -259,326 +220,329 @@ void MainWindow::executeCommand()
     int ret = dlg.exec();\r
     command = dlg.textValue();\r
     if (ret == QDialog::Accepted && !command.isEmpty()) {\r
-        startProcess(command, v->dir(), tr("コマンドの実行に失敗しました。"));\r
+        startProcess(command, tr("コマンドの実行に失敗しました。"));\r
     }\r
 }\r
 \r
-void MainWindow::historyBack()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onExpandLeft\r
+///\r
+/// 左パネルを拡大します。\r
+///\r
+void MainWindow::onExpandLeft()\r
 {\r
-    qDebug() << "MainWindow::historyBack();";\r
+    qDebug() << "MainWindow::onExpandLeft()";\r
 \r
-    if (folderView()->historyBack()) {\r
-        updateActions();\r
-    }\r
-}\r
+    QList<int> sizes = ui->splitter->sizes();\r
+    QList<int> newSizes;\r
 \r
-void MainWindow::historyForward()\r
-{\r
-    qDebug() << "MainWindow::historyForward();";\r
+    newSizes << sizes[0] + 30;\r
+    newSizes << sizes[1] - 30;\r
 \r
-    if (folderView()->historyForward()) {\r
-        updateActions();\r
-    }\r
+    ui->splitter->setSizes(newSizes);\r
 }\r
 \r
-void MainWindow::itemFound()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onExpandRight\r
+///\r
+/// 右パネルを拡大します。\r
+///\r
+void MainWindow::onExpandRight()\r
 {\r
-    qDebug() << "MainWindow::itemFound";\r
+    qDebug() << "MainWindow::onExpandLeft()";\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
+    QList<int> sizes = ui->splitter->sizes();\r
+    QList<int> newSizes;\r
 \r
-void MainWindow::itemNotFound()\r
-{\r
-    qDebug() << "MainWindow::itemNotFound";\r
+    newSizes << sizes[0] - 30;\r
+    newSizes << sizes[1] + 30;\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
+    ui->splitter->setSizes(newSizes);\r
 }\r
 \r
-void MainWindow::markAll()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onToggleMark\r
+///\r
+/// マーク状態を反転します。\r
+///\r
+void MainWindow::onToggleMark()\r
 {\r
-    qDebug() << "MainWindow::markAll();";\r
+    qDebug() << "MainWindow::onToggleMark()";\r
+\r
+    QModelIndex index = focusItemView()->currentIndex();\r
+    if (activeModel()->isMarked(index)) {\r
+        activeModel()->setData(index, Qt::Unchecked, Qt::CheckStateRole);\r
+    }\r
+    else {\r
+        activeModel()->setData(index, Qt::Checked, Qt::CheckStateRole);\r
+    }\r
 \r
-    folderView()->setCheckStateAll(true);\r
+    if (index.row() < activeModel()->rowCount() - 1) {\r
+        index = activeModel()->index(index.row() + 1, 0);\r
+        focusItemView()->setCurrentIndex(index);\r
+    }\r
 }\r
 \r
-void MainWindow::markAllFiles()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::view_statusChanged\r
+/// \param text ステータス文字列\r
+///\r
+/// ビューから受け取った文字列をステータスバーに表示します。\r
+///\r
+void MainWindow::view_statusChanged(const QString &text)\r
 {\r
-    qDebug() << "MainWindow::markAllFiles();";\r
-\r
-    folderView()->setCheckStateAllFiles();\r
+    ui->statusBar->findChild<QLabel*>("Right")->setText(text);\r
 }\r
 \r
-void MainWindow::markAllOff()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::view_currentChanged\r
+/// \param current  新しいカレントインデックス\r
+/// \param previous (使用しません)\r
+///\r
+/// カレントインデックスが変更された場合の処理を行います。\r
+///\r
+void MainWindow::view_currentChanged(const QModelIndex &current, const QModelIndex &previous)\r
 {\r
-    qDebug() << "MainWindow::markAllOff();";\r
+    qDebug() << "MainWindow::view_currentChanged()" << current;\r
+    Q_UNUSED(previous);\r
 \r
-    folderView()->setCheckStateAll(false);\r
-}\r
+    if (focusItemView() != sender()->parent()) {\r
+        return;\r
+    }\r
 \r
-void MainWindow::markInvert()\r
-{\r
-    qDebug() << "MainWindow::markInvert();";\r
+    ui->statusBar->showMessage(activeModel()->filePath(current));\r
 \r
-    folderView()->invertCheckState();\r
+    if (m_viewMode == ModePreview) {\r
+        inactivePanel()->setViewItem(current);\r
+    }\r
+\r
+    updateActions();\r
 }\r
 \r
-void MainWindow::markToggle()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::view_finished\r
+///\r
+/// ビューアの終了\r
+///\r
+void MainWindow::view_finished()\r
 {\r
-    qDebug() << "MainWindow::markToggle();";\r
+    qDebug() << "MainWindow::view_finished()";\r
+\r
+    ui->statusBar->findChild<QLabel*>("Right")->setText("");\r
 \r
-    folderView()->toggleCheckState(folderView()->currentIndex());\r
+    setViewMode(m_prevMode);\r
 }\r
 \r
-void MainWindow::moveItems()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onMove\r
+///\r
+/// 選択アイテムを隣のパネルに移動します。\r
+///\r
+void MainWindow::onMove()\r
 {\r
-    qDebug() << "MainWindow::moveItems";\r
+    qDebug() << "MainWindow::onMove";\r
 \r
-    FolderView *v = folderView();\r
-    QFileInfoList list = v->selectedItems();\r
+    QFileInfoList list = 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
+    int row = focusItemView()->currentIndex().row();\r
 \r
-    settings.setValue(IniKey_AutoCloseCopy, opDlg.autoClose());\r
+    QString tgtPath = inactiveModel()->rootPath();\r
+    moveItems(list, tgtPath);\r
 \r
-    // 念のため、リフレッシュ\r
-    ui->folderView1->refresh();\r
-    ui->folderView2->refresh();\r
+    if (row >= activeModel()->rowCount()) {\r
+        row = activeModel()->rowCount() - 1;\r
+    }\r
+    focusItemView()->setCurrentIndex(activeModel()->index(row, 1));\r
 }\r
 \r
-void MainWindow::keyPress(QKeyEvent *event)\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onKeyLeft\r
+///\r
+/// ←キー押下時の処理を行います。\r
+///\r
+void MainWindow::onKeyLeft()\r
 {\r
-    QString ksq = KeyEventToSequence(event);\r
-    if (ksq == "") {\r
-        event->ignore();\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::onKeyLeft()";\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
+    QWidget *w = qApp->focusWidget();\r
+    if (w->objectName() == "folderView")\r
+    {\r
+        QWidget *panel = w->parentWidget()->parentWidget();\r
+        if (panel == ui->LPanel) {\r
+            activeModel()->onCdUp();\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
+        else if (ui->LPanel->folderPanel()->isVisible()){\r
+            ui->LPanel->folderPanel()->itemView()->setFocus();\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
+    else {\r
+        QKeyEvent event = QKeyEvent(QEvent::KeyPress, Qt::Key_PageUp, Qt::NoModifier);\r
+        qApp->sendEvent(w, &event);\r
     }\r
-\r
-    event->ignore();\r
 }\r
 \r
-void MainWindow::returnPressInSearchBox()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onKeyRight\r
+///\r
+/// →キー押下時の処理を行います。\r
+///\r
+void MainWindow::onKeyRight()\r
 {\r
-    qDebug() << "MainWindow::returnPressInSearchBox";\r
+    qDebug() << "MainWindow::onKeyRight()";\r
 \r
-    if (QApplication::keyboardModifiers() & Qt::ShiftModifier) {\r
-        emit ui->action_SearchPrev->triggered();\r
+    QWidget *w = qApp->focusWidget();\r
+    if (w->objectName() == "folderView")\r
+    {\r
+        QWidget *panel = w->parentWidget()->parentWidget();\r
+        if (panel == ui->RPanel) {\r
+            activeModel()->onCdUp();\r
+        }\r
+        else if (ui->RPanel->folderPanel()->isVisible()){\r
+            ui->RPanel->folderPanel()->itemView()->setFocus();\r
+        }\r
     }\r
     else {\r
-        emit ui->action_SearchNext->triggered();\r
+        QKeyEvent event = QKeyEvent(QEvent::KeyPress, Qt::Key_PageDown, Qt::NoModifier);\r
+        qApp->sendEvent(w, &event);\r
     }\r
 }\r
 \r
-void MainWindow::chooseFolder()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onChooseFolder\r
+///\r
+/// 選択したフォルダに移動します。\r
+///\r
+void MainWindow::onChooseFolder()\r
 {\r
-    qDebug() << "MainWindow::chooseFolder();";\r
+    qDebug() << "MainWindow::onChooseFolder()";\r
 \r
     QString path = QFileDialog::getExistingDirectory(\r
-                this, tr("フォルダを選択"), folderView()->dir());\r
+                this, tr("フォルダを選択"), activeModel()->rootPath());\r
     if (!path.isEmpty()) {\r
-        folderView()->setPath(path, true);\r
-        updateActions();\r
+        activeModel()->setRootPath(path);\r
+//        updateActions();\r
     }\r
 }\r
 \r
-void MainWindow::copyFilenameToClipboard()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onCopyFileName\r
+///\r
+/// ファイル名をクリップボードにコピーします。\r
+///\r
+void MainWindow::onCopyFileName()\r
 {\r
-    qDebug() << "MainWindow::copyFilenameToClipboard();";\r
+    qDebug() << "MainWindow::onCopyFileName()";\r
 \r
-    QClipboard *clipboard = QApplication::clipboard();\r
-    clipboard->setText(folderView()->currentItem().fileName());\r
+    QClipboard *clipboard = qApp->clipboard();\r
+    clipboard->setText(activeModel()->fileName(focusItemView()->currentIndex()));\r
 }\r
 \r
-void MainWindow::copyFullpathTpClipboard()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onCopyFilePath\r
+///\r
+/// フルパスをクリップボードにコピーします。\r
+///\r
+void MainWindow::onCopyFilePath()\r
 {\r
-    qDebug() << "MainWindow::copyFullpathTpClipboard();";\r
+    qDebug() << "MainWindow::onCopyFilePath()";\r
 \r
-    QClipboard *clipboard = QApplication::clipboard();\r
-    clipboard->setText(folderView()->currentItem().absoluteFilePath());\r
+    QClipboard *clipboard = qApp->clipboard();\r
+    clipboard->setText(activeModel()->filePath(focusItemView()->currentIndex()));\r
 }\r
 \r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::askOverWrite\r
+/// \param copyMethod   上書き方法\r
+/// \param alias        別名\r
+/// \param srcPath      コピー元パス\r
+/// \param tgtPath      コピー先パス\r
+///\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
+    qDebug() << "MainWindow::askOverWrite()";\r
 \r
     CopyMoveWorker *worker = static_cast<CopyMoveWorker*>(sender());\r
-    if (!m_overwriteDialog->isKeepSetting() ||\r
-        m_overwriteDialog->copyMethod() == "rbRename")\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
+        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
+    *copyMethod = m_overwriteDialog.copyMethod();\r
+    *alias = m_overwriteDialog.alias();\r
 \r
     worker->endAsking();\r
 }\r
 \r
-void MainWindow::currentChange(const QFileInfo &info)\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onAddBookmark\r
+///\r
+/// ブックマークを追加します。\r
+///\r
+void MainWindow::onAddBookmark()\r
 {\r
-    qDebug() << "MainWindow::currentChange();";\r
+    qDebug() << "MainWindow::onAddBookmark()";\r
+    qDebug() << sender()->objectName();\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
+    FolderModel *m;\r
+    if (sender()->objectName() == "bookmarkBtn") {\r
+        FolderPanel *p = static_cast<FolderPanel*>(sender()->parent());\r
+        m = p->model();\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
+        m = activeModel();\r
     }\r
 \r
-}\r
-\r
-void MainWindow::dataChange()\r
-{\r
-    qDebug() << "MainWindow::dataChange();";\r
+    QFileInfo fi(m->rootPath());\r
+    Preferences(this).addBookmark(fi.fileName(), fi.absoluteFilePath());\r
+    initBookmarkMenu();\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
+    activePanel()->folderPanel()->itemView()->setFocus();\r
+    ui->statusBar->showMessage(tr("%1をブックマークに追加しました").arg(fi.absoluteFilePath()));\r
 }\r
 \r
-void MainWindow::dropAccept(const QFileInfoList &list)\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::view_copyAvailable\r
+/// \param yes  コピー可能ならtrue\r
+///\r
+/// 選択範囲の有無をメニューに反映します。\r
+///\r
+void MainWindow::view_copyAvailable(bool yes)\r
 {\r
-    copyItems(list, static_cast<FolderView*>(sender())->dir());\r
+    ui->text_Copy->setEnabled(yes);\r
 }\r
 \r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::copyItems\r
+/// \param list     コピー元リスト\r
+/// \param tgtDir   コピー先フォルダ\r
+///\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
+    qDebug() << "MainWindow::copyItems()" << tgtDir;\r
+\r
+    Preferences prefs(this);\r
+    if (prefs.isConfirmCopy() &&\r
+        QMessageBox::question(this, tr("確認"), tr("コピーを実行しますか?"))\r
             != QMessageBox::Yes)\r
-        {\r
-            return;\r
-        }\r
+    {\r
+        return;\r
     }\r
 \r
     // 上書き確認ダイアログを初期化する\r
-    m_overwriteDialog->reset();\r
+    m_overwriteDialog.reset();\r
 \r
     // ワーカースレッドを作成する\r
     CopyMoveWorker *worker = new CopyMoveWorker();\r
@@ -592,70 +556,286 @@ void MainWindow::copyItems(const QFileInfoList &list, const QString &tgtDir)
     OperationDialog opDlg(this);\r
     opDlg.setWindowTitle(tr("コピー"));\r
     opDlg.setWorker(worker);\r
-    opDlg.setAutoClose(settings.value(IniKey_AutoCloseCopy).toBool());\r
+    opDlg.setAutoClose(prefs.isAutoCloseCopy());\r
 \r
     opDlg.exec();\r
 \r
-    settings.setValue(IniKey_AutoCloseCopy, opDlg.autoClose());\r
-\r
-    // 念のため、リフレッシュ\r
-    ui->folderView1->refresh();\r
-    ui->folderView2->refresh();\r
+    prefs.setAutoCloseCopy(opDlg.autoClose());\r
 }\r
 \r
-void MainWindow::copyItems()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::moveItems\r
+/// \param list     移動元リスト\r
+/// \param tgtDir   移動先フォルダ\r
+///\r
+/// アイテムを移動します。\r
+///\r
+void MainWindow::moveItems(const QFileInfoList &list, const QString &tgtDir)\r
 {\r
-    qDebug() << "MainWindow::copyItems";\r
-\r
-    FolderView *v = folderView();\r
-    QFileInfoList list = v->selectedItems();\r
-    if (list.isEmpty()) {\r
-        return;\r
-    }\r
+    qDebug() << "MainWindow::moveItems()" << tgtDir;\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
+    Preferences prefs(this);\r
+    if (prefs.isConfirmMove() &&\r
+        QMessageBox::question(this, tr("確認"), tr("移動を実行しますか?"))\r
             != QMessageBox::Yes)\r
-        {\r
-            return;\r
-        }\r
+    {\r
+        return;\r
     }\r
 \r
     // 上書き確認ダイアログを初期化する\r
-    m_overwriteDialog->reset();\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
+    worker->setTargetDir(tgtDir);\r
+    worker->setMoveMode(true);\r
 \r
     // 進捗ダイアログを表示して、処理を開始する\r
     OperationDialog opDlg(this);\r
-    opDlg.setWindowTitle(tr("コピー"));\r
+    opDlg.setWindowTitle(tr("移動"));\r
     opDlg.setWorker(worker);\r
-    opDlg.setAutoClose(settings.value(IniKey_AutoCloseCopy).toBool());\r
+    opDlg.setAutoClose(prefs.isAutoCloseMove());\r
 \r
     opDlg.exec();\r
 \r
-    settings.setValue(IniKey_AutoCloseCopy, opDlg.autoClose());\r
+    prefs.setAutoCloseMove(opDlg.autoClose());\r
+}\r
 \r
-    // 念のため、リフレッシュ\r
-    ui->folderView1->refresh();\r
-    ui->folderView2->refresh();\r
-#endif\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onContextMenuEvent\r
+/// \param obj  イベントが発生したオブジェクト\r
+/// \param e    コンテキストメニューイベント\r
+/// \return 処理した場合はtrue, 処理しなかった場合はfalseを返します。\r
+///\r
+bool MainWindow::onContextMenuEvent(QObject *obj, QContextMenuEvent *e)\r
+{\r
+    QMenu menu(this);\r
+    if (obj->objectName() == "textView") {\r
+        menu.addAction(ui->text_ConvertFromEUC);\r
+        menu.addAction(ui->text_ConvertFromJIS);\r
+        menu.addAction(ui->text_ConvertFromSJIS);\r
+        menu.addAction(ui->text_ConvertFromUTF8);\r
+        menu.addAction(ui->text_ConvertFromUTF16);\r
+        menu.addAction(ui->text_ConvertFromUTF16BE);\r
+        menu.addAction(ui->text_ConvertFromUTF16LE);\r
+        menu.addSeparator();\r
+        menu.addAction(ui->text_Copy);\r
+        if (m_viewMode == ModeView) {\r
+            menu.addSeparator();\r
+            menu.addAction(ui->view_Back);\r
+        }\r
+    }\r
+    else if (obj->objectName() == "imageView") {\r
+        menu.addAction(ui->image_FitToWindow);\r
+        menu.addAction(ui->action_ScaleDown);\r
+        menu.addAction(ui->action_ScaleUp);\r
+        menu.addAction(ui->image_ScaleNormal);\r
+        menu.addSeparator();\r
+        menu.addAction(ui->image_Rotate90);\r
+        menu.addAction(ui->image_Rotate180);\r
+\r
+        if (m_viewMode == ModeView) {\r
+            menu.addSeparator();\r
+            menu.addAction(ui->view_Back);\r
+        }\r
+    }\r
+    else if (obj->objectName() == "folderView" || obj->objectName() == "thumbnailView") {\r
+        QModelIndex index = focusItemView()->indexAt(e->pos());\r
+        if (index.isValid()) {\r
+            menu.addAction(ui->action_Open);\r
+            menu.addAction(ui->action_OpenWith);\r
+            menu.addAction(ui->action_OpenEditor);\r
+            menu.addAction(ui->action_OpenTerminal);\r
+            menu.addAction(ui->action_OpenArchiver);\r
+            menu.addSeparator();\r
+            menu.addAction(ui->action_Copy);\r
+            menu.addAction(ui->action_Move);\r
+            menu.addSeparator();\r
+            menu.addAction(ui->action_Delete);\r
+            menu.addSeparator();\r
+            menu.addAction(ui->action_CopyFileName);\r
+            menu.addAction(ui->action_CopyFilePath);\r
+            menu.addSeparator();\r
+            menu.addAction(ui->action_Rename);\r
+        }\r
+        else {\r
+            menu.addAction(ui->action_historyBack);\r
+            menu.addAction(ui->action_HistoryForward);\r
+            menu.addSeparator();\r
+            menu.addAction(ui->action_CdUp);\r
+            menu.addAction(ui->action_CdHome);\r
+            menu.addAction(ui->action_CdRoot);\r
+            menu.addAction(ui->action_Cd);\r
+            menu.addSeparator();\r
+            menu.addAction(ui->action_CreateFile);\r
+            menu.addAction(ui->action_CreateFolder);\r
+        }\r
+    }\r
+    else {\r
+        qDebug() << "No context menu" << obj->objectName();\r
+        return false;\r
+    }\r
+\r
+    QAction *selected = menu.exec(e->globalPos());\r
+    if (selected == ui->action_ScaleDown ||\r
+        selected == ui->action_ScaleUp)\r
+    {\r
+        ui->image_FitToWindow->blockSignals(true);\r
+        ui->image_FitToWindow->setChecked(false);\r
+        ui->image_FitToWindow->blockSignals(false);\r
+    }\r
+\r
+    return true;\r
 }\r
 \r
-void MainWindow::createFile()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onDropEvent\r
+/// \param obj  イベントが発生したオブジェクト\r
+/// \param e    ドロップイベントオブジェクト\r
+/// \return 処理した場合はtrue, 処理しなかった場合はfalseを返します。\r
+///\r
+bool MainWindow::onDropEvent(QObject *obj, QDropEvent *e)\r
 {\r
-    qDebug() << "MainWindow::createFile";\r
+    qDebug() << "MainWindow::onDropEvent()";\r
+\r
+    if (obj->parent()->objectName() == "folderView" ||\r
+        obj->parent()->objectName() == "thumbnailView")\r
+    {\r
+        QAbstractItemView *v = static_cast<QAbstractItemView*>(obj->parent());\r
+        if (v->property("dragging").toBool()) {\r
+            // 自分自身へのドロップなら何もしない\r
+            return true;\r
+        }\r
+\r
+        QFileInfoList list;\r
+        foreach (const QUrl &url, e->mimeData()->urls()) {\r
+            QString path = QFileInfo(url.toLocalFile()).canonicalFilePath();\r
+            if (!path.isEmpty()) {\r
+                list << path;\r
+            }\r
+            else {\r
+                qDebug() << "drop path is empty." << url;\r
+            }\r
+        }\r
+\r
+        if (list.isEmpty()) {\r
+            // ローカルファイルのドロップでなければ何もしない\r
+            return true;\r
+        }\r
+\r
+        e->acceptProposedAction();\r
+\r
+        QMenu menu(this);\r
+        QAction *actCopy = menu.addAction(tr("コピー"));\r
+        QAction *actMove = menu.addAction(tr("移動"));\r
+        menu.addSeparator();\r
+        menu.addAction(tr("キャンセル"));\r
+\r
+        QAction *selected = menu.exec(v->mapToGlobal(e->pos()));\r
+        FolderModel *m = static_cast<FolderModel*>(v->model());\r
+        if (selected == actMove) {\r
+            moveItems(list, m->rootPath());\r
+        }\r
+        else if (selected == actCopy) {\r
+            copyItems(list, m->rootPath());\r
+        }\r
+        return true;\r
+    }\r
+    else {\r
+        qDebug() << obj->parent()->objectName();\r
+    }\r
+\r
+    return true;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onKeyPressEvent\r
+/// \param obj  イベントが発生したオブジェクト\r
+/// \param e    キーイベントオブジェクト\r
+/// \return 処理した場合はtrue, 処理しなかった場合はfalseを返します。\r
+///\r
+bool MainWindow::onKeyPressEvent(QObject *obj, QKeyEvent *e)\r
+{\r
+    qDebug() << "MainWindow::onKeyPressEvent()";\r
+\r
+    QString modifier = QString::null;\r
+    if (e->modifiers() & Qt::ShiftModifier)     { modifier += "Shift+"; }\r
+    if (e->modifiers() & Qt::ControlModifier)   { modifier += "Ctrl+"; }\r
+    if (e->modifiers() & Qt::AltModifier)       { modifier += "Alt+"; }\r
+    if (e->modifiers() & Qt::MetaModifier)      { modifier += "Meta+"; }\r
+\r
+    QString key = modifier + QKeySequence(e->key()).toString();\r
+\r
+    foreach (QAction *action, findChildren<QAction*>()) {\r
+        if (action->isEnabled()) {\r
+            foreach (const QKeySequence &ks, action->shortcuts()) {\r
+                if (ks.toString() == key) {\r
+                    qDebug() << "emit" << action->objectName();\r
+                    if (action->isCheckable()) {\r
+                        action->toggle();\r
+                    }\r
+                    else {\r
+                        action->trigger();\r
+                    }\r
+                    return true;\r
+                }\r
+             }\r
+        }\r
+    }\r
+\r
+    if (obj->objectName() == "folderView" || obj->objectName() == "thumbnailView")\r
+    {\r
+        // カーソル移動系のみ有効にする\r
+        switch (e->key()) {\r
+        case Qt::Key_Down:\r
+        case Qt::Key_Up:\r
+        case Qt::Key_Left:\r
+        case Qt::Key_Right:\r
+        case Qt::Key_Home:\r
+        case Qt::Key_End:\r
+        case Qt::Key_PageDown:\r
+        case Qt::Key_PageUp:\r
+        case Qt::Key_Tab:\r
+            return false;\r
+        }\r
+        return true;\r
+    }\r
+\r
+\r
+\r
+\r
+    return false;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onCopy\r
+///\r
+/// 選択アイテムを隣のパネルにコピーします。\r
+///\r
+void MainWindow::onCopy()\r
+{\r
+    qDebug() << "MainWindow::onCopy";\r
+\r
+    QFileInfoList list = selectedItems();\r
+    if (list.isEmpty()) {\r
+        return;\r
+    }\r
+\r
+    QString tgtPath = inactiveModel()->rootPath();\r
+    copyItems(list, tgtPath);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onCreateFile\r
+///\r
+/// ファイルを作成します。\r
+///\r
+void MainWindow::onCreateFile()\r
+{\r
+    qDebug() << "MainWindow::onCreateFile";\r
 \r
     bool bOk;\r
     QString name = QInputDialog::getText(\r
@@ -665,26 +845,28 @@ void MainWindow::createFile()
         return;\r
     }\r
 \r
-    QDir dir(folderView()->dir());\r
-    QFile file(dir.absoluteFilePath(name));\r
-    if (!file.open(QIODevice::WriteOnly)) {\r
+    QModelIndex index = activeModel()->touch(name);\r
+    if (!index.isValid()) {\r
         QMessageBox::critical(\r
                     this, tr("エラー"),\r
                     tr("ファイルの作成に失敗しました。"));\r
+        return;\r
     }\r
-    else {\r
-        file.close();\r
 \r
-        QSettings settings;\r
-        if (settings.value(IniKey_OpenAfterCreateFile).toBool()) {\r
-            openEditor(dir.absoluteFilePath(name));\r
-        }\r
+    focusItemView()->setCurrentIndex(index);\r
+    if (Preferences(this).isOpenAfterCreation()) {\r
+        onOpenEditor(index);\r
     }\r
 }\r
 \r
-void MainWindow::createFolder()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onCreateFolder\r
+///\r
+/// フォルダを作成します。\r
+///\r
+void MainWindow::onCreateFolder()\r
 {\r
-    qDebug() << "MainWindow::createFolder";\r
+    qDebug() << "MainWindow::onCreateFolder";\r
 \r
     bool bOk;\r
     QString name = QInputDialog::getText(\r
@@ -694,33 +876,36 @@ void MainWindow::createFolder()
         return;\r
     }\r
 \r
-    QDir dir(folderView()->dir());\r
-    if (!dir.mkpath(name)) {\r
+    QModelIndex index = activeModel()->mkdir(name);\r
+    if (!index.isValid()) {\r
         QMessageBox::critical(\r
                     this, tr("エラー"),\r
                     tr("フォルダの作成に失敗しました。"));\r
+        return;\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
+    focusItemView()->setCurrentIndex(index);\r
+    if (Preferences(this).isMoveAfterCreation()) {\r
+        onOpen(index);\r
     }\r
 }\r
 \r
-void MainWindow::deleteItems()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onDelete\r
+///\r
+/// 選択アイテムを削除します。\r
+///\r
+void MainWindow::onDelete()\r
 {\r
-    qDebug() << "MainWindow::deleteItems";\r
+    qDebug() << "MainWindow::onDelete";\r
 \r
-    FolderView *v = folderView();\r
-    QFileInfoList list = v->selectedItems();\r
+    QFileInfoList list = selectedItems();\r
     if (list.isEmpty()) {\r
         return;\r
     }\r
 \r
-    QSettings settings;\r
-    if (settings.value(IniKey_ConfirmDelete).toBool()) {\r
+    Preferences prefs(this);\r
+    if (prefs.isConfirmDelete()) {\r
         QString msg;\r
         if (list.size() == 1) {\r
             msg = list[0].fileName();\r
@@ -742,80 +927,63 @@ void MainWindow::deleteItems()
     OperationDialog opDlg(this);\r
     opDlg.setWindowTitle(tr("削除"));\r
     opDlg.setWorker(worker);\r
-    opDlg.setAutoClose(settings.value(IniKey_AutoCloseDelete).toBool());\r
+    opDlg.setAutoClose(prefs.isAutoCloseDelete());\r
+\r
+    int row = focusItemView()->currentIndex().row();\r
 \r
     opDlg.exec();\r
 \r
-    settings.setValue(IniKey_AutoCloseDelete, opDlg.autoClose());\r
+    if (row >= activeModel()->rowCount()) {\r
+        row = activeModel()->rowCount() - 1;\r
+    }\r
+    focusItemView()->setCurrentIndex(activeModel()->index(row, 1));\r
 \r
-    // 念のため、リフレッシュ\r
-    ui->folderView1->refresh();\r
-    ui->folderView2->refresh();\r
+    prefs.setAutoCloseDelete(opDlg.autoClose());\r
 }\r
 \r
-void MainWindow::open(const QModelIndex &index)\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onOpen\r
+/// \param index    (使用しません)\r
+///\r
+/// アイテムを開きます。\r
+///\r
+void MainWindow::onOpen(const QModelIndex &index)\r
 {\r
     Q_UNUSED(index);\r
-    qDebug() << "MainWindow::open";\r
+    qDebug() << "MainWindow::onOpen()" << index;\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
+    QModelIndex current = focusItemView()->currentIndex();\r
+    if (activeModel()->isDir(current)) {\r
+        activeModel()->setRootPath(activeModel()->filePath(current));\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
+    QString ext = activeModel()->fileInfo(current).suffix().toLower();\r
+    QStringList list = Preferences(this).getPreferExtensions().split(",", QString::SkipEmptyParts);\r
+    foreach (const QString& s, list) {\r
+        if (ext == s.trimmed().toLower()) {\r
+            QString path = QDir::toNativeSeparators(activeModel()->filePath(current));\r
+            QDesktopServices::openUrl(QUrl("file:///" + path));\r
+            return;\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
+    setViewMode(ModeView);\r
 }\r
 \r
-void MainWindow::openEditor(const QString &path)\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onOpenEditor\r
+/// \param path\r
+///\r
+/// 選択アイテムを外部エディタで開きます。\r
+///\r
+void MainWindow::onOpenEditor(const QModelIndex &index)\r
 {\r
-    qDebug() << "MainWindow::openEditor";\r
+    qDebug() << "MainWindow::onOpenEditor";\r
 \r
-    QSettings settings;\r
-    QString exe = settings.value(IniKey_EditorPath).toString();\r
+    QString exe = Preferences(this).getEditorPath();\r
     if (exe.isEmpty()) {\r
         QMessageBox::critical(\r
                     this, tr("エラー"),\r
@@ -823,38 +991,38 @@ void MainWindow::openEditor(const QString &path)
         return;\r
     }\r
 \r
-    FolderView *v = folderView();\r
-    Q_ASSERT(v);\r
-\r
     QFileInfoList list;\r
-    if (path.isEmpty()) {\r
-        list = v->selectedItems();\r
+    if (index.isValid()) {\r
+        list << activeModel()->fileInfo(index);\r
     }\r
     else {\r
-        list << path;\r
+        list = selectedItems();\r
     }\r
 \r
+    QString files;\r
     foreach (const QFileInfo &info, list) {\r
-        QString opt = settings.value(IniKey_EditorOption).toString();\r
-        replaceVars(opt, info);\r
-\r
+        files += " " + QQ(info.absoluteFilePath());\r
+    }\r
 #ifdef Q_OS_MAC\r
-        QString command = "open -a " + exe + " " + opt;\r
+    QString command = "open -a " + exe + files;\r
 #else\r
-        QString command = QQ(exe) + " " + opt;\r
+    QString command = exe + files;\r
 #endif\r
-        if (!startProcess(command, info.absolutePath(), tr("外部エディタの起動に失敗しました。"))) {\r
-            break;\r
-        }\r
+    if (!startProcess(command, tr("外部エディタの起動に失敗しました。"))) {\r
+        qDebug() << command;\r
     }\r
 }\r
 \r
-void MainWindow::openTerminal()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onOpenTerminal\r
+///\r
+/// 選択アイテムをターミナルで開きます。\r
+///\r
+void MainWindow::onOpenTerminal()\r
 {\r
-    qDebug() << "MainWindow::openTerminal";\r
+    qDebug() << "MainWindow::onOpenTerminal";\r
 \r
-    QSettings settings;\r
-    QString exe = settings.value(IniKey_TerminalPath).toString();\r
+    QString exe = Preferences(this).getTerminalPath();\r
     if (exe.isEmpty()) {\r
         QMessageBox::critical(\r
                     this, tr("エラー"),\r
@@ -862,64 +1030,110 @@ void MainWindow::openTerminal()
         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
+    QSet<QString> dirs;\r
+    foreach (const QFileInfo &info, selectedItems()) {\r
+        if (info.isDir()) {\r
+            dirs.insert(info.absoluteFilePath());\r
+        }\r
+        else {\r
+            dirs.insert(info.absolutePath());\r
+        }\r
+    }\r
 \r
+    foreach (const QString &dir, dirs) {\r
 #ifdef Q_OS_MAC\r
-        QString command = "open -a " + QQ(exe) + " --args " + opt;\r
+        QString command = "open -n -a " + exe + " " + QQ(dir);\r
 #else\r
-        QString command = QQ(exe) + " " + opt;\r
+        QString command = exe + " " + QQ(dir);\r
 #endif\r
-        if (!startProcess(command, info.absolutePath(), tr("ターミナルの起動に失敗しました。"))) {\r
+        if (!startProcess(command, tr("ターミナルの起動に失敗しました。"))) {\r
+            qDebug() << command;\r
             break;\r
         }\r
     }\r
 }\r
 \r
-void MainWindow::refresh()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onOpenArchiver\r
+///\r
+/// 選択アイテムをアーカイバで開きます。\r
+///\r
+void MainWindow::onOpenArchiver()\r
 {\r
-    qDebug() << "MainWindow::refresh();";\r
+    qDebug() << "MainWindow::onOpenArchiver";\r
 \r
-    folderView()->refresh();\r
-    updateActions();\r
+    QString exe = Preferences(this).getArchiverPath();\r
+    if (exe.isEmpty()) {\r
+        QMessageBox::critical(\r
+                    this, tr("エラー"),\r
+                    tr("アーカイバのパスが未定義です。"));\r
+        return;\r
+    }\r
+\r
+    QString files;\r
+    foreach (const QFileInfo &info, selectedItems()) {\r
+        files += " " + QQ(info.absoluteFilePath());\r
+    }\r
+#ifdef Q_OS_MAC\r
+    QString command = "open -a " + exe + files;\r
+#else\r
+    QString command = exe + files;\r
+#endif\r
+    if (!startProcess(command, tr("アーカイバの起動に失敗しました。"))) {\r
+        qDebug() << command;\r
+    }\r
 }\r
 \r
-void MainWindow::renameItems()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onOpenBookmark\r
+///\r
+/// ブックマークのメニュー項目をクリックしたときの処理を行います。\r
+///\r
+void MainWindow::onOpenBookmark()\r
 {\r
-    qDebug() << "MainWindow::renameItems";\r
+    qDebug() << "MainWindow::onOpenBookmark()";\r
+\r
+    QAction *action = qobject_cast<QAction*>(sender());\r
+    Q_CHECK_PTR(action);\r
+\r
+    int i = action->data().toInt();\r
+    activeModel()->setRootPath(Preferences(this).getBookmarkPath(i));\r
+}\r
 \r
-    FolderView *v = folderView();\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onRename\r
+///\r
+/// 選択アイテムの名前を変更します。\r
+///\r
+void MainWindow::onRename()\r
+{\r
+    qDebug() << "MainWindow::onRename";\r
 \r
-    QFileInfoList list = v->selectedItems();\r
+    QFileInfoList list = selectedItems();\r
     if (list.isEmpty()) {\r
         return;\r
     }\r
 \r
-    IRenameDialog *dlg;\r
+    AbstractRenameDialog *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->setWorkingDirectory(activeModel()->rootPath());\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
-    if (settings.value(IniKey_ConfirmRename).toBool()) {\r
-        int ret = QMessageBox::question(this, tr("確認"),\r
-                                        tr("名前の変更を実行しますか?"));\r
-        if (ret != QMessageBox::Yes) {\r
-            return;\r
-        }\r
+    Preferences prefs(this);\r
+    if (prefs.isConfirmRename() &&\r
+        QMessageBox::question(this, tr("確認"), tr("名前の変更を実行しますか?"))\r
+            != QMessageBox::Yes)\r
+    {\r
+        return;\r
     }\r
 \r
     RenameWorker *worker = new RenameWorker();\r
@@ -928,53 +1142,75 @@ void MainWindow::renameItems()
     OperationDialog opDlg(this);\r
     opDlg.setWindowTitle(tr("名前を変更"));\r
     opDlg.setWorker(worker);\r
-    opDlg.setAutoClose(settings.value(IniKey_AutoCloseRename).toBool());\r
+    opDlg.setAutoClose(prefs.isAutoCloseRename());\r
 \r
     opDlg.exec();\r
 \r
-    settings.setValue(IniKey_AutoCloseRename, opDlg.autoClose());\r
+    QFileInfo fi(dlg->renameMap().first());\r
+    focusItemView()->setCurrentIndex(activeModel()->search(fi.fileName()));\r
+\r
+    prefs.setAutoCloseRename(opDlg.autoClose());\r
 }\r
 \r
-void MainWindow::retrieveFinish()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onOpenWith\r
+///\r
+/// 関連付けられたアプリで開きます。\r
+///\r
+void MainWindow::onOpenWith()\r
 {\r
-    qDebug() << "MainWindow::retrieveFinish();";\r
+    qDebug() << "MainWindow::onOpenWith";\r
 \r
-    ui->statusBar->showMessage(tr("レディ"), 5000);\r
+    foreach (const QFileInfo &info, selectedItems()) {\r
+        QString path = QDir::toNativeSeparators(info.absoluteFilePath());\r
+        QDesktopServices::openUrl(QUrl("file:///" + path));\r
+    }\r
 }\r
 \r
-void MainWindow::retrieveStart(const QString &path)\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::showBookmarkDialog\r
+///\r
+/// ブックマーク一覧ダイアログを表示します。\r
+///\r
+void MainWindow::showBookmarkDialog()\r
 {\r
-    qDebug() << "MainWindow::retrieveStart();" << path;\r
+    qDebug() << "MainWindow::showBookmarkDialog()";\r
 \r
-    ui->statusBar->showMessage(tr("ファイルリストを取得しています..."));\r
-    if (sender() == ui->folderView1) {\r
-        ui->locationBox1->setText(path);\r
-    }\r
-    else {\r
-        Q_ASSERT(sender() == ui->folderView2);\r
-        ui->locationBox2->setText(path);\r
+    BookmarkDialog dlg(this);\r
+    dlg.setEditMode(false);\r
+    if (dlg.exec() == QDialog::Accepted) {\r
+        int n = dlg.selectedIndex();\r
+        activeModel()->setRootPath(Preferences(this).getBookmarkPath(n + 1));\r
     }\r
 }\r
 \r
-void MainWindow::shellExecute()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onEditBookmark\r
+///\r
+/// ブックマークの編集ダイアログを表示します。\r
+///\r
+void MainWindow::onEditBookmark()\r
 {\r
-    qDebug() << "MainWindow::shellExecute";\r
+    qDebug() << "MainWindow::onEditBookmark()";\r
 \r
-    FolderView *v = folderView();\r
-    Q_ASSERT(v);\r
+    BookmarkDialog dlg(this);\r
+    dlg.setEditMode(true);\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
+    if (dlg.exec() == QDialog::Accepted) {\r
+        initBookmarkMenu();\r
     }\r
 }\r
 \r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::showFilterDialog\r
+///\r
+/// フィルタ設定ダイアログを表示します。\r
+///\r
 void MainWindow::showFilterDialog()\r
 {\r
-    qDebug() << "MainWindow::showFilterDialog();";\r
+    qDebug() << "MainWindow::showFilterDialog()";\r
 \r
-    QString filters = folderView()->nameFilters().join(" ");\r
+    QString filters = activeModel()->nameFilters().join(" ");\r
 \r
     QInputDialog dlg(this);\r
     dlg.setInputMode(QInputDialog::TextInput);\r
@@ -984,395 +1220,499 @@ void MainWindow::showFilterDialog()
     dlg.resize(width() * 0.8, dlg.height());\r
 \r
     if (dlg.exec() == QDialog::Accepted) {\r
-        setNameFilters(folderView(), dlg.textValue());\r
+        filters = dlg.textValue();\r
+        if (filters.isEmpty()) {\r
+            filters = "*";\r
+        }\r
+\r
+        activeModel()->setNameFilters(filters.split(" ", QString::SkipEmptyParts));\r
+        activeModel()->refresh();\r
     }\r
 }\r
 \r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::showHistoryDialog\r
+///\r
+/// 履歴選択ダイアログを表示します。\r
+///\r
 void MainWindow::showHistoryDialog()\r
 {\r
-    qDebug() << "MainWindow::showHistoryDialog();";\r
-\r
-    FolderView *v = folderView();\r
-    FolderView *vOther = otherSideView(v);\r
+    qDebug() << "MainWindow::showHistoryDialog()";\r
 \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
-    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
+    dlg.setModel(ui->LPanel->model(), ui->RPanel->model(), activeModel());\r
+    dlg.exec();\r
 }\r
 \r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::showSortDialog\r
+///\r
+/// ソート方法選択ダイアログを表示します。\r
+///\r
 void MainWindow::showSortDialog()\r
 {\r
-    qDebug() << "MainWindow::showSortDialog();";\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
-    setSorting(folderView());\r
+    dlg.setModel(activeModel());\r
+    dlg.exec();\r
 }\r
 \r
-void MainWindow::swapView()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onSplitCenter\r
+///\r
+/// パネルを中央で分割します。\r
+///\r
+void MainWindow::onSplitCenter()\r
 {\r
-    qDebug() << "MainWindow::swapView();";\r
-\r
-    QString dir1 = ui->folderView1->dir();\r
-    QString dir2 = ui->folderView2->dir();\r
+    qDebug() << "MainWindow::onSplitCenter()";\r
 \r
-    ui->folderView1->setPath(dir2, true);\r
-    ui->folderView2->setPath(dir1, true);\r
-\r
-    updateActions();\r
+    QList<int> sizes = ui->splitter->sizes();\r
+    int sizeTotal = sizes[0] + sizes[1];\r
+    sizes[0] = sizeTotal / 2;\r
+    sizes[1] = sizeTotal - sizes[0];\r
+    ui->splitter->setSizes(sizes);\r
 }\r
 \r
-void MainWindow::setSorting(FolderView *view)\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onSwap\r
+///\r
+/// 左右のパネルでモデルを入れ替えます。\r
+///\r
+void MainWindow::onSwap()\r
 {\r
-    qDebug() << "MainWindow::setSorting();" << view->objectName();\r
+    qDebug() << "MainWindow::onSwap()";\r
 \r
-    QSettings settings;\r
-    QDir::SortFlags flags;\r
-\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
-    // デフォルトだと文字列は昇順で、数値は降順…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
+    FolderModel *tmp = ui->LPanel->model();\r
+    ui->LPanel->setModel(ui->RPanel->model());\r
+    ui->RPanel->setModel(tmp);\r
 \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
+    if (ui->LPanel->model()->isActive()) {\r
+        setActiveModel(ui->RPanel->model());\r
     }\r
-\r
-    if (settings.value(view->side() + slash + IniKey_IgnoreCase).toBool()) {\r
-        flags |= QDir::IgnoreCase;\r
+    else {\r
+        setActiveModel(ui->LPanel->model());\r
     }\r
-\r
-    view->setSorting(flags);\r
 }\r
 \r
-void MainWindow::showNameFilters(FolderView *view)\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onTogglePreviewMode\r
+/// \param checked  メニューのチェック状態\r
+///\r
+/// 通常モード/プレビューモードを切り替えます。\r
+///\r
+void MainWindow::onTogglePreviewMode(bool checked)\r
 {\r
-    filterLabel(view)->setText(tr("フィルタ:") + view->nameFilters().join(" "));\r
-}\r
-\r
-void MainWindow::searchItem(const QString &text)\r
-{\r
-    qDebug() << "MainWindow::searchItem" << text;\r
+    qDebug() << "MainWindow::onTogglePreviewMode()" << checked;\r
 \r
-    FolderView *v;\r
-    SearchBox *box;\r
-    if (ui->searchBox1->hasFocus()) {\r
-        v = ui->folderView1;\r
-        box = ui->searchBox1;\r
+    if (checked) {\r
+        setViewMode(ModePreview);\r
     }\r
     else {\r
-        Q_ASSERT(ui->searchBox2->hasFocus());\r
-        v = ui->folderView2;\r
-        box = ui->searchBox2;\r
+        setViewMode(ModeBasic);\r
     }\r
+}\r
 \r
-    if (text.right(1) == "/") {\r
-        box->setText(text.left(text.length() - 1));\r
-        ui->action_Search->setChecked(false);\r
-        return;\r
-    }\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onSearchNext\r
+///\r
+/// 次のアイテムを検索します。\r
+///\r
+void MainWindow::onSearchNext()\r
+{\r
+    qDebug() << "MainWindow::onSearchNext";\r
 \r
-    v->searchItem(box->text());\r
+    static_cast<FolderPanel*>(qApp->focusWidget()->parentWidget())->searchNext();\r
 }\r
 \r
-void MainWindow::searchNext()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onSearchPrev\r
+///\r
+/// 前のアイテムを検索します。\r
+///\r
+void MainWindow::onSearchPrev()\r
 {\r
-    qDebug() << "MainWindow::searchNext";\r
+    qDebug() << "MainWindow::onSearchPrev";\r
 \r
-    FolderView *v = folderView();\r
-    SearchBox *box = searchBox(v);\r
-    v->searchNext(box->text());\r
+    static_cast<FolderPanel*>(qApp->focusWidget()->parentWidget())->searchNext(-1);\r
 }\r
 \r
-void MainWindow::searchPrev()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onKeyDown\r
+///\r
+/// フォーカスウィジェットに↓キーイベントを送信します。\r
+///\r
+void MainWindow::onKeyDown()\r
 {\r
-    qDebug() << "MainWindow::searchPrev";\r
+    qDebug() << "MainWindow::onKeyDown()";\r
 \r
-    FolderView *v = folderView();\r
-    SearchBox *box = searchBox(v);\r
-    v->searchPrev(box->text());\r
+    QKeyEvent event = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier);\r
+    qApp->sendEvent(qApp->focusWidget(), &event);\r
 }\r
 \r
-void MainWindow::setCursorToBegin()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onKeyEnd\r
+///\r
+/// フォーカスウィジェットにEND, Ctrl+ENDキーイベントを送信します。\r
+///\r
+void MainWindow::onKeyEnd()\r
 {\r
-    qDebug() << "MainWindow::setCursorToBegin();";\r
+    qDebug() << "MainWindow::onKeyEnd()";\r
 \r
-    FolderView *v = folderView();\r
-    int row = 0;\r
-    v->setCurrentIndex(v->model()->index(row, 0));\r
+    QKeyEvent event1 = QKeyEvent(QEvent::KeyPress, Qt::Key_End, Qt::NoModifier);\r
+    qApp->sendEvent(qApp->focusWidget(), &event1);\r
+\r
+    QKeyEvent event2 = QKeyEvent(QEvent::KeyPress, Qt::Key_End, Qt::ControlModifier);\r
+    qApp->sendEvent(qApp->focusWidget(), &event2);\r
 }\r
 \r
-void MainWindow::cursorDown()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onKeyHome\r
+///\r
+/// フォーカスウィジェットにHOME, Ctrl+HOMEキーイベントを送信します。\r
+///\r
+void MainWindow::onKeyHome()\r
 {\r
-    qDebug() << "MainWindow::cursorDown();";\r
+    qDebug() << "MainWindow::onKeyHome()";\r
 \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
+    QKeyEvent event1 = QKeyEvent(QEvent::KeyPress, Qt::Key_Home, Qt::NoModifier);\r
+    qApp->sendEvent(qApp->focusWidget(), &event1);\r
+\r
+    QKeyEvent event2 = QKeyEvent(QEvent::KeyPress, Qt::Key_Home, Qt::ControlModifier);\r
+    qApp->sendEvent(qApp->focusWidget(), &event2);\r
 }\r
 \r
-void MainWindow::cursorUp()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onKeyUp\r
+///\r
+/// フォーカスウィジェットに↑キーイベントを送信します。\r
+///\r
+void MainWindow::onKeyUp()\r
 {\r
-    qDebug() << "MainWindow::cursorUp();";\r
+    qDebug() << "MainWindow::onKeyUp()";\r
 \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
+    QKeyEvent event = QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier);\r
+    qApp->sendEvent(qApp->focusWidget(), &event);\r
 }\r
 \r
-void MainWindow::setCursorToEnd()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onKeyHomeOther\r
+///\r
+/// 非フォーカスビューにHOME, Ctrl+HOMEキーイベントを送信します。\r
+///\r
+void MainWindow::onKeyHomeOther()\r
 {\r
-    qDebug() << "MainWindow::setCursorToEnd();";\r
+    qDebug() << "MainWindow::onKeyHomeOther()";\r
 \r
-    FolderView *v = folderView();\r
-    int row = v->model()->rowCount() - 1;\r
-    v->setCurrentIndex(v->model()->index(row, 0));\r
+    QKeyEvent event1 = QKeyEvent(QEvent::KeyPress, Qt::Key_Home, Qt::NoModifier);\r
+    sendEventOther(&event1);\r
+\r
+    QKeyEvent event2 = QKeyEvent(QEvent::KeyPress, Qt::Key_Home, Qt::ControlModifier);\r
+    sendEventOther(&event2);\r
 }\r
 \r
-void MainWindow::setFontSizeDown()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onKeyDownOther\r
+///\r
+/// 非フォーカスビューに↓キーイベントを送信します。\r
+///\r
+void MainWindow::onKeyDownOther()\r
 {\r
-    qDebug() << "MainWindow::setFontSizeDown();";\r
+    qDebug() << "MainWindow::onKeyDownOther()";\r
 \r
-    QSettings settings;\r
+    QKeyEvent event = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier);\r
+    sendEventOther(&event);\r
+}\r
 \r
-    QFont font = settings.value(IniKey_ViewFont).value<QFont>();\r
-    font.setPointSize(font.pointSize() - 1);\r
-    settings.setValue(IniKey_ViewFont, font);\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onKeyUpOther\r
+///\r
+/// 非フォーカスビューに↑キーイベントを送信します。\r
+///\r
+void MainWindow::onKeyUpOther()\r
+{\r
+    qDebug() << "MainWindow::onKeyUpOther()";\r
 \r
-    ui->folderView1->updateAppearance();\r
-    ui->folderView2->updateAppearance();\r
+    QKeyEvent event = QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier);\r
+    sendEventOther(&event);\r
 }\r
 \r
-void MainWindow::setFontSizeUp()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onKeyEndOther\r
+///\r
+/// 非フォーカスビューにEND, Ctrl+ENDキーイベントを送信します。\r
+///\r
+void MainWindow::onKeyEndOther()\r
 {\r
-    qDebug() << "MainWindow::setFontSizeUp();";\r
-\r
-    QSettings settings;\r
+    qDebug() << "MainWindow::onKeyEndOther()";\r
 \r
-    QFont font = settings.value(IniKey_ViewFont).value<QFont>();\r
-    font.setPointSize(font.pointSize() + 1);\r
-    settings.setValue(IniKey_ViewFont, font);\r
+    QKeyEvent event1 = QKeyEvent(QEvent::KeyPress, Qt::Key_End, Qt::NoModifier);\r
+    sendEventOther(&event1);\r
 \r
-    ui->folderView1->updateAppearance();\r
-    ui->folderView2->updateAppearance();\r
+    QKeyEvent event2 = QKeyEvent(QEvent::KeyPress, Qt::Key_End, Qt::ControlModifier);\r
+    sendEventOther(&event2);\r
 }\r
 \r
-void MainWindow::setPathFromOther()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onScaleDown\r
+///\r
+/// 表示を縮小します。\r
+///\r
+void MainWindow::onScaleDown()\r
 {\r
-    qDebug() << "MainWindow::setPathFromOther();";\r
+    qDebug() << "MainWindow::onScaleDown()";\r
 \r
-    FolderView *view = folderView();\r
-    FolderView *other = otherSideView(view);\r
+    AbstractView *view = dynamic_cast<AbstractView*>(qApp->focusWidget());\r
+    if (view) {\r
+        view->scaleDown();\r
+    }\r
 \r
-    view->setPath(other->dir(), true);\r
-    updateActions();\r
+    Preferences prefs(this);\r
+    if (ui->LPanel->isVisible()) {\r
+        ui->LPanel->updateAppearance(prefs);\r
+        ui->LPanel->model()->updateAppearance(prefs);\r
+    }\r
+    if (ui->RPanel->isVisible()) {\r
+        ui->RPanel->updateAppearance(prefs);\r
+        ui->RPanel->model()->updateAppearance(prefs);\r
+    }\r
+    if (ui->FPanel->isVisible()) {\r
+        ui->FPanel->updateAppearance(prefs);\r
+        ui->FPanel->model()->updateAppearance(prefs);\r
+    }\r
 }\r
 \r
-void MainWindow::setPathToHome()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onScaleUp\r
+///\r
+/// 表示を拡大します。\r
+///\r
+void MainWindow::onScaleUp()\r
 {\r
-    qDebug() << "MainWindow::setPathToHome();";\r
+    qDebug() << "MainWindow::onScaleUp()";\r
 \r
-    folderView()->setPath(QDir::homePath(), true);\r
-    updateActions();\r
+    AbstractView *view = dynamic_cast<AbstractView*>(qApp->focusWidget());\r
+    if (view) {\r
+        view->scaleUp();\r
+    }\r
+\r
+    Preferences prefs(this);\r
+    if (ui->LPanel->isVisible()) {\r
+        ui->LPanel->updateAppearance(prefs);\r
+        ui->LPanel->model()->updateAppearance(prefs);\r
+    }\r
+    if (ui->RPanel->isVisible()) {\r
+        ui->RPanel->updateAppearance(prefs);\r
+        ui->RPanel->model()->updateAppearance(prefs);\r
+    }\r
+    if (ui->FPanel->isVisible()) {\r
+        ui->FPanel->updateAppearance(prefs);\r
+        ui->FPanel->model()->updateAppearance(prefs);\r
+    }\r
 }\r
 \r
-void MainWindow::setPathToOther()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::initBookmarkMenu\r
+///\r
+/// ブックマークメニューを初期化します。\r
+///\r
+void MainWindow::initBookmarkMenu()\r
 {\r
-    qDebug() << "MainWindow::setPathToOther();";\r
+    qDebug() << "MainWindow::initBookmarkMenu()";\r
 \r
-    FolderView *view = folderView();\r
-    FolderView *other = otherSideView(view);\r
+    Preferences prefs(this);\r
+    QFileIconProvider iconProvider;\r
 \r
-    other->setPath(view->dir(), true);\r
-    updateActions();\r
+    ui->menu_Bookmark->clear();\r
+    ui->menu_Bookmark->addAction(ui->action_AddBookmark);\r
+    ui->menu_Bookmark->addAction(ui->action_EditBookmark);\r
+    ui->menu_Bookmark->addSeparator();\r
+    for (int n = 1; ; n++) {\r
+        QString name = prefs.getBookmarkEntry(n);\r
+        if (name.isEmpty()) {\r
+            break;\r
+        }\r
+        QString path = prefs.getBookmarkPath(n);\r
+\r
+        QAction *action = ui->menu_Bookmark->addAction(\r
+                    iconProvider.icon(QFileInfo(path)), name, this,\r
+                    SLOT(onOpenBookmark()));\r
+        action->setData(n);\r
+    }\r
+\r
+    m_actions = findChildren<QAction*>();\r
 }\r
 \r
-void MainWindow::setPathToParent()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::sendEventOther\r
+/// \param event    送信するイベント\r
+///\r
+/// 非フォーカスのビューにイベントを送信します。\r
+///\r
+void MainWindow::sendEventOther(QEvent *event)\r
 {\r
-    qDebug() << "MainWindow::setPathToParent();";\r
+    qDebug() << "MainWindow::sendEventOther()";\r
 \r
-    QDir dir(folderView()->dir());\r
-    if (!dir.isRoot()) {\r
-        dir.cdUp();\r
-        folderView()->setPath(dir.absolutePath(), true);\r
-        updateActions();\r
+    // フォーカスを持たない、可視状態のビューを検索する\r
+    foreach (QWidget *w, findChildren<QWidget*>()) {\r
+        AbstractView *view = dynamic_cast<AbstractView*>(w);\r
+        if (view) {\r
+            if (w->isVisible() && !w->hasFocus()) {\r
+                qDebug() << "Send event to" << w->objectName();\r
+                qApp->sendEvent(w, event);\r
+            }\r
+        }\r
     }\r
 }\r
 \r
-void MainWindow::setPathToRoot()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onSyncPanel\r
+///\r
+/// 隣のパネルと同じフォルダを表示します。\r
+///\r
+void MainWindow::onSyncPanel()\r
 {\r
-    qDebug() << "MainWindow::setPathToRoot();";\r
+    qDebug() << "MainWindow::onSyncPanel()";\r
 \r
-    folderView()->setPath(QDir::rootPath(), true);\r
-    updateActions();\r
+    activeModel()->setRootPath(inactiveModel()->rootPath());\r
 }\r
 \r
-void MainWindow::toggleSearchBox(bool checked)\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onSyncPanelTo\r
+///\r
+/// 隣のパネルに同じフォルダを表示します。\r
+///\r
+void MainWindow::onSyncPanelTo()\r
 {\r
-    qDebug() << "MainWindow::toggleSearchBox" << checked;\r
+    qDebug() << "MainWindow::onSyncPanelTo()";\r
 \r
-    FolderView *v;\r
-    SearchBox *box;\r
+    inactiveModel()->setRootPath(activeModel()->rootPath());\r
+}\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
+/// \brief MainWindow::onToggleFullMode\r
+/// \param checked  メニューのチェック状態\r
+///\r
+/// 単画面/二画面を切り替えます。\r
+///\r
+void MainWindow::onToggleFullMode(bool checked)\r
+{\r
+    qDebug() << "MainWindow::onToggleFullMode()" << checked;\r
 \r
-        box->setVisible(true);\r
-        box->setFocus();\r
-        box->selectAll();\r
+    if (checked) {\r
+        setViewMode(ModeFull);\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 (box->hasFocus()) {\r
-            v->setFocus();\r
-        }\r
-        box->setVisible(false);\r
+        setViewMode(ModeBasic);\r
     }\r
 }\r
 \r
-void MainWindow::openRequest(const QFileInfo &info)\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onToggleSearch\r
+/// \param checked  メニューのチェック状態\r
+///\r
+/// 検索ボックスの表示/非表示を切り替えます。\r
+///\r
+void MainWindow::onToggleSearch(bool checked)\r
 {\r
-    m_focusedView = QApplication::focusWidget();\r
+    qDebug() << "MainWindow::onToggleSearch" << checked;\r
 \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
+    ui->LPanel->folderPanel()->toggleSearch(checked);\r
+    ui->RPanel->folderPanel()->toggleSearch(checked);\r
 }\r
 \r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::showPreferenceDialog\r
+///\r
+/// 環境設定ダイアログを表示します。\r
+///\r
 void MainWindow::showPreferenceDialog()\r
 {\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
+        Preferences prefs(this);\r
+        if (ui->LPanel->isVisible()) {\r
+            ui->LPanel->updateAppearance(prefs);\r
+            ui->LPanel->model()->updateAppearance(prefs);\r
+        }\r
+        if (ui->RPanel->isVisible()) {\r
+            ui->RPanel->updateAppearance(prefs);\r
+            ui->RPanel->model()->updateAppearance(prefs);\r
+        }\r
+        if (ui->FPanel->isVisible()) {\r
+            ui->FPanel->updateAppearance(prefs);\r
+            ui->FPanel->model()->updateAppearance(prefs);\r
+        }\r
     }\r
 }\r
 \r
-void MainWindow::toggleShowHiddenFiles(bool checked)\r
-{\r
-    qDebug() << "MainWindow::toggleShowHiddenFiles" << checked;\r
-\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
-void MainWindow::toggleShowSystemFiles(bool checked)\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onToggleHidden\r
+/// \param checked  メニューのチェック状態\r
+///\r
+/// 隠しファイルの表示/非表示を切り替えます。\r
+///\r
+void MainWindow::onToggleHidden(bool checked)\r
 {\r
-    qDebug() << "MainWindow::toggleShowSystemFiles" << checked;\r
+    qDebug() << "MainWindow::onToggleHidden" << checked;\r
 \r
-    ui->folderView1->setFilter(QDir::System, checked);\r
-    ui->folderView1->refresh();\r
+    if (checked) {\r
+        activeModel()->setFilter(activeModel()->filter() | QDir::Hidden);\r
+    }\r
+    else {\r
+        activeModel()->setFilter(activeModel()->filter() ^ QDir::Hidden);\r
+    }\r
 \r
-    ui->folderView2->setFilter(QDir::System, checked);\r
-    ui->folderView2->refresh();\r
+    activeModel()->refresh();\r
 }\r
 \r
-void MainWindow::showContextMenu(QContextMenuEvent *event)\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onToggleSystem\r
+/// \param checked  メニューのチェック状態\r
+///\r
+/// システムファイルの表示/非表示を切り替えます。\r
+///\r
+void MainWindow::onToggleSystem(bool checked)\r
 {\r
-    qDebug() << "MainWindow::showContextMenu();";\r
+    qDebug() << "MainWindow::onToggleSystem" << checked;\r
 \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
+    if (checked) {\r
+        activeModel()->setFilter(activeModel()->filter() | QDir::System);\r
     }\r
     else {\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
+        activeModel()->setFilter(activeModel()->filter() ^ QDir::System);\r
     }\r
 \r
-    menu.exec(event->globalPos());\r
+    activeModel()->refresh();\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onToggleThumbnailMode\r
+/// \param checked  メニューのチェック状態\r
+///\r
+/// サムネイルモードの切り替えを行います。\r
+///\r
+void MainWindow::onToggleThumbnailMode(bool checked)\r
+{\r
+    qDebug() << "MainWindow::onToggleThumbnailMode()" << checked;\r
 \r
+    activePanel()->folderPanel()->toggleView(checked);\r
 }\r
 \r
-void MainWindow::checkUpdate(bool silent)\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onCheckUpdate\r
+/// \param silent   最新版を使用している場合に何も表示しないならtrue\r
+///\r
+/// アップデートの有無を確認します。\r
+///\r
+void MainWindow::onCheckUpdate(bool silent)\r
 {\r
-    qDebug() << "MainWindow::checkUpdate()" << silent;\r
+    qDebug() << "MainWindow::onCheckUpdate()" << silent;\r
 \r
     QNetworkAccessManager *manager = new QNetworkAccessManager(this);\r
 \r
@@ -1383,9 +1723,9 @@ void MainWindow::checkUpdate(bool silent)
         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
+    manager->get(QNetworkRequest(QUrl("http://gefu.sourceforge.jp/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
+    manager->get(QNetworkRequest(QUrl("http://gefu.sourceforge.jp/gefu_latest_mac.html")));\r
 #endif\r
 }\r
 \r
@@ -1426,119 +1766,302 @@ void MainWindow::checkUpdateFinished(QNetworkReply *reply, bool silent)
     }\r
 }\r
 \r
-void MainWindow::viewFinish(QWidget *sender)\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::initActions\r
+///\r
+/// アクションを初期化します。\r
+///\r
+void MainWindow::initActions()\r
 {\r
-    qDebug() << "MainWindow::viewFinish();" << sender->objectName();\r
+    qDebug() << "MainWindow::initActions()";\r
 \r
-    sender->setVisible(false);\r
-    ui->splitter->setVisible(true);\r
-    m_focusedView->setFocus();\r
-}\r
+    QList<QKeySequence> shortcuts;\r
+\r
+    //>>>>> 追加のショートカットキーを設定する\r
+    appendActionShortcut(ui->action_Open, "M");\r
+    appendActionShortcut(ui->action_OpenWith, "Shift+M");\r
+    appendActionShortcut(ui->view_Back, "Backspace");\r
+    // MacだとShift+の形で認識されてしまうもの\r
+    appendActionShortcut(ui->action_ScaleUp, "Shift++");\r
+    appendActionShortcut(ui->action_Filter, "Shift+*");\r
+    appendActionShortcut(ui->action_OpenTerminal, "Shift+>");\r
+    appendActionShortcut(ui->action_About, "Shift+?");\r
+    appendActionShortcut(ui->image_ScaleNormal, "Shift+=");\r
+\r
+    // SIGNAL -> SLOT\r
+    connect(ui->action_About, SIGNAL(triggered()), this, SLOT(onAbout()));\r
+    connect(ui->action_AddBookmark, SIGNAL(triggered()), this, SLOT(onAddBookmark()));\r
+    connect(ui->action_Cd, SIGNAL(triggered()), this, SLOT(onChooseFolder()));\r
+    connect(ui->action_CheckUpdate, SIGNAL(triggered()), this, SLOT(onCheckUpdate()));\r
+    connect(ui->action_Copy, SIGNAL(triggered()), this, SLOT(onCopy()));\r
+    connect(ui->action_CopyFileName, SIGNAL(triggered()), this, SLOT(onCopyFileName()));\r
+    connect(ui->action_CopyFilePath, SIGNAL(triggered()), this, SLOT(onCopyFilePath()));\r
+    connect(ui->action_CreateFile, SIGNAL(triggered()), this, SLOT(onCreateFile()));\r
+    connect(ui->action_CreateFolder, SIGNAL(triggered()), this, SLOT(onCreateFolder()));\r
+    connect(ui->action_Delete, SIGNAL(triggered()), this, SLOT(onDelete()));\r
+    connect(ui->action_EditBookmark, SIGNAL(triggered()), this, SLOT(onEditBookmark()));\r
+    connect(ui->action_ExpandLeft, SIGNAL(triggered()), this, SLOT(onExpandLeft()));\r
+    connect(ui->action_ExpandRight, SIGNAL(triggered()), this, SLOT(onExpandRight()));\r
+    connect(ui->action_Filter, SIGNAL(triggered()), this, SLOT(showFilterDialog()));\r
+    connect(ui->action_History, SIGNAL(triggered()), this, SLOT(showHistoryDialog()));\r
+    connect(ui->action_KeyDown, SIGNAL(triggered()), this, SLOT(onKeyDown()));\r
+    connect(ui->action_KeyDownOther, SIGNAL(triggered()), this, SLOT(onKeyDownOther()));\r
+    connect(ui->action_KeyEnd, SIGNAL(triggered()), this, SLOT(onKeyEnd()));\r
+    connect(ui->action_KeyEndOther, SIGNAL(triggered()), this, SLOT(onKeyEndOther()));\r
+    connect(ui->action_KeyHome, SIGNAL(triggered()), this, SLOT(onKeyHome()));\r
+    connect(ui->action_KeyHomeOther, SIGNAL(triggered()), this, SLOT(onKeyHomeOther()));\r
+    connect(ui->action_KeyLeft, SIGNAL(triggered()), this, SLOT(onKeyLeft()));\r
+    connect(ui->action_KeyUp, SIGNAL(triggered()), this, SLOT(onKeyUp()));\r
+    connect(ui->action_KeyUpOther, SIGNAL(triggered()), this, SLOT(onKeyUpOther()));\r
+    connect(ui->action_Move, SIGNAL(triggered()), this, SLOT(onMove()));\r
+    connect(ui->action_Open, SIGNAL(triggered()), this, SLOT(onOpen()));\r
+    connect(ui->action_OpenArchiver, SIGNAL(triggered()), this, SLOT(onOpenArchiver()));\r
+    connect(ui->action_OpenEditor, SIGNAL(triggered()), this, SLOT(onOpenEditor()));\r
+    connect(ui->action_OpenTerminal, SIGNAL(triggered()), this, SLOT(onOpenTerminal()));\r
+    connect(ui->action_OpenWith, SIGNAL(triggered()), this, SLOT(onOpenWith()));\r
+    connect(ui->action_Quit, SIGNAL(triggered()), this, SLOT(close()));\r
+    connect(ui->action_Rename, SIGNAL(triggered()), this, SLOT(onRename()));\r
+    connect(ui->action_KeyRight, SIGNAL(triggered()), this, SLOT(onKeyRight()));\r
+    connect(ui->action_RunCommand, SIGNAL(triggered()), this, SLOT(onRunCommand()));\r
+    connect(ui->action_ScaleDown, SIGNAL(triggered()), this, SLOT(onScaleDown()));\r
+    connect(ui->action_ScaleUp, SIGNAL(triggered()), this, SLOT(onScaleUp()));\r
+    connect(ui->action_SearchNext, SIGNAL(triggered()), this, SLOT(onSearchNext()));\r
+    connect(ui->action_SearchPrev, SIGNAL(triggered()), this, SLOT(onSearchPrev()));\r
+    connect(ui->action_Setting, SIGNAL(triggered()), this, SLOT(showPreferenceDialog()));\r
+    connect(ui->action_ShowBookmark, SIGNAL(triggered()), this, SLOT(showBookmarkDialog()));\r
+    connect(ui->action_Sort, SIGNAL(triggered()), this, SLOT(showSortDialog()));\r
+    connect(ui->action_SplitCenter, SIGNAL(triggered()), this, SLOT(onSplitCenter()));\r
+    connect(ui->action_Swap, SIGNAL(triggered()), this, SLOT(onSwap()));\r
+    connect(ui->action_SyncPanel, SIGNAL(triggered()), this, SLOT(onSyncPanel()));\r
+    connect(ui->action_SyncPanelTo, SIGNAL(triggered()), this, SLOT(onSyncPanelTo()));\r
+\r
+    connect(ui->toggle_FullMode, SIGNAL(toggled(bool)), this, SLOT(onToggleFullMode(bool)));\r
+    connect(ui->toggle_Hidden, SIGNAL(toggled(bool)), this, SLOT(onToggleHidden(bool)));\r
+    connect(ui->toggle_Mark, SIGNAL(triggered()), this, SLOT(onToggleMark()));\r
+    connect(ui->toggle_PreviewMode, SIGNAL(toggled(bool)), this, SLOT(onTogglePreviewMode(bool)));\r
+    connect(ui->toggle_Search, SIGNAL(toggled(bool)), this, SLOT(onToggleSearch(bool)));\r
+    connect(ui->toggle_System, SIGNAL(toggled(bool)), this, SLOT(onToggleSystem(bool)));\r
+    connect(ui->toggle_ThumbnailMode, SIGNAL(toggled(bool)), this, SLOT(onToggleThumbnailMode(bool)));\r
 \r
+    connect(ui->view_Back, SIGNAL(triggered()), this, SLOT(view_finished()));\r
+\r
+}\r
 \r
-void MainWindow::initActionConnections()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::setActiveModel\r
+/// \param m    新しいアクティブモデル\r
+///\r
+/// アクティブモデルを変更します。\r
+///\r
+void MainWindow::setActiveModel(FolderModel *m)\r
 {\r
-    qDebug() << "MainWindow::initActionConnections";\r
+    qDebug() << "MainWindow::setActiveModel()" << m;\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
-FolderView *MainWindow::folderView() const\r
-{\r
-    qDebug() << "MainWindow::folderView";\r
+    if (activeModel()) {\r
+        activeModel()->disconnect(this);\r
+        ui->action_CdHome->disconnect();\r
+        ui->action_CdRoot->disconnect();\r
+        ui->action_CdUp->disconnect();\r
+        ui->action_historyBack->disconnect();\r
+        ui->action_HistoryForward->disconnect();\r
+        ui->action_MarkAll->disconnect();\r
+        ui->action_MarkAllFiles->disconnect();\r
+        ui->action_MarkAllOff->disconnect();\r
+        ui->action_MarkInvert->disconnect();\r
+        ui->action_Refresh->disconnect();\r
+    }\r
 \r
-    QWidget *w = qApp->focusWidget();\r
-    if (w == ui->folderView1 || w == ui->searchBox1 || w == ui->locationBox1) {\r
-        return ui->folderView1;\r
+    m->setActive();\r
+\r
+    connect(activeModel(), SIGNAL(modelAboutToBeReset()), this, SLOT(model_PreReset()));\r
+    connect(activeModel(), SIGNAL(modelReset()), this, SLOT(model_PostReset()));\r
+    connect(ui->action_CdHome, SIGNAL(triggered()), activeModel(), SLOT(onCdHome()));\r
+    connect(ui->action_CdRoot, SIGNAL(triggered()), activeModel(), SLOT(onCdRoot()));\r
+    connect(ui->action_CdUp, SIGNAL(triggered()), activeModel(), SLOT(onCdUp()));\r
+    connect(ui->action_historyBack, SIGNAL(triggered()), activeModel(), SLOT(onHistoryBack()));\r
+    connect(ui->action_HistoryForward, SIGNAL(triggered()), activeModel(), SLOT(onHistoryForward()));\r
+    connect(ui->action_MarkAll, SIGNAL(triggered()), activeModel(), SLOT(onMarkAll()));\r
+    connect(ui->action_MarkAllFiles, SIGNAL(triggered()), activeModel(), SLOT(onMarkAllFiles()));\r
+    connect(ui->action_MarkAllOff, SIGNAL(triggered()), activeModel(), SLOT(onMarkAllOff()));\r
+    connect(ui->action_MarkInvert, SIGNAL(triggered()), activeModel(), SLOT(onMarkInvert()));\r
+    connect(ui->action_Refresh, SIGNAL(triggered()), activeModel(), SLOT(refresh()));\r
+\r
+    Preferences prefs(this);\r
+    if (ui->LPanel->isVisible()) {\r
+        ui->LPanel->updateAppearance(prefs);\r
+        ui->LPanel->model()->updateAppearance(prefs);\r
+    }\r
+    if (ui->RPanel->isVisible()) {\r
+        ui->RPanel->updateAppearance(prefs);\r
+        ui->RPanel->model()->updateAppearance(prefs);\r
+    }\r
+    if (ui->FPanel->isVisible()) {\r
+        ui->FPanel->updateAppearance(prefs);\r
+        ui->FPanel->model()->updateAppearance(prefs);\r
+    }\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::activeModel\r
+/// \return アクティブなフォルダモデルを返します。\r
+///\r
+FolderModel *MainWindow::activeModel() const\r
+{\r
+    return FolderModel::activeModel();\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::activePanel\r
+/// \return アクティブモデルを所有している可視状態のパネルを返します。\r
+///\r
+Panel *MainWindow::activePanel() const\r
+{\r
+    if (ui->FPanel->model() == activeModel() && ui->FPanel->isVisible()) {\r
+        return ui->FPanel;\r
+    }\r
+    if (ui->LPanel->model() == activeModel() && ui->LPanel->isVisible()) {\r
+        return ui->LPanel;\r
     }\r
-    if (w == ui->folderView2 || w == ui->searchBox2 || w == ui->locationBox2) {\r
-        return ui->folderView2;\r
+    if (ui->RPanel->model() == activeModel() && ui->RPanel->isVisible()) {\r
+        return ui->RPanel;\r
     }\r
 \r
-    qDebug() << w->objectName();\r
+    qDebug() << ">>>>>>>>>> activePanel() Logic error <<<<<<<<<<";\r
     return NULL;\r
 }\r
 \r
-void MainWindow::replaceVars(QString &str, const QFileInfo info)\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::inactiveModel\r
+/// \return 非アクティブなフォルダモデルを返します。\r
+///\r
+FolderModel *MainWindow::inactiveModel() const\r
 {\r
-    qDebug() << "MainWindow::replaceVars" << str;\r
+    if (ui->LPanel->model()->isActive()) {\r
+        return ui->RPanel->model();\r
+    }\r
+    Q_ASSERT(ui->RPanel->model()->isActive());\r
+    return ui->LPanel->model();\r
+}\r
 \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
+/// \brief MainWindow::inactivePanel\r
+/// \return 非アクティブモデルを所有している可視状態のパネルを返します。\r
+///\r
+Panel *MainWindow::inactivePanel() const\r
+{\r
+    if (ui->LPanel->model() == inactiveModel() && ui->LPanel->isVisible()) {\r
+        return ui->LPanel;\r
     }\r
-    else {\r
-        str.replace("$D", info.absolutePath());\r
+    if (ui->RPanel->model() == inactiveModel() && ui->RPanel->isVisible()) {\r
+        return ui->RPanel;\r
     }\r
-    str.replace("$P", info.absoluteFilePath());\r
+    if (ui->FPanel->model() == inactiveModel() && ui->FPanel->isVisible()) {\r
+        return ui->FPanel;\r
+    }\r
+\r
+    qDebug() << ">>>>>>>>>> inactivePanel() Logic error <<<<<<<<<<";\r
+    return NULL;\r
 }\r
 \r
-SearchBox *MainWindow::searchBox(FolderView *view) const\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::selectedItems\r
+/// \return マークされているアイテムまたはカレントアイテムのリスト\r
+///\r
+QFileInfoList MainWindow::selectedItems() const\r
 {\r
-    qDebug() << "MainWindow::searchBox()" << view->objectName();\r
-\r
-    if (view == ui->folderView1) {\r
-        return ui->searchBox1;\r
+    QFileInfoList list = activeModel()->markedItems();\r
+    if (list.isEmpty()) {\r
+        qDebug() << focusItemView();\r
+        qDebug() << focusItemView()->currentIndex();\r
+        Q_ASSERT(focusItemView()->currentIndex().isValid());\r
+        list << activeModel()->fileInfo(focusItemView()->currentIndex());\r
     }\r
-    else {\r
-        Q_ASSERT(view == ui->folderView2);\r
-        return ui->searchBox2;\r
+\r
+    return list;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::focusItemView\r
+/// \return フォーカスを持つアイテムビュー\r
+///\r
+QAbstractItemView *MainWindow::focusItemView() const\r
+{\r
+    return static_cast<QAbstractItemView*>(qApp->focusWidget());\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::setViewMode\r
+/// \param mode 新しいビューモード\r
+///\r
+/// ビューモードを変更します。\r
+///\r
+void MainWindow::setViewMode(Mode mode)\r
+{\r
+    qDebug() << "MainWindow::setViewMode()" << mode;\r
+\r
+    QWidget *newFocusWidget = NULL;\r
+\r
+    switch (mode) {\r
+    case ModeBasic:\r
+        ui->FPanel->setVisible(false);\r
+        ui->splitter->setVisible(true);\r
+        ui->LPanel->setViewItem();\r
+        ui->RPanel->setViewItem();\r
+        if (m_viewMode == ModeFull) {\r
+            activePanel()->folderPanel()->setItemView(focusItemView()->objectName());\r
+            activePanel()->folderPanel()->itemView()->setCurrentIndex(\r
+                        focusItemView()->currentIndex());\r
+            ui->FPanel->setModel(NULL);\r
+        }\r
+        newFocusWidget = activePanel()->folderPanel()->itemView();\r
+        break;\r
+\r
+    case ModeFull:\r
+        if (m_viewMode == ModeBasic) {\r
+            ui->FPanel->setModel(activeModel());\r
+            ui->splitter->setVisible(false);\r
+            ui->FPanel->setVisible(true);\r
+            ui->FPanel->folderPanel()->setItemView(focusItemView()->objectName());\r
+            ui->FPanel->folderPanel()->itemView()->setCurrentIndex(\r
+                            focusItemView()->currentIndex());\r
+        }\r
+        ui->FPanel->setViewItem();\r
+        newFocusWidget = activePanel()->folderPanel()->itemView();\r
+        break;\r
+\r
+    case ModeView:\r
+        ui->FPanel->setViewItem(focusItemView()->currentIndex());\r
+        ui->splitter->setVisible(false);\r
+        ui->FPanel->setVisible(true);\r
+        newFocusWidget = ui->FPanel->visibleView();\r
+        break;\r
+\r
+    case ModePreview:\r
+        inactivePanel()->setViewItem(focusItemView()->currentIndex());\r
+        break;\r
     }\r
+\r
+    m_prevMode = m_viewMode;\r
+    m_viewMode = mode;\r
+\r
+    if (newFocusWidget)\r
+        newFocusWidget->setFocus();\r
+    else\r
+        updateActions();\r
 }\r
 \r
-bool MainWindow::startProcess(const QString &cmd, const QString &workDir, const QString &errMsg)\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::startProcess\r
+/// \param cmd      実行するコマンド\r
+/// \param errMsg   エラー時の表示メッセージ\r
+/// \return true:成功, false:失敗\r
+///\r
+bool MainWindow::startProcess(const QString &cmd, const QString &errMsg)\r
 {\r
-    qDebug() << "MainWindow::startProcess" << cmd << workDir << errMsg;\r
+    qDebug() << "MainWindow::startProcess" << cmd << errMsg;\r
 \r
     QProcess process(this);\r
-    process.setWorkingDirectory(workDir);\r
+    process.setWorkingDirectory(activeModel()->rootPath());\r
     if (!process.startDetached(cmd)) {\r
         QMessageBox::critical(this, tr("エラー"), errMsg + "<br/>" + cmd);\r
         return false;\r
@@ -1546,96 +2069,211 @@ bool MainWindow::startProcess(const QString &cmd, const QString &workDir, const
     return true;\r
 }\r
 \r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::updateActions\r
+///\r
+/// アクションの有効/無効を設定します。\r
+///\r
 void MainWindow::updateActions()\r
 {\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
+    bool isView = true;\r
+    bool isSearch = false;\r
+    bool isImageView = false;\r
+    bool toggleSearch = true;\r
+\r
+\r
+    QWidget *w = qApp->focusWidget();\r
+    if (w->objectName() == "folderView" || w->objectName() == "thumbnailView") {\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
+        QFileInfoList list = selectedItems();\r
+        if (list.size() == 1 && list[0].fileName() == "..") {\r
+            ui->action_Copy->setEnabled(false);\r
+            ui->action_Delete->setEnabled(false);\r
+            ui->action_Move->setEnabled(false);\r
+            ui->action_Rename->setEnabled(false);\r
+        }\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
+        if (!ui->LPanel->folderPanel()->isVisible() ||\r
+            !ui->RPanel->folderPanel()->isVisible())\r
+        {\r
+            ui->action_Copy->setEnabled(false);\r
+            ui->action_Move->setEnabled(false);\r
+            ui->action_Swap->setEnabled(false);\r
+            ui->action_SyncPanel->setEnabled(false);\r
+            ui->action_SyncPanelTo->setEnabled(false);\r
+        }\r
 \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
+        if (m_viewMode == ModeFull) {\r
+            ui->toggle_PreviewMode->setEnabled(false);\r
+        }\r
+\r
+        // サムネイル表示の場合、左右キーはカーソル移動\r
+        if (w->objectName() == "thumbnailView") {\r
+            ui->action_KeyLeft->setEnabled(false);\r
+            ui->action_KeyRight->setEnabled(false);\r
+            ui->toggle_ThumbnailMode->blockSignals(true);\r
+            ui->toggle_ThumbnailMode->setChecked(true);\r
+            ui->toggle_ThumbnailMode->blockSignals(false);\r
+        }\r
+        else {\r
+            ui->toggle_ThumbnailMode->blockSignals(true);\r
+            ui->toggle_ThumbnailMode->setChecked(false);\r
+            ui->toggle_ThumbnailMode->blockSignals(false);\r
         }\r
     }\r
-}\r
+    else if (w->objectName() == "searchBox"){\r
+        setEnabledAllActions(false);\r
+        isView = false;\r
+        isSearch = true;\r
+    }\r
+    else if (w->objectName() == "locationBox") {\r
+        setEnabledAllActions(false);\r
+        isView = false;\r
+    }\r
+    else if (w->objectName() == "textView") {\r
+        SimpleTextView *v = static_cast<SimpleTextView*>(w);\r
+        setEnabledAllActions(false);\r
+        toggleSearch = false;\r
 \r
-void MainWindow::setNameFilters(FolderView *view, const QString &filters)\r
-{\r
-    qDebug() << "MainWindow::setNameFilters();" << view->objectName() << filters;\r
+        ui->text_ConvertFromEUC->setEnabled(true);\r
+        ui->text_ConvertFromEUC->disconnect();\r
+        connect(ui->text_ConvertFromEUC, SIGNAL(triggered()), v, SLOT(convertFromEUC()));\r
+\r
+        ui->text_ConvertFromJIS->setEnabled(true);\r
+        ui->text_ConvertFromJIS->disconnect();\r
+        connect(ui->text_ConvertFromJIS, SIGNAL(triggered()), v, SLOT(convertFromJIS()));\r
+\r
+        ui->text_ConvertFromSJIS->setEnabled(true);\r
+        ui->text_ConvertFromSJIS->disconnect();\r
+        connect(ui->text_ConvertFromSJIS, SIGNAL(triggered()), v, SLOT(convertFromSJIS()));\r
+\r
+        ui->text_ConvertFromUTF8->setEnabled(true);\r
+        ui->text_ConvertFromUTF8->disconnect();\r
+        connect(ui->text_ConvertFromUTF8, SIGNAL(triggered()), v, SLOT(convertFromUTF8()));\r
+\r
+        ui->text_ConvertFromUTF16->setEnabled(true);\r
+        ui->text_ConvertFromUTF16->disconnect();\r
+        connect(ui->text_ConvertFromUTF16, SIGNAL(triggered()), v, SLOT(convertFromUTF16()));\r
+\r
+        ui->text_ConvertFromUTF16BE->setEnabled(true);\r
+        ui->text_ConvertFromUTF16BE->disconnect();\r
+        connect(ui->text_ConvertFromUTF16BE, SIGNAL(triggered()), v, SLOT(convertFromUTF16BE()));\r
+\r
+        ui->text_ConvertFromUTF16LE->setEnabled(true);\r
+        ui->text_ConvertFromUTF16LE->disconnect();\r
+        connect(ui->text_ConvertFromUTF16LE, SIGNAL(triggered()), v, SLOT(convertFromUTF16LE()));\r
+\r
+        ui->text_Copy->disconnect();\r
+        connect(ui->text_Copy, SIGNAL(triggered()), v, SLOT(copy()));\r
 \r
-    QStringList list = filters.split(" ", QString::SkipEmptyParts);\r
-    if (list.isEmpty()) {\r
-        list << "*";\r
     }\r
-    view->setNameFilters(list);\r
-    showNameFilters(view);\r
-}\r
+    else if (w->objectName() == "imageView") {\r
+        SimpleImageView *v = static_cast<SimpleImageView*>(w);\r
+        setEnabledAllActions(false);\r
+        toggleSearch = false;\r
+        isImageView = true;\r
+\r
+        ui->image_FitToWindow->setEnabled(true);\r
+        ui->image_FitToWindow->disconnect();\r
+        connect(ui->image_FitToWindow, SIGNAL(toggled(bool)), v, SLOT(fitToWindow(bool)));\r
+\r
+        ui->image_ScaleNormal->setEnabled(true);\r
+        ui->image_ScaleNormal->disconnect();\r
+        connect(ui->image_ScaleNormal, SIGNAL(triggered()), v, SLOT(scaleNormal()));\r
+\r
+        ui->image_Rotate90->setEnabled(true);\r
+        ui->image_Rotate90->disconnect();\r
+        connect(ui->image_Rotate90, SIGNAL(triggered()), v, SLOT(rotate90()));\r
+\r
+        ui->image_Rotate180->setEnabled(true);\r
+        ui->image_Rotate180->disconnect();\r
+        connect(ui->image_Rotate180, SIGNAL(triggered()), v, SLOT(rotate180()));\r
+    }\r
+\r
+    ui->action_About->setEnabled(true);\r
+    ui->action_CheckUpdate->setEnabled(true);\r
+    ui->action_KeyDown->setEnabled(isView);\r
+    ui->action_KeyEnd->setEnabled(isView);\r
+    ui->action_KeyHome->setEnabled(isView);\r
+    ui->action_KeyUp->setEnabled(isView);\r
+    ui->action_Quit->setEnabled(true);\r
+    ui->action_ScaleDown->setEnabled(isView);\r
+    ui->action_ScaleUp->setEnabled(isView);\r
+    ui->action_SearchNext->setEnabled(isSearch);\r
+    ui->action_SearchPrev->setEnabled(isSearch);\r
+    ui->action_Setting->setEnabled(true);\r
+    ui->toggle_Search->setEnabled(toggleSearch);\r
+    ui->view_Back->setEnabled(m_viewMode == ModeView);\r
+\r
+    if (isImageView) {\r
+        ui->action_ScaleDown->setText(tr("縮小"));\r
+        ui->action_ScaleUp->setText(tr("拡大"));\r
+    }\r
+    else {\r
+        ui->action_ScaleDown->setText(tr("文字を小さく"));\r
+        ui->action_ScaleUp->setText(tr("文字を大きく"));\r
+    }\r
 \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
+    if (m_viewMode == ModeBasic || m_viewMode == ModeFull) {\r
+        ui->toggle_FullMode->setEnabled(true);\r
     }\r
     else {\r
-        Q_ASSERT(view == ui->folderView2);\r
-        return ui->filterLabel2;\r
+        ui->toggle_FullMode->setEnabled(false);\r
     }\r
+\r
+    ui->action_historyBack->setEnabled(!activeModel()->isHistoryBegin());\r
+    ui->action_HistoryForward->setEnabled(!activeModel()->isHistoryEnd());\r
 }\r
 \r
-void MainWindow::about()\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::setEnabledAllActions\r
+/// \param enable   有効にする場合はtrue\r
+///\r
+/// 全てのアクションを有効または無効にします。\r
+///\r
+void MainWindow::setEnabledAllActions(bool enable)\r
+{\r
+    qDebug() << "MainWindow::setEnabledAllActions()" << enable;\r
+    foreach (QAction *action, m_actions) {\r
+        action->setEnabled(enable);\r
+    }\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::onAbout\r
+///\r
+/// Aboutダイアログを表示します。\r
+///\r
+void MainWindow::onAbout()\r
 {\r
     QMessageBox::about(\r
                 this,\r
                 tr("げふぅ について"),\r
-                tr("<h3>Gefu Ver%1</h3>").arg(VERSION_VALUE) +\r
+                qApp->applicationDisplayName() +\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>最新版の情報は<a href='http://gefu.sourceforge.jp/'>公式サイト</a>で公開しています。</p>"\r
                    "<p><small>Copyright 2014 @miyabi_satoh All rights reserved.</small></p>"));\r
 }\r
 \r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::closeEvent\r
+/// \param event    クローズイベント\r
+///\r
+/// 終了処理を行います。\r
+///\r
 void MainWindow::closeEvent(QCloseEvent *event)\r
 {\r
-    QSettings settings;\r
+    qDebug() << "MainWindow::closeEvent()";\r
+    Preferences prefs(this);\r
 \r
-    if (settings.value(IniKey_ConfirmExit).toBool()) {\r
+    if (prefs.isConfirmQuit()) {\r
         QMessageBox msgBox;\r
         QCheckBox *checkBox = new QCheckBox();\r
         checkBox->setText(tr("次回以降は確認しない"));\r
@@ -1645,26 +2283,44 @@ void MainWindow::closeEvent(QCloseEvent *event)
         msgBox.setIcon(QMessageBox::Question);\r
 \r
         if (msgBox.exec() == QMessageBox::No) {\r
+            qDebug() << ">>>>> ユーザによりキャンセルされました <<<<<";\r
             event->ignore();\r
             return;\r
         }\r
-        settings.setValue(IniKey_ConfirmExit, !checkBox->isChecked());\r
+        prefs.setConfirmQuit(!checkBox->isChecked());\r
     }\r
 \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
+    prefs.saveModel("Left", ui->LPanel->model());\r
+    prefs.saveModel("Right", ui->RPanel->model());\r
+    prefs.saveWindow(this);\r
     QMainWindow::closeEvent(event);\r
 }\r
 \r
-\r
-void MainWindow::keyPressEvent(QKeyEvent *event)\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief MainWindow::eventFilter\r
+/// \param watched  イベントの発生元オブジェクト\r
+/// \param e        発生したイベント\r
+/// \return イベントを処理した場合はtrueを返します。\r
+///\r
+bool MainWindow::eventFilter(QObject *watched, QEvent *e)\r
 {\r
-    QString ksq = KeyEventToSequence(event);\r
-    qDebug() << ksq << " @MainWindow";\r
+    switch (e->type()) {\r
+    case QEvent::KeyPress:\r
+        // キーイベントの処理\r
+        return onKeyPressEvent(watched, static_cast<QKeyEvent*>(e));\r
+\r
+    case QEvent::ContextMenu:\r
+        // コンテキストメニューイベントの処理\r
+        return onContextMenuEvent(watched, static_cast<QContextMenuEvent*>(e));\r
+\r
+    case QEvent::Drop:\r
+        qDebug() << "QEvent::Drop";\r
+        // ドロップイベントの処理\r
+        return onDropEvent(watched, static_cast<QDropEvent*>(e));\r
+\r
+    default:\r
+        break;\r
+    }\r
 \r
-    QMainWindow::keyPressEvent(event);\r
+    return false;\r
 }\r