lib

editoritem.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
3 Copyright (C) 2004 Alexander Dymo <cloudtemple@mskat.net>
4 Copyright (C) 2004-2006 Jaroslaw Staniek <js@iidea.pl>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20*/
21
22#include "editoritem.h"
23#include "editor.h"
24#include "property.h"
25#include "widget.h"
26#include "factory.h"
27#include "utils.h"
28
29#include <tqpainter.h>
30#include <tqpixmap.h>
31#include <tqheader.h>
32#include <tqstyle.h>
33#include <tqlabel.h>
34#include <tqlayout.h>
35
36#include <kdebug.h>
37#include <kiconloader.h>
38#include <tdestyle.h>
39#include <tdepopupmenu.h>
40#include <tdeapplication.h>
41
42#define BRANCHBOX_SIZE 9
43
44namespace KoProperty {
45class EditorItemPrivate
46{
47 public:
48 EditorItemPrivate()
49 : property(0) {}
50 ~EditorItemPrivate() {}
51
52 Property *property;
53 Editor *editor;
54};
55
57static void paintListViewExpander(TQPainter* p, TQWidget* w, int height, const TQColorGroup& cg, bool isOpen)
58{
59 const int marg = (height -2 - BRANCHBOX_SIZE) / 2;
60 int xmarg = marg;
61// if (dynamic_cast<EditorGroupItem*>(item))
62// xmarg = xmarg * 10 / 14 -1;
63#if 0
65 TDEStyle* tdestyle = dynamic_cast<TDEStyle*>(widget->style());
66 if (tdestyle) {
67 tdestyle->drawTDEStylePrimitive(
68 TDEStyle::KPE_ListViewExpander, p, w, TQRect( xmarg, marg, BRANCHBOX_SIZE, BRANCHBOX_SIZE ),
69 cg, isOpen ? 0 : TQStyle::Style_On,
70 TQStyleOption::Default);
71 }
72 else {
73#endif
74 Q_UNUSED(w);
75 //draw by hand
76 p->setPen( KPROPEDITOR_ITEM_BORDER_COLOR );
77 p->drawRect(xmarg, marg, BRANCHBOX_SIZE, BRANCHBOX_SIZE);
78 p->fillRect(xmarg+1, marg + 1, BRANCHBOX_SIZE-2, BRANCHBOX_SIZE-2,
79// item->listView()->paletteBackgroundColor());
80 cg.base());
81// p->setPen( item->listView()->paletteForegroundColor() );
82 p->setPen( cg.foreground() );
83 p->drawLine(xmarg+2, marg+BRANCHBOX_SIZE/2, xmarg+BRANCHBOX_SIZE-3, marg+BRANCHBOX_SIZE/2);
84 if(!isOpen) {
85 p->drawLine(xmarg+BRANCHBOX_SIZE/2, marg+2,
86 xmarg+BRANCHBOX_SIZE/2, marg+BRANCHBOX_SIZE-3);
87 }
88// }
89}
90
93class GroupWidgetBase : public TQWidget
94{
95 public:
96 GroupWidgetBase(TQWidget* parent)
97 : TQWidget(parent)
98 , m_isOpen(true)
99 , m_mouseDown(false)
100 {
101 setSizePolicy(TQSizePolicy(TQSizePolicy::Preferred, TQSizePolicy::Fixed, 0, 1));
102 }
103
104 void setText( const TQString &text )
105 {
106 m_titleStr = text;
107 }
108
109 void setIcon( const TQPixmap &pix )
110 {
111 m_miniicon = pix;
112 }
113
114 virtual bool isOpen() const
115 {
116 return m_isOpen;
117 }
118
119 virtual void setOpen(bool set)
120 {
121 m_isOpen = set;
122 }
123
124 virtual TQSize sizeHint () const
125 {
126 TQSize s( TQWidget::sizeHint() );
127 s.setHeight(fontMetrics().height()*2);
128 return s;
129 }
130
131 protected:
132 virtual void paintEvent(TQPaintEvent *) {
133 TQRect r(rect());
134 TQPainter p(this);
135 TQStyle::StyleFlags flags = m_mouseDown ? TQStyle::Style_Down : TQStyle::Style_Default;
136 kapp->style().drawPrimitive(TQStyle::PE_HeaderSection, &p, r, palette().active(), flags);
137
138 paintListViewExpander(&p, this, r.height()+2, palette().active(), isOpen());
139 if (!m_miniicon.isNull()) {
140 p.drawPixmap(24, (r.height()-m_miniicon.height())/2, m_miniicon);
141 }
142
143 if (!m_titleStr.isNull())
144 {
145 int indent = 16 + (m_miniicon.isNull() ? 0 : (m_miniicon.width()+4));
146 p.setPen(palette().active().text());
147 TQFont f = p.font();
148 f.setBold(true);
149 p.setFont(f);
150 p.drawText(indent+8, 0, width()-(indent+8),
151 height(), AlignLeft | AlignVCenter | SingleLine,
152 m_titleStr);
153 }
154// p.setPen(palette().active().mid());
155// p.drawLine(0, 0, r.right(), 0);
156 }
157
158 virtual bool event( TQEvent * e ) {
159 if (e->type()==TQEvent::MouseButtonPress || e->type()==TQEvent::MouseButtonRelease) {
160 TQMouseEvent* me = static_cast<TQMouseEvent*>(e);
161 if (me->button() == TQt::LeftButton) {
162 m_mouseDown = e->type()==TQEvent::MouseButtonPress;
163 update();
164 }
165 }
166 return TQWidget::event(e);
167 }
168
169 protected:
170 TQString m_titleStr;
171 TQPixmap m_miniicon;
172 bool m_isOpen : 1;
173 bool m_mouseDown : 1;
174};
175
176class GroupWidget : public GroupWidgetBase
177{
178 public:
179 GroupWidget(EditorGroupItem *parentItem)
180 : GroupWidgetBase(parentItem->listView()->viewport())
181 , m_parentItem(parentItem)
182 {
183 }
184
185 virtual bool isOpen() const
186 {
187 return m_parentItem->isOpen();
188 }
189
190 protected:
191 EditorGroupItem *m_parentItem;
192};
193
194class GroupContainer::Private
195{
196 public:
197 Private() {}
198 TQVBoxLayout* lyr;
199 GroupWidgetBase *groupWidget;
200 TQGuardedPtr<TQWidget> contents;
201};
202
203}//namespace
204
205using namespace KoProperty;
206
207GroupContainer::GroupContainer(const TQString& title, TQWidget* parent)
208: TQWidget(parent)
209, d(new Private())
210{
211 setSizePolicy(TQSizePolicy(TQSizePolicy::Preferred, TQSizePolicy::Fixed, 0, 1));
212 d->lyr = new TQVBoxLayout(this);
213 d->groupWidget = new GroupWidgetBase(this);
214 d->groupWidget->setText( title );
215 d->lyr->addWidget(d->groupWidget);
216 d->lyr->addSpacing(4);
217}
218
219GroupContainer::~GroupContainer()
220{
221 delete d;
222}
223
224void GroupContainer::setContents( TQWidget* contents )
225{
226 if (d->contents) {
227 d->contents->hide();
228 d->lyr->remove(d->contents);
229 delete d->contents;
230 }
231 d->contents = contents;
232 if (d->contents) {
233 d->lyr->addWidget(d->contents);
234 d->contents->show();
235 }
236 update();
237}
238
239bool GroupContainer::event( TQEvent * e ) {
240 if (e->type()==TQEvent::MouseButtonPress) {
241 TQMouseEvent* me = static_cast<TQMouseEvent*>(e);
242 if (me->button() == TQt::LeftButton && d->contents && d->groupWidget->rect().contains(me->pos())) {
243 d->groupWidget->setOpen(!d->groupWidget->isOpen());
244 if (d->groupWidget->isOpen())
245 d->contents->show();
246 else
247 d->contents->hide();
248 d->lyr->invalidate();
249 update();
250 }
251 }
252 return TQWidget::event(e);
253}
254
256
257EditorItem::EditorItem(Editor *editor, EditorItem *parent, Property *property, TQListViewItem *after)
258 : TDEListViewItem(parent, after,
259 property->captionForDisplaying().isEmpty() ? property->name() : property->captionForDisplaying())
260{
261 d = new EditorItemPrivate();
262 d->property = property;
263 d->editor = editor;
264
265 setMultiLinesEnabled(true);
266 //setHeight(static_cast<Editor*>(listView())->baseRowHeight()*3);
267/*
268 if (property && !property->caption().isEmpty()) {
269 TQSimpleRichText srt(property->caption(), font());
270 srt.setWidth(columnWidth(0)-KPROPEDITOR_ITEM_MARGIN*2-20+1);
271 int oldHeight = it.current()->height();
272 int textHeight = srt.height()+KPROPEDITOR_ITEM_MARGIN;
273 int textLines = textHeight / d->baseRowHeight + (((textHeight % d->baseRowHeight) > 0) ? 1 : 0);
274 kdDebug() << " textLines: " << textLines << endl;
275 if (textLines != newNumLines) {
276 dynamic_cast<EditorItem*>(it.current())->setHeight(newNumLines * d->baseRowHeight);
277 }
278 kdDebug() << it.current()->text(0) << ": " << oldHeight << " -> " << newHeight << endl;
279 }
280*/
281}
282
284 : TDEListViewItem(parent)
285{
286 d = new EditorItemPrivate();
287 d->property = 0;
288 d->editor = 0;
289 setMultiLinesEnabled(true);
290}
291
292EditorItem::EditorItem(EditorItem *parent, const TQString &text)
293 : TDEListViewItem(parent, text)
294{
295 d = new EditorItemPrivate();
296 d->property = 0;
297 d->editor = 0;
298 setMultiLinesEnabled(true);
299}
300
301EditorItem::EditorItem(EditorItem *parent, EditorItem *after, const TQString &text)
302 : TDEListViewItem(parent, after, text)
303{
304 d = new EditorItemPrivate();
305 d->property = 0;
306 d->editor = 0;
307 setMultiLinesEnabled(true);
308}
309
310EditorItem::~EditorItem()
311{
312 delete d;
313}
314
317{
318 return d->property;
319}
320
321void
322EditorItem::paintCell(TQPainter *p, const TQColorGroup & cg, int column, int width, int align)
323{
324 //int margin = static_cast<Editor*>(listView())->itemMargin();
325 if(!d->property)
326 return;
327
328 if(column == 0)
329 {
330 TQFont font = listView()->font();
331 if(d->property->isModified())
332 font.setBold(true);
333 p->setFont(font);
334 p->setBrush(cg.highlight());
335 p->setPen(cg.highlightedText());
336 TDEListViewItem::paintCell(p, cg, column, width, align);
337 p->fillRect(parent() ? 0 : 50, 0, width, height()-1,
338 TQBrush(isSelected() ? cg.highlight() : backgroundColor()));
339 p->setPen(isSelected() ? cg.highlightedText() : cg.text());
340 int delta = -20+KPROPEDITOR_ITEM_MARGIN;
341 if ((firstChild() && dynamic_cast<EditorGroupItem*>(parent()))) {
342 delta = -KPROPEDITOR_ITEM_MARGIN-1;
343 }
344 if (dynamic_cast<EditorDummyItem*>(parent())) {
345 delta = KPROPEDITOR_ITEM_MARGIN*2;
346 }
347 else if (parent() && dynamic_cast<EditorDummyItem*>(parent()->parent())) {
348 if (dynamic_cast<EditorGroupItem*>(parent()))
349 delta += KPROPEDITOR_ITEM_MARGIN*2;
350 else
351 delta += KPROPEDITOR_ITEM_MARGIN*5;
352 }
353 p->drawText(
354 TQRect(delta,2, width+listView()->columnWidth(1)-KPROPEDITOR_ITEM_MARGIN*2, height()),
355 TQt::AlignLeft | TQt::AlignTop /*| TQt::SingleLine*/, text(0));
356
357 p->setPen( KPROPEDITOR_ITEM_BORDER_COLOR );
358 p->drawLine(width-1, 0, width-1, height()-1);
359 p->drawLine(0, -1, width-1, -1);
360
361 p->setPen( KPROPEDITOR_ITEM_BORDER_COLOR );
362 if (dynamic_cast<EditorDummyItem*>(parent()))
363 p->drawLine(0, 0, 0, height()-1 );
364 }
365 else if(column == 1)
366 {
367 TQColorGroup icg(cg);
368 icg.setColor(TQColorGroup::Background, backgroundColor());
369 p->setBackgroundColor(backgroundColor());
370 Widget *widget = d->editor->createWidgetForProperty(d->property, false /*don't change Widget::property() */);
371 if(widget) {
372 TQRect r(0, 0, d->editor->header()->sectionSize(1), height() - (widget->hasBorders() ? 0 : 1));
373 p->setClipRect(r, TQPainter::CoordPainter);
374 p->setClipping(true);
375 widget->drawViewer(p, icg, r, d->property->value());
376 p->setClipping(false);
377 }
378 }
379 p->setPen( KPROPEDITOR_ITEM_BORDER_COLOR );
380 p->drawLine(0, height()-1, width, height()-1 );
381}
382
383void
384EditorItem::paintBranches(TQPainter *p, const TQColorGroup &cg, int w, int y, int h)
385{
386 p->eraseRect(0,0,w,h);
387 TDEListViewItem *item = static_cast<TDEListViewItem*>(firstChild());
388 if(!item)
389 return;
390
391 TQColor backgroundColor;
392 p->save();
393 p->translate(0,y);
394 TQFont font = listView()->font();
395 while(item)
396 {
397 if(item->isSelected())
398 backgroundColor = cg.highlight();
399 else {
400 if (dynamic_cast<EditorGroupItem*>(item))
401 backgroundColor = cg.base();
402 else
404 }
405// p->fillRect(-50,0,50, item->height(), TQBrush(backgroundColor));
406 p->save();
407 p->setPen( KPROPEDITOR_ITEM_BORDER_COLOR );
408 int delta = 0;
409 int fillWidth = w;
410 int x = 0;
411 if (dynamic_cast<EditorGroupItem*>(item->parent())) {
412 delta = 0;//-19;
413 fillWidth += 19;
414 }
415 else {
416 if (dynamic_cast<EditorGroupItem*>(item) || /*for flat mode*/ dynamic_cast<EditorDummyItem*>(item->parent()))
417 x = 19;
418 else
419 x = -19;
420 fillWidth += 19;
421 }
422 if (dynamic_cast<EditorDummyItem*>(item->parent())) {
423 x = 19;
424 }
425 else if (item->parent() && dynamic_cast<EditorDummyItem*>(item->parent()->parent())) {
426 x = 0;
427 }
428 p->fillRect(x+1, 0, fillWidth-1, item->height()-1, TQBrush(backgroundColor));
429 p->drawLine(x, item->height()-1, w, item->height()-1 );
430 if (!dynamic_cast<EditorGroupItem*>(item))
431 p->drawLine(x, 0, x, item->height()-1 );
432 p->restore();
433
434// for (int i=0; i<10000000; i++)
435// ;
436// if(item->isSelected()) {
437// p->fillRect(parent() ? 0 : 50, 0, w, item->height()-1, TQBrush(cg.highlight()));
438// p->fillRect(-50,0,50, item->height(), TQBrush(cg.highlight()));
439// }
440
441 //sorry, but we need to draw text here again
442 font.setBold( dynamic_cast<EditorGroupItem*>(item)
443 || (static_cast<EditorItem*>(item)->property() && static_cast<EditorItem*>(item)->property()->isModified()) );
444 p->setFont(font);
445 p->setPen(item->isSelected() ? cg.highlightedText() : cg.text());
446 if (item->firstChild() && dynamic_cast<EditorGroupItem*>(item->parent())) {
447 delta = 19-KPROPEDITOR_ITEM_MARGIN-1;
448 }
449 else if (dynamic_cast<EditorDummyItem*>(item->parent())) {
450 delta = 19;
451 }
452 if (item->parent() && dynamic_cast<EditorDummyItem*>(item->parent()->parent())) {
453 if (dynamic_cast<EditorGroupItem*>(item->parent()))
454 delta += KPROPEDITOR_ITEM_MARGIN*2;
455 else
456 delta += KPROPEDITOR_ITEM_MARGIN*5;
457 }
458
459 if (!dynamic_cast<EditorDummyItem*>(item->parent()))
460 p->drawText(TQRect(delta+1,0, w+listView()->columnWidth(1), item->height()),
461 TQt::AlignLeft | TQt::AlignVCenter /*| TQt::SingleLine*/, item->text(0));
462
463 if(item->firstChild()) {
464 paintListViewExpander(p, listView(), item->height(),
465 cg, item->isOpen());
466 }
467
468 // draw icon (if there is one)
469 EditorItem *editorItem = dynamic_cast<EditorItem*>(item);
470 if (editorItem && editorItem->property() && !editorItem->property()->icon().isEmpty()) {
471 //int margin = listView()->itemMargin();
472 TQPixmap pix = SmallIcon(editorItem->property()->icon());
473 if (!pix.isNull())
474 p->drawPixmap(-19+(19-pix.width())/2, (item->height() - pix.height()) / 2, pix);
475 }
476
477 p->translate(0, item->totalHeight());
478 item = (TDEListViewItem*)item->nextSibling();
479 }
480 p->restore();
481}
482
483void
484EditorItem::paintFocus(TQPainter *, const TQColorGroup &, const TQRect & )
485{
486}
487
488int
489EditorItem::compare( TQListViewItem *i, int col, bool ascending ) const
490{
491 if (!ascending)
492 return -TQListViewItem::key( col, ascending ).localeAwareCompare( i->key( col, ascending ) );
493
494 if (d->property) {
495// kopropertydbg << d->property->name() << " " << d->property->sortingKey() << " | "
496// << static_cast<EditorItem*>(i)->property()->name() << " "
497// << static_cast<EditorItem*>(i)->property()->sortingKey() << endl;
498 return d->property->sortingKey()
499 - ((dynamic_cast<EditorItem*>(i) && dynamic_cast<EditorItem*>(i)->property())
500 ? dynamic_cast<EditorItem*>(i)->property()->sortingKey() : 0);
501 }
502
503 return 0;
504// return d->order - static_cast<EditorItem*>(i)->d->order;
505}
506
507void
508EditorItem::setHeight( int height )
509{
510 TDEListViewItem::setHeight(height);
511}
512
514
515EditorGroupItem::EditorGroupItem(EditorItem *parent, EditorItem *after, const TQString &text, const TQString &icon, int sortOrder)
516 : EditorItem(parent, after, text)
517 , m_label(0)
518 , m_sortOrder(sortOrder)
519{
520 init(icon);
521}
522
523EditorGroupItem::EditorGroupItem(EditorItem *parent, const TQString &text, const TQString &icon, int sortOrder)
524 : EditorItem(parent, text)
525 , m_label(0)
526 , m_sortOrder(sortOrder)
527{
528 init(icon);
529}
530
531EditorGroupItem::~EditorGroupItem()
532{
533 delete m_label;
534}
535
536TQWidget* EditorGroupItem::label() const
537{
538 return m_label;
539}
540
541void EditorGroupItem::init(const TQString &icon)
542{
543 setOpen(true);
544 setSelectable(false);
545 m_label = new GroupWidget(this);
546 m_label->setText(text(0)); //todo: icon?
547 if (!icon.isEmpty())
548 m_label->setIcon( SmallIcon(icon) );
549 m_label->show();
550}
551
552void
553EditorGroupItem::paintCell(TQPainter *p, const TQColorGroup & cg, int column, int width, int /*align*/)
554{
555 Q_UNUSED(p);
556 Q_UNUSED(cg);
557 Q_UNUSED(column);
558 Q_UNUSED(width);
559 //no need to draw anything since there's a label on top of it
560// p->fillRect(0, 0, width, height(), cg.base());
561
562 //if(column == 1)
563 // return;
564 /*p->setPen( KPROPEDITOR_ITEM_BORDER_COLOR ); //! \todo custom color?
565
566 p->setClipRect(listView()->itemRect(this));
567 if(column == 1)
568 p->translate(-listView()->columnWidth(0) + 20, 0);
569 int totalWidth = listView()->columnWidth(0) + listView()->columnWidth(1) - 20;
570 p->eraseRect(TQRect(0,0, totalWidth,height()-1));
571 p->drawLine(0, height()-1, totalWidth-1, height()-1);
572
573 TQFont font = listView()->font();
574 font.setBold(true);
575 p->setFont(font);
576 p->setBrush(cg.highlight());
577 //p->setPen(cg.highlightedText());
578 TDEListViewItem::paintCell(p, cg, column, width, align);
579 p->setPen(cg.text());
580 p->drawText(TQRect(0,0, totalWidth, height()),
581 TQt::AlignLeft | TQt::AlignVCenter | TQt::SingleLine, text(0));*/
582}
583
584void
585EditorGroupItem::setup()
586{
587 TDEListViewItem::setup();
588 setHeight( height()+4 );
589}
590
591int
592EditorGroupItem::compare( TQListViewItem *i, int col, bool ascending ) const
593{
594 Q_UNUSED(col);
595 Q_UNUSED(ascending);
596 if (dynamic_cast<EditorGroupItem*>(i)) {
597 return m_sortOrder
598 - dynamic_cast<EditorGroupItem*>(i)->m_sortOrder;
599 }
600 return 0;
601}
602
604
605EditorDummyItem::EditorDummyItem(TDEListView *listview)
606 : EditorItem(listview)
607{
608 setSelectable(false);
609 setOpen(true);
610}
611
612EditorDummyItem::~EditorDummyItem()
613{}
614
615void
616EditorDummyItem::setup()
617{
618 setHeight(0);
619}
Item for a single property displayed within Editor object.
Definition editoritem.h:48
EditorItem(Editor *editor, EditorItem *parent, Property *property, TQListViewItem *after=0)
virtual void paintCell(TQPainter *p, const TQColorGroup &cg, int column, int width, int align)
virtual void paintBranches(TQPainter *p, const TQColorGroup &cg, int w, int y, int h)
A listview to edit properties Editor widgets use property options using Property::option(const char *...
Definition editor.h:64
The base class representing a single property.
Definition property.h:177
TQString icon() const
Definition property.cpp:302
int sortingKey() const
Definition property.cpp:732
The base class for all item editors used in Editor.
Definition widget.h:37
virtual void drawViewer(TQPainter *p, const TQColorGroup &cg, const TQRect &r, const TQVariant &value)
Definition widget.cpp:88
bool hasBorders() const
Definition widget.cpp:184
const TQColor & backgroundColor() TDE_DEPRECATED
TDEListViewItem(TQListView *parent)
Namespace for a set of classes implementing generic properties framework.