[prev in list] [next in list] [prev in thread] [next in thread] 

List:       koffice-devel
Subject:    KWord frames refactor
From:       Thomas Zander <zander () kde ! org>
Date:       2005-10-23 19:30:03
Message-ID: 200510232130.12061.zander () kde ! org
[Download RAW message or body]

[Attachment #2 (multipart/signed)]

[Attachment #4 (multipart/mixed)]


Hi,

with Qt4 the concept of separating model and view has become clear to 
everyone, probably including the advantages.  I'm assuming this is a 
known pattern.

In KWord the KWFrame, KWFrameSet and KWDocument do most of the view stuff, 
while also being the data objects.
In order to allow instantiation of the data objects without linking to any 
KDE technologies like kparts I need to get rid of the KWDocument usage 
since thats a KPart.
We need to have this if we want to do any unit testing.  The separation of 
concerns will also open up other refactorings to make KWord less fragile 
in the future :)

I created a KWFrameView class that will contain a KWFrame member and we 
instantiate one KWFrameView per frame shown, as well as one per view. 
This class will contain stuff like a paint method that draws the outlines 
and resize handles of a frame as well as a boolean to state the frame is 
selected.
This gets rid of the need for ResizeHandles.
A context sensative popup is also created there.

Next; I created a KWFrameViewManager that will hold all the KWFrameView 
instances for one particular view.  Lots of methods from KWFrameSet as 
well as KWDocument can be moved there. (see the attached .h file)
This class will also replace the framesInPage structured which are now 
stored per frameset.

The changes to the model (i.e. frame and framesets) will be emitted by 
signals connecting to the KWFrameViewManager from the doc and the 
framesets, and will then update the appropriate views after _all_ the 
signals have been handled.
The idea here is that only after all the changes to the model have been 
done should the view update, eliminating most race conditions I have seen 
in the current code.  See the .h file for details.

Mostly to David; thoughts/corrections/questions?
-- 
Thomas Zander

["KWFrameViewManager.h" (text/x-c++hdr)]

/**
 * Class that knows about all the (visible) frames in the document and will act as
 * a manager between the GUI code and the data objects to couple any GUI action to \
                the
 * right frame.
 * All coordinates used in this object are pt based, i.e. the same as the Frames. Any
 * coordinates in pixels should first be converted in the KoTextZoomHandler (in KWord
 * thats the KWDocument)
 */
class KWFrameViewManager : public QObject {
    Q_OBJECT

public:
    KWFrameViewManager();
    virtual ~KWFrameViewManager();

    // frames based stuff..
    // methods coming from KWDocument:
    KWFrame * frameAtPos( const KoPoint& point, bool* border = 0L, bool \
firstNonSelected = false );  void deleteSelectedFrames();
    QCursor getMouseCursor( const QPoint& KoPoint, int keyState );
    QPtrList<KWFrame> getSelectedFrames() const;
    KWFrame *getFirstSelectedFrame() const;
    QPtrList<KWFrame> framesInPage( int pageNum , bool sorted=true) const;
    bool isOnlyOneFrameSelected() const;


    // methods coming from KWFrameSet:
    /** return a frame if nPoint in on one of its borders */
    KWFrame *frameByBorder( const KoPoint & nPoint ) const;
    void createEmptyRegion( const KoRect & crect, QRegion & emptyRegion, KWViewMode \
*viewMode );  void drawContents( QPainter *painter, const KoRect &crect, const \
QColorGroup &cg, bool onlyChanged, bool resetChanged, KWFrameSetEdit *edit, \
KWViewMode *viewMode );  void drawFrameAndBorders( KWFrame *frame, QPainter *painter, \
const KoRect &crect, const QColorGroup &cg, bool, bool, KWFrameSetEdit *edit, \
KWViewMode *viewMode, KWFrame *settingsFrame, bool drawUnderlyingFrames );  void \
drawFrameBorder( QPainter *painter, KWFrame *frame, KWFrame *settingsFrame, const \
KoRect &crect, KWViewMode *viewMode );  MouseMeaning getMouseMeaning( const KoPoint \
&nPoint, int keyState );  MouseMeaning getMouseMeaningInsideFrame( const KoPoint& );
    void showPopup( KWView *view, const KoPoint &point );


    // listeners; see the fireEvents method signature for more info.
    void addKWFramesListener(KWFramesListener *listener);
    void removeKWFramesListener(KWFramesListener *listener);

public slots:
    /// notify this slot if a FrameSet has been created and should become visible.
    void slotFrameSetAdded(KWFrameSet *fs);
    /// notify this slot if a FrameSet has been removed
    void slotFrameSetRemoved(KWFrameSet *fs);
    /// notify this slot if a Frame has been created and should become visible.
    void slotFrameAdded(KWFrame *f);
    /// notify this slot if a Frame has been removed
    void slotFrameRemoved(KWFrame *f);

private:
    /**
     * Various classes are not, not should be heavyweight QObjects, but still want to
     * keep uptodate about frames being deleted.  This method will propagate all the
     * events saved up to the listeners.
     * Note; this method should be called _after_ all the events from the slots have
     * come in, which is needed to minimize race conditions.  So; first update all \
                the
     * data objects and when that is done all the views will be updated.
     */
    void fireEvents();
    /// prepare or update the singleshot timer to fire events.
    void requestFireEvents();

private:
    class FrameEvent {
        public:
        enum actionAction { FrameRemoved, FrameAdded, FrameSetRemoved, FrameSetAdded \
};  FrameEvent (actionEnum, KWFrame *frame);
            FrameEvent (actionEnum, KWFrameSet *frameSet);
        private:
            actionEnum m_action;
            KWFrame *m_frame;
            KWFrameSet *m_frameSet;
        friend class KWFrameViewManager;
    };

private:
    QValueList<KWFrameView> m_frames;
    QValueList<KWFramesListener*> m_framesListener;
    QValueList<FrameEvent*> m_frameEvents;
    QTimer m_fireEventsSingleShot;
};

class KWFramesListener {
    void frameSetAddedSlot(KWFrameSet *fs) = 0;
    void frameSetRemovedSlot(KWFrameSet *fs) = 0;
    void frameAddedSlot(KWFrame *f) = 0;
    void frameRemovedSlot(KWFrame *f) = 0;
};


["KWFrameView.h" (text/x-c++hdr)]

class KWFrameView {
public:
    KWFrameView(KWFrame *frame);

    /// draw the frame background and borders and all the other things that are not actual content
    void drawFrameBase( lotsaargs );
    void drawPadding( foo bar );
    MouseMeaning getMouseMeaning( const KoPoint &nPoint, int keyState );
    QPopup createPopup( const KoPoint &point );

    bool isSelected();
    void setSelected(bool selected);

private:
    KWFrame *m_frame;
    bool m_selected;
    FramePolicy *policy;
};

class FramePolicy {
    MouseMeaning getMouseMeaning( const KoPoint &nPoint, int keyState ) = 0;
    QPopup createPopup( const KoPoint &point ) = 0;
}

class TableFramePolicy : public FramePolicy {
    MouseMeaning getMouseMeaning( const KoPoint &nPoint, int keyState );
    QPopup createPopup( const KoPoint &point );
}

class PartFramePolicy : public FramePolicy {
    MouseMeaning getMouseMeaning( const KoPoint &nPoint, int keyState );
    QPopup createPopup( const KoPoint &point );
}

class TextFramePolicy : public FramePolicy {
    MouseMeaning getMouseMeaning( const KoPoint &nPoint, int keyState );
    QPopup createPopup( const KoPoint &point );
}

[Attachment #9 (application/pgp-signature)]

_______________________________________________
koffice-devel mailing list
koffice-devel@kde.org
https://mail.kde.org/mailman/listinfo/koffice-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic