kexi

kexirecordmarker.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2002 Lucijan Busch <lucijan@gmx.at>
3 Copyright (C) 2002 Till Busch <till@bux.at>
4 Copyright (C) 2002 Daniel Molkentin <molkentin@kde.org>
5 Copyright (C) 2003-2006 Jaroslaw Staniek <js@iidea.pl>
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21*/
22
23#include "kexirecordmarker.h"
24
25#include <tqcolor.h>
26#include <tqstyle.h>
27#include <tqpixmap.h>
28#include <tqpainter.h>
29#include <tqimage.h>
30#include <tqapplication.h>
31
32#include <kdebug.h>
33#include <kstaticdeleter.h>
34
35#include <kexiutils/utils.h>
36
37static KStaticDeleter<TQImage> KexiRecordMarker_pen_deleter, KexiRecordMarker_plus_deleter;
38TQImage* KexiRecordMarker_pen = 0, *KexiRecordMarker_plus = 0;
39
40static const unsigned char img_pen_data[] = {
41 0x00,0x00,0x03,0x30,0x78,0x9c,0xfb,0xff,0xff,0x3f,0xc3,0x7f,0x32,0x30,
42 0x10,0x80,0x88,0xff,0xe4,0xe8,0x85,0xe9,0xc7,0xc6,0x26,0x55,0x3f,0x3a,
43 0x4d,0x8e,0x7e,0x72,0xfc,0x32,0xd2,0xf5,0xa3,0xeb,0xa5,0xb5,0x7e,0x5c,
44 0xe9,0x85,0x54,0xfb,0xb1,0xa5,0x1b,0x52,0xdc,0x0e,0x00,0xf2,0xea,0x0a,
45 0x13
46};
47static const unsigned char img_plus_data[] = {
48 0x00,0x00,0x01,0x90,0x78,0x9c,0xfb,0xff,0xff,0x3f,0xc3,0x7f,0x28,0x86,
49 0x82,0xff,0x50,0x0c,0x17,0x47,0xc7,0xd4,0x50,0x87,0x05,0xc0,0xd5,0xe1,
50 0x10,0xa7,0x16,0x26,0xca,0x5e,0x7c,0xfe,0x20,0x47,0x1d,0xb2,0x5a,0x5c,
51 0xea,0x40,0x72,0x00,0x03,0x6e,0x74,0x8c
52};
53
54static struct EmbedImage {
55 int width, height, depth;
56 const unsigned char *data;
57 ulong compressed;
58 int numColors;
59 const TQRgb *colorTable;
60 bool alpha;
61 const char *name;
62} embed_image[] = {
63 { 17, 12, 32, (const unsigned char*)img_pen_data, 57, 0, 0, true, "tableview_pen.png" },
64 { 10, 10, 32, (const unsigned char*)img_pen_data, 50, 0, 0, true, "tableview_plus.png" }
65};
66
67TQImage* getImg(const unsigned char* data, int id)
68{
69 TQByteArray baunzip;
70 baunzip = tqUncompress( data, embed_image[id].compressed );
71 TQImage *img = new TQImage( TQImage((uchar*)baunzip.data(),
72 embed_image[id].width, embed_image[id].height,
73 embed_image[id].depth, (TQRgb*)embed_image[id].colorTable,
74 embed_image[id].numColors, TQImage::BigEndian
75 ).copy() );
76 if ( embed_image[id].alpha )
77 img->setAlphaBuffer(true);
78 return img;
79}
80
81static void initRecordMarkerImages()
82{
83 if (!KexiRecordMarker_pen) {
85 KexiRecordMarker_pen_deleter.setObject( KexiRecordMarker_pen, getImg(img_pen_data, 0) );
86 KexiRecordMarker_plus_deleter.setObject( KexiRecordMarker_plus, getImg(img_plus_data, 1) );
87 }
88}
89
90//----------------------------------------------------------------
91
93class KexiRecordMarker::Private
94{
95public:
96 Private()
97 : rowHeight(1)
98 , offset(0)
99 , currentRow(-1)
100 , highlightedRow(-1)
101 , editRow(-1)
102 , rows(0)
103 , selectionBackgroundColor(tqApp->palette().active().highlight())
104 , showInsertRow(true)
105 {
106 }
107 int rowHeight;
108 int offset;
109 int currentRow;
110 int highlightedRow;
111 int editRow;
112 int rows;
113 TQColor selectionBackgroundColor;
114 bool showInsertRow : 1;
115};
116
117//----------------------------------------------------------------
118
119KexiRecordMarker::KexiRecordMarker(TQWidget *parent, const char* name)
120 : TQWidget(parent, name)
121 , d( new Private() )
122{
123 initRecordMarkerImages();
124}
125
126KexiRecordMarker::~KexiRecordMarker()
127{
128 delete d;
129}
130
131TQImage* KexiRecordMarker::penImage()
132{
133 initRecordMarkerImages();
134 return KexiRecordMarker_pen;
135}
136
137TQImage* KexiRecordMarker::plusImage()
138{
139 initRecordMarkerImages();
140 return KexiRecordMarker_plus;
141}
142
143void KexiRecordMarker::addLabel(bool upd)
144{
145 d->rows++;
146 if (upd)
147 update();
148}
149
150void KexiRecordMarker::removeLabel(bool upd)
151{
152 if (d->rows > 0) {
153 d->rows--;
154 if (upd)
155 update();
156 }
157}
158
159void KexiRecordMarker::addLabels(int num, bool upd)
160{
161 d->rows += num;
162 if (upd)
163 update();
164}
165
166void KexiRecordMarker::clear(bool upd)
167{
168 d->rows=0;
169 if (upd)
170 update();
171}
172
173int KexiRecordMarker::rows() const
174{
175 if (d->showInsertRow)
176 return d->rows +1;
177 else
178 return d->rows;
179}
180
181void KexiRecordMarker::paintEvent(TQPaintEvent *e)
182{
183 TQPainter p(this);
184 TQRect r(e->rect());
185
186 int first = (r.top() + d->offset) / d->rowHeight;
187 int last = (r.bottom() + d->offset) / d->rowHeight;
188 if(last > (d->rows-1+(d->showInsertRow?1:0)))
189 last = d->rows-1+(d->showInsertRow?1:0);
190
191 TQColorGroup selectedColorGroup(colorGroup());
192 selectedColorGroup.setColor( TQColorGroup::Button,
193 KexiUtils::blendedColors( selectedColorGroup.color(TQColorGroup::Background),
194 d->selectionBackgroundColor, 2, 1) );
195 selectedColorGroup.setColor( TQColorGroup::Background,
196 selectedColorGroup.color(TQColorGroup::Button) ); //set background color as well (e.g. for thinkeramik)
197 TQColorGroup highlightedColorGroup(colorGroup());
198 highlightedColorGroup.setColor( TQColorGroup::Button,
199 KexiUtils::blendedColors( highlightedColorGroup.color(TQColorGroup::Background),
200 d->selectionBackgroundColor, 4, 1) );
201 highlightedColorGroup.setColor( TQColorGroup::Background,
202 highlightedColorGroup.color(TQColorGroup::Button) ); //set background color as well (e.g. for thinkeramik)
203 for(int i=first; i <= last; i++)
204 {
205 int y = ((d->rowHeight * i)-d->offset);
206 TQRect r(0, y, width(), d->rowHeight);
207 p.drawRect(r);
208 style().drawPrimitive( TQStyle::PE_HeaderSection, &p, r,
209 (d->currentRow == i) ? selectedColorGroup : (d->highlightedRow == i ? highlightedColorGroup : colorGroup()),
210 TQStyle::Style_Raised | (isEnabled() ? TQStyle::Style_Enabled : 0));
211 }
212 if (d->editRow!=-1 && d->editRow >= first && d->editRow <= (last/*+1 for insert row*/)) {
213 //show pen when editing
214 int ofs = d->rowHeight / 4;
215 int pos = ((d->rowHeight*(d->currentRow>=0?d->currentRow:0))-d->offset)-ofs/2+1;
216 p.drawImage((d->rowHeight-KexiRecordMarker_pen->width())/2,
217 (d->rowHeight-KexiRecordMarker_pen->height())/2+pos,*KexiRecordMarker_pen);
218 }
219 else if (d->currentRow >= first && d->currentRow <= last
220 && (!d->showInsertRow || (d->showInsertRow && d->currentRow < last)))/*don't display marker for 'insert' row*/
221 {
222 //show marker
223 p.setBrush(colorGroup().foreground());
224 p.setPen(TQPen(TQt::NoPen));
225 TQPointArray points(3);
226 int ofs = d->rowHeight / 4;
227 int ofs2 = (width() - ofs) / 2 -1;
228 int pos = ((d->rowHeight*d->currentRow)-d->offset)-ofs/2+2;
229 points.putPoints(0, 3, ofs2, pos+ofs, ofs2 + ofs, pos+ofs*2,
230 ofs2,pos+ofs*3);
231 p.drawPolygon(points);
232// kdDebug() <<"KexiRecordMarker::paintEvent(): POLYGON" << endl;
233/* int half = d->rowHeight / 2;
234 points.setPoints(3, 2, pos + 2, width() - 5, pos + half, 2, pos + (2 * half) - 2);*/
235 }
236 if (d->showInsertRow && d->editRow < last
237 && last == (d->rows-1+(d->showInsertRow?1:0)) ) {
238 //show plus sign
239 int pos = ((d->rowHeight*last)-d->offset)+(d->rowHeight-KexiRecordMarker_plus->height())/2;
240// p.drawImage((width()-d->plusImg.width())/2-1, pos, d->plusImg);
241 p.drawImage((width()-KexiRecordMarker_plus->width())/2, pos, *KexiRecordMarker_plus);
242 }
243}
244
245void KexiRecordMarker::setCurrentRow(int row)
246{
247 if (row == d->currentRow)
248 return;
249 int oldRow = d->currentRow;
250 d->currentRow=row;
251
252 if (oldRow != -1)
253 update(0,(d->rowHeight*(oldRow))-d->offset-1, width()+2, d->rowHeight+2);
254 if (d->currentRow != -1)
255 update(0,(d->rowHeight*d->currentRow)-d->offset-1, width()+2, d->rowHeight+2);
256}
257
258void KexiRecordMarker::setHighlightedRow(int row)
259{
260 if (row == d->highlightedRow)
261 return;
262 int oldRow = d->highlightedRow;
263 d->highlightedRow = row;
264
265 if (oldRow != -1)
266 update(0,(d->rowHeight*(oldRow))-d->offset-1, width()+2, d->rowHeight+2);
267 if (d->currentRow != -1)
268 update(0,(d->rowHeight*d->highlightedRow)-d->offset-1, width()+2, d->rowHeight+2);
269}
270
271void KexiRecordMarker::setOffset(int offset)
272{
273 int oldOff = d->offset;
274 d->offset = offset;
275 scroll(0,oldOff-offset);
276}
277
278void KexiRecordMarker::setCellHeight(int cellHeight)
279{
280 d->rowHeight = cellHeight;
281}
282
284{
285 d->editRow = row;
286//TODO: update only needed area!
287 update();
288}
289
290void KexiRecordMarker::showInsertRow(bool show)
291{
292 d->showInsertRow = show;
293//TODO: update only needed area!
294 update();
295}
296
297void KexiRecordMarker::setSelectionBackgroundColor(const TQColor &color)
298{
299 d->selectionBackgroundColor = color;
300}
301
302TQColor KexiRecordMarker::selectionBackgroundColor() const
303{
304 return d->selectionBackgroundColor;
305}
306
307#include "kexirecordmarker.moc"
void setEditRow(int row)
void addLabels(int num, bool upd=true)
KEXIUTILS_EXPORT TQColor blendedColors(const TQColor &c1, const TQColor &c2, int factor1=1, int factor2=1)