ksimpleeditor.cpp

ksimpleeditor.cpp

#include <kaccel.h>
#include <kdebug.h>
#include <keditcl.h>
#include <kfiledialog.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kstatusbar.h>
#include "ksimpleeditor.h"

それぞれ必要なヘッダーファイルを読み込みます。

KSimpleEditor::KSimpleEditor()
{
    txtEdit = new KTextEdit( this );
    setCentralWidget( txtEdit );
    setupMenuBar();
    setupToolBar();
    setupStatusBar();
    fileNew();
    resize( 800, 600 );
}

コンストラクタです。
メインのKTextEditウィジットを作成し、メニューバー、ツールバー、ステータスバーを作成する関数を呼んでいます。
最初の状態はファイルの新規作成とし、適度な大きさにリサイズしておきます。

KSimpleEditor::~KSimpleEditor()
{
}

デストラクタです。
あいかわらずなにもしませんが、一応書いておきます。

void KSimpleEditor::setupStatusBar()
{
    statusBar()->insertItem("", 0, 1, false );
    statusBar()->setSizeGripEnabled( true );
    statusBar()->show();
}

ステータスバーの設定です。
KMainWindowにはあらかじめステータスバーが定義されているので、空文字の場所をつくり、 リサイズ用の場所を右下に表示させます。

void KSimpleEditor::setupToolBar()
{
    tlbFile = toolBar();
    tlbEdit = new KToolBar( this, KMainWindow::Top );

    tlbFile->insertButton( BarIcon("filenew"), 0,
                SIGNAL( clicked() ), this,
                SLOT( slotFileNew() ), TRUE, i18n("New") );
    tlbFile->insertButton( BarIcon("fileopen"), 0,
                SIGNAL( clicked() ), this,
                SLOT( slotFileOpen() ), TRUE, i18n("Open") );
    tlbFile->insertButton(BarIcon("filesave"), 0,
                SIGNAL( clicked() ), this,
                SLOT( slotFileSave() ), TRUE, i18n("Save") );

    tlbFile->insertButton( BarIcon("filesaveas"), 0,
                SIGNAL( clicked() ), this,
                SLOT( slotFileSaveAs() ), TRUE, i18n("SaveAs") );

    tlbEdit->insertButton( BarIcon("editcut"), 0,
                SIGNAL( clicked() ), txtEdit,
                SLOT( cut() ), TRUE, i18n("Cut") );

    tlbEdit->insertButton( BarIcon("editcopy"), 0,
                SIGNAL( clicked() ), txtEdit,
                SLOT( copy() ), TRUE, i18n("Copy") );

    tlbEdit->insertButton( BarIcon("editpaste"), 0,
                SIGNAL( clicked() ), txtEdit,
                SLOT( paste() ), TRUE, i18n("Paste") );

    tlbEdit->insertLineSeparator();

    tlbEdit->insertButton( BarIcon("undo"), 0,
                SIGNAL( clicked() ), txtEdit,
                SLOT( undo() ), TRUE, i18n("Undo") );

    tlbEdit->insertButton( BarIcon("redo"), 0,
                SIGNAL( clicked() ), txtEdit,
                SLOT( redo() ), TRUE, i18n("Redo") );
}

ツールバーの設定です。
KMainWindowにあらかじめ用意されているツールバーをファイル用にし、編集用に新たなツールバーを作ります。
ファイル用のボタンは自前のスロットに接続し、編集用のボタンはKTextEditウィジットのスロットに直接接続しています。
表示するアイコンはあらかじめ準備されているものをBarIcon("name")で使います。

void KSimpleEditor::setupMenuBar()
{
    KAccel* accel = accel();
    accel->connectItem( KStdAccel::New, this, SLOT( slotFileNew() ) );
    accel->connectItem( KStdAccel::Open, this, SLOT( slotFileOpen() ) );
    accel->connectItem( KStdAccel::Save, this, SLOT( slotFileSave() ) );
    accel->connectItem( KStdAccel::Quit, this, SLOT( close() ) );
    accel->connectItem( KStdAccel::Cut, txtEdit, SLOT( cut() ) );
    accel->connectItem( KStdAccel::Copy, txtEdit, SLOT( copy() ) );
    accel->connectItem( KStdAccel::Paste, txtEdit, SLOT( paste() ) );
    accel->connectItem( KStdAccel::Undo, txtEdit, SLOT( undo() ) );
    accel->connectItem( KStdAccel::Redo, txtEdit, SLOT( redo() ) );

    QPopupMenu* mnFile = new QPopupMenu;
    QPopupMenu* mnEdit = new QPopupMenu;
    QPopupMenu* mnHelp = (QPopupMenu *)helpMenu();
    int idMenu;

    idMenu = mnFile->insertItem( SmallIcon("filenew"), i18n("&New"), this, SLOT( slotFileNew() ) );
    accel->changeMenuAccel( mnFile, idMenu, KStdAccel::New );

    idMenu = mnFile->insertItem( SmallIcon("fileopen"), i18n("&Open"), this, SLOT( slotFileOpen() ) );
    accel->changeMenuAccel( mnFile, idMenu, KStdAccel::Open );

    idMenu = mnFile->insertItem( SmallIcon("filesave"), i18n("&Save"), this, SLOT( slotFileSave() ) );
    accel->changeMenuAccel( mnFile, idMenu, KStdAccel::Save );

    idMenu = mnFile->insertItem( SmallIcon("filesaveas"), i18n("Save&As"), this, SLOT( slotFileSaveAs() ) );

    mnFile->insertSeparator();

    idMenu = mnFile->insertItem( SmallIcon("exit"), i18n("&Quit"), this, SLOT( close() ) );
    accel->changeMenuAccel( mnFile, idMenu, KStdAccel::Quit );

    idMenu = mnEdit->insertItem( SmallIcon("editcut"), i18n("Cu&t"), txtEdit, SLOT( cut() ) );
    accel->changeMenuAccel( mnEdit, idMenu, KStdAccel::Cut );

    idMenu = mnEdit->insertItem( SmallIcon("editcopy"), i18n("&Copy"), txtEdit, SLOT( copy() ) );
    accel->changeMenuAccel( mnEdit, idMenu, KStdAccel::Copy );

    idMenu = mnEdit->insertItem( SmallIcon("editpaste"), i18n("&Paste"), txtEdit, SLOT( paste() ) );
    accel->changeMenuAccel( mnEdit, idMenu, KStdAccel::Paste );

    mnEdit->insertSeparator();

    idMenu = mnEdit->insertItem( SmallIcon("undo"), i18n("&Undo"), txtEdit, SLOT( undo() ) );
    accel->changeMenuAccel( mnEdit, idMenu, KStdAccel::Undo );

    idMenu = mnEdit->insertItem( SmallIcon("redo"), i18n("&Redo"), txtEdit, SLOT( redo() ) );
    accel->changeMenuAccel( mnEdit, idMenu, KStdAccel::Redo );

    menuBar()->insertItem( i18n("&File"), mnFile );
    menuBar()->insertItem( i18n("&Edit"), mnEdit );
    menuBar()->insertItem( i18n("&Help"), mnHelp );
    menuBar()->show();
}

メニューの設定です。
各項目にKDE標準のアクセラレータキーを割り当てている以外はほとんどツールバーと一緒です。
KMainWindowに用意されているメニューバーにそれぞれのQPopupMenuウィジットを登録しています。

bool KSimpleEditor::CheckChangedAndSaved()
{
    bool blRtn = true;
    if( txtEdit->isModified() ){
        int ans = KMessageBox::questionYesNoCancel( this, i18n("This file is modified\nDo you save change?"), i18n("Confirm") );
        switch( ans )
        {
            case KMessageBox::Yes:
                blRtn = fileSave();
                break;
            case KMessageBox::No:
                break;
            case KMessageBox::Cancel:
                blRtn = false;
                break;
        }
    }
    return blRtn;
}

ファイルの内容に変更があった場合保存するかどうかを聞き、保存する場合は保存させます。
ファイルの変更が正常に保存されたり、変更を破棄するなど、次の作業に移っていい場合trueを返し、キャンセルや保存が失敗した場合falseを返します。

void KSimpleEditor::slotFileNew()
{
    if( !CheckChangedAndSaved() ) return;
    fileNew();
}

「ファイルの新規作成」用のスロットです。
ファイルが変更されているかチェックした後新規作成用の関数を呼びます。

void KSimpleEditor::slotFileOpen()
{
    if( !CheckChangedAndSaved() ) return;
    fileOpen();
}

「ファイルを開く」用のスロットです。
ファイルが変更されているかチェックした後ファイルオープン用の関数を呼びます。

void KSimpleEditor::slotFileSave()
{
    if( !GfileName.isEmpty() && !txtEdit->isModified() ) return;
    fileSave();
}

「ファイルを保存」用のスロットです。
新規かファイルが変更されている場合ファイル保存用の関数を呼びます。

void KSimpleEditor::slotFileSaveAs()
{
    fileSaveAs();
}

「名前を付けて保存」用のスロットです。
名前を付けて保存用の関数を呼びます。

void KSimpleEditor::fileOpen()
{
    KURL url = KFileDialog::getOpenURL( QString::null, "*.txt|Text File (*.txt)\n*|All files" );
    if( url.isEmpty() ) return;

    if( !url.isLocalFile() ){
        KMessageBox::sorry( this, i18n("KSimpleEditor can not handle remote files yet") );
        return;
    }

    GfileName = url.path();
    if( !GfileName.isEmpty() ){
        QFile file( GfileName );
        if ( !file.open( IO_ReadOnly ) ){
            KMessageBox::sorry( this, i18n("KSimpleEditor can not open the file") );
            return;
        }
        QTextStream ts( &file );
        QString txt = ts.read();
        txtEdit->setText( txt );

        txtEdit->viewport()->setFocus();
        setCaption( GfileName );
    }
}

ファイルオープン用の関数です。
KFileDialogのgetOpenURLメソッドでファイル名を取り出し、ローカルファイルの場合読み込んでエディタにセットします。
ファイル名をGfileNameにセットし、キャプションをファイル名に変えます。

bool KSimpleEditor::fileSave()
{
    if( GfileName.isEmpty() ){
        return fileSaveAs();
    }
    QFile file( GfileName );
    if ( !file.open( IO_WriteOnly ) ){
        KMessageBox::sorry( this, i18n("Can not open file") );
        return false;
    }
    QTextStream ts( &file );
    ts << txtEdit->text();
    txtEdit->setModified( false );
    return true;
}

ファイル保存用の関数です。
ファイル名が無いときは名前を付けて保存し、保存が成功したときにtrueを返します。

bool KSimpleEditor::fileSaveAs()
{
    bool blRtn = false;
    GfileName = KFileDialog::getSaveFileName( QString::null, i18n( "*.txt|Text File (*.txt)\n*|All files" ), this );
    if( !GfileName.isEmpty() ) {
        blRtn = fileSave();
        setCaption( GfileName );
    }
    return blRtn;
}

名前を付けて保存用の関数です。
KFileDialogのgetSaveFileNameメソッドでファイル名を取り出しfileSave()を呼び出します。

bool KSimpleEditor::queryClose()
{
    return CheckChangedAndSaved();
}

×ボタンが押されたときにファイルが変更されているかチェックし、本当に閉じるかを返します。

追加情報

2003/11/03:Atsushi Odagiriさん...から以下のような指摘を受けました。

void KSimpleEditor::setupMenuBar()
{
    KAccel* accel = accel();
}

でコンパイルエラーが起き、

void KSimpleEditor::setupMenuBar()
{
    KAccel* accel = this->accel();
}

のように直すとコンパイルがとおります。

thisを書くのは気持ち悪いので変数名の方のaccelをaclに変更することで対処したいとおもいます。

void KSimpleEditor::setupMenuBar()
{
    KAccel* acl = accel();
}

のように変数名accelをaclに全て変更してください。
2003/11/09に配布ファイルの内容も修正しました。

Linux Life
プログラミング > C++ > KDE > KDEプログラミング入門 > KSimpleEditor > ksimpleeditor.cpp