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

Last change on this file since 49 was 49, checked in by sven, 10 years ago
  • Text editing part:

Improved Column counting
80 column line bar

  • Saving with Jones Format works
File size: 6.0 KB
Line 
1#ifndef CARD_H
2#define CARD_H
3
4#include <QBitArray>
5#include <QHash>
6#include <QList>
7#include <QPointer>
8#include <QDebug>
9#include <QUndoStack>
10#include <QFile>
11#include <QSharedPointer>
12
13#include <QModelIndex>
14
15namespace QPunchCard {
16        class Column; class Card; class Deck; class DeckIndex;
17};
18
19#include "format.h"
20//#include "codec.h"
21
22namespace QPunchCard {
23
24/**
25 * A Column is a 12 bit storage...
26 **/
27class Column : public QBitArray {
28public:
29        Column() : QBitArray(13) {}
30
31        Column(int value) : QBitArray(13) {
32                // TODO: range check, throw exception if bad
33                for(int s=0; s<12; s++) {
34                        setBit(s, (1 << s) & value);
35                        //setBit(s, (value >> s) & 0x01);
36                }
37        }
38
39
40        operator int() const {
41                int ret=0;
42                for(int s=0; s<12; s++)
43                        ret |= testBit(s) << s;
44                return ret;
45        }
46};
47
48/**
49 * This is a punch card.
50 **/
51class Card : public QObject {
52        Q_OBJECT // must be qobject for signals/slots and QPointer usage
53
54public:
55        Card() {};
56        QHash<QString,QString> properties;
57
58        Column column[80];
59        Column& get(int x) {
60                if(x < 0 || x > 80)
61                        throw "Out of range exception";
62                return column[x];
63        }
64        const Column& get(int x) const {
65                if(x < 0 || x > 80)
66                        throw "Out of range exception";
67                return column[x];
68        }
69        Column& operator[](int x) { return get(x); }
70        const Column& operator[](int x) const { return column[x]; }
71        int length() const { return 80; } // aja...
72
73        /*Card& operator=(const Card& other) {
74                // copy assignment, etc.
75                for(int x=0; x<80; x++) column[x] = other[x];
76                return *this;
77        }*/
78
79        ~Card() {};
80
81signals:
82        // auf das level will echt keiner runter!
83        void dataChanged(int left_index, int right_index);
84        // wenn signal: klasse muss QObject sein =>
85        //              kein copy constructor möglich =>
86        //              File = QVector<Card*>
87};
88
89
90/**
91 * File uses the strategy pattern to switch between different
92 * I/O formats (using the FileFormat class).
93 **/
94class Deck : public QObject, public QList< QPointer<Card> > {
95        Q_OBJECT
96
97        QSharedPointer<const FileFormat> created_format;
98        void init();
99
100public:
101        typedef QList< QPointer<Card> >::iterator iterator;
102        QPointer<QUndoStack> undo;
103
104        // Creation and I/O handling ===================
105        /// Create empty
106        Deck() : QList< QPointer<Card> >() { init(); }
107        ~Deck() {};
108        /// Create from file/stream/etc., that is, calls format->read()
109        Deck(const FileFormat* format) : QList< QPointer<Card> >(), created_format(format) { init(); }
110        /// Save with same device/format as created
111        bool save(QFile& file) { return save(created_format.data(), file); }
112        /// Save
113        bool save(const FileFormat* format, QFile& file);
114        bool read(QFile& file) { return read(created_format.data(), file); }
115        bool read(const FileFormat* format, QFile& file);
116
117        bool canSave() const { return created_format; }
118        void setFormat(const FileFormat* format);
119        //File* getFile() { if(created_format && created_format->file) return created_format->file; }
120
121        bool isModified() const { return !undo->isClean(); }
122
123        // index handling ======================
124        inline bool isValid(int i);
125        inline DeckIndex createIndex(int i);
126
127        // Bearbeitungsfunktionen
128        bool insert(DeckIndex after); // neue Karte hinzufuegen
129        bool insertTimes(DeckIndex after, int times = 1);
130        bool move(DeckIndex from, DeckIndex to);
131        bool erase(DeckIndex from, DeckIndex to);
132
133        // Quick & dirty
134        inline void emitChanged(DeckIndex lower, DeckIndex upper);
135signals:
136        void cardCountChanged(int newCardCount); // wer braucht das?
137
138        // das hier ist das FAVORISIERTE FORMAT:
139        void contentsChanged(DeckIndex lowerCard, DeckIndex upperCard);
140
141
142        void modified(bool modified);
143        //void redoAvailable(bool available);
144        //void undoAvailable(bool available);
145        //void undoCommandAdded();
146
147public slots:
148        //void redo() {}
149        //void undo() {}
150        //void setModified(bool modified) {}
151};
152
153// Java-style iterator
154typedef QListIterator< QPointer<Card> > DeckIterator;
155
156
157/**
158 * CardIndex feels like an int (normalized)
159 **/
160class DeckIndex {
161private:
162        QPointer<Deck> deck;
163        int i;
164public:
165        // behaves like int, copy constructor and operator= will be created automatically
166        DeckIndex(int i = 0) : i(i) {}
167        operator int() const { return normalized(); }
168        int asInt() const { return normalized(); }
169
170        DeckIndex(Deck* d, int i) : deck(d), i(i) { if(!deck) qDebug() << "NULL DECK!"; }
171        bool isValid() const { return deck ? (i >= 0 && i < deck->count()) : false; }
172
173        // "normalisierung" = in Deck Bounds
174        int normalized() const { if(!deck) return i; if(i < 0) return 0; else if(i >= deck->count()) return deck->count()-1; else return i; }
175        void normalize() { i = normalized(); }
176        bool canNormalize() const { return deck; }
177
178        // special positions
179        bool isTop() const { return i < 0; }
180        bool isEnd() const { return i >= deck->count(); }
181        bool isFirst() const { return i == 0; }
182        bool isLast() const { return i == deck->count(); }
183
184        const QPointer<Deck> getDeck() const { return deck; }
185        void setDeck(Deck* deck) { this->deck = deck; }
186        bool assertDeck(Deck* fallback) { if(!deck) deck=fallback; return deck == fallback; }
187        bool hasDeck() const { return deck; }
188
189        // ein paar abkuerzungen
190        /// @returns null wenn nicht normalisierbar (also letztlich kein Deck da ist)
191        QPointer<Card> getCard() const { return canNormalize() ? deck->at(normalized()) : NULL; }
192
193        DeckIndex& operator++() { i++; return *this; }
194        DeckIndex& operator+=(int x) { i+= x; return *this; }
195};
196
197/****************************************************************************
198  debug functions
199 ***************************************************************************/
200
201 QDebug operator<<(QDebug dbg, const Column &c);
202 QDebug operator<<(QDebug dbg, const Card &c);
203 QDebug operator<<(QDebug dbg, const Deck &c);
204 QDebug operator<<(QDebug dbg, const DeckIndex &c);
205
206
207/****************************************************************************
208  inline functions
209 ***************************************************************************/
210
211inline bool Deck::isValid(int i) { return createIndex(i).isValid(); }
212inline DeckIndex Deck::createIndex(int i) { return DeckIndex(this, i); }
213inline void Deck::emitChanged(DeckIndex lower, DeckIndex upper) {
214        emit contentsChanged(lower, upper);
215}
216
217}; // Namespace
218#endif // CARD_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