/* This file is part of the KDE project Copyright (C) 2004 Cedric Pasteur Copyright (C) 2004 Alexander Dymo Copyright (C) 2004-2006 Jaroslaw Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "editoritem.h" #include "editor.h" #include "property.h" #include "widget.h" #include "factory.h" #include "utils.h" #include #include #include #include #include #include #include #include #include #include #include #define BRANCHBOX_SIZE 9 namespace KoProperty { class EditorItemPrivate { public: EditorItemPrivate() : property(0) {} ~EditorItemPrivate() {} Property *property; Editor *editor; }; //! @internal static void paintListViewExpander(TQPainter* p, TQWidget* w, int height, const TQColorGroup& cg, bool isOpen) { const int marg = (height -2 - BRANCHBOX_SIZE) / 2; int xmarg = marg; // if (dynamic_cast(item)) // xmarg = xmarg * 10 / 14 -1; #if 0 //! @todo disabled: kstyles do not paint background yet... reenable in the future... KStyle* kstyle = dynamic_cast(widget->style()); if (kstyle) { kstyle->drawKStylePrimitive( KStyle::KPE_ListViewExpander, p, w, TQRect( xmarg, marg, BRANCHBOX_SIZE, BRANCHBOX_SIZE ), cg, isOpen ? 0 : TQStyle::Style_On, TQStyleOption::Default); } else { #endif Q_UNUSED(w); //draw by hand p->setPen( KPROPEDITOR_ITEM_BORDER_COLOR ); p->drawRect(xmarg, marg, BRANCHBOX_SIZE, BRANCHBOX_SIZE); p->fillRect(xmarg+1, marg + 1, BRANCHBOX_SIZE-2, BRANCHBOX_SIZE-2, // item->listView()->paletteBackgroundColor()); cg.base()); // p->setPen( item->listView()->paletteForegroundColor() ); p->setPen( cg.foreground() ); p->drawLine(xmarg+2, marg+BRANCHBOX_SIZE/2, xmarg+BRANCHBOX_SIZE-3, marg+BRANCHBOX_SIZE/2); if(!isOpen) { p->drawLine(xmarg+BRANCHBOX_SIZE/2, marg+2, xmarg+BRANCHBOX_SIZE/2, marg+BRANCHBOX_SIZE-3); } // } } //! @internal //! Based on KPopupTitle, see kpopupmenu.cpp class GroupWidgetBase : public TQWidget { public: GroupWidgetBase(TQWidget* parent) : TQWidget(parent) , m_isOpen(true) , m_mouseDown(false) { setSizePolicy(TQSizePolicy(TQSizePolicy::Preferred, TQSizePolicy::Fixed, 0, 1)); } void setText( const TQString &text ) { m_titleStr = text; } void setIcon( const TQPixmap &pix ) { m_miniicon = pix; } virtual bool isOpen() const { return m_isOpen; } virtual void setOpen(bool set) { m_isOpen = set; } virtual TQSize sizeHint () const { TQSize s( TQWidget::sizeHint() ); s.setHeight(fontMetrics().height()*2); return s; } protected: virtual void paintEvent(TQPaintEvent *) { TQRect r(rect()); TQPainter p(this); TQStyle::StyleFlags flags = m_mouseDown ? TQStyle::Style_Down : TQStyle::Style_Default; kapp->tqstyle().tqdrawPrimitive(TQStyle::PE_HeaderSection, &p, r, tqpalette().active(), flags); paintListViewExpander(&p, this, r.height()+2, tqpalette().active(), isOpen()); if (!m_miniicon.isNull()) { p.drawPixmap(24, (r.height()-m_miniicon.height())/2, m_miniicon); } if (!m_titleStr.isNull()) { int indent = 16 + (m_miniicon.isNull() ? 0 : (m_miniicon.width()+4)); p.setPen(tqpalette().active().text()); TQFont f = p.font(); f.setBold(true); p.setFont(f); p.drawText(indent+8, 0, width()-(indent+8), height(), AlignLeft | AlignVCenter | SingleLine, m_titleStr); } // p.setPen(palette().active().mid()); // p.drawLine(0, 0, r.right(), 0); } virtual bool event( TQEvent * e ) { if (e->type()==TQEvent::MouseButtonPress || e->type()==TQEvent::MouseButtonRelease) { TQMouseEvent* me = TQT_TQMOUSEEVENT(e); if (me->button() == Qt::LeftButton) { m_mouseDown = e->type()==TQEvent::MouseButtonPress; update(); } } return TQWidget::event(e); } protected: TQString m_titleStr; TQPixmap m_miniicon; bool m_isOpen : 1; bool m_mouseDown : 1; }; class GroupWidget : public GroupWidgetBase { public: GroupWidget(EditorGroupItem *parentItem) : GroupWidgetBase(parentItem->listView()->viewport()) , m_parentItem(parentItem) { } virtual bool isOpen() const { return m_parentItem->isOpen(); } protected: EditorGroupItem *m_parentItem; }; class GroupContainer::Private { public: Private() {} TQVBoxLayout* lyr; GroupWidgetBase *groupWidget; TQGuardedPtr contents; }; }//namespace using namespace KoProperty; GroupContainer::GroupContainer(const TQString& title, TQWidget* parent) : TQWidget(parent) , d(new Private()) { setSizePolicy(TQSizePolicy(TQSizePolicy::Preferred, TQSizePolicy::Fixed, 0, 1)); d->lyr = new TQVBoxLayout(this); d->groupWidget = new GroupWidgetBase(this); d->groupWidget->setText( title ); d->lyr->addWidget(d->groupWidget); d->lyr->addSpacing(4); } GroupContainer::~GroupContainer() { delete d; } void GroupContainer::setContents( TQWidget* contents ) { if (d->contents) { d->contents->hide(); d->lyr->remove(d->contents); delete d->contents; } d->contents = contents; if (d->contents) { d->lyr->addWidget(d->contents); d->contents->show(); } update(); } bool GroupContainer::event( TQEvent * e ) { if (e->type()==TQEvent::MouseButtonPress) { TQMouseEvent* me = TQT_TQMOUSEEVENT(e); if (me->button() == Qt::LeftButton && d->contents && TQT_TQRECT_OBJECT(d->groupWidget->rect()).contains(me->pos())) { d->groupWidget->setOpen(!d->groupWidget->isOpen()); if (d->groupWidget->isOpen()) d->contents->show(); else d->contents->hide(); d->lyr->invalidate(); update(); } } return TQWidget::event(e); } ////////////////////////////////////////////////////// EditorItem::EditorItem(Editor *editor, EditorItem *parent, Property *property, TQListViewItem *after) : KListViewItem(parent, after, property->captionForDisplaying().isEmpty() ? property->name() : property->captionForDisplaying()) { d = new EditorItemPrivate(); d->property = property; d->editor = editor; setMultiLinesEnabled(true); //setHeight(static_cast(listView())->baseRowHeight()*3); /* if (property && !property->caption().isEmpty()) { TQSimpleRichText srt(property->caption(), font()); srt.setWidth(columnWidth(0)-KPROPEDITOR_ITEM_MARGIN*2-20+1); int oldHeight = it.current()->height(); int textHeight = srt.height()+KPROPEDITOR_ITEM_MARGIN; int textLines = textHeight / d->baseRowHeight + (((textHeight % d->baseRowHeight) > 0) ? 1 : 0); kdDebug() << " textLines: " << textLines << endl; if (textLines != newNumLines) { dynamic_cast(it.current())->setHeight(newNumLines * d->baseRowHeight); } kdDebug() << it.current()->text(0) << ": " << oldHeight << " -> " << newHeight << endl; } */ } EditorItem::EditorItem(KListView *parent) : KListViewItem(parent) { d = new EditorItemPrivate(); d->property = 0; d->editor = 0; setMultiLinesEnabled(true); } EditorItem::EditorItem(EditorItem *parent, const TQString &text) : KListViewItem(parent, text) { d = new EditorItemPrivate(); d->property = 0; d->editor = 0; setMultiLinesEnabled(true); } EditorItem::EditorItem(EditorItem *parent, EditorItem *after, const TQString &text) : KListViewItem(parent, after, text) { d = new EditorItemPrivate(); d->property = 0; d->editor = 0; setMultiLinesEnabled(true); } EditorItem::~EditorItem() { delete d; } Property* EditorItem::property() { return d->property; } void EditorItem::paintCell(TQPainter *p, const TQColorGroup & cg, int column, int width, int align) { //int margin = static_cast(listView())->itemMargin(); if(!d->property) return; if(column == 0) { TQFont font = listView()->font(); if(d->property->isModified()) font.setBold(true); p->setFont(font); p->setBrush(cg.highlight()); p->setPen(cg.highlightedText()); KListViewItem::paintCell(p, cg, column, width, align); p->fillRect(parent() ? 0 : 50, 0, width, height()-1, TQBrush(isSelected() ? cg.highlight() : backgroundColor())); p->setPen(isSelected() ? cg.highlightedText() : cg.text()); int delta = -20+KPROPEDITOR_ITEM_MARGIN; if ((firstChild() && dynamic_cast(parent()))) { delta = -KPROPEDITOR_ITEM_MARGIN-1; } if (dynamic_cast(parent())) { delta = KPROPEDITOR_ITEM_MARGIN*2; } else if (parent() && dynamic_cast(parent()->parent())) { if (dynamic_cast(parent())) delta += KPROPEDITOR_ITEM_MARGIN*2; else delta += KPROPEDITOR_ITEM_MARGIN*5; } p->drawText( TQRect(delta,2, width+listView()->columnWidth(1)-KPROPEDITOR_ITEM_MARGIN*2, height()), TQt::AlignLeft | TQt::AlignTop /*| TQt::SingleLine*/, text(0)); p->setPen( KPROPEDITOR_ITEM_BORDER_COLOR ); p->drawLine(width-1, 0, width-1, height()-1); p->drawLine(0, -1, width-1, -1); p->setPen( KPROPEDITOR_ITEM_BORDER_COLOR ); //! \todo custom color? if (dynamic_cast(parent())) p->drawLine(0, 0, 0, height()-1 ); } else if(column == 1) { TQColorGroup icg(cg); icg.setColor(TQColorGroup::Background, backgroundColor()); p->setBackgroundColor(backgroundColor()); Widget *widget = d->editor->createWidgetForProperty(d->property, false /*don't change Widget::property() */); if(widget) { TQRect r(0, 0, d->editor->header()->sectionSize(1), height() - (widget->hasBorders() ? 0 : 1)); p->setClipRect(r, TQPainter::CoordPainter); p->setClipping(true); widget->drawViewer(p, icg, r, d->property->value()); p->setClipping(false); } } p->setPen( KPROPEDITOR_ITEM_BORDER_COLOR ); //! \todo custom color? p->drawLine(0, height()-1, width, height()-1 ); } void EditorItem::paintBranches(TQPainter *p, const TQColorGroup &cg, int w, int y, int h) { p->eraseRect(0,0,w,h); KListViewItem *item = static_cast(firstChild()); if(!item) return; TQColor backgroundColor; p->save(); p->translate(0,y); TQFont font = listView()->font(); while(item) { if(item->isSelected()) backgroundColor = cg.highlight(); else { if (dynamic_cast(item)) backgroundColor = cg.base(); else backgroundColor = item->backgroundColor(); } // p->fillRect(-50,0,50, item->height(), TQBrush(backgroundColor)); p->save(); p->setPen( KPROPEDITOR_ITEM_BORDER_COLOR ); int delta = 0; int fillWidth = w; int x = 0; if (dynamic_cast(item->parent())) { delta = 0;//-19; fillWidth += 19; } else { if (dynamic_cast(item) || /*for flat mode*/ dynamic_cast(item->parent())) x = 19; else x = -19; fillWidth += 19; } if (dynamic_cast(item->parent())) { x = 19; } else if (item->parent() && dynamic_cast(item->parent()->parent())) { x = 0; } p->fillRect(x+1, 0, fillWidth-1, item->height()-1, TQBrush(backgroundColor)); p->drawLine(x, item->height()-1, w, item->height()-1 ); if (!dynamic_cast(item)) p->drawLine(x, 0, x, item->height()-1 ); p->restore(); // for (int i=0; i<10000000; i++) // ; // if(item->isSelected()) { // p->fillRect(parent() ? 0 : 50, 0, w, item->height()-1, TQBrush(cg.highlight())); // p->fillRect(-50,0,50, item->height(), TQBrush(cg.highlight())); // } //sorry, but we need to draw text here again font.setBold( dynamic_cast(item) || (static_cast(item)->property() && static_cast(item)->property()->isModified()) ); p->setFont(font); p->setPen(item->isSelected() ? cg.highlightedText() : cg.text()); if (item->firstChild() && dynamic_cast(item->parent())) { delta = 19-KPROPEDITOR_ITEM_MARGIN-1; } else if (dynamic_cast(item->parent())) { delta = 19; } if (item->parent() && dynamic_cast(item->parent()->parent())) { if (dynamic_cast(item->parent())) delta += KPROPEDITOR_ITEM_MARGIN*2; else delta += KPROPEDITOR_ITEM_MARGIN*5; } if (!dynamic_cast(item->parent())) p->drawText(TQRect(delta+1,0, w+listView()->columnWidth(1), item->height()), TQt::AlignLeft | TQt::AlignVCenter /*| TQt::SingleLine*/, item->text(0)); if(item->firstChild()) { paintListViewExpander(p, listView(), item->height(), cg, item->isOpen()); } // draw icon (if there is one) EditorItem *editorItem = dynamic_cast(item); if (editorItem && editorItem->property() && !editorItem->property()->icon().isEmpty()) { //int margin = listView()->itemMargin(); TQPixmap pix = SmallIcon(editorItem->property()->icon()); if (!pix.isNull()) p->drawPixmap(-19+(19-pix.width())/2, (item->height() - pix.height()) / 2, pix); } p->translate(0, item->totalHeight()); item = (KListViewItem*)item->nextSibling(); } p->restore(); } void EditorItem::paintFocus(TQPainter *, const TQColorGroup &, const TQRect & ) { } int EditorItem::compare( TQListViewItem *i, int col, bool ascending ) const { if (!ascending) return -TQListViewItem::key( col, ascending ).localeAwareCompare( i->key( col, ascending ) ); if (d->property) { // kopropertydbg << d->property->name() << " " << d->property->sortingKey() << " | " // << static_cast(i)->property()->name() << " " // << static_cast(i)->property()->sortingKey() << endl; return d->property->sortingKey() - ((dynamic_cast(i) && dynamic_cast(i)->property()) ? dynamic_cast(i)->property()->sortingKey() : 0); } return 0; // return d->order - static_cast(i)->d->order; } void EditorItem::setHeight( int height ) { KListViewItem::setHeight(height); } ////////////////////////////////////////////////////// EditorGroupItem::EditorGroupItem(EditorItem *parent, EditorItem *after, const TQString &text, const TQString &icon, int sortOrder) : EditorItem(parent, after, text) , m_label(0) , m_sortOrder(sortOrder) { init(icon); } EditorGroupItem::EditorGroupItem(EditorItem *parent, const TQString &text, const TQString &icon, int sortOrder) : EditorItem(parent, text) , m_label(0) , m_sortOrder(sortOrder) { init(icon); } EditorGroupItem::~EditorGroupItem() { delete m_label; } TQWidget* EditorGroupItem::label() const { return m_label; } void EditorGroupItem::init(const TQString &icon) { setOpen(true); setSelectable(false); m_label = new GroupWidget(this); m_label->setText(text(0)); //todo: icon? if (!icon.isEmpty()) m_label->setIcon( SmallIcon(icon) ); m_label->show(); } void EditorGroupItem::paintCell(TQPainter *p, const TQColorGroup & cg, int column, int width, int /*align*/) { Q_UNUSED(p); Q_UNUSED(cg); Q_UNUSED(column); Q_UNUSED(width); //no need to draw anything since there's a label on top of it // p->fillRect(0, 0, width, height(), cg.base()); //if(column == 1) // return; /*p->setPen( KPROPEDITOR_ITEM_BORDER_COLOR ); //! \todo custom color? p->setClipRect(listView()->itemRect(this)); if(column == 1) p->translate(-listView()->columnWidth(0) + 20, 0); int totalWidth = listView()->columnWidth(0) + listView()->columnWidth(1) - 20; p->eraseRect(TQRect(0,0, totalWidth,height()-1)); p->drawLine(0, height()-1, totalWidth-1, height()-1); TQFont font = listView()->font(); font.setBold(true); p->setFont(font); p->setBrush(cg.highlight()); //p->setPen(cg.highlightedText()); KListViewItem::paintCell(p, cg, column, width, align); p->setPen(cg.text()); p->drawText(TQRect(0,0, totalWidth, height()), TQt::AlignLeft | TQt::AlignVCenter | TQt::SingleLine, text(0));*/ } void EditorGroupItem::setup() { KListViewItem::setup(); setHeight( height()+4 ); } int EditorGroupItem::compare( TQListViewItem *i, int col, bool ascending ) const { Q_UNUSED(col); Q_UNUSED(ascending); if (dynamic_cast(i)) { return m_sortOrder - dynamic_cast(i)->m_sortOrder; } return 0; } //////////////////////////////////////////////////////// EditorDummyItem::EditorDummyItem(KListView *listview) : EditorItem(listview) { setSelectable(false); setOpen(true); } EditorDummyItem::~EditorDummyItem() {} void EditorDummyItem::setup() { setHeight(0); }