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

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