OSDN Git Service

ReadMe更新
[gefu/Gefu.git] / folderpanel.cpp
index 281d95e..f9c3e7b 100644 (file)
@@ -1,3 +1,5 @@
+#include "common.h"\r
+#include "filetablemodel.h"\r
 #include "folderpanel.h"\r
 #include "mainwindow.h"\r
 #include "ui_folderpanel.h"\r
 #include <QDebug>\r
 #include <QDateTime>\r
 #include <QDesktopServices>\r
+#include <QSettings>\r
+#ifdef Q_OS_WIN32\r
+    #include <windows.h>\r
+#endif\r
+\r
+QString FilesizeToString(quint64 size)\r
+{\r
+    if (size >= 1024 * 1024 * 1024) {\r
+        return QString("%1GB").arg(int(10 * size / (1024 * 1024 * 1024)) / 10.0);\r
+    }\r
+    if (size >= 1024 * 1024) {\r
+        return QString("%1MB").arg(int(10 * size / (1024 * 1024)) / 10.0);\r
+    }\r
+    if (size >= 1024) {\r
+        return QString("%1KB").arg(int(10 * size / 1024) / 10.0);\r
+    }\r
+    return QString("%1B").arg(size);\r
+}\r
 \r
 FolderPanel::FolderPanel(QWidget *parent) :\r
     QWidget(parent),\r
-    ui(new Ui::FolderPanel),\r
-    m_dir(),\r
-    m_IconFactory(),\r
-    m_fsWatcher(new QFileSystemWatcher(this)),\r
-    m_bUpdating(false)\r
+    ui(new Ui::FolderPanel)\r
 {\r
     ui->setupUi(this);\r
-\r
-    // MainWindowのスロットに接続する\r
-    MainWindow *mainWnd = this->mainWindow();\r
-    if (mainWnd) {\r
-        connect(ui->fileTable, SIGNAL(cellDoubleClicked(int,int)), mainWnd, SLOT(onActionOpen()));\r
-    }\r
-\r
-    // ヘッダーラベルを設定する\r
-    QStringList labels;\r
-    labels << tr("") << tr("名前") << tr("サイズ") << tr("更新日時");\r
-    ui->fileTable->setHorizontalHeaderLabels(labels);\r
-\r
-    // イベントフィルタを設定する\r
-    ui->fileTable->installEventFilter(this);\r
+    ui->fileTable->setModel(new FileTableModel(this));\r
 \r
     // リサイズ時の動作を設定する\r
-    ui->fileTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);\r
-    ui->fileTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);\r
-    ui->fileTable->horizontalHeader()->setSectionResizeMode(2, QHeaderView::ResizeToContents);\r
-    ui->fileTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::ResizeToContents);\r
-\r
-    // フォルダの要素を表示\r
-    m_dir.setFilter(QDir::NoDot | QDir::AllEntries);\r
-    m_dir.setSorting(QDir::DirsFirst | QDir::Name);\r
+    QHeaderView *header = ui->fileTable->horizontalHeader();\r
+    header->setSectionResizeMode(0, QHeaderView::ResizeToContents);\r
+    header->setSectionResizeMode(1, QHeaderView::Stretch);\r
+    header->setSectionResizeMode(2, QHeaderView::ResizeToContents);\r
+    header->setSectionResizeMode(3, QHeaderView::ResizeToContents);\r
+    header->setDefaultSectionSize(header->minimumSectionSize());\r
+\r
+    QHeaderView *vHeader = ui->fileTable->verticalHeader();\r
+    vHeader->setDefaultSectionSize(vHeader->defaultSectionSize() * 0.75);\r
 }\r
 \r
 FolderPanel::~FolderPanel()\r
 {\r
-    UninstallWatcher();\r
     delete ui;\r
 }\r
 \r
-QTableWidget* FolderPanel::fileTable()\r
+QTableView* FolderPanel::fileTable()\r
 {\r
     return ui->fileTable;\r
 }\r
 \r
-const QTableWidget* FolderPanel::fileTable() const\r
+const QTableView *FolderPanel::fileTable() const\r
 {\r
     return ui->fileTable;\r
 }\r
 \r
-MainWindow* FolderPanel::mainWindow()\r
+const QString FolderPanel::side() const\r
 {\r
-    foreach (QWidget *w, qApp->topLevelWidgets()) {\r
-        if (w->objectName() == "MainWindow") {\r
-            return static_cast<MainWindow*>(w);\r
-        }\r
-    }\r
-    return NULL;\r
+    return ui->fileTable->side();\r
 }\r
 \r
-bool FolderPanel::eventFilter(QObject *obj, QEvent *event)\r
+void FolderPanel::setSide(const QString &side)\r
 {\r
-    if (event->type() == QEvent::KeyPress) {\r
-        QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);\r
-        switch (keyEvent->key()) {\r
-        case Qt::Key_A: {\r
-            // A            すべてのファイルをマーク\r
-            // Shift + A    すべてマーク\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                if (keyEvent->modifiers() & Qt::ShiftModifier) {\r
-                    mainWnd->onMarkAll();\r
-                }\r
-                else {\r
-                    mainWnd->onMarkAllFiles();\r
-                }\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-\r
-        case Qt::Key_D: {\r
-            // Ctrl + D ファイルを削除\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                if (keyEvent->modifiers() & Qt::ControlModifier) {\r
-                    mainWnd->onCmdDelete();\r
-                }\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-\r
-        case Qt::Key_E: {\r
-            // E        エディタで開く\r
-            // Ctrl + E ファイルを作成\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                if (keyEvent->modifiers() & Qt::ControlModifier) {\r
-                    mainWnd->onCmdNewFile();\r
-                }\r
-                else {\r
-                }\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-\r
-        case Qt::Key_G: {\r
-            // G            カーソルを先頭に移動\r
-            // Shift + G    カーソルを末尾に移動\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                if (keyEvent->modifiers() & Qt::ShiftModifier) {\r
-                    mainWnd->onMoveCursorEnd();\r
-                }\r
-                else {\r
-                    mainWnd->onMoveCursorBegin();\r
-                }\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-\r
-        case Qt::Key_H: {\r
-            // H            ホームフォルダに移動\r
-            // Shift + H    隠しファイルを表示/非表示\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                if (keyEvent->modifiers() & Qt::ShiftModifier) {\r
-                    mainWnd->onViewHidden();\r
-                }\r
-                else {\r
-                    mainWnd->onMoveHome();\r
-                }\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-\r
-        case Qt::Key_I: {\r
-            // I    マークを反転\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                mainWnd->onMarkInvert();\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-\r
-        case Qt::Key_J: {\r
-            // J            カーソルを下に移動\r
-            // Shift + J    フォルダを選択して移動\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                if (keyEvent->modifiers() & Qt::ShiftModifier) {\r
-                    mainWnd->onMoveJump();\r
-                }\r
-                else {\r
-                    mainWnd->onMoveCursorDown();\r
-                }\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-\r
-        case Qt::Key_K: {\r
-            // K        カーソルを上に移動\r
-            // Ctrl + K フォルダを作成\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                if (keyEvent->modifiers() & Qt::ControlModifier) {\r
-                    mainWnd->onCmdNewFolder();\r
-                }\r
-                else {\r
-                    mainWnd->onMoveCursorUp();\r
-                }\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-\r
-        case Qt::Key_O: {\r
-            // O            隣のパネルと同じフォルダを表示\r
-            // Shift + O    隣のパネルに同じフォルダを表示\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                if (keyEvent->modifiers() & Qt::ShiftModifier) {\r
-                    mainWnd->onViewToOther();\r
-                }\r
-                else {\r
-                    mainWnd->onViewFromOther();\r
-                }\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-\r
-        case Qt::Key_Q: {\r
-            // Q    アプリケーションを終了\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                mainWnd->onActionQuit();\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-\r
-        case Qt::Key_R: {\r
-            // R        履歴を表示\r
-            // Ctrl + R 名前を変更\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                if (keyEvent->modifiers() & Qt::ControlModifier) {\r
-                    mainWnd->onCmdRename();\r
-                }\r
-                else {\r
-\r
-                }\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-\r
-        case Qt::Key_U: {\r
-            // U    すべてのマークを解除\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                mainWnd->onMarkAllOff();\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-\r
-        case Qt::Key_W: {\r
-            // W    表示フォルダを交換\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                mainWnd->onViewSwap();\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-\r
-        case Qt::Key_X: {\r
-            // X     コマンドを実行\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                mainWnd->onActionCommand();\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-\r
-        case Qt::Key_Question: {\r
-            // ?    アプリケーション情報を表示\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                mainWnd->onHelpAbout();\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-\r
-        case Qt::Key_Space: {\r
-            // マーク/解除\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                mainWnd->onMarkToggle();\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-\r
-        case Qt::Key_Tab: {\r
-            // 隣のパネルに移動\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                mainWnd->onMoveOther();\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-\r
-        case Qt::Key_Backspace: {\r
-            // BS           親フォルダに移動\r
-            // Shift + BS   ルートフォルダに移動\r
-            MainWindow *mainWnd = this->mainWindow();\r
-            if (mainWnd) {\r
-                if (keyEvent->modifiers() & Qt::ShiftModifier) {\r
-                    mainWnd->onMoveRoot();\r
-                }\r
-                else {\r
-                    mainWnd->onMoveParent();\r
-                }\r
-            }\r
-            keyEvent->accept();\r
-            return true; }\r
-        }\r
+    ui->fileTable->setSide(side);\r
+\r
+    QSettings settings;\r
+    FileTableModel *model = new FileTableModel();\r
+    connect(model, SIGNAL(rootChanged(QString)),\r
+            ui->locationField, SLOT(setText(QString)));\r
+    connect(model, SIGNAL(stateChanged(int,int,quint64)),\r
+            this, SLOT(onStateChanged(int,int,quint64)));\r
+    connect(model, SIGNAL(listUpdated()),\r
+            ui->fileTable, SLOT(refresh()));\r
+\r
+    //>>>>> フィルタ初期化\r
+    model->setFilter(QDir::NoDot | QDir::AllDirs | QDir::Files);\r
+    if (settings.value(IniKey_ShowHidden, false).toBool()) {\r
+        model->setFilter(model->filter() | QDir::Hidden);\r
     }\r
-\r
-    return QWidget::eventFilter(obj, event);\r
-}\r
-\r
-void FolderPanel::setCurrentFolder(const QString &path)\r
-{\r
-    mainWindow()->setStatusText(tr("ファイルリストを更新中..."));\r
-    QString curDir = m_dir.absolutePath();\r
-    m_dir.setPath(QDir::cleanPath(path));\r
-    m_dir.canonicalPath();\r
-    QFileInfoList list = m_dir.entryInfoList();\r
-\r
-    if (list.empty()) {\r
-        QMessageBox::critical(\r
-                    this,\r
-                    tr("エラー"),\r
-                    tr("フォルダが存在しないか利用できません。"));\r
-        m_dir.setPath(curDir);\r
-        ui->locationField->setText(curDir);\r
-        mainWindow()->setStatusText(tr("レディ"));\r
-        return;\r
+    if (settings.value(IniKey_ShowSystem, false).toBool()) {\r
+        model->setFilter(model->filter() | QDir::System);\r
     }\r
-\r
-    // フォルダの変更監視\r
-    InstallWatcher();\r
-\r
-    m_bUpdating = true;\r
-    ui->fileTable->model()->removeRows(0, ui->fileTable->rowCount());\r
-    for (int i = 0; i < list.size(); i++) {\r
-        QFileInfo info = list.at(i);\r
-        if (info.fileName() == ".." && m_dir.isRoot()) {\r
-            continue;\r
-        }\r
-\r
-        int row = ui->fileTable->rowCount();\r
-        ui->fileTable->insertRow(row);\r
-\r
-        // ファイル名とアイコン\r
-        QTableWidgetItem *iName = new QTableWidgetItem(info.fileName());\r
-        iName->setFlags(iName->flags() ^ Qt::ItemIsEditable);\r
-        if (info.fileName() == "..") {\r
-            iName->setIcon(QIcon(":/images/Up.png"));\r
-        }\r
-        else {\r
-            iName->setIcon(m_IconFactory.icon(info));\r
-        }\r
-        ui->fileTable->setItem(row, 1, iName);\r
-\r
-        // サイズ\r
-        QString str;\r
-        if (info.isDir()) {\r
-            str = tr("<DIR>");\r
-        }\r
-        else if (info.size() >= 1024 * 1024 * 1024) {\r
-            str = tr("%1GB").arg(int(info.size() / (1024 * 1024 * 1024)));\r
-        }\r
-        else if (info.size() >= 1024 * 1024) {\r
-            str = tr("%1MB").arg(int(info.size() / (1024 * 1024)));\r
-        }\r
-        else if (info.size() >= 1024) {\r
-            str = tr("%1KB").arg(int(info.size() / 1024));\r
-        }\r
-        else {\r
-            str = tr("%1B").arg(info.size());\r
-        }\r
-        QTableWidgetItem *iSize = new QTableWidgetItem(str);\r
-        iSize->setFlags(iSize->flags() ^ Qt::ItemIsEditable);\r
-        iSize->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);\r
-\r
-        ui->fileTable->setItem(row, 2, iSize);\r
-\r
-        // 最終更新日時\r
-        QTableWidgetItem *iDateTime = new QTableWidgetItem(\r
-                    info.lastModified().toString("yy/MM/dd hh:mm"));\r
-        iDateTime->setFlags(iDateTime->flags() ^ Qt::ItemIsEditable);\r
-        ui->fileTable->setItem(row, 3, iDateTime);\r
-\r
-        // シグナル処理の関係で、チェックボックスは最後に追加する\r
-        QTableWidgetItem *iCheck = new QTableWidgetItem(tr(""));\r
-        iCheck->setFlags(iCheck->flags() ^ Qt::ItemIsEditable);\r
-        if (info.fileName() != "..") {\r
-            iCheck->setFlags(iCheck->flags() | Qt::ItemIsUserCheckable);\r
-            iCheck->setCheckState(Qt::Unchecked);\r
-        }\r
-        ui->fileTable->setItem(row, 0, iCheck);\r
-\r
+    //>>>>> ソート順初期化\r
+    model->setSorting(QDir::Name);  // 0\r
+    int sortBy = settings.value(side + slash + IniKey_SortBy, SortByName).toInt();\r
+    switch (sortBy) {\r
+    case SortByDate:    model->setSorting(model->sorting() | QDir::Time); break;\r
+    case SortBySize:    model->setSorting(model->sorting() | QDir::Size); break;\r
+    case SortByType:    model->setSorting(model->sorting() | QDir::Type); break;\r
+    default:            model->setSorting(model->sorting() | QDir::Name); break;\r
     }\r
-    ui->fileTable->selectRow(0);\r
-    ui->fileTable->resizeRowsToContents();\r
-\r
-    ui->locationField->setText(m_dir.absolutePath());\r
-    mainWindow()->setStatusText(tr("レディ"));\r
-    m_bUpdating = false;\r
-}\r
-\r
-void FolderPanel::InstallWatcher()\r
-{\r
-    UninstallWatcher();\r
+    // デフォルトだと文字列は昇順で、数値は降順…orz\r
+    int orderBy = settings.value(side + slash + IniKey_OrderBy, OrderByAsc).toInt();\r
+    if (((sortBy == SortByName || sortBy == SortByType) && orderBy == OrderByDesc) ||\r
+        ((sortBy == SortByDate || sortBy == SortBySize) && orderBy == OrderByAsc))\r
+    {\r
+        model->setSorting(model->sorting() | QDir::Reversed);\r
+    }\r
+    // フォルダの位置\r
+    switch (settings.value(side + slash + IniKey_PutDirs, PutDirsFirst).toInt()) {\r
+    case PutDirsFirst:  model->setSorting(model->sorting() | QDir::DirsFirst); break;\r
+    case PutDirsLast:   model->setSorting(model->sorting() | QDir::DirsLast); break;\r
+    }\r
+    // 大文字小文字の区別\r
+    if (settings.value(side + slash + IniKey_IgnoreCase, true).toBool()) {\r
+        model->setSorting(model->sorting() | QDir::IgnoreCase);\r
+    }\r
+    //>>>>> 監視フォルダ初期化\r
+    QString key = side + slash + IniKey_Dir;\r
+    QString path = settings.value(key, QDir::homePath()).toString();\r
 \r
-    m_fsWatcher = new QFileSystemWatcher(this);\r
-    m_fsWatcher->addPath(m_dir.absolutePath());\r
-    connect(m_fsWatcher, SIGNAL(directoryChanged(QString)),\r
-            this, SLOT(on_directoryChanged(QString)));\r
+    model->updateAppearance();\r
+    ui->fileTable->setModel(model);\r
+    ui->fileTable->setRootPath(path, true);\r
 }\r
 \r
-void FolderPanel::UninstallWatcher()\r
+void FolderPanel::updateAppearance()\r
 {\r
-    if (m_fsWatcher != NULL) {\r
-        delete m_fsWatcher;\r
+    QSettings settings;\r
+    QPalette palette;\r
+    QFont font;\r
+\r
+    font = ui->locationField->font();\r
+    font = settings.value(IniKey_BoxFont, font).value<QFont>();\r
+    palette = ui->locationField->palette();\r
+    palette.setColor(\r
+                QPalette::Base,\r
+                settings.value(IniKey_BoxColorBg, palette.base()).value<QColor>());\r
+    palette.setColor(\r
+                QPalette::Text,\r
+                settings.value(IniKey_BoxColorFg, palette.text()).value<QColor>());\r
+    ui->locationField->setFont(font);\r
+    ui->locationField->setPalette(palette);\r
+\r
+    palette = ui->fileTable->palette();\r
+    palette.setColor(\r
+                QPalette::Base,\r
+                settings.value(IniKey_ViewColorBgNormal, palette.base()).value<QColor>());\r
+    ui->fileTable->setPalette(palette);\r
+\r
+    FileTableModel *model = static_cast<FileTableModel*>(ui->fileTable->model());\r
+    if (model) {\r
+        model->updateAppearance();\r
     }\r
-    m_fsWatcher = NULL;\r
 }\r
 \r
-void FolderPanel::on_fileTable_cellChanged(int row, int column)\r
+void FolderPanel::onStateChanged(int checkedFolders, int checkedFiles, quint64 totalSize)\r
 {\r
-    if (column == 0) {\r
-        if (ui->fileTable->item(row, 0)->checkState() == Qt::Checked) {\r
-            for (int n = 0; n < 4; n++) {\r
-                ui->fileTable->item(row, n)->setForeground(Qt::red);\r
-                ui->fileTable->item(row, n)->setBackground(Qt::green);\r
-            }\r
-        }\r
-        else {\r
-            for (int n = 0; n < 4; n++) {\r
-                ui->fileTable->item(row, n)->setForeground(Qt::black);\r
-                ui->fileTable->item(row, n)->setBackground(Qt::white);\r
-            }\r
-        }\r
-        ui->fileTable->selectRow(row);\r
+    QString msg = "";\r
+    if (checkedFolders > 0) {\r
+        msg += tr("%1個のフォルダ ").arg(checkedFolders);\r
+    }\r
+    if (checkedFiles > 0) {\r
+        msg += tr("%1個のファイル ").arg(checkedFiles);\r
     }\r
+    if (msg.length() > 0) {\r
+        msg += "を選択 合計 ";\r
+        msg += FilesizeToString(totalSize);\r
+    }\r
+\r
+    ui->label->setText(msg);\r
+\r
 }\r
 \r
 void FolderPanel::on_locationField_editingFinished()\r
@@ -429,29 +175,8 @@ void FolderPanel::on_locationField_editingFinished()
     ui->locationField->blockSignals(true);\r
 \r
     QString path = ui->locationField->text();\r
-    setCurrentFolder(path);\r
+    ui->fileTable->setRootPath(path, true);\r
 \r
     ui->locationField->blockSignals(false);\r
 }\r
 \r
-void FolderPanel::on_directoryChanged(QString)\r
-{\r
-    int row = ui->fileTable->currentRow();\r
-    this->setCurrentFolder(m_dir.absolutePath());\r
-    if (row >= ui->fileTable->rowCount()) {\r
-        row = ui->fileTable->rowCount() - 1;\r
-    }\r
-    ui->fileTable->selectRow(row);\r
-}\r
-\r
-void FolderPanel::on_fileTable_itemSelectionChanged()\r
-{\r
-    if (m_bUpdating) {\r
-        return;\r
-    }\r
-\r
-    int row = ui->fileTable->currentRow();\r
-    if (0 <= row && row < ui->fileTable->rowCount()) {\r
-        mainWindow()->setStatusText(ui->fileTable->item(row, 1)->text());\r
-    }\r
-}\r