• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • applications API Reference
  • KDE Home
  • Contact Us
 

Kate

  • kde-4.14
  • applications
  • kate
  • part
  • completion
  • expandingtree
expandingdelegate.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE libraries and the Kate part.
2  *
3  * Copyright (C) 2006 Hamish Rodda <rodda@kde.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB. If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #include "expandingdelegate.h"
22 
23 #include <QtGui/QTextLine>
24 #include <QtGui/QPainter>
25 #include <QtGui/QBrush>
26 #include <QKeyEvent>
27 #include <QTreeView>
28 #include <QApplication>
29 
30 #include <kdebug.h>
31 
32 #include "expandingwidgetmodel.h"
33 
34 ExpandingDelegate::ExpandingDelegate(ExpandingWidgetModel* model, QObject* parent)
35  : QItemDelegate(parent)
36  , m_model(model)
37 {
38 }
39 
40 //Gets the background-color in the way QItemDelegate does it
41 static QColor getUsedBackgroundColor(const QStyleOptionViewItem & option, const QModelIndex& index) {
42 if (option.showDecorationSelected && (option.state & QStyle::State_Selected)) {
43  QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
44  ? QPalette::Normal : QPalette::Disabled;
45  if (cg == QPalette::Normal && !(option.state & QStyle::State_Active))
46  cg = QPalette::Inactive;
47 
48  return option.palette.brush(cg, QPalette::Highlight).color();
49  } else {
50  QVariant value = index.data(Qt::BackgroundRole);
51  if (qVariantCanConvert<QBrush>(value))
52  return qvariant_cast<QBrush>(value).color();
53  }
54 
55  return QApplication::palette().base().color();
56 }
57 
58 static void dampColors(QColor& col) {
59  //Reduce the colors that are less visible to the eye, because they are closer to black when it comes to contrast
60  //The most significant color to the eye is green. Then comes red, and then blue, with blue _much_ less significant.
61 
62  col.setBlue(0);
63  col.setRed(col.red() / 2);
64 }
65 
66 //A hack to compute more eye-focused contrast values
67 static double readabilityContrast(QColor foreground, QColor background) {
68  dampColors(foreground);
69  dampColors(background);
70  return abs(foreground.green()-background.green()) + abs(foreground.red()-background.red()) + abs(foreground.blue() - background.blue());
71 }
72 
73 void ExpandingDelegate::paint( QPainter * painter, const QStyleOptionViewItem & optionOld, const QModelIndex & index ) const
74 {
75  QStyleOptionViewItem option(optionOld);
76 
77  m_currentIndex = index;
78 
79  adjustStyle(index, option);
80 
81  if( index.column() == 0 )
82  model()->placeExpandingWidget(index);
83 
84  //Make sure the decorations are painted at the top, because the center of expanded items will be filled with the embedded widget.
85  if( model()->isPartiallyExpanded(index) == ExpandingWidgetModel::ExpandUpwards )
86  m_cachedAlignment = Qt::AlignBottom;
87  else
88  m_cachedAlignment = Qt::AlignTop;
89 
90  option.decorationAlignment = m_cachedAlignment;
91  option.displayAlignment = m_cachedAlignment;
92 
93  //kDebug( 13035 ) << "Painting row " << index.row() << ", column " << index.column() << ", internal " << index.internalPointer() << ", drawselected " << option.showDecorationSelected << ", selected " << (option.state & QStyle::State_Selected);
94 
95  m_cachedHighlights.clear();
96  m_backgroundColor = getUsedBackgroundColor(option, index);
97 
98  if (model()->indexIsItem(index) ) {
99  m_currentColumnStart = 0;
100  m_cachedHighlights = createHighlighting(index, option);
101  }
102 
103  /*kDebug( 13035 ) << "Highlights for line:";
104  foreach (const QTextLayout::FormatRange& fr, m_cachedHighlights)
105  kDebug( 13035 ) << fr.start << " len " << fr.length << " format ";*/
106 
107  QItemDelegate::paint(painter, option, index);
108 
111  if( model()->isExpanded(index) && model()->expandingWidget( index ) )
112  model()->expandingWidget( index )->update();
113 }
114 
115 QList<QTextLayout::FormatRange> ExpandingDelegate::createHighlighting(const QModelIndex& index, QStyleOptionViewItem& option) const {
116  Q_UNUSED( index );
117  Q_UNUSED( option );
118  return QList<QTextLayout::FormatRange>();
119 }
120 
121 QSize ExpandingDelegate::basicSizeHint( const QModelIndex& index ) const {
122  return QItemDelegate::sizeHint( QStyleOptionViewItem(), index );
123 }
124 
125 QSize ExpandingDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
126 {
127  QSize s = QItemDelegate::sizeHint( option, index );
128  if( model()->isExpanded(index) && model()->expandingWidget( index ) )
129  {
130  QWidget* widget = model()->expandingWidget( index );
131  QSize widgetSize = widget->size();
132 
133  s.setHeight( widgetSize.height() + s.height() + 10 ); //10 is the sum that must match exactly the offsets used in ExpandingWidgetModel::placeExpandingWidgets
134  } else if( model()->isPartiallyExpanded( index ) ) {
135  s.setHeight( s.height() + 30 + 10 );
136  }
137  return s;
138 }
139 
140 void ExpandingDelegate::adjustStyle( const QModelIndex& index, QStyleOptionViewItem & option ) const
141 {
142  Q_UNUSED(index)
143  Q_UNUSED(option)
144 }
145 
146 void ExpandingDelegate::adjustRect(QRect& rect) const {
147  if (!model()->indexIsItem(m_currentIndex) /*&& m_currentIndex.column() == 0*/) {
148 
149  rect.setLeft(model()->treeView()->columnViewportPosition(0));
150  int columnCount = model()->columnCount(m_currentIndex.parent());
151 
152  if(!columnCount)
153  return;
154  rect.setRight(model()->treeView()->columnViewportPosition(columnCount-1) + model()->treeView()->columnWidth(columnCount-1));
155  }
156 }
157 
158 void ExpandingDelegate::drawDisplay( QPainter * painter, const QStyleOptionViewItem & option, const QRect & _rect, const QString & text ) const
159 {
160  QRect rect(_rect);
161 
162  adjustRect(rect);
163 
164  QTextLayout layout(text, option.font, painter->device());
165 
166  QList<QTextLayout::FormatRange> additionalFormats;
167 
168  int missingFormats = text.length();
169 
170  for (int i = 0; i < m_cachedHighlights.count(); ++i) {
171  if (m_cachedHighlights[i].start + m_cachedHighlights[i].length <= m_currentColumnStart)
172  continue;
173 
174  if (!additionalFormats.count())
175  if (i != 0 && m_cachedHighlights[i - 1].start + m_cachedHighlights[i - 1].length > m_currentColumnStart) {
176  QTextLayout::FormatRange before;
177  before.start = 0;
178  before.length = m_cachedHighlights[i - 1].start + m_cachedHighlights[i - 1].length - m_currentColumnStart;
179  before.format = m_cachedHighlights[i - 1].format;
180  additionalFormats.append(before);
181  }
182 
183 
184  QTextLayout::FormatRange format;
185  format.start = m_cachedHighlights[i].start - m_currentColumnStart;
186  format.length = m_cachedHighlights[i].length;
187  format.format = m_cachedHighlights[i].format;
188 
189  additionalFormats.append(format);
190  }
191  if(!additionalFormats.isEmpty())
192  missingFormats = text.length() - (additionalFormats.back().length + additionalFormats.back().start);
193 
194  if (missingFormats > 0) {
195  QTextLayout::FormatRange format;
196  format.start = text.length() - missingFormats;
197  format.length = missingFormats;
198  QTextCharFormat fm;
199  fm.setForeground(option.palette.text());
200  format.format = fm;
201  additionalFormats.append(format);
202  }
203 
204  if(m_backgroundColor.isValid()) {
205  QColor background = m_backgroundColor;
206 // kDebug() << text << "background:" << background.name();
207  //Now go through the formats, and make sure the contrast background/foreground is readable
208  for(int a = 0; a < additionalFormats.size(); ++a) {
209  QColor currentBackground = background;
210  if(additionalFormats[a].format.hasProperty(QTextFormat::BackgroundBrush))
211  currentBackground = additionalFormats[a].format.background().color();
212 
213  QColor currentColor = additionalFormats[a].format.foreground().color();
214 
215  double currentContrast = readabilityContrast(currentColor, currentBackground);
216  QColor invertedColor(0xffffffff-additionalFormats[a].format.foreground().color().rgb());
217  double invertedContrast = readabilityContrast(invertedColor, currentBackground);
218 
219 // kDebug() << "values:" << invertedContrast << currentContrast << invertedColor.name() << currentColor.name();
220 
221  if(invertedContrast > currentContrast) {
222 // kDebug() << text << additionalFormats[a].length << "switching from" << currentColor.name() << "to" << invertedColor.name();
223  QBrush b(additionalFormats[a].format.foreground());
224  b.setColor(invertedColor);
225  additionalFormats[a].format.setForeground(b);
226  }
227  }
228  }
229 
230  for(int a = additionalFormats.size()-1; a >= 0; --a) {
231  if(additionalFormats[a].length == 0){
232  additionalFormats.removeAt(a);
233  }else{
236  QTextCharFormat fm;
237  fm.setForeground(QBrush(additionalFormats[a].format.foreground().color()));
238  fm.setBackground(additionalFormats[a].format.background());
239  fm.setUnderlineStyle( additionalFormats[a].format.underlineStyle() );
240  fm.setUnderlineColor( additionalFormats[a].format.underlineColor() );
241  fm.setFontWeight( additionalFormats[a].format.fontWeight() );
242  additionalFormats[a].format = fm;
243  }
244  }
245 
246 // kDebug( 13035 ) << "Highlights for text [" << text << "] col start " << m_currentColumnStart << ":";
247 // foreach (const QTextLayout::FormatRange& fr, additionalFormats)
248 // kDebug( 13035 ) << fr.start << " len " << fr.length << "foreground" << fr.format.foreground() << "background" << fr.format.background();
249 
250  layout.setAdditionalFormats(additionalFormats);
251 
252  QTextOption to;
253 
254  to.setAlignment( static_cast<Qt::Alignment>(m_cachedAlignment | option.displayAlignment) );
255 
256  to.setWrapMode(QTextOption::WrapAnywhere);
257  layout.setTextOption(to);
258 
259  layout.beginLayout();
260  QTextLine line = layout.createLine();
261  // Leave some extra space when the text is right-aligned
262  line.setLineWidth(rect.width() - (option.displayAlignment == Qt::AlignRight ? 8 : 0));
263  layout.endLayout();
264 
265  //We need to do some hand layouting here
266  if( to.alignment() & Qt::AlignBottom)
267  layout.draw(painter, QPoint(rect.left(), rect.bottom() - (int)line.height()) );
268  else
269  layout.draw(painter, rect.topLeft() );
270 
271  return;
272 
273  //if (painter->fontMetrics().width(text) > textRect.width() && !text.contains(QLatin1Char('\n')))
274  //str = elidedText(option.fontMetrics, textRect.width(), option.textElideMode, text);
275  //qt_format_text(option.font, textRect, option.displayAlignment, str, 0, 0, 0, 0, painter);
276 }
277 
278 void ExpandingDelegate::drawDecoration(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, const QPixmap& pixmap) const {
279  if (model()->indexIsItem(m_currentIndex) )
280  QItemDelegate::drawDecoration(painter, option, rect, pixmap);
281 }
282 
283 void ExpandingDelegate::drawBackground ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const {
284  Q_UNUSED(index)
285  QStyleOptionViewItemV4 opt = option;
286  //initStyleOption(&opt, index);
287  //Problem: This isn't called at all, because drawBrackground is not virtual :-/
288  QStyle *style = model()->treeView()->style() ? model()->treeView()->style() : QApplication::style();
289  style->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
290 }
291 
292 ExpandingWidgetModel* ExpandingDelegate::model() const {
293  return m_model;
294 }
295 
296 void ExpandingDelegate::heightChanged() const {
297 }
298 
299 bool ExpandingDelegate::editorEvent ( QEvent * event, QAbstractItemModel * /*model*/, const QStyleOptionViewItem & /*option*/, const QModelIndex & index )
300 {
301  if( event->type() == QEvent::MouseButtonRelease )
302  {
303  event->accept();
304  model()->setExpanded(index, !model()->isExpanded( index ));
305  heightChanged();
306 
307  return true;
308  } else {
309  event->ignore();
310  }
311 
312  return false;
313 }
314 
315 QList<QTextLayout::FormatRange> ExpandingDelegate::highlightingFromVariantList(const QList<QVariant>& customHighlights) const
316 {
317  QList<QTextLayout::FormatRange> ret;
318 
319  for (int i = 0; i + 2 < customHighlights.count(); i += 3) {
320  if (!customHighlights[i].canConvert(QVariant::Int) || !customHighlights[i+1].canConvert(QVariant::Int) || !customHighlights[i+2].canConvert<QTextFormat>()) {
321  kWarning() << "Unable to convert triple to custom formatting.";
322  continue;
323  }
324 
325  QTextLayout::FormatRange format;
326  format.start = customHighlights[i].toInt();
327  format.length = customHighlights[i+1].toInt();
328  format.format = customHighlights[i+2].value<QTextFormat>().toCharFormat();
329 
330  if(!format.format.isValid())
331  kWarning() << "Format is not valid";
332 
333  ret << format;
334  }
335  return ret;
336 }
337 
338 #include "expandingdelegate.moc"
QList::clear
void clear()
QModelIndex
ExpandingDelegate::adjustStyle
virtual void adjustStyle(const QModelIndex &index, QStyleOptionViewItem &option) const
Definition: expandingdelegate.cpp:140
QEvent
QWidget
QSize::setHeight
void setHeight(int height)
QTextCharFormat::setUnderlineStyle
void setUnderlineStyle(UnderlineStyle style)
QEvent::type
Type type() const
ExpandingDelegate::paint
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
Definition: expandingdelegate.cpp:73
QTextLine::height
qreal height() const
QList::length
int length() const
ExpandingWidgetModel::treeView
virtual QTreeView * treeView() const =0
QItemDelegate::drawDecoration
virtual void drawDecoration(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QPixmap &pixmap) const
QWidget::style
QStyle * style() const
ExpandingDelegate::ExpandingDelegate
ExpandingDelegate(ExpandingWidgetModel *model, QObject *parent=0L)
Definition: expandingdelegate.cpp:34
ExpandingDelegate::sizeHint
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
Definition: expandingdelegate.cpp:125
ExpandingWidgetModel::isPartiallyExpanded
ExpansionType isPartiallyExpanded(const QModelIndex &index) const
Returns whether the given index is currently partially expanded. Does not do any other checks like ca...
Definition: expandingwidgetmodel.cpp:139
QColor::setBlue
void setBlue(int blue)
ExpandingDelegate::heightChanged
virtual void heightChanged() const
Definition: expandingdelegate.cpp:296
QBrush
QTextOption::alignment
Qt::Alignment alignment() const
QItemDelegate::paint
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
QPoint
ExpandingDelegate::m_currentIndex
QModelIndex m_currentIndex
Definition: expandingdelegate.h:87
QColor::setRed
void setRed(int red)
ExpandingDelegate::drawDecoration
virtual void drawDecoration(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QPixmap &pixmap) const
Definition: expandingdelegate.cpp:278
expandingwidgetmodel.h
QWidget::update
void update()
ExpandingDelegate::editorEvent
virtual bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
Definition: expandingdelegate.cpp:299
QList::value
T value(int i) const
QTextLine::setLineWidth
void setLineWidth(qreal width)
QBrush::color
const QColor & color() const
QTextFormat::setForeground
void setForeground(const QBrush &brush)
QWidget::size
size
ExpandingWidgetModel::placeExpandingWidget
void placeExpandingWidget(const QModelIndex &row)
Places and shows the expanding-widget for the given row, if it should be visible and is valid...
Definition: expandingwidgetmodel.cpp:370
QTextOption::setWrapMode
void setWrapMode(WrapMode mode)
QRect
QList::count
int count(const T &value) const
QList::append
void append(const T &value)
ExpandingDelegate::createHighlighting
virtual QList< QTextLayout::FormatRange > createHighlighting(const QModelIndex &index, QStyleOptionViewItem &option) const
Definition: expandingdelegate.cpp:115
ExpandingDelegate::adjustRect
void adjustRect(QRect &rect) const
Definition: expandingdelegate.cpp:146
QStyleOptionViewItem
QObject
QStyle
QColor::red
int red() const
QRect::left
int left() const
ExpandingWidgetModel::expandingWidget
QWidget * expandingWidget(const QModelIndex &row) const
Definition: expandingwidgetmodel.cpp:431
QPainter
QTextLayout
QTextFormat::setBackground
void setBackground(const QBrush &brush)
QItemDelegate
QPainter::device
QPaintDevice * device() const
QItemDelegate::sizeHint
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
ExpandingDelegate::model
ExpandingWidgetModel * model() const
Definition: expandingdelegate.cpp:292
QString
QList< QTextLayout::FormatRange >
QColor
readabilityContrast
static double readabilityContrast(QColor foreground, QColor background)
Definition: expandingdelegate.cpp:67
ExpandingDelegate::drawDisplay
virtual void drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QString &text) const
Definition: expandingdelegate.cpp:158
QModelIndex::parent
QModelIndex parent() const
QApplication::palette
QPalette palette()
QTextOption
ExpandingDelegate::basicSizeHint
QSize basicSizeHint(const QModelIndex &index) const
Definition: expandingdelegate.cpp:121
ExpandingDelegate::highlightingFromVariantList
QList< QTextLayout::FormatRange > highlightingFromVariantList(const QList< QVariant > &customHighlights) const
Creates a list of FormatRanges as should be returned by createHighlighting from a list of QVariants a...
Definition: expandingdelegate.cpp:315
QPixmap
QTextFormat
QColor::green
int green() const
QTextCharFormat
ExpandingDelegate::m_currentColumnStart
int m_currentColumnStart
Definition: expandingdelegate.h:81
QSize
ExpandingDelegate::m_cachedAlignment
Qt::Alignment m_cachedAlignment
Definition: expandingdelegate.h:85
QTextCharFormat::setFontWeight
void setFontWeight(int weight)
QRect::setRight
void setRight(int x)
QColor::blue
int blue() const
dampColors
static void dampColors(QColor &col)
Definition: expandingdelegate.cpp:58
QPalette::base
const QBrush & base() const
QRect::width
int width() const
ExpandingWidgetModel::setExpanded
void setExpanded(QModelIndex index, bool expanded)
Change the expand-state of the row given through index. The display will be updated.
Definition: expandingwidgetmodel.cpp:311
QTextLine
QModelIndex::data
QVariant data(int role) const
QApplication::style
QStyle * style()
QStyle::drawControl
virtual void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const =0
QAbstractItemModel::columnCount
virtual int columnCount(const QModelIndex &parent) const =0
ExpandingDelegate::drawBackground
virtual void drawBackground(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
Definition: expandingdelegate.cpp:283
QSize::height
int height() const
expandingdelegate.h
QRect::bottom
int bottom() const
QRect::topLeft
QPoint topLeft() const
QModelIndex::column
int column() const
QString::length
int length() const
QAbstractItemModel
getUsedBackgroundColor
static QColor getUsedBackgroundColor(const QStyleOptionViewItem &option, const QModelIndex &index)
Definition: expandingdelegate.cpp:41
ExpandingDelegate::m_cachedHighlights
QList< QTextLayout::FormatRange > m_cachedHighlights
Definition: expandingdelegate.h:83
QTextCharFormat::setUnderlineColor
void setUnderlineColor(const QColor &color)
QStyleOptionViewItemV4
QTextLayout::FormatRange
QBrush::setColor
void setColor(const QColor &color)
QTextOption::setAlignment
void setAlignment(QFlags< Qt::AlignmentFlag > alignment)
QRect::setLeft
void setLeft(int x)
QColor::isValid
bool isValid() const
ExpandingDelegate::m_backgroundColor
QColor m_backgroundColor
Definition: expandingdelegate.h:86
QVariant
ExpandingWidgetModel
Cares about expanding/un-expanding items in a tree-view together with ExpandingDelegate.
Definition: expandingwidgetmodel.h:36
ExpandingWidgetModel::ExpandUpwards
Definition: expandingwidgetmodel.h:68
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sat May 9 2020 03:56:57 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Kate

Skip menu "Kate"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

applications API Reference

Skip menu "applications API Reference"
  •   kate
  •       kate
  •   KTextEditor
  •   Kate
  • Konsole

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal