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 QColor();
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 adjustStyle(index, option);
00076
00077 if( index.column() == 0 )
00078 model()->placeExpandingWidget(index);
00079
00080
00081 if( model()->isPartiallyExpanded(index) == ExpandingWidgetModel::ExpandUpwards )
00082 m_cachedAlignment = Qt::AlignBottom;
00083 else
00084 m_cachedAlignment = Qt::AlignTop;
00085
00086 option.decorationAlignment = m_cachedAlignment;
00087 option.displayAlignment = m_cachedAlignment;
00088
00089
00090
00091 m_cachedHighlights.clear();
00092 m_backgroundColor = getUsedBackgroundColor(option, index);
00093
00094 if (!model()->indexIsItem(index) )
00095 return QItemDelegate::paint(painter, option, index);
00096
00097 m_currentColumnStart = 0;
00098 m_cachedHighlights = createHighlighting(index, option);
00099
00100
00101
00102
00103
00104 QItemDelegate::paint(painter, option, index);
00105 }
00106
00107 QList<QTextLayout::FormatRange> ExpandingDelegate::createHighlighting(const QModelIndex& index, QStyleOptionViewItem& option) const {
00108 Q_UNUSED( index );
00109 Q_UNUSED( option );
00110 return QList<QTextLayout::FormatRange>();
00111 }
00112
00113 QSize ExpandingDelegate::basicSizeHint( const QModelIndex& index ) const {
00114 return QItemDelegate::sizeHint( QStyleOptionViewItem(), index );
00115 }
00116
00117 QSize ExpandingDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
00118 {
00119 QSize s = QItemDelegate::sizeHint( option, index );
00120 if( model()->isExpanded(index) && model()->expandingWidget( index ) )
00121 {
00122 QWidget* widget = model()->expandingWidget( index );
00123 QSize widgetSize = widget->size();
00124
00125 s.setHeight( widgetSize.height() + s.height() + 10 );
00126 } else if( model()->isPartiallyExpanded( index ) ) {
00127 s.setHeight( s.height() + 30 + 10 );
00128 }
00129 return s;
00130 }
00131
00132 void ExpandingDelegate::adjustStyle( const QModelIndex& index, QStyleOptionViewItem & option ) const
00133 {
00134 }
00135
00136 void ExpandingDelegate::drawDisplay( QPainter * painter, const QStyleOptionViewItem & option, const QRect & rect, const QString & text ) const
00137 {
00138
00139
00140
00141 QTextLayout layout(text, option.font, painter->device());
00142
00143 QRect textRect = rect.adjusted(1, 0, -1, 0);
00144
00145 QList<QTextLayout::FormatRange> additionalFormats;
00146
00147 int missingFormats = text.length();
00148
00149 for (int i = 0; i < m_cachedHighlights.count(); ++i) {
00150 if (m_cachedHighlights[i].start + m_cachedHighlights[i].length <= m_currentColumnStart)
00151 continue;
00152
00153 if (!additionalFormats.count())
00154 if (i != 0 && m_cachedHighlights[i - 1].start + m_cachedHighlights[i - 1].length > m_currentColumnStart) {
00155 QTextLayout::FormatRange before;
00156 before.start = 0;
00157 before.length = m_cachedHighlights[i - 1].start + m_cachedHighlights[i - 1].length - m_currentColumnStart;
00158 before.format = m_cachedHighlights[i - 1].format;
00159 additionalFormats.append(before);
00160 }
00161
00162
00163 QTextLayout::FormatRange format;
00164 format.start = m_cachedHighlights[i].start - m_currentColumnStart;
00165 format.length = m_cachedHighlights[i].length;
00166 format.format = m_cachedHighlights[i].format;
00167
00168 additionalFormats.append(format);
00169 }
00170 if(!additionalFormats.isEmpty())
00171 missingFormats = text.length() - (additionalFormats.back().length + additionalFormats.back().start);
00172
00173 if (missingFormats > 0) {
00174 QTextLayout::FormatRange format;
00175 format.start = text.length() - missingFormats;
00176 format.length = missingFormats;
00177 QTextCharFormat fm;
00178 fm.setForeground(option.palette.text());
00179 format.format = fm;
00180 additionalFormats.append(format);
00181 }
00182
00183 if(m_backgroundColor.isValid()) {
00184 QColor background = m_backgroundColor;
00185
00186
00187 for(int a = 0; a < additionalFormats.size(); ++a) {
00188 QColor currentBackground = background;
00189 if(additionalFormats[a].format.hasProperty(QTextFormat::BackgroundBrush))
00190 currentBackground = additionalFormats[a].format.background().color();
00191
00192 QColor currentColor = additionalFormats[a].format.foreground().color();
00193
00194 double currentContrast = readabilityContrast(currentColor, currentBackground);
00195 QColor invertedColor(0xffffffff-additionalFormats[a].format.foreground().color().rgb());
00196 double invertedContrast = readabilityContrast(invertedColor, currentBackground);
00197
00198
00199
00200 if(invertedContrast > currentContrast) {
00201
00202 QBrush b(additionalFormats[a].format.foreground());
00203 b.setColor(invertedColor);
00204 additionalFormats[a].format.setForeground(b);
00205 }
00206 }
00207 }
00208
00209 for(int a = additionalFormats.size()-1; a >= 0; --a) {
00210 if(additionalFormats[a].length == 0){
00211 additionalFormats.removeAt(a);
00212 }else{
00215 QTextCharFormat fm;
00216 fm.setForeground(QBrush(additionalFormats[a].format.foreground().color()));
00217 fm.setBackground(additionalFormats[a].format.background());
00218 fm.setUnderlineStyle( additionalFormats[a].format.underlineStyle() );
00219 fm.setUnderlineColor( additionalFormats[a].format.underlineColor() );
00220 fm.setFontWeight( additionalFormats[a].format.fontWeight() );
00221 additionalFormats[a].format = fm;
00222 }
00223 }
00224
00225
00226
00227
00228
00229 layout.setAdditionalFormats(additionalFormats);
00230
00231 QTextOption to;
00232
00233 to.setAlignment( m_cachedAlignment );
00234
00235 to.setWrapMode(QTextOption::WrapAnywhere);
00236 layout.setTextOption(to);
00237
00238 layout.beginLayout();
00239 QTextLine line = layout.createLine();
00240 line.setLineWidth(rect.width());
00241 layout.endLayout();
00242
00243
00244 if( to.alignment() & Qt::AlignBottom)
00245 layout.draw(painter, QPoint(rect.left(), rect.bottom() - (int)line.height()) );
00246 else
00247 layout.draw(painter, rect.topLeft() );
00248
00249 return;
00250
00251
00252
00253
00254 }
00255
00256 void ExpandingDelegate::drawBackground ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const {
00257 QStyleOptionViewItemV4 opt = option;
00258
00259
00260 QStyle *style = model()->treeView()->style() ? model()->treeView()->style() : QApplication::style();
00261 style->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
00262 }
00263
00264 ExpandingWidgetModel* ExpandingDelegate::model() const {
00265 return m_model;
00266 }
00267
00268 void ExpandingDelegate::heightChanged() const {
00269 }
00270
00271 bool ExpandingDelegate::editorEvent ( QEvent * event, QAbstractItemModel * , const QStyleOptionViewItem & , const QModelIndex & index )
00272 {
00273 QKeyEvent* keyEvent = 0;
00274 if( event->type() == QEvent::KeyPress )
00275 keyEvent = reinterpret_cast<QKeyEvent*>(event);
00276
00277 if( event->type() == QEvent::MouseButtonRelease )
00278 {
00279 event->accept();
00280 model()->setExpanded(index, !model()->isExpanded( index ));
00281 heightChanged();
00282
00283 return true;
00284 } else {
00285 event->ignore();
00286 }
00287
00288 return false;
00289 }
00290
00291 QList<QTextLayout::FormatRange> ExpandingDelegate::highlightingFromVariantList(const QList<QVariant>& customHighlights) const
00292 {
00293 QList<QTextLayout::FormatRange> ret;
00294
00295 for (int i = 0; i + 2 < customHighlights.count(); i += 3) {
00296 if (!customHighlights[i].canConvert(QVariant::Int) || !customHighlights[i+1].canConvert(QVariant::Int) || !customHighlights[i+2].canConvert<QTextFormat>()) {
00297 kWarning() << "Unable to convert triple to custom formatting.";
00298 continue;
00299 }
00300
00301 QTextLayout::FormatRange format;
00302 format.start = customHighlights[i].toInt();
00303 format.length = customHighlights[i+1].toInt();
00304 format.format = customHighlights[i+2].value<QTextFormat>().toCharFormat();
00305
00306 if(!format.format.isValid())
00307 kWarning() << "Format is not valid";
00308
00309 ret << format;
00310 }
00311 return ret;
00312 }
00313
00314 #include "expandingdelegate.moc"