source: projects/punch-card/punch-card-editor/src/app/decktexteditor.cc @ 47

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

Continued implementation:

  • removed bugs
  • improved features

Programming continues, but quite slow since I've got few time... unfortunately

File size: 7.5 KB
Line 
1#include "decktexteditor.h"
2
3#include <QPainter>
4#include <QTextBlock>
5
6using namespace QPunchCard;
7
8TextEditorDock::TextEditorDock(EditorWindow* parent) : QDockWidget(parent), main(parent) {
9        // Title grundsaetzlich angeben (wird ueberall angezeigt)
10        setWindowTitle(tr("Text Editor"));
11
12        // - Codec erstellen oder kriegen
13        editor = new DeckTextEditor(main);
14
15        // Signal weiterleiten
16        connect(editor, SIGNAL(cursorRowChanged(DeckIndex)), this, SIGNAL(cardSelected(DeckIndex)));
17        connect(main, SIGNAL(contentsChanged(DeckIndex,DeckIndex)), editor, SLOT(contentsChanged(DeckIndex,DeckIndex)));
18
19        // spaeter: oben (in Titelleiste oder drunter) Codeauswahl,
20        //          unten Legende mit Farbauswahl
21        setWidget(editor);
22        setFeatures(QDockWidget::AllDockWidgetFeatures);
23}
24
25void TextEditorDock::setCard(DeckIndex i) {
26        editor->highlightRow(i);
27}
28
29void DeckTextEditor::contentsChanged(DeckIndex lower_card, DeckIndex upper_card) {
30        // translate indices to text rows and load new text
31        qDebug("Loading new text between [%d, %d]", (int)lower_card, (int)upper_card);
32        for(int i = lower_card; i < upper_card; i++) {
33                DeckIndex index(main->deck, i);
34                if(!index.isValid()) {
35                        qDebug("text update: skipping invalid %d", i);
36                        continue;
37                }
38
39                // Ganzen Block markieren und ueberschreiben
40                QTextCursor cursor( this->document()->findBlockByNumber(i) );
41                cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
42                // an dieser Stelle: Ungueltige Zeichen maskieren (per anderem QTextCharFormat)!
43                cursor.insertText(QString("Zeile %d von Lochkarte").arg(i));
44        }
45}
46
47DeckTextEditor::DeckTextEditor(EditorWindow* main) : QPlainTextEdit(main), main(main) {
48        row_area = new NumberArea(this);
49        col_area = new NumberArea(this);
50
51        connect(this->document(), SIGNAL(contentsChange(int,int,int)),
52                this, SLOT(translateChanges(int, int, int)));
53
54
55        // Font einstellen
56        QFont font;
57        font.setFamily("Courier");
58        font.setFixedPitch(true);
59        font.setPointSize(13);
60        setFont(font);
61
62        QFont col_font = font;
63        col_font.setPointSize(8);
64        col_area->setFont(col_font);
65
66        connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
67        connect(this, SIGNAL(updateRequest(const QRect &, int)), this, SLOT(updateLineNumberArea(const QRect &, int)));
68        connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentCursorPos()));
69
70        updateLineNumberAreaWidth(0);
71        highlightCurrentCursorPos();
72}
73
74void DeckTextEditor::translateChanges(int position, int charsRemoved, int charsAdded) {
75        // Dieser slot wird durch das QTextDocument aufgerufen, wenn der Benutzer
76        // den Inhalt geaendert hat. => Uebersetzen ins Kartenmodell und als Signal
77        // weitergeben.
78        // NATÜRLICH muss ZUSAETZLICH auch noch das MODEL DIREKT VERAENDERT werden.
79        // also die betreffenden Karten AUSTAUSCHEN durch den neuen Inhalt, der dann
80        // per Codec uebersetzt wird!
81        qDebug("Pos: %d, removed: %d, added: %d", position, charsRemoved, charsAdded);
82}
83
84QSize DeckTextEditor::numberAreaSize(const NumberArea* area) const {
85        if(area == row_area) {
86                int digits = 1;
87                int max = qMax(1, blockCount());
88                while (max >= 10) {
89                        max /= 10;
90                        ++digits;
91                }
92
93                int space = 10 + fontMetrics().width(QLatin1Char('9')) * digits;
94
95                return QSize(space, 0);
96        } else if(area == col_area) {
97                return QSize(0, 4 + fontMetrics().height());
98        } else {
99                qDebug("Illegal area at numberAreaSize()");
100                return QSize();
101        }
102}
103
104void DeckTextEditor::updateLineNumberAreaWidth(int /* newBlockCount */) {
105        // this is called when the block count changed (line count changed)
106        setViewportMargins(numberAreaSize(row_area).width(), numberAreaSize(col_area).height(), 0, 0);
107}
108
109void DeckTextEditor::updateLineNumberArea(const QRect &rect, int dy) {
110        if (dy)
111                row_area->scroll(0, dy);
112        else
113                row_area->update(0, rect.y(), row_area->width(), rect.height());
114
115        if (rect.contains(viewport()->rect()))
116                updateLineNumberAreaWidth(0);
117 }
118
119void DeckTextEditor::resizeEvent(QResizeEvent *e) {
120        QPlainTextEdit::resizeEvent(e);
121
122        QRect cr = contentsRect();
123        row_area->setGeometry(QRect(cr.left(), cr.top(), numberAreaSize(row_area).width(), cr.height()));
124        col_area->setGeometry(QRect(cr.left(), cr.top(), cr.width(), numberAreaSize(col_area).height()));
125}
126
127void DeckTextEditor::highlightCurrentCursorPos() {
128        // emit signal: Cursor position changed!
129        emit cursorRowChanged(textCursor().blockNumber());
130        paintHighlights();
131}
132
133void DeckTextEditor::highlightRow(DeckIndex i) {
134        // externe eingabe: Highlighted_row machen und so...
135        highlighted_row = i;
136        paintHighlights();
137}
138
139void DeckTextEditor::paintHighlights() {
140        // first: Update Row Mark
141        QList<QTextEdit::ExtraSelection> extra_selections;
142
143        {
144                // Row Mark
145                QTextEdit::ExtraSelection selection;
146
147                QColor row_color = QColor(Qt::yellow).lighter(160);
148
149                selection.format.setBackground(row_color);
150                selection.format.setProperty(QTextFormat::FullWidthSelection, true);
151                selection.cursor = textCursor();
152                selection.cursor.clearSelection();
153                extra_selections.append(selection);
154        }
155        if(highlighted_row >= 0 && highlighted_row < textCursor().blockNumber()) {
156                // highlighted row mark
157                QTextEdit::ExtraSelection selection;
158                QColor row_color = QColor(Qt::blue).lighter(160);
159
160                selection.format.setBackground(row_color);
161                selection.format.setProperty(QTextFormat::FullWidthSelection, true);
162                selection.cursor = textCursor();
163                selection.cursor.clearSelection();
164                extra_selections.append(selection);
165        }
166        {
167                // Col Mark
168                QTextEdit::ExtraSelection selection_template;
169
170                QColor col_color = QColor(Qt::green).lighter(160);
171                selection_template.format.setBackground(col_color);
172
173                // ueber alle sichtbaren reihen iterieren
174                QTextBlock block = firstVisibleBlock();
175
176                while(block.isValid() && block.isVisible()) {
177                        // Eine Selection *kopieren*
178                        QTextEdit::ExtraSelection selection; // nicht mehr von selection_template
179                        selection.format.setBackground(col_color);
180                        // Cursor am Anfang des Blocks
181                        selection.cursor = QTextCursor(block);
182                        selection.cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, textCursor().columnNumber()-1);
183                        selection.cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 1);
184                        extra_selections.append(selection);
185
186                        block = block.next();
187                }
188        }
189
190        setExtraSelections(extra_selections);
191}
192
193void DeckTextEditor::numberAreaPaintEvent(NumberArea* area, QPaintEvent *event) {
194        if(area == row_area) {
195                QPainter painter(row_area);
196                painter.fillRect(event->rect(), Qt::lightGray);
197
198
199                QTextBlock block = firstVisibleBlock();
200                int blockNumber = block.blockNumber();
201                int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
202                int bottom = top + (int) blockBoundingRect(block).height();
203
204                while (block.isValid() && top <= event->rect().bottom()) {
205                        if (block.isVisible() && bottom >= event->rect().top()) {
206                                QString number = QString::number(blockNumber + 1);
207                                painter.setPen(Qt::black);
208                                painter.drawText(0, top + col_area->height(), row_area->width(), fontMetrics().height(),
209                                        Qt::AlignRight, number);
210                        }
211
212                        block = block.next();
213                        top = bottom;
214                        bottom = top + (int) blockBoundingRect(block).height();
215                        ++blockNumber;
216                }
217        } else if(area == col_area) {
218                QPainter painter(col_area);
219                painter.fillRect(event->rect(), Qt::darkGray);
220                painter.setPen(Qt::black);
221                /*QFont font = painter.font();
222                font.setPixelSize(8);
223                painter.setFont(font);*/
224
225                int font_width = fontMetrics().width('4');
226
227                // ueber alle *zeichen* iterieren.
228                for(int i = 0; i < 80; i++) {
229                        painter.drawText(row_area->width() + i * font_width, 4, font_width, fontMetrics().height(), Qt::AlignCenter,
230                                QString::number(i));
231                }
232        } else {
233                qDebug("Illegal number area at numberAreaPaintEvent");
234        }
235}
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