1 /****************************************************************************
2 **
3 ** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
4 **
5 ** This file is part of the Edyuk project <http://edyuk.org>
6 **
7 ** This file may be used under the terms of the GNU General Public License
8 ** version 3 as published by the Free Software Foundation and appearing in the
9 ** file GPL.txt included in the packaging of this file.
10 **
11 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13 **
14 ****************************************************************************/
15
16 #include "qlinemarkpanel.h"
17
18 /*!
19 \file qlinemarkpanel.cpp
20 \brief Implementation of the QLineMarkPanel class.
21 */
22
23 #include "qeditor.h"
24
25 #include "qdocument.h"
26 #include "qdocumentline.h"
27
28 #include "qlanguagedefinition.h"
29 #include "qlinemarksinfocenter.h"
30
31 /*!
32 \ingroup widgets
33 @{
34 */
35
36 /*!
37 \class QLineMarkPanel
38 \brief A specific panel in charge of drawing line marks of an editor
39 */
40
QCE_AUTO_REGISTER(QLineMarkPanel)41 QCE_AUTO_REGISTER(QLineMarkPanel)
42
43 /*!
44 \brief Constructor
45 */
46 QLineMarkPanel::QLineMarkPanel(QWidget *p)
47 : QPanel(p)
48 {
49 setObjectName("lineMarkPanel");
50 minMarksPerLine=1;
51 maxMarksPerLine=1;
52 setFixedWidth(minMarksPerLine*16+2);
53 }
54
55 /*!
56 \brief Empty destructor
57 */
~QLineMarkPanel()58 QLineMarkPanel::~QLineMarkPanel()
59 {
60
61 }
62
63 /*!
64
65 */
type() const66 QString QLineMarkPanel::type() const
67 {
68 return "Line marks";
69 }
70
setToolTipForTouchedMark(QString text)71 void QLineMarkPanel::setToolTipForTouchedMark(QString text){
72 markToolTip=text;
73 }
74
75 /*!
76 \internal
77 */
event(QEvent * e)78 bool QLineMarkPanel::event(QEvent *e) {
79 if (e->type() == QEvent::ToolTip) {
80 QHelpEvent *helpEvent = static_cast<QHelpEvent *>(e);
81 int linen=editor()->document()->lineNumber(editor()->verticalOffset()+helpEvent->y());
82 markToolTip="";
83 if (linen>-1 && linen<editor()->document()->lines()) {
84 QDocumentLine line = editor()->document()->line(linen);
85 QList<int> lm = line.marks();
86 int count = 1;
87 int bestMark = -1;
88 QLineMarksInfoCenter *mic = QLineMarksInfoCenter::instance();
89 foreach ( int id, lm )
90 {
91 if (mic->markType(id).icon.isNull())
92 continue;
93 if (helpEvent->x()>count && helpEvent->x()<count+16)
94 bestMark = id; //no break do to overdraw
95 if (count < 16*(maxMarksPerLine-1)) {
96 count += 16;
97 if (bestMark!=-1) break;
98 }
99 }
100 if (bestMark!=-1)
101 emit toolTipRequested(linen,bestMark);
102 }
103 if (markToolTip.isEmpty()) QToolTip::hideText();
104 else QToolTip::showText(helpEvent->globalPos(), markToolTip);
105 e->setAccepted(true);
106 }
107 return QWidget::event(e);
108 }
paint(QPainter * p,QEditor * e)109 bool QLineMarkPanel::paint(QPainter *p, QEditor *e)
110 {
111 if ( !e || !e->document() )
112 return true;
113
114 m_rects.clear();
115 m_lines.clear();
116 QDocument *d = e->document();
117
118 int realMarksPerLine = d->maxMarksPerLine();
119 int marksPerLine = realMarksPerLine;
120 if (marksPerLine<minMarksPerLine) marksPerLine=minMarksPerLine;
121 if (marksPerLine>maxMarksPerLine) marksPerLine=maxMarksPerLine;
122 setFixedWidth(marksPerLine ? marksPerLine * 16 + 2 : 18);
123
124 int n;
125 qreal posY,
126 as = QFontMetricsF(d->font()).ascent(),
127 ls = d->getLineSpacing(),
128 pageBottom = e->viewport()->height(),
129 contentsY = e->verticalOffset();
130
131 QLineMarksInfoCenter *mic = QLineMarksInfoCenter::instance();
132
133 n = d->lineNumber(contentsY);
134 posY = 2 + d->y(n) - contentsY;
135
136 //qDebug("first = %i; last = %i", first, last);
137 //qDebug("beg pos : %i", posY);
138 //qDebug("<session>");
139 for ( ; ; ++n )
140 {
141 //qDebug("n = %i; pos = %i", n, posY);
142 QDocumentLine line = d->line(n);
143
144 if ( line.isNull() || ((posY - as) > pageBottom) )
145 break;
146
147 if ( line.isHidden() )
148 continue;
149
150 m_lines << n;
151 m_rects << QRectF(0, posY, width(), ls);
152
153 if ( realMarksPerLine )
154 {
155 int count = 1;
156 QList<int> lm = line.marks();
157
158 foreach ( int id, lm )
159 {
160 const QIcon & icon = mic->markType(id).icon;
161
162 if ( icon.isNull() )
163 continue;
164
165 int size = qMin(16., ls-4); // (maxWidth, maxHeight) assuming square icons
166
167
168 qreal x = count,
169 y = posY + ( (ls - size) /2 );
170 #ifdef Q_OS_MAC
171 QPixmap pix=icon.pixmap(2*size); // oversampling on mac !!!!
172 #else
173 QPixmap pix=icon.pixmap(size);
174 #endif
175
176 p->drawPixmap(QRectF(x, y, size,size),pix,pix.rect());
177
178 if (count < 16*(maxMarksPerLine-1))
179 count += 16;
180 }
181 }
182
183 posY += ls * line.lineSpan();
184 }
185 //qDebug("</session>");
186
187 return true;
188 }
189
190 /*!
191 \internal
192 */
mousePressEvent(QMouseEvent * e)193 void QLineMarkPanel::mousePressEvent(QMouseEvent *e)
194 {
195 // if ( !editor() || !editor()->document() || !editor()->marker() )
196 // {
197 // return QPanel::mousePressEvent(e);
198 // }
199 //
200 QPanel::mousePressEvent(e);
201 e->accept();
202 }
203
204 /*!
205 \internal
206 */
mouseReleaseEvent(QMouseEvent * e)207 void QLineMarkPanel::mouseReleaseEvent(QMouseEvent *e)
208 {
209 if ( !editor() || !editor()->document() || !editor()->languageDefinition() || e->button()!= Qt::LeftButton)
210 {
211 QPanel::mouseReleaseEvent(e);
212 return;
213 }
214
215 int line=editor()->document()->lineNumber(editor()->verticalOffset()+e->y());
216 if (editor()->document()->line(line).isValid())
217 emit lineClicked(line);
218
219 //QMessageBox::warning(0, 0, "clik.");
220
221 QDocumentLine l;
222 QLanguageDefinition *d = editor()->languageDefinition();
223 const int id = QLineMarksInfoCenter::instance()->markTypeId(d->defaultLineMark());
224 if ( id < 0 )
225 return;
226
227 e->accept();
228
229
230 for ( int i = 0; i < m_rects.count(); ++i )
231 {
232 if ( m_rects.at(i).contains(e->pos()) )
233 {
234 l = editor()->document()->line(m_lines.at(i));
235 l.toggleMark(id);
236 //m->toggleDefaultMark(l, -1);
237
238 break;
239 }
240 }
241
242 QPanel::mouseReleaseEvent(e);
243 }
244
245 /*!
246 \internal
247 */
contextMenuEvent(QContextMenuEvent * e)248 void QLineMarkPanel::contextMenuEvent(QContextMenuEvent *e)
249 {
250 if ( !editor() || !editor()->document() )
251 {
252 e->ignore();
253 return;
254 }
255
256 int line=editor()->document()->lineNumber(editor()->verticalOffset()+e->y());
257 if (editor()->document()->line(line).isValid())
258 emit contextMenuRequested(line, e->globalPos());
259
260 /*
261 QTextBlock b;
262 QMarker *m = editor()->marker();
263 QTextDocument *d = editor()->document();
264
265 e->accept();
266
267 QHash<int, QRect>::iterator i;
268
269 for ( i = rects.begin(); i != rects.end(); i++ )
270 {
271 b = d->findBlock(i.key());
272
273 if ( i->contains( e->pos() ) )
274 return m->menu(b, e->globalPos());
275 }
276 */
277 }
278
279 /*! @} */
280