3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
16 #define DEFAULT_WIDTH 100
17 #define DEFAULT_LINEHEIGHT 1
19 KTextView::KTextView(QWidget
* parent
, const char* name
, WFlags f
) :
20 TableView(parent
, name
, f
),
21 m_width(DEFAULT_WIDTH
),
22 m_height(DEFAULT_LINEHEIGHT
),
27 setBackgroundColor(colorGroup().base());
30 KTextView::~KTextView()
35 * Update cell width and hight; returns whether there is a change
36 * Cell geometry: There are 2 pixels to the left and to the right
37 * and 1 pixel _below_ the line
39 bool KTextView::updateCellSize(const QString
& text
)
43 QRect r
= p
.boundingRect(0,0, 0,0,
44 AlignLeft
| SingleLine
| DontClip
| ExpandTabs
,
48 int w
= r
.width() + 4;
53 int h
= r
.height() + 1;
61 void KTextView::setText(const QString
& text
)
63 QStringList l
= QStringList::split('\n', text
, true);
65 bool autoU
= autoUpdate();
68 int lineNo
= QMIN(m_texts
.size(), l
.size());
69 for (int i
= 0; i
< lineNo
; i
++) {
72 if (l
.size() > m_texts
.size()) {
73 // the new text has more lines than the old one
74 // here lineNo is the number of lines of the old text
75 for (size_t i
= lineNo
; i
< l
.size(); i
++) {
79 // the new file has fewer lines
80 // here lineNo is the number of lines of the new file
81 // remove the excessive lines
82 m_texts
.resize(lineNo
);
92 // if the cursor is in the deleted lines, move it to the last line
93 if (m_curRow
>= int(m_texts
.size())) {
94 m_curRow
= -1; /* at this point don't have an active row */
95 activateLine(m_texts
.size()-1); /* now we have */
99 void KTextView::insertLine(const QString
& text
)
101 m_texts
.push_back(text
);
102 setNumRows(m_texts
.size());
104 updateCellSize(text
);
113 * TODO: This function doesn't shrink the line length if the longest line
114 * is replaced by a shorter one.
116 void KTextView::replaceLine(int line
, const QString
& text
)
118 if (line
< 0 || line
>= int(m_texts
.size()))
121 m_texts
[line
] = text
;
123 bool update
= updateCellSize(text
);
133 void KTextView::insertParagraph(const QString
& text
, int row
)
135 m_texts
.insert(m_texts
.begin()+row
, text
);
137 // update line widths
138 updateCellSize(text
);
140 setNumRows(m_texts
.size());
142 if (autoUpdate() && isVisible()) {
148 void KTextView::removeParagraph(int row
)
150 m_texts
.erase(m_texts
.begin()+row
);
151 setNumRows(m_texts
.size());
153 if (autoUpdate() && isVisible()) {
159 void KTextView::setCursorPosition(int row
, int)
164 void KTextView::cursorPosition(int* row
, int* col
)
170 int KTextView::cellWidth(int /*col*/) const
175 int KTextView::cellHeight(int /*row*/) const
180 int KTextView::textCol() const
182 // by default, the text is in column 0
186 void KTextView::paintCell(QPainter
* p
, int row
, int /*col*/)
188 if (row
>= int(m_texts
.size())) {
191 if (row
== m_curRow
) {
193 p
->fillRect(0,0, m_width
,m_height
, QBrush(colorGroup().background()));
195 const QString
& text
= m_texts
[row
];
196 p
->drawText(2,0, m_width
-4, m_height
,
197 AlignLeft
| SingleLine
| DontClip
| ExpandTabs
,
198 text
, text
.length());
201 void KTextView::keyPressEvent(QKeyEvent
* ev
)
203 int oldRow
= m_curRow
;
205 // go to line 0 if no current line
211 int numVisibleRows
, newRow
, newX
;
216 activateLine(m_curRow
-1);
220 if (m_curRow
< numRows()-1) {
221 activateLine(m_curRow
+1);
225 /* this method doesn't work for variable height lines */
226 numVisibleRows
= lastRowVisible()-topCell();
227 newRow
= m_curRow
- QMAX(numVisibleRows
,1);
230 activateLine(newRow
);
233 /* this method doesn't work for variable height lines */
234 numVisibleRows
= lastRowVisible()-topCell();
235 newRow
= m_curRow
+ QMAX(numVisibleRows
,1);
236 if (newRow
>= numRows())
237 newRow
= numRows()-1;
238 activateLine(newRow
);
241 // scroll left and right by a few pixels
243 newX
= xOffset() - viewWidth()/10;
244 setXOffset(QMAX(newX
, 0));
247 newX
= xOffset() + viewWidth()/10;
248 setXOffset(QMIN(newX
, maxXOffset()));
252 QWidget::keyPressEvent(ev
);
257 if (m_curRow
!= oldRow
&& !rowIsVisible(m_curRow
)) {
258 // if the old row was visible, we scroll the view by some pixels
259 // if the old row was not visible, we place active row at the top
260 if (oldRow
>= 0 && rowIsVisible(oldRow
)) {
261 int diff
= m_curRow
- oldRow
;
262 int newTop
= topCell() + diff
;
263 setTopCell(QMAX(newTop
,0));
265 setTopCell(m_curRow
);
271 void KTextView::mousePressEvent(QMouseEvent
* ev
)
273 int row
= findRow(ev
->y());
277 void KTextView::focusInEvent(QFocusEvent
*)
280 * The base class does a repaint(), which causes flicker. So we do
285 void KTextView::focusOutEvent(QFocusEvent
*)
288 * The base class does a repaint(), which causes flicker. So we do
293 void KTextView::activateLine(int row
)
300 int oldRow
= m_curRow
;
301 // note that row may be < 0
303 // must change m_curRow first, so that updateCell(oldRow) erases the old line!
305 updateCell(oldRow
, col
);
308 updateCell(row
, col
);
313 /* This is needed to make the kcontrol's color setup working */
314 void KTextView::paletteChange(const QPalette
& oldPal
)
316 setBackgroundColor(colorGroup().base());
317 TableView::paletteChange(oldPal
);
319 // recompute window size
320 m_width
= DEFAULT_WIDTH
;
321 m_height
= DEFAULT_LINEHEIGHT
;
322 for (size_t i
= 0; i
< m_texts
.size(); i
++) {
323 updateCellSize(m_texts
[i
]);
328 void KTextView::setTabWidth(int numChars
)
330 QFontMetrics fm
= font();
331 int newTabWidth
= fm
.width('x') * numChars
;
332 if (newTabWidth
== m_tabWidth
)
334 m_tabWidth
= newTabWidth
;
336 // recompute window width
337 m_width
= DEFAULT_WIDTH
;
338 for (size_t i
= 0; i
< m_texts
.size(); i
++) {
339 updateCellSize(m_texts
[i
]);
348 void KTextView::setupPainter(QPainter
* p
)
350 p
->setTabStops(m_tabWidth
);
353 int KTextView::charAt(const QPoint
& p
, int* para
)
355 if (findCol(p
.x()) != textCol())
357 int row
= findRow(p
.y());
362 // find top-left corner of text cell
364 if (!colXPos(textCol(), &left
))
366 if (!rowYPos(row
, &top
))
369 // get the bounding rect of the text
370 QPainter
painter(this);
371 setupPainter(&painter
);
372 const QString
& text
= m_texts
[row
];
374 painter
.boundingRect(left
+2, top
, 0,0,
375 AlignLeft
| SingleLine
| DontClip
| ExpandTabs
,
376 text
, text
.length());
377 if (!bound
.contains(p
))
378 return -1; /* p is outside text */
380 for (uint n
= 0; n
< text
.length(); n
++)
383 * If p is in the rectangle that has n+1 characters, than n
384 * is the character we are looking for
387 painter
.boundingRect(left
+2, top
, 0,0,
388 AlignLeft
| SingleLine
| DontClip
| ExpandTabs
,
390 if (bound
.contains(p
))