source: projects/punch-card/punch-card-editor/src/qpunchcard/deck.h @ 53

Last change on this file since 53 was 53, checked in by sven, 10 years ago

Punch Card Editor, ongoing development

  • Extended new Deck interface, expanding the undo framework
  • Implemented editor changes via undo framework
  • revised the menu and toolbar actions and structure (now dynamic construction at deck load time), implemented undo viewer
  • Started implementation of device driver framework in menu
  • Embedded the Qextserialport library (http://qextserialport.sourceforge.net/)
  • Started the Documation M200 Client device driver (well, just created the directory structure and qmake project file infrastructure)
  • At the current state, the complete project compiles :-)

Statistics: About 3500 Lines of code (without libqextserialport)

-- sven @ workstation

File size: 7.3 KB
Line 
1#ifndef DECK_H
2#define DECK_H
3
4#include <QList>
5#include <QSharedPointer>
6#include <QFile>
7#include <QUndoCommand>
8
9namespace QPunchCard {
10        class Deck;
11        class DeckIndex;
12
13        class DeckUndoCommand;
14        class DeckAppendCard;
15        class DeckModifyCard;
16        // usw.
17}
18
19#include "qpunchcard/card.h"
20#include "qpunchcard/format.h"
21
22namespace QPunchCard {
23
24/**
25 * File uses the strategy pattern to switch between different
26 * I/O formats (using the FileFormat class).
27 **/
28class Deck : public QObject {
29        Q_OBJECT
30
31        QSharedPointer<const FileFormat> format;
32        QList< Card > cards;
33        QSharedPointer< QFile > file;
34        //QPointer<QUndoStack> undo_stack;
35        QUndoStack undo_stack;
36        friend class FileFormat;
37        friend class DeckIndex;
38        friend class DeckAppendCard;
39        friend class DeckModifyCard;
40
41        void init();
42
43public:
44        //typedef QList< QPointer<Card> >::iterator iterator;
45
46        // =========== Constructors ==================
47        /// Create empty
48        Deck(QObject* parent = 0);
49        ~Deck() {};
50        /// Create from file/stream/etc., that is, calls format->read()
51        Deck(const FileFormat* format, QObject* parent = 0);
52
53        // =========== Loading and Saving, File Format Handling ==================
54        // (All Functions are just Shorthands for other direct public method calls)
55        bool save();
56        bool save(QFile& file);
57        bool save(const FileFormat* format, QFile& file);
58        bool read();
59        bool read(QFile& file);
60        bool read(const FileFormat* format, QFile& file);
61
62        bool canRead() const { return hasFile() && hasFormat(); }
63        bool canSave() const { return canRead(); }
64        bool hasFormat() const { return format; }
65        void setFormat(const FileFormat* format);
66        bool hasFile() const { return file; }
67        void setFile(QFile* file);
68
69        // =========== Undo Framework ==================
70        bool isModified() const { return !undo_stack.isClean(); }
71        /// for advanced usage. Handle with care. Object still owned by the Deck.
72        QUndoStack* getUndoStack() { return &undo_stack; }
73        QAction* createRedoAction(const QString& prefix = QString()) { return undo_stack.createRedoAction(this,prefix); }
74        QAction* createUndoAction(const QString& prefix = QString()) { return undo_stack.createUndoAction(this,prefix); }
75
76
77        // =========== Index Handling, reading access to cards ==================
78        bool isValid(int i);
79        DeckIndex createIndex(int i);
80        int count() const { return cards.count(); }
81        int length() const { return count(); }
82        int size() const { return count(); }
83        bool empty() const { return cards.empty(); }
84        const Card& at(int i) const { return cards.at(i); }
85
86public:
87        // =========== Editing (Undo captured) ==================
88        /**
89         * The main editing command interface. Your code creates a undo
90         * command and executes it by calling this method. It will push
91         * the command on the undo stack *AND* call command->redo() (by
92         * default), if call_redo is true.
93         * It won't return anything. If command is associated with no
94         * or another deck, it will be changed.
95         **/
96        void run(DeckUndoCommand* command, bool call_redo = true);
97
98        // all following functions are shorthands for run() with
99        // appropriate commands.
100
101        /// Insert one new card
102        bool insert(DeckIndex after);
103        /// Insert `times` empty cards after DeckIndex
104        bool insertTimes(DeckIndex after, int times = 1);
105        /// Move card from `from` to `to`
106        bool move(DeckIndex from, DeckIndex to);
107        /// Removes all items from `from` to `to`
108        bool erase(DeckIndex from, DeckIndex to);
109        /// Append a card
110        void append(Card card = Card());
111        void push_back(Card card) { append(card); }
112
113        // Quick & dirty, no official standard
114        void emitChanged(DeckIndex lower, DeckIndex upper);
115
116signals:
117        // =========== The fully official signals ==================
118
119        // wer brauchts?
120        void cardCountChanged(int newCardCount); // wer braucht das?
121
122        // das hier ist das FAVORISIERTE FORMAT:
123        void contentsChanged(DeckIndex lowerCard, DeckIndex upperCard);
124
125
126        void modified(bool modified);
127        //void redoAvailable(bool available);
128        //void undoAvailable(bool available);
129        //void undoCommandAdded();
130
131public slots:
132        void redo() { undo_stack.redo(); }
133        void undo() { undo_stack.undo(); }
134        //void setModified(bool modified) {}
135};
136
137// Java-style iterator
138//typedef QListIterator< QPointer<Card> > DeckIterator;
139
140
141/**
142 * CardIndex feels like an int (normalized)
143 **/
144class DeckIndex {
145private:
146        QPointer<Deck> deck;
147        int i;
148public:
149        // behaves like int, copy constructor and operator= will be created automatically
150        DeckIndex(int i = 0) : i(i) {}
151        operator int() const { return normalized(); }
152        int asInt() const { return normalized(); }
153
154        DeckIndex(Deck* d, int i) : deck(d), i(i) { if(!deck) qDebug() << "NULL DECK!"; }
155        bool isValid() const { return deck ? (i >= 0 && i < deck->count()) : false; }
156
157        // "normalisierung" = in Deck Bounds
158        int normalized() const { if(!deck) return i; if(i < 0) return 0; else if(i >= deck->count()) return deck->count()-1; else return i; }
159        void normalize() { i = normalized(); }
160        bool canNormalize() const { return deck; }
161
162        // special positions
163        bool isTop() const { return i < 0; }
164        bool isEnd() const { return i >= deck->count(); }
165        bool isFirst() const { return i == 0; }
166        bool isLast() const { return i == deck->count(); }
167
168        QPointer<Deck> getDeck() const { return deck; }
169        void setDeck(Deck* deck) { this->deck = deck; }
170        bool assertDeck(Deck* fallback) { if(!deck) deck=fallback; return deck == fallback; }
171        bool hasDeck() const { return deck; }
172
173        // ein paar abkuerzungen
174        /// @returns null wenn nicht normalisierbar (also letztlich kein Deck da ist)
175        // QPointer geht nicht (mehr) weil Card jetzt kein QObject mehr ist
176        const Card* getCard() const { return canNormalize() ? &(deck->cards.at(normalized())) : NULL; }
177        // das wird crashen. *UNGUT*
178        //const Card& getCard() const { return canNormalize() ? deck->cards.at(normalized()) : Card(); }
179
180        DeckIndex& operator++() { i++; return *this; }
181        DeckIndex& operator+=(int x) { i+= x; return *this; }
182};
183
184/**
185 * The base undo command. Still abstract.
186 **/
187class DeckUndoCommand : public QUndoCommand {
188public:
189        DeckUndoCommand(Deck* deck = 0, QUndoCommand* parent = 0) : QUndoCommand(parent) {
190                this->deck = deck;
191        }
192        //const QPointer<Deck> getDeck() const { return deck; }
193protected:
194        QPointer<Deck> deck;
195};
196
197/**
198 * Lauter schoene UndoCommands
199 **/
200class DeckAppendCard : public DeckUndoCommand {
201public:
202        DeckAppendCard(Deck* deck, Card* card, QUndoCommand* parent = 0) : DeckUndoCommand(deck, parent) {
203                this->deck = deck;
204                this->card = card;
205                setText(deck->tr("Adding card to deck"));
206        }
207        void undo() { deck->cards.removeLast(); }
208        void redo() { deck->cards.push_back(*card); }
209private:
210        Deck* deck;
211        Card* card;
212};
213
214class DeckModifyCard : public DeckUndoCommand {
215public:
216        DeckModifyCard(Deck* deck, DeckIndex& position, Card new_content, QUndoCommand* parent=0)
217                        : DeckUndoCommand(deck, parent), position(position), new_content(new_content) {
218                position.assertDeck(deck);
219                Q_ASSERT(this->deck);
220
221                // alten Inhalt irgendwie sichern
222                old_content = *position.getCard();
223                setText(position.getDeck()->tr("Changed contents of card").arg(position));
224        }
225        void undo() {
226                position.getDeck()->cards[position] = old_content;
227                deck->emitChanged(position, position);
228        }
229        void redo() {
230                position.getDeck()->cards[position] = new_content;
231                deck->emitChanged(position, position);
232        }
233private:
234        DeckIndex position;
235        Card new_content;
236        Card old_content;
237};
238
239// usw.
240
241QDebug operator<<(QDebug dbg, const Deck &c);
242QDebug operator<<(QDebug dbg, const DeckIndex &c);
243
244}; // namespace
245
246#endif /* DECK_H */
Note: See TracBrowser for help on using the repository browser.
© 2008 - 2013 technikum29 • Sven Köppel • Some rights reserved
Powered by Trac
Expect where otherwise noted, content on this site is licensed under a Creative Commons 3.0 License