2013年1月16日水曜日

(Sample)Qt C++でリネームソフトを作る 第4回 実装


はいそれでは実装をやっていきます。

簡単な説明のみです。詳細についてはfreesoftページにアップロードしたプロジェクトを参照してください。1000行以下なので簡単に読めるはずです。

ではおおまかな説明を

(mainwindow.h)

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMessageBox>
#include <QFileDialog>
#include <QFileInfo>
#include <QDateTime>
#include <QtGlobal>
#include <QTreeWidgetItem>
#include <QFileIconProvider>
#include <QTextCodec>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    
private slots:
    void on_FolderDialog_triggered();

    void on_FormClose_triggered();

    void on_Run_triggered();

    void on_NameSort_triggered();

    void on_TimeSort_triggered();

    void on_SizeSort_triggered();

    void on_ExtentionSort_triggered();

private:
    Ui::MainWindow *ui;
    QDir::SortFlags m_SortFlag;//ソートの種類
    QString m_FolderPath;//読込フォルダのパス
    QStringList m_FileNameList;//ファイル名のリスト。表示に使用する。
    QStringList m_AbsolutePathList;//ファイルの絶対パスリスト
    void GetFiles(QString path, QDir::SortFlags sort);//ファイルを取得・編集する
    void InitTree(QString dir, QStringList list);//ツリービューの初期化
    void ShowMessage(QString m);//メッセージボックス関数
    bool ShowYesNoMessage(QString m);//yes,noボタンのメッセージボックス
    void ClearCheck();//ソートのチェックを全てクリアする
};

#endif // MAINWINDOW_H

ヘッダは以上です。コメントのとおりです。


 (mainwindow.cpp)
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_SortFlag = QDir::Name;
    ui->NameSort->setChecked(true);
}

MainWindow::~MainWindow()
{
    delete ui;
}

//フォルダ選択クリック
void MainWindow::on_FolderDialog_triggered()
{
    QFileDialog file_dialog(this);
    file_dialog.setFileMode(QFileDialog::Directory);//フォルダ選択ダイアログ

    if (file_dialog.exec())
    {
        GetFiles(file_dialog.selectedFiles()[0], m_SortFlag);
        InitTree(m_FolderPath, m_AbsolutePathList);
    }
}

//終了クリック
void MainWindow::on_FormClose_triggered()
{
    this->close();
}

//実行クリック
void MainWindow::on_Run_triggered()
{
    QTextCodec *codec = QTextCodec::codecForName("UTF-8");//文字化け対策
    if(m_AbsolutePathList.length() <= 0 || ShowYesNoMessage(codec->toUnicode("実行してもよいか?")) == false) return;

    QString error_files = QString::null;//リネームに失敗したファイル名を格納していく
    int count = ui->spinBox->value();//リネーム時に付加する開始番号。
    for(int i = 0; i < m_AbsolutePathList.length(); i++)
    {
        QFileInfo file_info(m_AbsolutePathList[i]);
        QFile file(m_AbsolutePathList[i]);
        QString ext = file_info.completeSuffix();//拡張子の文字列取得

        if(file.exists() == false)//対象のファイルがあるのかどうか
        {
            ShowMessage("File Not Exist!!\nNot Completed!\n\n<Detail>\n" + m_AbsolutePathList[i]);
            return;
        }

        if(ext.count() > 0)//拡張子ありなら
        {
            if(!QFile::rename(file.fileName(), m_FolderPath + "/"+ ui->baseLineEdit->text() + QString::number((count + i)) + "." +  ext))
                error_files += m_AbsolutePathList[i] + "\n\n";
        }
        else//拡張子なしなら
        {
            if(!QFile::rename(file.fileName(), m_FolderPath + "/"+ ui->baseLineEdit->text() + QString::number((count + i))))
                error_files += m_AbsolutePathList[i] + "\n\n";
        }
    }

    GetFiles(m_FolderPath, m_SortFlag);
    InitTree(m_FolderPath, m_AbsolutePathList);

    if(error_files != QString::null)
    {
        QMessageBox msg;
        msg.setWindowTitle("Error!");
        msg.setText("Error! Can't rename there files");
        msg.setDetailedText(error_files);
        msg.exec();
    }

    ShowMessage("Completed!!");
}

//ファイルの取得・編集
void MainWindow::GetFiles(QString path, QDir::SortFlags sort)
{
    m_FolderPath = path;
    QDir dir(m_FolderPath);//フォルダの絶対パスをセットする
    if(m_FolderPath.length() == 0 || !dir.exists()) return;

    m_FileNameList.clear();
    m_AbsolutePathList.clear();

    m_FileNameList = dir.entryList(QDir::Files, sort);//フォルダ内のファイルをソートして全て取得

    foreach(QString str, m_FileNameList)
    {
        m_AbsolutePathList << dir.path() + "/" + str;
    }
}

//ツリービュー初期化
void MainWindow::InitTree(QString dir, QStringList list)
{
    ui->treeWidget->clear();

    QTreeWidgetItem *base_item = new QTreeWidgetItem;
    base_item->setText(0, dir);
    QFileIconProvider icon_pro;
    base_item->setIcon(0, icon_pro.icon(QFileIconProvider::Folder));//システムのフォルダアイコンを取得

    for(int i = 0; i < list.length(); i++)
    {
        QTreeWidgetItem *item = new QTreeWidgetItem;
        QFileInfo file_info(list[i]);
        item->setText(0, file_info.fileName());//ファイル名
        item->setText(1, QString("%1byte").arg(file_info.size()));//バイト数
        item->setText(2, file_info.lastModified().toString() + "(last)");//更新日
        item->setIcon(0,  icon_pro.icon(QFileIconProvider::File));//アイコン
        base_item->addChild(item);
    }

    ui->treeWidget->insertTopLevelItem(0, base_item);
    ui->treeWidget->expandAll();//ツリービューを開いた状態にする
}

//通常のメッセージボックスを表示
void MainWindow::ShowMessage(QString m)
{
    QMessageBox msgBox;
    msgBox.setText(m);
    msgBox.exec();
}

//Yes,Noのボタンのついたメッセージボックスを表示
bool MainWindow::ShowYesNoMessage(QString m)
{
    QMessageBox msg_box;
    msg_box.setText(m);
    msg_box.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
    msg_box.setDefaultButton(QMessageBox::Yes);

    int ret = msg_box.exec();

    switch(ret)
    {
    case QMessageBox::Yes:
        return true;
        break;
    case QMessageBox::No:
        return false;
        break;
    }

    return false;
}

//ソートのチェック状態をクリアする
void MainWindow::ClearCheck()
{
    ui->NameSort->setChecked(false);
    ui->TimeSort->setChecked(false);
    ui->SizeSort->setChecked(false);
    ui->ExtentionSort->setChecked(false);
}

//ソートの名前順クリック
void MainWindow::on_NameSort_triggered()
{
    ClearCheck();
    ui->NameSort->setChecked(true);
    m_SortFlag = QDir::Name;
    if(m_FolderPath.length() == 0) return;
    GetFiles(m_FolderPath, m_SortFlag);
    InitTree(m_FolderPath, m_AbsolutePathList);
}

//ソートの時間順クリック
void MainWindow::on_TimeSort_triggered()
{
    ClearCheck();
    ui->TimeSort->setChecked(true);
    m_SortFlag = QDir::Time;
    if(m_FolderPath.length() == 0) return;
    GetFiles(m_FolderPath, m_SortFlag);
    InitTree(m_FolderPath, m_AbsolutePathList);
}

//ソートのサイズ順クリック
void MainWindow::on_SizeSort_triggered()
{
    ClearCheck();
    ui->SizeSort->setChecked(true);
    m_SortFlag = QDir::Size;
    if(m_FolderPath.length() == 0) return;
    GetFiles(m_FolderPath, m_SortFlag);
    InitTree(m_FolderPath, m_AbsolutePathList);
}

//ソートの拡張子順クリック
void MainWindow::on_ExtentionSort_triggered()
{
    ClearCheck();
    ui->ExtentionSort->setChecked(true);
    m_SortFlag = QDir::Type;
    if(m_FolderPath.length() == 0) return;
    GetFiles(m_FolderPath, m_SortFlag);
    InitTree(m_FolderPath, m_AbsolutePathList);
}


これも見てのとおりです。コンストラクタ、デストラクタは見たまんまですので説明を省きます。

フォルダの選択ではQFileDialogを使います。Fileと書かれていますが、setFileModeでQFileDialog::Directoryを事前にセットすることでフォルダダイアログとなります。

終了も説明を省きます。closeするだけです。

実行はコメントのとおりです。特別な処理はありません。

ソートは今回はひとつしかチェックできないようにしておりますが、複数セットすることが可能のようです。
あとは見てのとおりです。

実行すると以下のようになります。






以上です。