KDE Application Tutorials: KScribble-1.0 Example Sourcecode

Next Previous Table of Contents

### 15. KScribble-1.0 Example Sourcecode

### 15.1 Project Tarball

The example tarball is locally installed and can be downloaded to your home directory, where you can untar it and test it. After untarring the tarball with `tar zxvf kscribble-1.0.tar.gz`, load the project and call "Automake and autoconf" from the "Build" menu in KDevelop, then call "./configure" from the same menu. The configure options are those of my installtion of the KDE 2 and Qt 2.1, so you have to change them manually to match your installation path for these options.

$(KDEDIR)/share/apps/kdevelop/examples/kscribble-1.0.tar.gz

### 15.2 main.cpp

    /***************************************************************************
                              main.cpp  -  description
                                 -------------------
        begin                : Mon Jan 31 11:05:05 CET 2000
        copyright            : (C) 2000 by Ralf Nolden
        email                : Ralf.Nolden@post.rwth-aachen.de
     ***************************************************************************/

    /***************************************************************************
     *                                                                         *
     *   This program is free software; you can redistribute it and/or modify  *
     *   it under the terms of the GNU General Public License as published by  *
     *   the Free Software Foundation; either version 2 of the License, or     *
     *   (at your option) any later version.                                   *
     *                                                                         *
     ***************************************************************************/
    #include <kcmdlineargs.h>
    #include <kaboutdata.h>
    #include <klocale.h>

    #include "kscribble.h"

    static const char *description =
       I18N_NOOP("KDE 2 example application");

    static KCmdLineOptions options[] =
    {
       {  "+[File]", I18N_NOOP("image file to open"), 0  },
       {  0, 0, 0  }
    };

    int main(int argc, char *argv[])
    {
       KAboutData aboutData( "kscribble", I18N_NOOP("KScribble"),
          VERSION, description, KAboutData::License_GPL,
          "(c) 2000, Ralf Nolden");
       aboutData.addAuthor("Ralf Nolden",0, "rnolden@kdevelop.de");
       KCmdLineArgs::init( argc, argv, &aboutData );
       KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.

       KApplication app;
       KImageIO::registerFormats();

       if (app.isRestored())
       {
          RESTORE(KScribbleApp);
       }
       else
       {
          KScribbleApp *kscribble = new KScribbleApp();
          kscribble->show();

          KCmdLineArgs *args = KCmdLineArgs::parsedArgs();

          if (args->count())
            for(int i=0;i<args->count();i++)
              kscribble->openDocumentFile(args->arg(i));
          else
            kscribble->openDocumentFile();

          args->clear();
       }

       return app.exec();
    }

### 15.3 kscribble.h

    /***************************************************************************
                              kscribble.h  -  description
                                 -------------------
        begin                : Mon Jan 31 11:05:05 CET 2000
        copyright            : (C) 2000 by Ralf Nolden
        email                : Ralf.Nolden@post.rwth-aachen.de
     ***************************************************************************/

    /***************************************************************************
     *                                                                         *
     *   This program is free software; you can redistribute it and/or modify  *
     *   it under the terms of the GNU General Public License as published by  *
     *   the Free Software Foundation; either version 2 of the License, or     *
     *   (at your option) any later version.                                   *
     *                                                                         *
     ***************************************************************************/

    #ifndef KSCRIBBLE_H
    #define KSCRIBBLE_H

    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif

    // include files for Qt
    #include <qstrlist.h>
    #include <qworkspace.h>

    // include files for KDE
    #include <kapp.h>
    #include <ktmainwindow.h>
    #include <kaccel.h>
    #include <kimgio.h>

    // forward declaration of the KScribble classes
    class KScribbleDoc;
    class KScribbleView;

    /**
      * The base class for KScribble application windows. It sets up the main
      * window and reads the config file as well as providing a menubar, toolbar
      * and statusbar. In initView(), your main view is created as the MDI child window manager.
      * Child windows are created in createClient(), which gets a document instance as it's document to
      * display whereby one document can have several views.The MDI child is an instance of KScribbleView,
      * the document an instance of KScribbleDoc.
      * KScribbleApp reimplements the methods that KTMainWindow provides for main window handling and supports
      * full session management as well as keyboard accelerator configuration by using KAccel.
      * @see KTMainWindow
      * @see KApplication
      * @see KConfig
      * @see KAccel
      *
      * @author Source Framework Automatically Generated by KDevelop, (c) The KDevelop Team.
      * @version KDevelop version 1.1 code generation
      */
    class KScribbleApp : public KTMainWindow
    {
      Q_OBJECT

      public:
        /** construtor of KScribbleApp, calls all init functions to create the application.
         *  @see initMenuBar initToolBar
         */
        KScribbleApp();
        ~KScribbleApp();
        /** enables menuentries/toolbar items
         */
        void enableCommand(int id_);
        /** disables menuentries/toolbar items
         */
        void disableCommand(int id_);
        /** opens a file specified by commandline option
         */
        void openDocumentFile(const char *file=0);

      protected:
        /** queryClose is called by KTMainWindow on each closeEvent of a window. Against the
         *  default implementation (only returns true), this overridden function retrieves all modified documents
         *  from the open document list and asks the user to select which files to save before exiting the application.
         *  @see KTMainWindow#queryClose
         *  @see KTMainWindow#closeEvent
         */
        virtual bool queryClose();
        /** queryExit is called by KTMainWindow when the last window of the application is going to be closed
         *  during the closeEvent().
         *  Against the default implementation that just returns true, this calls saveOptions() to save the
         *  settings of the last window's properties.
         *  @see KTMainWindow#queryExit
         *  @see KTMainWindow#closeEvent
         */
        virtual bool queryExit();
        /** saves the window properties for each open window during session end to the session config file,
         *  including saving the currently opened file by a temporary filename provided by KApplication.
         *  @see KTMainWindow#saveProperties
         */
        virtual void saveProperties(KConfig *_cfg);
        /** reads the session config file and restores the application's state including the last
         *  opened files and documents by reading the temporary files saved by saveProperties()
         *  @see KTMainWindow#readProperties
         */
        virtual void readProperties(KConfig *_cfg);
        /** event filter to catch close events for MDI child windows and is installed in createClient() on every
          * child window. Closing a window calls the eventFilter first which removes the view from the connected
          * documents' view list. If the last view is going to be closed, the eventFilter() tests if the document
          * is modified; if yes, it asks the user to save the document. If the document title contains "Untitled",
          * slotFileSaveAs() gets called to get a save name and path.
          */
        virtual bool eventFilter(QObject* object, QEvent* event);
        /** creates a new child window. The document that will be connected to it
         *  has to be created before and the instances filled, with e.g. openDocument().
         *  Then call createClient() to get a new MDI child window.
         *  @see KScribbleDoc#addView
         *  @see KScribbleDoc#openDocument
         *  @param doc pointer to the document instance that the view will
         *  be connected to.
         */
        void createClient(KScribbleDoc* doc);
        /** accepts drag events for images */
        virtual void dragEnterEvent( QDragEnterEvent* );
        /** accepts drops and opens a new document
         *  for each drop */
        virtual void dropEvent( QDropEvent* );

      private slots:
        /** sets the main application window title each time the active MDI child window changes. */
        void setWndTitle(QWidget*);
        /** switch argument for slot selection by menu or toolbar ID */
        void commandCallback(int id_);
        /** switch argument for Statusbar help entries on slot selection. Add your ID's help
         *  here for toolbars and menubar entries. */
        void statusCallback(int id_);
        /** add a opened file to the recent file list and update recent file menu*/
        void addRecentFile(const QString &file);
        /** clears the document in the actual view to reuse it as the new document */
        void slotFileNew();
        /** open a file and load it into the document*/
        void slotFileOpen();
        /** opens a file from the recent files menu */
        void slotFileOpenRecent(int id_);
        /** save a document */
        void slotFileSave();
        /** save a document by a new filename*/
        void slotFileSaveAs();
        /** asks for saving if the file is modified, then closes the actual file and window*/
        void slotFileClose();
        /** print the actual file */
        void slotFilePrint();
        /** closes all documents and quits the application.*/
        void slotFileQuit();
        /** reverts the last user action for the active window */
        void slotEditUndo();
        /** put the marked text/object into the clipboard and remove
         *  it from the document
         */
        void slotEditCut();
        /** put the marked text/object into the clipboard
         */
        void slotEditCopy();
        /** paste the clipboard into the document
         */
        void slotEditPaste();
        /** clears the current document */
        void slotEditClearAll();
        /** sets the pen width */
        void slotPenBrush();
        /** sets the pen color */
        void slotPenColor();
        /** toggles the toolbar
         */
        void slotViewToolBar();
        /** toggles the statusbar
         */
        void slotViewStatusBar();
        /** creates a new view for the document in the active child window and adds the new view to the
         * list of views the document maintains.
         */
        void slotWindowNewWindow();
        /** changes the statusbar contents for the standard label permanently, used to indicate current actions.
         * @param text the text that is displayed in the statusbar
         */
        void slotStatusMsg(const QString &text);
        /** changes the status message of the whole statusbar for two seconds, then restores the last status.
         * This is used to display statusbar messages that give information about actions for
         * toolbar icons and menuentries.
         * @param text the text that is displayed in the statusbar
         */
        void slotStatusHelpMsg(const QString &text);
        /** gets called when the window menu is activated; recreates the window menu with all opened window titles. */
        void windowMenuAboutToShow();
        /** activates the MDI child widget when it gets selected from the window menu. */
        void windowMenuActivated( int id );

      private:
        /** save general Options like all bar positions and status as well as the geometry and
         * the recent file list to the configuration file
         */
        void saveOptions();
        /** read general Options again and initialize all variables like the recent file list
         */
        void readOptions();
        /** initKeyAccel creates the keyboard accelerator items for the available slots and changes the menu accelerators.
         * @see KAccel
         */
        void initKeyAccel();
        /** initMenuBar creates the menubar and inserts the menupopups as well as creating the helpMenu.
         */
        void initMenuBar();
        /** this creates the toolbars.
         */
        void initToolBar();
        /** sets up the statusbar for the main window by initialzing a statuslabel.
         */
        void initStatusBar();

        /** Creates the main view of the KTMainWindow instance and initializes the MDI view area including any needed
         *  connections.
         */
        void initView();

        /** contains the recently used filenames */
        QStrList recentFiles;

        /** the configuration object of the application */
        KConfig *config;
        /** the key accelerator container */
        KAccel *keyAccel;
        /** the recent file menu containing the last five opened files */
        QPopupMenu *pRecentFileMenu;
        /** the file menu */
        QPopupMenu* pFileMenu;
        /** the edit menu */
        QPopupMenu* pEditMenu;
        /** the pen menu */
        QPopupMenu* pPenMenu;
        /** the view menu */
        QPopupMenu* pViewMenu;
        /** the window menu */
        QPopupMenu *pWindowMenu;
        /** pWorkspace is the MDI frame widget that handles MDI child widgets. Inititalized in
         * initView()
         */
        QWorkspace *pWorkspace;
        /** the printer instance */
        QPrinter *printer;
        /** a counter that gets increased each time the user creates a new document with "File"->"New" */
        int untitledCount;
        /** a list of all open documents. If the last window of a document gets closed, the installed eventFilter
         * removes this document from the list. The document list is checked for modified documents when the user
         * is about to close the application. */
        QList<KScribbleDoc> *pDocList;

    };

    #endif // KSCRIBBLE_H

### 15.4 kscribble.cpp

    /***************************************************************************
                              kscribble.cpp  -  description
                                 -------------------
        begin                : Mon Jan 31 11:05:05 CET 2000
        copyright            : (C) 2000 by Ralf Nolden
        email                : Ralf.Nolden@post.rwth-aachen.de
     ***************************************************************************/

    /***************************************************************************
     *                                                                         *
     *   This program is free software; you can redistribute it and/or modify  *
     *   it under the terms of the GNU General Public License as published by  *
     *   the Free Software Foundation; either version 2 of the License, or     *
     *   (at your option) any later version.                                   *
     *                                                                         *
     ***************************************************************************/

    // include files for QT
    #include <qdir.h>
    #include <qprinter.h>
    #include <qvbox.h>
    #include <qwhatsthis.h>
    #include <qtooltip.h>
    #include <qtoolbutton.h>
    #include <qimage.h>
    #include <qdragobject.h>

    // include files for KDE
    #include <kiconloader.h>
    #include <kmessagebox.h>
    #include <kfiledialog.h>
    #include <kcolordlg.h>
    #include <kmenubar.h>
    #include <klocale.h>
    #include <kconfig.h>

    // application specific includes
    #include "kscribble.h"
    #include "kscribbleview.h"
    #include "kscribbledoc.h"
    #include "resource.h"
    #include "kpenbrushdlg.h"

    KScribbleApp::KScribbleApp()
    {
      config=kapp->config();
      printer = new QPrinter;
      untitledCount=0;
      pDocList = new QList<KScribbleDoc>();
      pDocList->setAutoDelete(true);
      setAcceptDrops(true);

      ///////////////////////////////////////////////////////////////////
      // call inits to invoke all other construction parts
      initMenuBar();
      initToolBar();
      initStatusBar();
      initKeyAccel();
      initView();

      readOptions();

      ///////////////////////////////////////////////////////////////////
      // disable menu and toolbar items at startup
      disableCommand(ID_EDIT_UNDO);
    }

    KScribbleApp::~KScribbleApp()
    {
      delete printer;
    }

    void KScribbleApp::initKeyAccel()
    {
      keyAccel = new KAccel(this);

      // fileMenu accelerators
      keyAccel->connectItem(KStdAccel::New, this, SLOT(slotFileNew()));
      keyAccel->connectItem(KStdAccel::Open, this, SLOT(slotFileOpen()));
      keyAccel->connectItem(KStdAccel::Save, this, SLOT(slotFileSave()));
      keyAccel->connectItem(KStdAccel::Close, this, SLOT(slotFileClose()));
      keyAccel->connectItem(KStdAccel::Print, this, SLOT(slotFilePrint()));
      keyAccel->connectItem(KStdAccel::Quit, this, SLOT(slotFileQuit()));
      // editMenu accelerators
      keyAccel->connectItem(KStdAccel::Cut, this, SLOT(slotEditCut()));
      keyAccel->connectItem(KStdAccel::Copy, this, SLOT(slotEditCopy()));
      keyAccel->connectItem(KStdAccel::Paste, this, SLOT(slotEditPaste()));

      keyAccel->connectItem(KStdAccel::Help, this, SLOT(appHelpActivated()));

      keyAccel->changeMenuAccel(pFileMenu, ID_FILE_NEW, KStdAccel::New);
      keyAccel->changeMenuAccel(pFileMenu, ID_FILE_OPEN, KStdAccel::Open);
      keyAccel->changeMenuAccel(pFileMenu, ID_FILE_SAVE, KStdAccel::Save);
      keyAccel->changeMenuAccel(pFileMenu, ID_FILE_CLOSE, KStdAccel::Close);
      keyAccel->changeMenuAccel(pFileMenu, ID_FILE_PRINT, KStdAccel::Print);
      keyAccel->changeMenuAccel(pFileMenu, ID_FILE_QUIT, KStdAccel::Quit);

      keyAccel->changeMenuAccel(pEditMenu, ID_EDIT_CUT, KStdAccel::Cut);
      keyAccel->changeMenuAccel(pEditMenu, ID_EDIT_COPY, KStdAccel::Copy);
      keyAccel->changeMenuAccel(pEditMenu, ID_EDIT_PASTE, KStdAccel::Paste);

      keyAccel->readSettings();
    }

    void KScribbleApp::initMenuBar()
    {
      ///////////////////////////////////////////////////////////////////
      // MENUBAR
      pRecentFileMenu = new QPopupMenu(this);
      connect(pRecentFileMenu, SIGNAL(activated(int)), SLOT(slotFileOpenRecent(int)));

      ///////////////////////////////////////////////////////////////////
      // menuBar entry file-Menu
      pFileMenu = new QPopupMenu(this);
      pFileMenu->insertItem(BarIcon("filenew"), i18n("&New"), ID_FILE_NEW);
      pFileMenu->insertItem(BarIcon("fileopen"), i18n("&Open..."), ID_FILE_OPEN);
      pFileMenu->insertItem(i18n("Open &recent"), pRecentFileMenu, ID_FILE_OPEN_RECENT);

      pFileMenu->insertItem(i18n("&Close"), ID_FILE_CLOSE);
      pFileMenu->insertSeparator();
      pFileMenu->insertItem(BarIcon("filefloppy") ,i18n("&Save"), ID_FILE_SAVE);
      pFileMenu->insertItem(i18n("Save &As..."), ID_FILE_SAVE_AS);
      pFileMenu->insertSeparator();
      pFileMenu->insertItem(BarIcon("fileprint"), i18n("&Print..."), ID_FILE_PRINT);
      pFileMenu->insertSeparator();
      pFileMenu->insertItem(i18n("E&xit"), ID_FILE_QUIT);

      ///////////////////////////////////////////////////////////////////
      // menuBar entry edit-Menu
      pEditMenu = new QPopupMenu(this);
      pEditMenu->insertItem(BarIcon("undo"), i18n("&Undo"), ID_EDIT_UNDO);
      pEditMenu->insertSeparator();
      pEditMenu->insertItem(BarIcon("editcut"), i18n("Cu&t"), ID_EDIT_CUT);
      pEditMenu->insertItem(BarIcon("editcopy"), i18n("&Copy"), ID_EDIT_COPY);
      pEditMenu->insertItem(BarIcon("editpaste"), i18n("&Paste"), ID_EDIT_PASTE);
      pEditMenu->insertItem(BarIcon("delete"),i18n("&Clear All"), ID_EDIT_CLEAR_ALL);

      ///////////////////////////////////////////////////////////////////
      // menuBar entry pen-Menu
      pPenMenu = new QPopupMenu();
      pPenMenu->insertItem(i18n("&Color"), ID_PEN_COLOR);
      pPenMenu->insertItem(i18n("&Brush"), ID_PEN_BRUSH);

      ///////////////////////////////////////////////////////////////////
      // menuBar entry view-Menu
      pViewMenu = new QPopupMenu(this);
      pViewMenu->setCheckable(true);
      pViewMenu->insertItem(i18n("&Toolbar"), ID_VIEW_TOOLBAR);
      pViewMenu->insertItem(i18n("&Statusbar"), ID_VIEW_STATUSBAR);

      ///////////////////////////////////////////////////////////////////
      // menuBar entry window-Menu
      pWindowMenu = new QPopupMenu(this);
      pWindowMenu->setCheckable(true);

      ///////////////////////////////////////////////////////////////////
      // menuBar entry helpMenu
      QPopupMenu* pHelpMenu = helpMenu(i18n("KScribble" VERSION "\n\n(c) 2000 by\n"
                                      "Ralf Nolden\nRalf.Nolden@post.rwth-aachen.de"));

      ///////////////////////////////////////////////////////////////////
      // MENUBAR CONFIGURATION
      // insert your popup menus with the according menubar entries in the order
      // they will appear later from left to right
      menuBar()->insertItem(i18n("&File"), pFileMenu);
      menuBar()->insertItem(i18n("&Edit"), pEditMenu);
      menuBar()->insertItem(i18n("&Pen"), pPenMenu);
      menuBar()->insertItem(i18n("&View"), pViewMenu);
      menuBar()->insertItem(i18n("&Window"), pWindowMenu );
      menuBar()->insertItem(i18n("&Help"), pHelpMenu);

      ///////////////////////////////////////////////////////////////////
      // CONNECT THE MENU SLOTS WITH SIGNALS
      // for execution slots and statusbar messages
      connect(pFileMenu, SIGNAL(activated(int)), SLOT(commandCallback(int)));
      connect(pFileMenu, SIGNAL(highlighted(int)), SLOT(statusCallback(int)));

      connect(pEditMenu, SIGNAL(activated(int)), SLOT(commandCallback(int)));
      connect(pEditMenu, SIGNAL(highlighted(int)), SLOT(statusCallback(int)));

      connect(pPenMenu, SIGNAL(activated(int)), SLOT(commandCallback(int)));
      connect(pPenMenu, SIGNAL(highlighted(int)), SLOT(statusCallback(int)));

      connect(pViewMenu, SIGNAL(activated(int)), SLOT(commandCallback(int)));
      connect(pViewMenu, SIGNAL(highlighted(int)), SLOT(statusCallback(int)));

      connect(pWindowMenu, SIGNAL(aboutToShow() ), SLOT( windowMenuAboutToShow() ) );
      connect(pWindowMenu, SIGNAL(activated(int)), SLOT(commandCallback(int)));
      connect(pWindowMenu, SIGNAL(highlighted(int)), SLOT(statusCallback(int)));

    }

    void KScribbleApp::initToolBar()
    {

      ///////////////////////////////////////////////////////////////////
      // TOOLBAR
      toolBar()->insertButton(BarIcon("filenew"), ID_FILE_NEW, true, i18n("New File"));
      toolBar()->insertButton(BarIcon("fileopen"), ID_FILE_OPEN, true, i18n("Open File"));
      toolBar()->insertButton(BarIcon("filefloppy"), ID_FILE_SAVE, true, i18n("Save File"));
      toolBar()->insertButton(BarIcon("fileprint"), ID_FILE_PRINT, true, i18n("Print"));
      toolBar()->insertSeparator();
      toolBar()->insertButton(BarIcon("editcut"), ID_EDIT_CUT, true, i18n("Cut"));
      toolBar()->insertButton(BarIcon("editcopy"), ID_EDIT_COPY, true, i18n("Copy"));
      toolBar()->insertButton(BarIcon("editpaste"), ID_EDIT_PASTE, true, i18n("Paste"));
      toolBar()->insertSeparator();
      toolBar()->insertButton(BarIcon("pencolor"), ID_PEN_COLOR, true, i18n("Color") );
      toolBar()->insertButton(BarIcon("penwidth"), ID_PEN_BRUSH, true, i18n("Width") );
      toolBar()->insertSeparator();
      toolBar()->insertButton(BarIcon("help"), ID_HELP_CONTENTS, SIGNAL(clicked()),
              this, SLOT(appHelpActivated()), true,i18n("Help"));

      QToolButton *btnwhat = QWhatsThis::whatsThisButton(toolBar());
      QToolTip::add(btnwhat, i18n("What's this...?"));
      toolBar()->insertWidget(ID_HELP_WHATS_THIS, btnwhat->sizeHint().width(), btnwhat);

      ///////////////////////////////////////////////////////////////////
      // INSERT YOUR APPLICATION SPECIFIC TOOLBARS HERE WITH toolBar(n)

      ///////////////////////////////////////////////////////////////////
      // CONNECT THE TOOLBAR SLOTS WITH SIGNALS - add new created toolbars by their according number
      // connect for invoking the slot actions
      connect(toolBar(), SIGNAL(clicked(int)), SLOT(commandCallback(int)));
      // connect for the status help on holing icons pressed with the mouse button
      connect(toolBar(), SIGNAL(pressed(int)), SLOT(statusCallback(int)));

    }

    void KScribbleApp::initStatusBar()
    {
      ///////////////////////////////////////////////////////////////////
      // STATUSBAR
      // TODO: add your own items you need for displaying current application status.
      statusBar()->insertItem(i18n("Ready."), ID_STATUS_MSG);
    }

    void KScribbleApp::initView()
    {
      ////////////////////////////////////////////////////////////////////
      // here the main view of the KTMainWindow is created by a background box and
      // the QWorkspace instance for MDI view.
      QVBox* view_back = new QVBox( this );
      view_back->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken );
      pWorkspace = new QWorkspace( view_back );
      connect(pWorkspace, SIGNAL(windowActivated(QWidget*)), this, SLOT(setWndTitle(QWidget*)));
      setView(view_back);
    }

    void KScribbleApp::setWndTitle(QWidget*){
      setCaption(pWorkspace->activeWindow()->caption());
    }

    void KScribbleApp::enableCommand(int id_)
    {
      ///////////////////////////////////////////////////////////////////
      // enable menu and toolbar functions by their ID's
      menuBar()->setItemEnabled(id_, true);
      toolBar()->setItemEnabled(id_, true);
    }

    void KScribbleApp::disableCommand(int id_)
    {
      ///////////////////////////////////////////////////////////////////
      // disable menu and toolbar functions by their ID's
      menuBar()->setItemEnabled(id_, false);
      toolBar()->setItemEnabled(id_, false);
    }

    void KScribbleApp::addRecentFile(const QString &file)
    {
      if(recentFiles.contains(file))
        return; // it's already there

      if( recentFiles.count() < 5)
        recentFiles.prepend(file);
      else{
        recentFiles.remove(recentFiles.last());
        recentFiles.prepend(file);
      }

      pRecentFileMenu->clear();

      for ( int i =0 ; i < (int)recentFiles.count(); i++){
        pRecentFileMenu->insertItem(recentFiles.at(i));
      }

    }

    void KScribbleApp::createClient(KScribbleDoc* doc)
    {
      KScribbleView* w = new KScribbleView(doc, pWorkspace,0,WDestructiveClose);
      w->installEventFilter(this);
      doc->addView(w);
      w->setIcon(kapp->miniIcon());
      if ( pWorkspace->windowList().isEmpty() ) // show the very first window in maximized mode
        w->showMaximized();
      else
        w->show();
    }

    void KScribbleApp::openDocumentFile(const char* file)
    {
      slotStatusMsg(i18n("Opening file..."));
      KScribbleDoc* doc;
      // check, if document already open. If yes, set the focus to the first view
      for(doc=pDocList->first(); doc > 0; doc=pDocList->next())
      {
        if(doc->pathName()==file)
        {
           KScribbleView* view=doc->firstView();
           view->setFocus();
           return;
         }
      }
      doc = new KScribbleDoc();
      pDocList->append(doc);
      doc->newDocument();
      // Creates an untitled window if file is 0
      if(!file)
      {
        untitledCount+=1;
        QString fileName=QString(i18n("Untitled%1")).arg(untitledCount);
        doc->setPathName(fileName);
        doc->setTitle(fileName);
      }
      // Open the file
      else
      {
        QString format=QImageIO::imageFormat(file);
        if(!doc->openDocument(file,format))
          KMessageBox::error (this,i18n("Could not open document !"), i18n("Error !"));
        addRecentFile(file);
      }
      // create the window
      createClient(doc);

      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::saveOptions()
    {
      config->setGroup("General Options");
      config->writeEntry("Geometry", size());
      config->writeEntry("Show Toolbar", toolBar()->isVisible());
      config->writeEntry("Show Statusbar",statusBar()->isVisible());
      config->writeEntry("ToolBarPos", (int) toolBar()->barPos());
      config->writeEntry("Recent Files", recentFiles);
    }

    void KScribbleApp::readOptions()
    {

      config->setGroup("General Options");

      // bar status settings
      bool bViewToolbar = config->readBoolEntry("Show Toolbar", true);
      menuBar()->setItemChecked(ID_VIEW_TOOLBAR, bViewToolbar);
      if(!bViewToolbar)
      {
         enableToolBar(KToolBar::Hide);
      }

      bool bViewStatusbar = config->readBoolEntry("Show Statusbar", true);
      menuBar()->setItemChecked(ID_VIEW_STATUSBAR, bViewStatusbar);
      if(!bViewStatusbar)
      {
        enableStatusBar(KStatusBar::Hide);
      }

      // bar position settings
      KToolBar::BarPosition toolBarPos;
      toolBarPos=(KToolBar::BarPosition) config->readNumEntry("ToolBarPos", KToolBar::Top);
      toolBar()->setBarPos(toolBarPos);

      // initialize the recent file list
      config->readListEntry("Recent Files",recentFiles);

      for (int i=0; i < (int) recentFiles.count(); i++)
      {
        pRecentFileMenu->insertItem(recentFiles.at(i));
      }

      QSize size=config->readSizeEntry("Geometry");
      if(!size.isEmpty())
      {
        resize(size);
      }
      else
        resize(400,350);

    }

    void KScribbleApp::saveProperties(KConfig *_cfg)
    {

    }

    void KScribbleApp::readProperties(KConfig* _cfg)
    {
    }

    bool KScribbleApp::queryClose()
    {

      QStringList saveFiles;
      KScribbleDoc* doc;
      if(pDocList->isEmpty())
        return true;

      for(doc=pDocList->first(); doc!=0;doc=pDocList->next()){
        if(doc->isModified())
          saveFiles.append(doc->title());
      }
      if(saveFiles.isEmpty())
        return true;

      switch (KMessageBox::questionYesNoList(this,
          i18n("One or more documents have been modified.\nSave changes before exiting?"),saveFiles))
      {
        case KMessageBox::Yes:
          for(doc=pDocList->first(); doc!=0;doc=pDocList->next()){
            if(doc->title().contains(i18n("Untitled")))
              slotFileSaveAs();
            else
            {
              if(!doc->saveDocument(doc->pathName())){
                KMessageBox::error (this,i18n("Could not save the current document !"), i18n("I/O Error !"));
                return false;
              }
            }
           }
          return true;
        case KMessageBox::No:
        default:
          return true;
      }
    }

    bool KScribbleApp::queryExit()
    {
      saveOptions();
      return true;
    }

    bool KScribbleApp::eventFilter(QObject* object, QEvent* event){
      if(event->type() == QEvent::Close)
      {
        QCloseEvent* e=(QCloseEvent*)event;
        KScribbleView* pView=(KScribbleView*)object;
        KScribbleDoc* pDoc=pView->getDocument();
        if(pDoc->canCloseFrame(pView))
        {
           pDoc->removeView(pView);
           if(!pDoc->firstView())
             pDocList->remove(pDoc);

          e->accept();
          //////////////
          if(pWorkspace->windowList().count()==1)
            setPlainCaption(kapp->caption());
          else
            setCaption(pWorkspace->activeWindow()->caption());
          //////////////
        }
        else
          e->ignore();
      }
      return QWidget::eventFilter( object, event );    // standard event processing
    }

    /////////////////////////////////////////////////////////////////////
    // SLOT IMPLEMENTATION
    /////////////////////////////////////////////////////////////////////

    void KScribbleApp::slotFileNew()
    {
      slotStatusMsg(i18n("Creating new document..."));

      openDocumentFile();

      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotFileOpen()
    {
      slotStatusMsg(i18n("Opening file..."));

      QString fileToOpen=KFileDialog::getOpenFileName(QDir::currentDirPath(),
                KImageIO::pattern(KImageIO::Reading), this, i18n("Open File..."));
      if(!fileToOpen.isEmpty())
      {
        openDocumentFile(fileToOpen);
      }

      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotFileOpenRecent(int id_)
    {
      slotStatusMsg(i18n("Opening file..."));

      openDocumentFile(pRecentFileMenu->text(id_));

      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotFileSave()
    {
      slotStatusMsg(i18n("Saving file..."));
      KScribbleView* m = (KScribbleView*)pWorkspace->activeWindow();
      if( m )
      {
        KScribbleDoc* doc =  m->getDocument();
        if(doc->title().contains(i18n("Untitled")))
         slotFileSaveAs();
        else
          if(!doc->saveDocument(doc->pathName()))
            KMessageBox::error (this,i18n("Could not save the current document !"), i18n("I/O Error !"));
      }

      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotFileSaveAs()
    {
      slotStatusMsg(i18n("Saving file with a new filename..."));

      QString newName=KFileDialog::getSaveFileName(QDir::currentDirPath(),
                                   KImageIO::pattern(KImageIO::Writing), this, i18n("Save as..."));
      if(!newName.isEmpty())
      {
        KScribbleView* m = (KScribbleView*)pWorkspace->activeWindow();
        if( m )
        {
          KScribbleDoc* doc =  m->getDocument();
          QString format=QFileInfo(newName).extension();
          format=format.upper();
          if(!doc->saveDocument(newName,format))
          {
            KMessageBox::error (this,i18n("Could not save the current document !"), i18n("I/O Error !"));
            return;
          }
          doc->changedViewList();
          setWndTitle(m);
        }

      }

      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotFileClose()
    {
      slotStatusMsg(i18n("Closing file..."));

      KScribbleView* m = (KScribbleView*)pWorkspace->activeWindow();
      if( m )
      {
        KScribbleDoc* doc=m->getDocument();
        doc->closeDocument();
      }

      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotFilePrint()
    {
      slotStatusMsg(i18n("Printing..."));

      KScribbleView* m = (KScribbleView*) pWorkspace->activeWindow();
      if ( m )
        m->print( printer );

      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotFileQuit()
    {
      slotStatusMsg(i18n("Exiting..."));
      saveOptions();
      // close the first window, the list makes the next one the first again.
      // This ensures that queryClose() is called on each window to ask for closing
      KTMainWindow* w;
      if(memberList)
      {
        for(w=memberList->first(); w!=0; w=memberList->first())
        {
          // only close the window if the closeEvent is accepted. If the user
          // presses Cancel on the saveModified() dialog,
          // the window and the application stay open.
          if(!w->close())
          break;
        }
      }
      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotEditUndo()
    {
      slotStatusMsg(i18n("Reverting last action..."));

      KScribbleView* m = (KScribbleView*) pWorkspace->activeWindow();
      if ( m )
    //    m->undo();

      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotEditCut()
    {
      slotStatusMsg(i18n("Cutting selection..."));

      KScribbleView* m = (KScribbleView*) pWorkspace->activeWindow();
      if ( m )
        m->cutSelection();

      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotEditCopy()
    {
      slotStatusMsg(i18n("Copying selection to clipboard..."));

      KScribbleView* m = (KScribbleView*) pWorkspace->activeWindow();
      if ( m )
        m->copySelection();

      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotEditPaste()
    {
      slotStatusMsg(i18n("Inserting clipboard contents..."));

      KScribbleView* m = (KScribbleView*) pWorkspace->activeWindow();
      if ( m )
        m->pasteSelection();

      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotEditClearAll()
    {
      slotStatusMsg(i18n("Clearing the document contents..."));

      KScribbleView* m = (KScribbleView*) pWorkspace->activeWindow();
      if ( m ){
        KScribbleDoc* pDoc = m->getDocument();
        pDoc->editClearAll();
      }
      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotPenBrush()
    {
      slotStatusMsg(i18n("Setting brush width..."));

      // get one window with document for a current pen width
      QWidgetList windows = pWorkspace->windowList();
      KScribbleView* m = (KScribbleView*)windows.at(0);
      KScribbleDoc* pDoc = m->getDocument();
      int curr_width=pDoc->penWidth();

      // create the dialog, get the new width and set the pen width for all documents
      KPenBrushDlg* dlg= new KPenBrushDlg(curr_width,this);
      if(dlg->exec()){
        int width=dlg->width();
        for ( int i = 0; i < int(windows.count()); ++i )
        {
          m = (KScribbleView*)windows.at(i);
          if ( m )
          {
            pDoc = m->getDocument();
            pDoc->setPenWidth(width);
          }
        }
      }
      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotPenColor()
    {
      slotStatusMsg(i18n("Selecting pen color..."));

      QColor myColor;
      int result = KColorDialog::getColor( myColor, this );
      if ( result == KColorDialog::Accepted )
      {
        QWidgetList windows = pWorkspace->windowList();
        KScribbleDoc* pDoc;
        KScribbleView* m;
        for ( int i = 0; i < int(windows.count()); ++i )
        {
          m = (KScribbleView*)windows.at(i);
          if ( m )
          {
            pDoc = m->getDocument();
            pDoc->setPenColor(myColor);
          }
        }
      }
      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotViewToolBar()
    {
      slotStatusMsg(i18n("Toggle the toolbar..."));
      ///////////////////////////////////////////////////////////////////
      // turn Toolbar on or off
      if( menuBar()->isItemChecked(ID_VIEW_TOOLBAR))
      {
        menuBar()->setItemChecked(ID_VIEW_TOOLBAR, false);
        enableToolBar(KToolBar::Hide);
      }
      else
      {
        menuBar()->setItemChecked(ID_VIEW_TOOLBAR, true);
        enableToolBar(KToolBar::Show);
      }

      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotViewStatusBar()
    {
      slotStatusMsg(i18n("Toggle the statusbar..."));
      ///////////////////////////////////////////////////////////////////
      //turn Statusbar on or off
      if( menuBar()->isItemChecked(ID_VIEW_STATUSBAR))
      {
        menuBar()->setItemChecked(ID_VIEW_STATUSBAR, false);
        enableStatusBar(KStatusBar::Hide);
      }
      else
      {
        menuBar()->setItemChecked(ID_VIEW_STATUSBAR, true);
        enableStatusBar(KStatusBar::Show);
      }

      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotWindowNewWindow()
    {
      slotStatusMsg(i18n("Opening a new application window..."));

      KScribbleView* m = (KScribbleView*) pWorkspace->activeWindow();
      if ( m ){
         KScribbleDoc* doc = m->getDocument();
        createClient(doc);
      }

      slotStatusMsg(i18n("Ready."));
    }

    void KScribbleApp::slotStatusMsg(const QString &text)
    {
      ///////////////////////////////////////////////////////////////////
      // change status message permanently
      statusBar()->clear();
      statusBar()->changeItem(text, ID_STATUS_MSG);
    }

    void KScribbleApp::slotStatusHelpMsg(const QString &text)
    {
      ///////////////////////////////////////////////////////////////////
      // change status message of whole statusbar temporary (text, msec)
      statusBar()->message(text, 2000);
    }

    void KScribbleApp::windowMenuAboutToShow()
    {
      pWindowMenu->clear();

      pWindowMenu->insertItem(i18n("&New Window"), ID_WINDOW_NEW_WINDOW);
      pWindowMenu->insertItem(i18n("&Cascade"),
                              pWorkspace, SLOT(cascade() ),0 , ID_WINDOW_CASCADE );
      pWindowMenu->insertItem(i18n("&Tile"),
                              pWorkspace, SLOT(tile() ),0 , ID_WINDOW_TILE );

      if ( pWorkspace->windowList().isEmpty() ) {
        disableCommand(ID_WINDOW_NEW_WINDOW);
        disableCommand(ID_WINDOW_CASCADE);
        disableCommand(ID_WINDOW_TILE);
      }

      pWindowMenu->insertSeparator();

      QWidgetList windows = pWorkspace->windowList();
      for ( int i = 0; i < int(windows.count()); ++i ) {
        int id = pWindowMenu->insertItem(QString("&%1 ").arg(i+1)+windows.at(i)->caption(),
                                         this, SLOT( windowMenuActivated( int ) ) );
        pWindowMenu->setItemParameter( id, i );
        pWindowMenu->setItemChecked( id, pWorkspace->activeWindow() == windows.at(i) );
      }
    }

    void KScribbleApp::windowMenuActivated( int id )
    {
      QWidget* w = pWorkspace->windowList().at( id );
      if ( w )
        w->setFocus();
    }

    void KScribbleApp::commandCallback(int id_)
    {
      switch (id_)
      {
        case ID_FILE_NEW:
           slotFileNew();
             break;

        case ID_FILE_OPEN:
             slotFileOpen();
             break;

        case ID_FILE_SAVE:
             slotFileSave();
             break;

        case ID_FILE_SAVE_AS:
             slotFileSaveAs();
             break;

        case ID_FILE_CLOSE:
             slotFileClose();
             break;

        case ID_FILE_PRINT:
             slotFilePrint();
             break;

        case ID_FILE_QUIT:
             slotFileQuit();
             break;

        case ID_EDIT_CUT:
             slotEditCut();
             break;

        case ID_EDIT_COPY:
             slotEditCopy();
             break;

        case ID_EDIT_PASTE:
             slotEditPaste();
             break;

        case ID_EDIT_CLEAR_ALL:
             slotEditClearAll();
             break;

        case ID_PEN_BRUSH:
             slotPenBrush();
             break;

        case ID_PEN_COLOR:
             slotPenColor();
             break;

        case ID_VIEW_TOOLBAR:
             slotViewToolBar();
             break;

        case ID_VIEW_STATUSBAR:
             slotViewStatusBar();
             break;

        case ID_WINDOW_NEW_WINDOW:
             slotWindowNewWindow();
           break;

        default:
             break;
      }
    }

    void KScribbleApp::statusCallback(int id_)
    {
      switch (id_)
      {
        case ID_FILE_NEW:
             slotStatusHelpMsg(i18n("Creates a new document"));
             break;

        case ID_FILE_OPEN:
             slotStatusHelpMsg(i18n("Opens an existing document"));
             break;

        case ID_FILE_OPEN_RECENT:
             slotStatusHelpMsg(i18n("Opens a recently used file"));
             break;

        case ID_FILE_SAVE:
             slotStatusHelpMsg(i18n("Saves the currently active document"));
             break;

        case ID_FILE_SAVE_AS:
             slotStatusHelpMsg(i18n("Saves the currently active document as under a new filename"));
             break;

        case ID_FILE_CLOSE:
             slotStatusHelpMsg(i18n("Closes the currently active document"));
             break;

        case ID_FILE_PRINT:
             slotStatusHelpMsg(i18n("Prints out the actual document"));
             break;

        case ID_FILE_QUIT:
             slotStatusHelpMsg(i18n("Quits the application"));
             break;

        case ID_EDIT_UNDO:
             slotStatusHelpMsg(i18n("Reverts the last editing action"));
             break;

        case ID_EDIT_CUT:
             slotStatusHelpMsg(i18n("Cuts the selected section and puts it to the clipboard"));
             break;

        case ID_EDIT_COPY:
             slotStatusHelpMsg(i18n("Copies the selected section to the clipboard"));
             break;

        case ID_EDIT_PASTE:
             slotStatusHelpMsg(i18n("Pastes the clipboard contents to actual position"));
             break;

        case ID_EDIT_CLEAR_ALL:
             slotStatusHelpMsg(i18n("Clears the document contents"));
             break;

        case ID_PEN_BRUSH:
             slotStatusHelpMsg(i18n("Sets the pen width"));
             break;

        case ID_PEN_COLOR:
             slotStatusHelpMsg(i18n("Sets the current pen color"));
             break;

        case ID_VIEW_TOOLBAR:
             slotStatusHelpMsg(i18n("Enables/disables the toolbar"));
             break;

        case ID_VIEW_STATUSBAR:
             slotStatusHelpMsg(i18n("Enables/disables the statusbar"));
             break;

        case ID_WINDOW_NEW_WINDOW:
             slotStatusHelpMsg(i18n("Opens a new view for the current document"));
             break;

        case ID_WINDOW_CASCADE:
             slotStatusHelpMsg(i18n("Cascades all windows"));
             break;

        case ID_WINDOW_TILE:
             slotStatusHelpMsg(i18n("Tiles all windows"));
             break;

        default:
             break;
      }
    }
    /** accepts drops and opens a new document
    for each drop */
    void KScribbleApp::dropEvent( QDropEvent* e){

      QImage img;
      if ( QImageDrag::decode(e, img) )
      {
        KScribbleDoc* doc = new KScribbleDoc();
        untitledCount+=1;
        QString fileName=QString(i18n("Untitled%1")).arg(untitledCount);
        doc->setPathName(fileName);
        doc->setTitle(fileName);
        doc->newDocument();
        pDocList->append(doc);
        KPixmap tmp;
        tmp.resize(img.size());
        tmp.convertFromImage(img);
        doc->setPixmap(tmp);
        doc->resizeDocument(tmp.size());
        doc->setModified();
        createClient(doc);
      }
    }
    /** accepts drag events for images */
    void KScribbleApp::dragEnterEvent( QDragEnterEvent* e){
      e->accept(QImageDrag::canDecode(e));
    }

### 15.5 kscribbledoc.h

    /***************************************************************************
                              kscribbledoc.h  -  description
                                 -------------------
        begin                : Mon Jan 31 11:05:05 CET 2000
        copyright            : (C) 2000 by Ralf Nolden
        email                : Ralf.Nolden@post.rwth-aachen.de
     ***************************************************************************/

    /***************************************************************************
     *                                                                         *
     *   This program is free software; you can redistribute it and/or modify  *
     *   it under the terms of the GNU General Public License as published by  *
     *   the Free Software Foundation; either version 2 of the License, or     *
     *   (at your option) any later version.                                   *
     *                                                                         *
     ***************************************************************************/

    #ifndef KSCRIBBLEDOC_H
    #define KSCRIBBLEDOC_H

    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif

    // include files for QT
    #include <qobject.h>
    #include <qstring.h>
    #include <qlist.h>

    #include <qsize.h>
    #include <qpen.h>
    #include <qpoint.h>
    //#include <qpixmap.h>
    #include <qpointarray.h>

    #include <kpixmap.h>

    // forward declaration of the KScribble classes
    class KScribbleView;

    /**  KScribbleDoc provides a document object for a document-view model.
      *
      * The KScribbleDoc class provides a document object that can be used in conjunction with the classes
      * KScribbleApp and KScribbleView to create a document-view model for MDI (Multiple Document Interface)
      * KDE 2 applications based on KApplication and KTMainWindow as main classes and QWorkspace as MDI manager widget.
      * Thereby, the document object is created by the KScribbleApp instance (and kept in a document list) and contains
      * the document structure with the according methods for manipulating the document
      * data by KScribbleView objects. Also, KScribbleDoc contains the methods for serialization of the document data
      * from and to files.
      * @author Source Framework Automatically Generated by KDevelop, (c) The KDevelop Team.
      * @version KDevelop version 1.1 code generation
      */
    class KScribbleDoc : public QObject
    {
      Q_OBJECT

      friend KScribbleView;

      public:
        /** Constructor for the fileclass of the application */
        KScribbleDoc();
        /** Destructor for the fileclass of the application */
        ~KScribbleDoc();

        /** adds a view to the document which represents the document contents. Usually this is your main view. */
        void addView(KScribbleView *view);
        /** removes a view from the list of currently connected views */
        void removeView(KScribbleView *view);
        /** gets called if a view is removed or added */
        void changedViewList();
        /** returns the first view instance */
        KScribbleView* firstView(){ return pViewList->first(); };
        /** returns true, if the requested view is the last view of the document */
        bool isLastView();
        /** This method gets called when the user is about to close a frame window. It checks, if more than one view
         * is connected to the document (then the frame can be closed), if pFrame is the last view and the document is
         * modified, the user gets asked if he wants to save the document.
         */
        bool canCloseFrame(KScribbleView* pFrame);
        /** sets the modified flag for the document after a modifying action on the view connected to the document.*/
        void setModified(bool _m=true){ modified=_m; };
        /** returns if the document is modified or not. Use this to determine if your document needs
         * saving by the user on closing.
         */
        bool isModified(){ return modified; };
        /** deletes the document's contents */
        void deleteContents();
        /** initializes the document generally */
        bool newDocument();
        /** closes the acutal document */
        void closeDocument();
        /** loads the document by filename and format and emits the updateViews() signal */
        bool openDocument(const QString &filename, const char *format=0);
        /** saves the document under filename and format.*/
        bool saveDocument(const QString &filename, const char *format=0);
        /** sets the path to the file connected with the document */
        void setPathName(const QString &name);
        /** returns the pathname of the current document file*/
        const QString& pathName() const;

        /** sets the filename of the document */
        void setTitle(const QString &title);
        /** returns the title of the document */
        const QString& title() const;
        /** get the current Pen */
        const QPen currentPen(){ return pen;};
        /** returns the pen width */
        const int penWidth() { return pen.width(); }
        /** returns the pen color */
        const QColor penColor(){ return pen.color(); }
        /** sets the pen width */
        void setPenWidth( int w ){ pen.setWidth( w ); }
        /** sets the pen color */
        void setPenColor( const QColor &c ){ pen.setColor( c ); }
        /** sets the pen style by a second toolbar */
        void setPenStyle( PenStyle s){ pen.setStyle(s);}
        /** clears the document contents */
        void editClearAll();

        /** get the document size */
        const QSize docSize(){ return size;};
        /** sets the pixmap contents. Used by KScribbleApp
        to create a new document by drop events */
        void setPixmap(KPixmap pix) { buffer=pix;};
        void resizeDocument(QSize m_size) { size=m_size; };
      public slots:
        /** calls repaint() on all views connected to the document object and is called by the view by
         * which the document has been changed.
         * As this view normally repaints itself, it is excluded from the paintEvent.
         */
        void updateAllViews(KScribbleView *sender);

      protected:

        QPen pen;
        QPointArray polyline;
        KPixmap buffer;

      private:
        /** the modified flag of the current document */
        bool modified;
        QString m_title;
        QString m_filename;
        /** the list of the views currently connected to the document */
        QList<KScribbleView> *pViewList;
        QSize size;
    };

    #endif // KSCRIBBLEDOC_H

### 15.6 kscribbledoc.cpp

    /***************************************************************************
                              kscribbledoc.cpp  -  description
                                 -------------------
        begin                : Mon Jan 31 11:05:05 CET 2000
        copyright            : (C) 2000 by Ralf Nolden
        email                : Ralf.Nolden@post.rwth-aachen.de
     ***************************************************************************/

    /***************************************************************************
     *                                                                         *
     *   This program is free software; you can redistribute it and/or modify  *
     *   it under the terms of the GNU General Public License as published by  *
     *   the Free Software Foundation; either version 2 of the License, or     *
     *   (at your option) any later version.                                   *
     *                                                                         *
     ***************************************************************************/

    // include files for Qt
    #include <qdir.h>
    #include <qfileinfo.h>
    #include <qwidget.h>

    // include files for KDE
    #include <klocale.h>
    #include <kmessagebox.h>
    #include <kfiledialog.h>

    // application specific includes
    #include "kscribbledoc.h"
    #include "kscribble.h"
    #include "kscribbleview.h"

    KScribbleDoc::KScribbleDoc()
    {
      pViewList = new QList<KScribbleView>;
      pViewList->setAutoDelete(false);
    }

    KScribbleDoc::~KScribbleDoc()
    {
      delete pViewList;
    }

    void KScribbleDoc::addView(KScribbleView *view)
    {
      pViewList->append(view);
      changedViewList();
    }

    void KScribbleDoc::removeView(KScribbleView *view)
    {
        pViewList->remove(view);
        if(!pViewList->isEmpty())
          changedViewList();
        else
          deleteContents();
    }

    void KScribbleDoc::changedViewList(){

      KScribbleView *w;
      if((int)pViewList->count() == 1){
        w=pViewList->first();
        w->setCaption(m_title);
      }
      else{
        int i;
        for( i=1,w=pViewList->first(); w!=0; i++, w=pViewList->next())
          w->setCaption(QString(m_title+":%1").arg(i));
      }
    }

    bool KScribbleDoc::isLastView() {
      return ((int) pViewList->count() == 1);
    }

    void KScribbleDoc::updateAllViews(KScribbleView *sender)
    {
      KScribbleView *w;
      for(w=pViewList->first(); w!=0; w=pViewList->next())
      {
          w->update(sender);
      }

    }

    void KScribbleDoc::setPathName(const QString &name)
    {
      m_filename=name;
      m_title=QFileInfo(name).fileName();
    }

    const QString& KScribbleDoc::pathName() const
    {
      return m_filename;
    }

    void KScribbleDoc::setTitle(const QString &title)
    {
      m_title=title;
    }

    const QString &KScribbleDoc::title() const
    {
      return m_title;
    }

    void KScribbleDoc::closeDocument()
    {
      KScribbleView *w;
      if(!isLastView())
      {
        for(w=pViewList->first(); w!=0; w=pViewList->next())
        {
            if(!w->close())
             break;
        }
      }
      if(isLastView())
      {
        w=pViewList->first();
        w->close();
      }
    }

    bool KScribbleDoc::newDocument()
    {
      /////////////////////////////////////////////////
      // TODO: Add your document initialization code here
      size=QSize(300,200 );
      pen=QPen( Qt::black, 3 );
      polyline=QPointArray(3);
      buffer.resize(size);
      buffer.fill( Qt::white );
      /////////////////////////////////////////////////
      modified=false;
      return true;
    }

    bool KScribbleDoc::openDocument(const QString &filename, const char *format /*=0*/)
    {

      QFile f( filename );
    //  if ( !f.open( IO_ReadOnly ) )
    //    return false;
      /////////////////////////////////////////////////
      // TODO: Add your document opening code here
      if(!buffer.load( filename, format ))
        return false;
      size=buffer.size();
      /////////////////////////////////////////////////
    //  f.close();

      modified=false;
      m_filename=filename;
      m_title=QFileInfo(f).fileName();
      return true;
    }

    bool KScribbleDoc::saveDocument(const QString &filename, const char *format /*=0*/)
    {
      QFile f( filename );
    //  if ( !f.open( IO_WriteOnly ) )
    //    return false;

      /////////////////////////////////////////////////
      // TODO: Add your document saving code here
      if(!buffer.save( filename, format ))
        return false;
      /////////////////////////////////////////////////

    //  f.close();

      modified=false;
      m_filename=filename;
      m_title=QFileInfo(f).fileName();
      return true;
    }

    void KScribbleDoc::deleteContents()
    {
      /////////////////////////////////////////////////
      // TODO: Add implementation to delete the document contents
      buffer.fill( Qt::white );
      /////////////////////////////////////////////////

    }

    bool KScribbleDoc::canCloseFrame(KScribbleView* pFrame)
    {
      if(!isLastView())
        return true;

      bool ret=false;
      if(isModified())
      {
        QString saveName;
        switch(KMessageBox::warningYesNoCancel(pFrame, i18n("The current file has been modified.\n"
        "Do you want to save it?"),title()))
        {
        case KMessageBox::Yes:
          if(title().contains(i18n("Untitled")))
          {
            saveName=KFileDialog::getSaveFileName(QDir::currentDirPath(),
                                 i18n("*|All files"), pFrame, i18n("Save as..."));
            if(saveName.isEmpty())
            return false;
          }
          else
           saveName=pathName();

          if(!saveDocument(saveName))
          {
            switch(KMessageBox::warningYesNo(pFrame,i18n("Could not save the current document !\n"
                              "Close anyway ?"), i18n("I/O Error !")))
            {
              case KMessageBox::Yes:
                ret=true;
              case KMessageBox::No:
                ret=false;
            }
          }
          else
            ret=true;
            break;
        case KMessageBox::No:
          ret=true;
          break;
        case KMessageBox::Cancel:
        default:
          ret=false;
          break;
        }
      }
      else
        ret=true;

      return ret;
    }

    void KScribbleDoc::editClearAll()
    {
      deleteContents();
      setModified();
      updateAllViews(0);
    }

### 15.7 kscribbleview.h

    /***************************************************************************
                              kscribbleview.h  -  description
                                 -------------------
        begin                : Mon Jan 31 11:05:05 CET 2000
        copyright            : (C) 2000 by Ralf Nolden
        email                : Ralf.Nolden@post.rwth-aachen.de
     ***************************************************************************/

    /***************************************************************************
     *                                                                         *
     *   This program is free software; you can redistribute it and/or modify  *
     *   it under the terms of the GNU General Public License as published by  *
     *   the Free Software Foundation; either version 2 of the License, or     *
     *   (at your option) any later version.                                   *
     *                                                                         *
     ***************************************************************************/

    #ifndef KSCRIBBLEVIEW_H
    #define KSCRIBBLEVIEW_H

    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif

    // include files for Qt
    #include <qscrollview.h>
    #include <kpixmap.h>

    class KScribbleDoc;

    /** The KScribbleView class provides the view widget for the document instance connected to it and is displayed
     * as a MDI child window in the main view area of the KScribbleApp class instance. The KScribbleApp
     * class also has an eventFilter()  method that gets installed on every KScribbleView instance to
     * control events of the type QEvent::Close.The document connected to the view instance keeps a list
     * of all view that represent the document contents as there can be more than one view. Views get created in
     * KScribbleApp::createClient() and automatically added to the list of views.
     * The KScribbleView class inherits QWidget as a base. Another possible inheritance besides specialized
     + widgets could be QMainWindow so that you can easily set up the main area of your view by setting another view
     * as main widget (QMainWindow::setMainWidget() ).
     * NOTE: The close event always has to be empty (DON`T CALL QWidget::closeEvent(e) in closeEvent())
     * because the installed event filter can only manage a forward implementation. If the QCloseEvent
     * is received by the KScribbleView, the overwritten event handler has to do nothing as the eventFilter
     * has set accept() or ignore() already. If QWidget::closeEvent() is called again, the default event
     * handler will accept the close event and the window gets destroyed even if the installed eventFilter
     * has set the event to be ignored.
     * @author Source Framework Automatically Generated by KDevelop, (c) The KDevelop Team.
     * @version KDevelop version 1.1 code generation
     */
    class KScribbleView : public QScrollView
    {
      Q_OBJECT

      friend KScribbleDoc;

      public:
        /** Constructor for the view
          * @param pDoc  your document instance that the view represents. Create a document
          * before calling the constructor or connect an already existing document to a new MDI child widget.*/
        KScribbleView(KScribbleDoc* pDoc, QWidget* parent, const char *name, int wflags);
        /** Destructor for the main view */
        ~KScribbleView();
        /** returns a pointer to the document connected to the view*/
        KScribbleDoc *getDocument() const;
        /** gets called to redraw the document contents if it has been modified */
        void update(KScribbleView* pSender);
        /** contains the implementation for printing functionality and gets called by KScribbleApp::slotFilePrint() */
        void print(QPrinter *pPrinter);
        /** cuts out a selection */
        void cutSelection();
        /** copies a selection to the clipboard */
        void copySelection();
        /** pastes the clipboard contents to a selection that can be inserted into the picture */
        void pasteSelection();

      protected:

        /** overwritten QWidget::closeEvent() to catch closing views. Does nothing, as the closeEvents for
        * KScribbleView's are processed by KScribbleApp::eventFilter(), so this overwitten closeEvent is necessary
        * and has to be empty. Don't overwrite this method !
        */
        virtual void closeEvent(QCloseEvent* );
        /** overwritten to interpret key events for scrollbars */
        virtual void keyPressEvent( QKeyEvent* );
        /** changed from mousePressEvent() overwriting QScrollView method */
        virtual void viewportMousePressEvent( QMouseEvent* );
        /** changed from mouseReleaseEvent() overwriting QScrollView method */
        virtual void viewportMouseReleaseEvent( QMouseEvent* );
        /** On paste actions inserts the pasted clipboard contents */
        virtual void viewportMouseDoubleClickEvent(QMouseEvent* e);
        /** changed from mouseMoveEvent() overwriting QScrollView method */
        virtual void viewportMouseMoveEvent( QMouseEvent* );
        /** changed from resizeEvent() overwriting QScrollView method */
    //    virtual void viewportResizeEvent( QResizeEvent* );
        /** changed from paintEvent() overwriting QScrollView method */
        virtual void viewportPaintEvent( QPaintEvent* );

        virtual void viewportDragEnterEvent ( QDragEnterEvent * );

        virtual void viewportDragMoveEvent ( QDragMoveEvent * );

        virtual void viewportDragLeaveEvent ( QDragLeaveEvent * );

        virtual void viewportDropEvent ( QDropEvent * );

        /** the document instance */
        KScribbleDoc *doc;

      private:
        KPixmap tmp;
        QRect select;
        QClipboard *cb;
        enum Action{IDLE=0, DRAW, SELECT, PASTE, DRAG} action;
    };

    #endif // KSCRIBBLEVIEW_H

### 15.8 kscribbleview.cpp

    /***************************************************************************
                              kscribbleview.cpp  -  description
                                 -------------------
        begin                : Mon Jan 31 11:05:05 CET 2000
        copyright            : (C) 2000 by Ralf Nolden
        email                : Ralf.Nolden@post.rwth-aachen.de
     ***************************************************************************/

    /***************************************************************************
     *                                                                         *
     *   This program is free software; you can redistribute it and/or modify  *
     *   it under the terms of the GNU General Public License as published by  *
     *   the Free Software Foundation; either version 2 of the License, or     *
     *   (at your option) any later version.                                   *
     *                                                                         *
     ***************************************************************************/
    #include <iostream.h>

    // include files for Qt
    #include <qprinter.h>
    #include <qpainter.h>
    #include <qdir.h>
    #include <qsize.h>
    #include <qclipboard.h>
    #include <qimage.h>
    #include <qdragobject.h>

    // include files for KDE
    #include <kiconloader.h>

    // application specific includes
    #include "kscribbleview.h"
    #include "kscribbledoc.h"
    #include "kscribble.h"

    KScribbleView::KScribbleView(KScribbleDoc* pDoc, QWidget *parent, const char* name, int wflags)
     : QScrollView(parent, name, wflags | WPaintClever | WNorthWestGravity | WRepaintNoErase)
    {
      cb = QApplication::clipboard();
      viewport()->setAcceptDrops(true);
      setDragAutoScroll(true);
      doc=pDoc;
      action=IDLE;
      viewport()->setCursor( Qt::crossCursor );
      QSize size=doc->docSize();
      resizeContents(size.width(), size.height());
      resize(size);
    }

    KScribbleView::~KScribbleView()
    {
    }

    KScribbleDoc *KScribbleView::getDocument() const
    {
      return doc;
    }

    void KScribbleView::update(KScribbleView* pSender){
      if(pSender != this)
        viewport()->repaint(0,0,visibleWidth(), visibleHeight(), false);
    }

    void KScribbleView::print(QPrinter *pPrinter)
    {
      if (pPrinter->setup(this))
      {
        QPainter p;
        p.begin(pPrinter);

        ///////////////////////////////
        // TODO: add your printing code here
        p.drawPixmap(0,0,doc->buffer);
        ///////////////////////////////
        p.end();
      }
    }

    /** cuts out a selection */
    void KScribbleView::cutSelection(){
      select=select.normalize();
      QPixmap cb_pix;
      cb_pix.resize(select.size());
      // copy selection to cb_pix and copy to clipboard
      bitBlt(&cb_pix, 0, 0,
             &doc->buffer, select.x()+contentsX(),  select.y()+contentsY(), cb_pix.width(), cb_pix.height());
      cb->setPixmap(cb_pix);
      // fill cb_pix with white and copy to selection area
      cb_pix.fill(Qt::white);
      bitBlt(&doc->buffer, select.x()+contentsX(), select.y()+contentsY(),
             &cb_pix, 0, 0, cb_pix.width(), cb_pix.height());
      action = IDLE;
      doc->setModified();
      doc->updateAllViews(this);
      viewport()->repaint(0,0,visibleWidth(), visibleHeight(), false);
    }
    /** copies a selection to the clipboard */
    void KScribbleView::copySelection(){
      select=select.normalize();
      QPixmap cb_pix;
      cb_pix.resize(select.size());
      // copy selection to cb_pix and copy to clipboard
      bitBlt(&cb_pix, 0, 0,
             &doc->buffer, select.x()+contentsX(),  select.y()+contentsY(),cb_pix.width(), cb_pix.height());
      cb->setPixmap(cb_pix);
      action = IDLE;
      viewport()->repaint(0,0,visibleWidth(), visibleHeight(), false);
    }
    /** pastes the clipboard contents to a selection that can be inserted into the picture */
    void KScribbleView::pasteSelection(){
      select=cb->pixmap().rect();
      action = PASTE;
      viewport()->setCursor( Qt::sizeAllCursor );
    }

    void KScribbleView::closeEvent(QCloseEvent* e){

    // DO NOT CALL QWidget::closeEvent(e) here !!
    // This will accept the closing by QCloseEvent::accept() by default.
    // The installed eventFilter() in KScribbleApp takes care for closing the widget
    // or ignoring the close event

    }

    void KScribbleView::keyPressEvent( QKeyEvent *e )
    {
      switch (e->key())
      {
        case Key_Right:
          scrollBy( 10, 0 );
          break;
        case Key_Left:
          scrollBy( -10,0);
          break;
        case Key_Up:
          scrollBy( 0, -10 );
          break;
        case Key_Down:
          scrollBy( 0, 10 );
          break;
        case Key_Home:
          setContentsPos(0,0);
          break;
        case Key_End:
          setContentsPos(0,viewport()->height()-viewport()->height());
          break;
        case Key_PageUp:
          scrollBy( 0, -viewport()->height() );
          break;
        case Key_PageDown:
          scrollBy( 0, viewport()->height() );
          break;
      }

    }

    void KScribbleView::viewportMousePressEvent( QMouseEvent *e )
    {
      if ( e->button() == LeftButton && action == IDLE)
      {
        action=DRAW;
        doc->polyline[2] = doc->polyline[1] = doc->polyline[0] = viewportToContents(e->pos());
        doc->updateAllViews(this);
      }
      else if ( e->button() == RightButton && action == IDLE)
      {
        action = SELECT;
        QPoint pt=e->pos();
        int x = pt.x() > contentsWidth() ? contentsWidth() : pt.x();
        int y = pt.y() > contentsHeight() ? contentsHeight() : pt.y();
        select.setLeft(x-1);
        select.setTop(y-1);
        select.setRight(x-1);
        select.setBottom(y-1);
      }
      else if( action == SELECT )
      {
        action = IDLE;
        select=select.normalize();
        // drag
        if(select.contains(e->pos(), true)) // point inside the selection
        {
          tmp.resize(select.size());
          bitBlt(&tmp, 0, 0,
                 &doc->buffer, select.x()+contentsX(),  select.y()+contentsY(), tmp.width(), tmp.height());
          QImage img =tmp.convertToImage();
          QDragObject *d = new QImageDrag( img, viewport() );
          d->setPixmap(BarIcon("filenew"));
          d->drag();
        }
        // remove selection
        else
          viewport()->repaint(0,0,visibleWidth(), visibleHeight(), false);
      }
      else if( action == PASTE )
      {
        if ( e->button() == RightButton )
        {
          action = IDLE;
          viewport()->setCursor( Qt::crossCursor );
        }
        QPoint mv_pt (viewport()->height(), viewport()->width());
        if(QRect(0,0,mv_pt.x(),mv_pt.y()).contains(e->pos()))
          select.moveCenter(e->pos());
        else
        {
          select.moveBottomRight(mv_pt);
        }
        viewport()->repaint(0,0,visibleWidth(), visibleHeight(), false);
      }
    }

    void KScribbleView::viewportMouseReleaseEvent( QMouseEvent *e )
    {
      if ( action == DRAW )
      {
        action = IDLE;
        doc->updateAllViews(this);
      }
      if ( action == SELECT)
      {
        QPoint pt=e->pos();
        int x = pt.x() > 0 ? pt.x() : 0;
        int y = pt.y() > 0 ? pt.y() : 0;
        select.setRight(x);
        select.setBottom(y);
        QSize size=doc->docSize();
        select = select.intersect(QRect(0,0,size.width(), size.height()));
      }
    }

    /** On paste actions inserts the pasted clipboard contents
     */
    void KScribbleView::viewportMouseDoubleClickEvent(QMouseEvent* e)
    {
      if( action == PASTE )
      {
        action = IDLE;
        select.moveCenter(e->pos());
        viewport()->setCursor( Qt::crossCursor );
        QPixmap cb_pix;
        cb_pix.resize(cb->pixmap().size());
        cb_pix=cb->pixmap();
        bitBlt( &doc->buffer, contentsX()+select.x(), contentsY()+select.y(),
                &cb_pix, 0,0 , select.width(),select.height() );
        viewport()->repaint(0,0,visibleWidth(), visibleHeight(), false);
        doc->setModified();
        doc->updateAllViews(this);
      }

    }

    void KScribbleView::viewportMouseMoveEvent( QMouseEvent *e )
    {
      if ( action == DRAW )
      {
        QPainter painter;
        painter.begin( &doc->buffer );
        painter.setPen( doc->currentPen() );
        doc->polyline[2] = doc->polyline[1];
        doc->polyline[1] = doc->polyline[0];
        doc->polyline[0] = viewportToContents(e->pos());
        painter.drawPolyline( doc->polyline );
        painter.end();

        QRect r = doc->polyline.boundingRect();
        r = r.normalize();
        r.setLeft( r.left() - doc->penWidth() );
        r.setTop( r.top() - doc->penWidth() );
        r.setRight( r.right() + doc->penWidth() );
        r.setBottom( r.bottom() + doc->penWidth() );

        bitBlt(viewport(), r.x()-contentsX(), r.y()-contentsY() ,
               &doc->buffer, r.x(), r.y(), r.width(), r.height() );
        doc->setModified();
        doc->updateAllViews(this);
      }
      if ( action == SELECT )
      {
        QPoint pt=e->pos();
        select.setWidth(select.x()+pt.x());
        select.setHeight(select.y()+pt.y());
        select.setRight(pt.x());
        select.setBottom(pt.y());
        QSize size=doc->docSize();
        select = select.intersect(QRect(0,0,size.width(), size.height()));
        viewport()->repaint(0,0,visibleWidth(), visibleHeight(), false);
      }
      if( action == PASTE )
      {
        QPoint mv_pt (viewport()->height(), viewport()->width());
        if(QRect(0,0,mv_pt.x(),mv_pt.y()).contains(e->pos()))
          select.moveCenter(e->pos());
        else
        {
          select.moveBottomRight(mv_pt);
        }
        QRect pm_rect=cb->pixmap().rect();
        select.setWidth(pm_rect.width());
        select.setHeight(pm_rect.height());
        QSize size=doc->docSize();
        select = select.intersect(QRect(0,0,size.width(), size.height()));
        viewport()->repaint(0,0,visibleWidth(), visibleHeight(), false);
        doc->setModified();
        doc->updateAllViews(this);
      }
    }

    //void KScribbleView::viewportResizeEvent( QResizeEvent *e )
    //{
    //}

    void KScribbleView::viewportPaintEvent( QPaintEvent *e )
    {
      bitBlt( viewport(),0,0, &doc->buffer,contentsX() ,contentsY() );

      if( action == PASTE )
      {
        tmp.resize(cb->pixmap().size());
        tmp=cb->pixmap();
      }
      if( action == PASTE || action == DRAG )
      {
        QSize size=doc->docSize();
        select = select.intersect(QRect(0,0,size.width(), size.height()));
        if(select.intersects(e->rect()))
          bitBlt(viewport(), select.x(), select.y(), &tmp, 0, 0, select.width(), select.height());
      }
      if( action == PASTE || action == DRAG || action == SELECT )
      {
    //    if(select.intersects(e->rect()))
    //    {
          QPainter paint_area;
          paint_area.begin(viewport());
          paint_area.setPen(QPen(Qt::black, 0, DashLine));
          paint_area.drawRect( select );
          paint_area.end();
    //    }
      }
      QScrollView::viewportPaintEvent(e);
    }

    void  KScribbleView::viewportDragEnterEvent ( QDragEnterEvent * e)
    {
      e->accept(QImageDrag::canDecode(e));
      action = DRAG;
    }

    void  KScribbleView::viewportDragMoveEvent ( QDragMoveEvent * e)
    {
      QImage img;
      if ( QImageDrag::decode(e, img) ){
        tmp.resize(img.size());
        tmp.convertFromImage(img);
        select.setWidth(tmp.width());
        select.setHeight(tmp.height());
        select.moveCenter(e->pos());
        viewport()->repaint(0,0,visibleWidth(), visibleHeight(), false);
      }
    }

    void  KScribbleView::viewportDragLeaveEvent ( QDragLeaveEvent * )
    {
      action = IDLE;
      viewport()->repaint(0,0,visibleWidth(), visibleHeight(), false);
    }

    void  KScribbleView::viewportDropEvent ( QDropEvent * e)
    {
      QImage img;
      if ( QImageDrag::decode(e, img) )
      {
        tmp.resize(img.size());
        tmp.convertFromImage(img);
        select.setWidth(tmp.width());
        select.setHeight(tmp.height());
        select.moveCenter(e->pos());
        bitBlt(&doc->buffer, select.x()+contentsX(), select.y()+contentsY(),
               &tmp, 0, 0, tmp.width(), tmp.height());
        doc->setModified();
        doc->updateAllViews(this);
      }
      action = IDLE;
        viewport()->repaint(0,0,visibleWidth(), visibleHeight(), false);
    }

### 15.9 kpenbrushdlg.h

    /***************************************************************************
                              kpenbrushdlg.h  -  description
                                 -------------------
        begin                : Fri Jul 23 1999
        copyright            : (C) 1999 by Ralf Nolden
        email                : Ralf.Nolden@post.rwth-aachen.de
     ***************************************************************************/

    /***************************************************************************
     *                                                                         *
     *   This program is free software; you can redistribute it and/or modify  *
     *   it under the terms of the GNU General Public License as published by  *
     *   the Free Software Foundation; either version 2 of the License, or     *
     *   (at your option) any later version.                                   *
     *                                                                         *
     ***************************************************************************/

    #ifndef KPENBRUSHDLG_H
    #define KPENBRUSHDLG_H

    //Generated area. DO NOT EDIT!!!(begin)
    #include <qwidget.h>
    #include <qspinbox.h>
    #include <qlabel.h>
    #include <qpushbutton.h>
    //Generated area. DO NOT EDIT!!!(end)

    #include <qdialog.h>
    #include <klocale.h>

    /**
      *@author Ralf Nolden
      */

    class KPenBrushDlg : public QDialog  {
       Q_OBJECT
    public:
      KPenBrushDlg(int curr, QWidget *parent=0, const char *name=0);
      ~KPenBrushDlg();

      int width() { return width_spbox->value(); };

    protected slots:
      void slotDefault();

    protected:
      void initDialog();
      //Generated area. DO NOT EDIT!!!(begin)
      QSpinBox *width_spbox;
      QLabel *width_label;
      QPushButton *default_btn;
      QPushButton *ok_btn;
      QPushButton *cancel_btn;
      //Generated area. DO NOT EDIT!!!(end)

    private:
    };

    #endif

### 15.10 kpenbrushdlg.cpp

    /***************************************************************************
                              kpenbrushdlg.cpp  -  description
                                 -------------------
        begin                : Fri Jul 23 1999
        copyright            : (C) 1999 by Ralf Nolden
        email                : Ralf.Nolden@post.rwth-aachen.de
     ***************************************************************************/

    /***************************************************************************
     *                                                                         *
     *   This program is free software; you can redistribute it and/or modify  *
     *   it under the terms of the GNU General Public License as published by  *
     *   the Free Software Foundation; either version 2 of the License, or     *
     *   (at your option) any later version.                                   *
     *                                                                         *
     ***************************************************************************/

    #include "kpenbrushdlg.h"
    #include <qwhatsthis.h>
    #include <kapp.h>

    KPenBrushDlg::KPenBrushDlg(int curr, QWidget *parent, const char *name)
      : QDialog(parent,name,true,WStyle_ContextHelp)
    {
      initDialog();
      QWhatsThis::add(width_spbox,i18n("Select brush width"));

      width_spbox->setValue(curr);
      connect(default_btn, SIGNAL(clicked()), this, SLOT(slotDefault()));
      connect(ok_btn, SIGNAL(clicked()), this, SLOT(accept()));
      connect(cancel_btn, SIGNAL(clicked()), this, SLOT(reject()));
    }

    KPenBrushDlg::~KPenBrushDlg(){
    }

    void KPenBrushDlg::slotDefault(){
      width_spbox->setValue(3);
    }

### 15.11 kpenbrushdlgdata.cpp

    /**********************************************************************
                --- KDevelop (KDlgEdit)  generated file ---

                Last generated: Fri Jul 23 10:43:10 1999

                DO NOT EDIT!!!  This file will be automatically
                regenerated by KDevelop.  All changes will be lost.

    **********************************************************************/
    #include <kapp.h>
    #include "kpenbrushdlg.h"

    void  KPenBrushDlg::initDialog(){
      this->resize(370,210);
      this->setMinimumSize(0,0);
      width_spbox= new QSpinBox(this,"width_spbox");
      width_spbox->setGeometry(150,50,100,25);
      width_spbox->setMinimumSize(0,0);
      width_spbox->setValue(1);
      width_spbox->setRange(1,99);

      width_label= new QLabel(this,"width_label");
      width_label->setGeometry(20,50,120,25);
      width_label->setMinimumSize(0,0);
      width_label->setText(i18n("Pen Width:"));

      default_btn= new QPushButton(this,"default");
      default_btn->setGeometry(30,160,100,30);
      default_btn->setMinimumSize(0,0);
      default_btn->setText(i18n("Default"));
      default_btn->setAutoDefault(true);

      ok_btn= new QPushButton(this,"ok");
      ok_btn->setGeometry(140,160,100,30);
      ok_btn->setMinimumSize(0,0);
      ok_btn->setText(i18n("OK"));
      ok_btn->setAutoDefault(true);

      cancel_btn= new QPushButton(this,"cancel");
      cancel_btn->setGeometry(250,160,100,30);
      cancel_btn->setMinimumSize(0,0);
      cancel_btn->setText(i18n("Cancel"));
      cancel_btn->setAutoDefault(true);

    }

### 15.12 resource.h

    /***************************************************************************
                              resource.h  -  description
                                 -------------------
        begin                : Mon Jan 31 11:05:05 CET 2000
        copyright            : (C) 2000 by Ralf Nolden
        email                : Ralf.Nolden@post.rwth-aachen.de
     ***************************************************************************/

    /***************************************************************************
     *                                                                         *
     *   This program is free software; you can redistribute it and/or modify  *
     *   it under the terms of the GNU General Public License as published by  *
     *   the Free Software Foundation; either version 2 of the License, or     *
     *   (at your option) any later version.                                   *
     *                                                                         *
     ***************************************************************************/

    #ifndef RESOURCE_H
    #define RESOURCE_H

    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif

    ///////////////////////////////////////////////////////////////////
    // resource.h  -- contains macros used for commands

    ///////////////////////////////////////////////////////////////////
    // COMMAND VALUES FOR MENUBAR AND TOOLBAR ENTRIES

    ///////////////////////////////////////////////////////////////////
    // File-menu entries
    #define ID_FILE_NEW                 10010
    #define ID_FILE_OPEN                10020
    #define ID_FILE_OPEN_RECENT         10030
    #define ID_FILE_CLOSE               10040

    #define ID_FILE_SAVE                10050
    #define ID_FILE_SAVE_AS             10060

    #define ID_FILE_PRINT               10070

    #define ID_FILE_QUIT                10080

    ///////////////////////////////////////////////////////////////////
    // Edit-menu entries
    #define ID_EDIT_UNDO                11010
    #define ID_EDIT_COPY                11020
    #define ID_EDIT_CUT                 11030
    #define ID_EDIT_PASTE               11040
    #define ID_EDIT_CLEAR_ALL           11050

    ///////////////////////////////////////////////////////////////////
    // Pen-menu entries
    #define ID_PEN_COLOR                14010
    #define ID_PEN_BRUSH                14020

    ///////////////////////////////////////////////////////////////////
    // Draw-menu entries
    #define ID_DRAW_FIND                15010
    #define ID_DRAW_FREEHAND            15020
    #define ID_DRAW_LINE                15030
    #define ID_DRAW_RECT                15040
    #define ID_DRAW_RECT_FILL           15050
    #define ID_DRAW_CIRCLE              15060
    #define ID_DRAW_CIRCLE_FILL         15070
    #define ID_DRAW_ELLIPSE             15080
    #define ID_DRAW_ELLIPSE_FILL        15090
    #define ID_DRAW_SPRAY               15100
    #define ID_DRAW_FILL                15110
    #define ID_DRAW_ERASE               15120

    ///////////////////////////////////////////////////////////////////
    // View-menu entries
    #define ID_VIEW_TOOLBAR             12010
    #define ID_VIEW_STATUSBAR           12020

    ///////////////////////////////////////////////////////////////////
    // Window-menu entries
    #define ID_WINDOW_NEW_WINDOW        13010
    #define ID_WINDOW_CASCADE           13020
    #define ID_WINDOW_TILE              13030

    ///////////////////////////////////////////////////////////////////
    // Help-menu entries
    #define ID_HELP_CONTENTS            1002
    #define ID_HELP_WHATS_THIS          1003
    ///////////////////////////////////////////////////////////////////
    // General application values
    #define ID_STATUS_MSG               1001
    #define TOOLS_TOOLBAR               1
    #endif // RESOURCE_H

Next Previous Table of Contents