Kate
expandingdelegate.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "expandingdelegate.h"
00020
00021 #include <QtGui/QTextLine>
00022 #include <QtGui/QPainter>
00023 #include <QtGui/QBrush>
00024 #include <QKeyEvent>
00025 #include <QTreeView>
00026 #include <QApplication>
00027
00028 #include <kdebug.h>
00029
00030 #include "expandingwidgetmodel.h"
00031
00032 ExpandingDelegate::ExpandingDelegate(ExpandingWidgetModel* model, QObject* parent)
00033 : QItemDelegate(parent)
00034 , m_model(model)
00035 {
00036 }
00037
00038
00039 static QColor getUsedBackgroundColor(const QStyleOptionViewItem & option, const QModelIndex& index) {
00040 if (option.showDecorationSelected && (option.state & QStyle::State_Selected)) {
00041 QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
00042 ? QPalette::Normal : QPalette::Disabled;
00043 if (cg == QPalette::Normal && !(option.state & QStyle::State_Active))
00044 cg = QPalette::Inactive;
00045
00046 return option.palette.brush(cg, QPalette::Highlight).color();
00047 } else {
00048 QVariant value = index.data(Qt::BackgroundRole);
00049 if (qVariantCanConvert<QBrush>(value))
00050 return qvariant_cast<QBrush>(value).color();
00051 }
00052
00053 return QApplication::palette().background().color();
00054 }
00055
00056 static void dampColors(QColor& col) {
00057
00058
00059
00060 col.setBlue(0);
00061 col.setRed(col.red() / 2);
00062 }
00063
00064
00065 static double readabilityContrast(QColor foreground, QColor background) {
00066 dampColors(foreground);
00067 dampColors(background);
00068 return abs(foreground.green()-background.green()) + abs(foreground.red()-background.red()) + abs(foreground.blue() - background.blue());
00069 }
00070
00071 void ExpandingDelegate::paint( QPainter * painter, const QStyleOptionViewItem & optionOld, const QModelIndex & index ) const
00072 {
00073 QStyleOptionViewItem option(optionOld);
00074
00075 m_currentIndex = index;
00076
00077 adjustStyle(index, option);
00078
00079 if( index.column() == 0 )
00080 model()->placeExpandingWidget(index);
00081
00082
00083 if( model()->isPartiallyExpanded(index) == ExpandingWidgetModel::ExpandUpwards )
00084 m_cachedAlignment = Qt::AlignBottom;
00085 else
00086 m_cachedAlignment = Qt::AlignTop;
00087
00088 option.decorationAlignment = m_cachedAlignment;
00089 option.displayAlignment = m_cachedAlignment;
00090
00091
00092
00093 m_cachedHighlights.clear();
00094 m_backgroundColor = getUsedBackgroundColor(option, index);
00095
00096 if (model()->indexIsItem(index) ) {
00097 m_currentColumnStart = 0;
00098 m_cachedHighlights = createHighlighting(index, option);
00099 }
00100
00101
00102
00103
00104
00105 QItemDelegate::paint(painter, option, index);
00106
00109 if( model()->isExpanded(index) && model()->expandingWidget( index ) )
00110 model()->expandingWidget( index )->update();
00111 }
00112
00113 QList<QTextLayout::FormatRange> ExpandingDelegate::createHighlighting(const QModelIndex& index, QStyleOptionViewItem& option) const {
00114 Q_UNUSED( index );
00115 Q_UNUSED( option );
00116 return QList<QTextLayout::FormatRange>();
00117 }
00118
00119 QSize ExpandingDelegate::basicSizeHint( const QModelIndex& index ) const {
00120 return QItemDelegate::sizeHint( QStyleOptionViewItem(), index );
00121 }
00122
00123 QSize ExpandingDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
00124 {
00125 QSize s = QItemDelegate::sizeHint( option, index );
00126 if( model()->isExpanded(index) && model()->expandingWidget( index ) )
00127 {
00128 QWidget* widget = model()->expandingWidget( index );
00129 QSize widgetSize = widget->size();
00130
00131 s.setHeight( widgetSize.height() + s.height() + 10 );
00132 } else if( model()->isPartiallyExpanded( index ) ) {
00133 s.setHeight( s.height() + 30 + 10 );
00134 }
00135 return s;
00136 }
00137
00138 void ExpandingDelegate::adjustStyle( const QModelIndex& index, QStyleOptionViewItem & option ) const
00139 {
00140 }
00141
00142 void ExpandingDelegate::adjustRect(QRect& rect) const {
00143 if (!model()->indexIsItem(m_currentIndex) ) {
00144
00145 rect.setLeft(model()->treeView()->columnViewportPosition(0));
00146 int columnCount = model()->columnCount(m_currentIndex.parent());
00147
00148 if(!columnCount)
00149 return;
00150 rect.setRight(model()->treeView()->columnViewportPosition(columnCount-1) + model()->treeView()->columnWidth(columnCount-1));
00151 }
00152 }
00153
00154 void ExpandingDelegate::drawDisplay( QPainter * painter, const QStyleOptionViewItem & option, const QRect & _rect, const QString & text ) const
00155 {
00156 QRect rect(_rect);
00157
00158 adjustRect(rect);
00159
00160 QTextLayout layout(text, option.font, painter->device());
00161
00162 QRect textRect = rect.adjusted(1, 0, -1, 0);
00163
00164 QList<QTextLayout::FormatRange> additionalFormats;
00165
00166 int missingFormats = text.length();
00167
00168 for (int i = 0; i < m_cachedHighlights.count(); ++i) {
00169 if (m_cachedHighlights[i].start + m_cachedHighlights[i].length <= m_currentColumnStart)
00170 continue;
00171
00172 if (!additionalFormats.count())
00173 if (i != 0 && m_cachedHighlights[i - 1].start + m_cachedHighlights[i - 1].length > m_currentColumnStart) {
00174 QTextLayout::FormatRange before;
00175 before.start = 0;
00176 before.length = m_cachedHighlights[i - 1].start + m_cachedHighlights[i - 1].length - m_currentColumnStart;
00177 before.format = m_cachedHighlights[i - 1].format;
00178 additionalFormats.append(before);
00179 }
00180
00181
00182 QTextLayout::FormatRange format;
00183 format.start = m_cachedHighlights[i].start - m_currentColumnStart;
00184 format.length = m_cachedHighlights[i].length;
00185 format.format = m_cachedHighlights[i].format;
00186
00187 additionalFormats.append(format);
00188 }
00189 if(!additionalFormats.isEmpty())
00190 missingFormats = text.length() - (additionalFormats.back().length + additionalFormats.back().start);
00191
00192 if (missingFormats > 0) {
00193 QTextLayout::FormatRange format;
00194 format.start = text.length() - missingFormats;
00195 format.length = missingFormats;
00196 QTextCharFormat fm;
00197 fm.setForeground(option.palette.text());
00198 format.format = fm;
00199 additionalFormats.append(format);
00200 }
00201
00202 if(m_backgroundColor.isValid()) {
00203 QColor background = m_backgroundColor;
00204
00205
00206 for(int a = 0; a < additionalFormats.size(); ++a) {
00207 QColor currentBackground = background;
00208 if(additionalFormats[a].format.hasProperty(QTextFormat::BackgroundBrush))
00209 currentBackground = additionalFormats[a].format.background().color();
00210
00211 QColor currentColor = additionalFormats[a].format.foreground().color();
00212
00213 double currentContrast = readabilityContrast(currentColor, currentBackground);
00214 QColor invertedColor(0xffffffff-additionalFormats[a].format.foreground().color().rgb());
00215 double invertedContrast = readabilityContrast(invertedColor, currentBackground);
00216
00217
00218
00219 if(invertedContrast > currentContrast) {
00220
00221 QBrush b(additionalFormats[a].format.foreground());
00222 b.setColor(invertedColor);
00223 additionalFormats[a].format.setForeground(b);
00224 }
00225 }
00226 }
00227
00228 for(int a = additionalFormats.size()-1; a >= 0; --a) {
00229 if(additionalFormats[a].length == 0){
00230 additionalFormats.removeAt(a);
00231 }else{
00234 QTextCharFormat fm;
00235 fm.setForeground(QBrush(additionalFormats[a].format.foreground().color()));
00236 fm.setBackground(additionalFormats[a].format.background());
00237 fm.setUnderlineStyle( additionalFormats[a].format.underlineStyle() );
00238 fm.setUnderlineColor( additionalFormats[a].format.underlineColor() );
00239 fm.setFontWeight( additionalFormats[a].format.fontWeight() );
00240 additionalFormats[a].format = fm;
00241 }
00242 }
00243
00244
00245
00246
00247
00248 layout.setAdditionalFormats(additionalFormats);
00249
00250 QTextOption to;
00251
00252 to.setAlignment( m_cachedAlignment );
00253
00254 to.setWrapMode(QTextOption::WrapAnywhere);
00255 layout.setTextOption(to);
00256
00257 layout.beginLayout();
00258 QTextLine line = layout.createLine();
00259 line.setLineWidth(rect.width());
00260 layout.endLayout();
00261
00262
00263 if( to.alignment() & Qt::AlignBottom)
00264 layout.draw(painter, QPoint(rect.left(), rect.bottom() - (int)line.height()) );
00265 else
00266 layout.draw(painter, rect.topLeft() );
00267
00268 return;
00269
00270
00271
00272
00273 }
00274
00275 void ExpandingDelegate::drawDecoration(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, const QPixmap& pixmap) const {
00276 if (model()->indexIsItem(m_currentIndex) )
00277 QItemDelegate::drawDecoration(painter, option, rect, pixmap);
00278 }
00279
00280 void ExpandingDelegate::drawBackground ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const {
00281 QStyleOptionViewItemV4 opt = option;
00282
00283
00284 QStyle *style = model()->treeView()->style() ? model()->treeView()->style() : QApplication::style();
00285 style->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
00286 }
00287
00288 ExpandingWidgetModel* ExpandingDelegate::model() const {
00289 return m_model;
00290 }
00291
00292 void ExpandingDelegate::heightChanged() const {
00293 }
00294
00295 bool ExpandingDelegate::editorEvent ( QEvent * event, QAbstractItemModel * , const QStyleOptionViewItem & , const QModelIndex & index )
00296 {
00297 QKeyEvent* keyEvent = 0;
00298 if( event->type() == QEvent::KeyPress )
00299 keyEvent = reinterpret_cast<QKeyEvent*>(event);
00300
00301 if( event->type() == QEvent::MouseButtonRelease )
00302 {
00303 event->accept();
00304 model()->setExpanded(index, !model()->isExpanded( index ));
00305 heightChanged();
00306
00307 return true;
00308 } else {
00309 event->ignore();
00310 }
00311
00312 return false;
00313 }
00314
00315 QList<QTextLayout::FormatRange> ExpandingDelegate::highlightingFromVariantList(const QList<QVariant>& customHighlights) const
00316 {
00317 QList<QTextLayout::FormatRange> ret;
00318
00319 for (int i = 0; i + 2 < customHighlights.count(); i += 3) {
00320 if (!customHighlights[i].canConvert(QVariant::Int) || !customHighlights[i+1].canConvert(QVariant::Int) || !customHighlights[i+2].canConvert<QTextFormat>()) {
00321 kWarning() << "Unable to convert triple to custom formatting.";
00322 continue;
00323 }
00324
00325 QTextLayout::FormatRange format;
00326 format.start = customHighlights[i].toInt();
00327 format.length = customHighlights[i+1].toInt();
00328 format.format = customHighlights[i+2].value<QTextFormat>().toCharFormat();
00329
00330 if(!format.format.isValid())
00331 kWarning() << "Format is not valid";
00332
00333 ret << format;
00334 }
00335 return ret;
00336 }
00337
00338 #include "expandingdelegate.moc"