Skip to content

Commit 4334234

Browse files
author
timlinux
committed
Implemented word wrap in manually draw detailed item delegate and other related cleanups
git-svn-id: http://svn.osgeo.org/qgis/trunk@8520 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 8d292c1 commit 4334234

File tree

5 files changed

+176
-28
lines changed

5 files changed

+176
-28
lines changed

src/gui/qgsdetaileditemdata.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@ void QgsDetailedItemData::setDetail(QString theDetail)
3535
mDetail=theDetail;
3636
}
3737

38+
void QgsDetailedItemData::setIcon(QPixmap theIcon)
39+
{
40+
mPixmap = theIcon;
41+
}
42+
void QgsDetailedItemData::setCheckable(bool theFlag)
43+
{
44+
mCheckableFlag = theFlag;
45+
}
46+
void QgsDetailedItemData::setChecked(bool theFlag)
47+
{
48+
mCheckedFlag = theFlag;
49+
}
50+
3851
QString QgsDetailedItemData::title()
3952
{
4053
return mTitle;
@@ -44,3 +57,18 @@ QString QgsDetailedItemData::detail()
4457
{
4558
return mDetail;
4659
}
60+
61+
QPixmap QgsDetailedItemData::icon()
62+
{
63+
return mPixmap;
64+
}
65+
66+
bool QgsDetailedItemData::isCheckable()
67+
{
68+
return mCheckableFlag;
69+
}
70+
71+
bool QgsDetailedItemData::isChecked()
72+
{
73+
return mCheckedFlag;
74+
}

src/gui/qgsdetaileditemdata.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <QMetaType>
2323
#include <QString>
24+
#include <QPixmap>
2425

2526
/** This class is the data only representation of a
2627
* QgsDetailedItemWidget, designed to be used in custom views.
@@ -32,13 +33,23 @@ class QgsDetailedItemData
3233
~QgsDetailedItemData();
3334
void setTitle(QString theTitle);
3435
void setDetail(QString theDetail);
36+
void setIcon(QPixmap theIcon);
37+
void setCheckable(bool theFlag);
38+
void setChecked(bool theFlag);
39+
3540
QString title();
3641
QString detail();
42+
QPixmap icon();
43+
bool isCheckable();
44+
bool isChecked();
45+
3746
private:
3847
QString mTitle;
3948
QString mDetail;
4049
QString mLibraryName;
41-
bool mCheckBoxEnabled;
50+
QPixmap mPixmap;
51+
bool mCheckableFlag;
52+
bool mCheckedFlag;
4253
};
4354

4455
// Make QVariant aware of this data type (see qtdocs star

src/gui/qgsdetaileditemdelegate.cpp

Lines changed: 128 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ QgsDetailedItemDelegate::QgsDetailedItemDelegate(QObject * parent) :
3232
mpCheckBox(new QCheckBox())
3333

3434
{
35+
//mpWidget->setFixedHeight(80);
3536
mpCheckBox->resize(16,16);
3637
}
3738

@@ -86,21 +87,24 @@ void QgsDetailedItemDelegate::paint(QPainter * thepPainter,
8687
QString myDetailString = theIndex.model()->data(theIndex, Qt::UserRole).toString();
8788
bool myCheckState = theIndex.model()->data(theIndex, Qt::CheckStateRole).toBool();
8889
mpCheckBox->setChecked(myCheckState);
89-
QPixmap myPixmap(mpCheckBox->size());
90-
mpCheckBox->render(&myPixmap); //we will draw this onto the widget further down
90+
QPixmap myCbxPixmap(mpCheckBox->size());
91+
mpCheckBox->render(&myCbxPixmap); //we will draw this onto the widget further down
92+
QPixmap myDecoPixmap;
9193

9294
//
9395
// Calculate the widget height and other metrics
9496
//
9597
QFont myFont = theOption.font;
96-
QFont myBoldFont = myFont;
97-
myBoldFont.setBold(true);
98-
myBoldFont.setPointSize(myFont.pointSize() + 3);
99-
QFontMetrics myMetrics(myBoldFont);
98+
QFont myTitleFont = myFont;
99+
myTitleFont.setBold(true);
100+
myTitleFont.setPointSize(myFont.pointSize() + 3);
101+
QFontMetrics myTitleMetrics(myTitleFont);
102+
QFontMetrics myDetailMetrics(myFont);
100103
int myVerticalSpacer = 3; //spacing between title and description
101104
int myHorizontalSpacer = 5; //spacing between checkbox / icon and description
102-
int myTextStartX = theOption.rect.x() + myPixmap.width() + myHorizontalSpacer;
103-
int myHeight = myMetrics.height() + myVerticalSpacer;
105+
int myTextStartX = theOption.rect.x() + myHorizontalSpacer;
106+
int myTextStartY= theOption.rect.y() + myVerticalSpacer;
107+
int myHeight = myTitleMetrics.height() + myVerticalSpacer;
104108

105109
//
106110
// Draw the item background with a gradient if its highlighted
@@ -110,7 +114,7 @@ void QgsDetailedItemDelegate::paint(QPainter * thepPainter,
110114
QColor myColor1 = theOption.palette.highlight();
111115
QColor myColor2 = myColor1;
112116
myColor2 = myColor2.lighter(110); //10% lighter
113-
int myHeight = myMetrics.height() + myVerticalSpacer;
117+
int myHeight = myTitleMetrics.height() + myVerticalSpacer;
114118
QLinearGradient myGradient(QPointF(0,theOption.rect.y()),
115119
QPointF(0,theOption.rect.y() + myHeight*2));
116120
myGradient.setColorAt(0, myColor1);
@@ -124,19 +128,61 @@ void QgsDetailedItemDelegate::paint(QPainter * thepPainter,
124128
//
125129
// Draw the checkbox
126130
//
127-
thepPainter->drawPixmap(theOption.rect.x(),
128-
theOption.rect.y() + mpCheckBox->height(),
129-
myPixmap);
130-
131+
bool myCheckableFlag = true;
132+
if (theIndex.flags() == Qt::ItemIsUserCheckable)
133+
{
134+
myCheckableFlag = false;
135+
}
136+
if (myCheckableFlag)
137+
{
138+
thepPainter->drawPixmap(theOption.rect.x(),
139+
theOption.rect.y() + mpCheckBox->height(),
140+
myCbxPixmap);
141+
myTextStartX = theOption.rect.x() + myCbxPixmap.width() + myHorizontalSpacer;
142+
}
143+
//
144+
// Draw the decoration (pixmap)
131145
//
132-
// Draw the title and description
146+
bool myIconFlag = false;
147+
if (!theIndex.model()->data(theIndex, Qt::DecorationRole).isNull())
148+
{
149+
myDecoPixmap = theIndex.model()->data(theIndex, Qt::DecorationRole).value<QPixmap>();
150+
thepPainter->drawPixmap(myTextStartX,
151+
myTextStartY + (myDecoPixmap.height() / 2),
152+
myDecoPixmap);
153+
myTextStartX += myDecoPixmap.width() + myHorizontalSpacer;
154+
}
155+
//
156+
// Draw the title
157+
//
158+
myTextStartY += myHeight/2;
159+
thepPainter->setFont(myTitleFont);
160+
thepPainter->drawText( myTextStartX ,
161+
myTextStartY ,
162+
myString);
163+
//
164+
// Draw the description with word wrapping if needed
133165
//
134-
thepPainter->setFont(myBoldFont);
135-
thepPainter->drawText( myTextStartX ,theOption.rect.y() + myHeight, myString);
136166
thepPainter->setFont(myFont); //return to original font set by client
137-
thepPainter->drawText( myTextStartX,
138-
theOption.rect.y() + (myHeight *2) - myVerticalSpacer,
139-
myDetailString);
167+
if (myIconFlag)
168+
{
169+
myTextStartY += myVerticalSpacer;
170+
}
171+
else
172+
{
173+
myTextStartY += myDetailMetrics.height() + myVerticalSpacer;
174+
}
175+
QStringList myList =
176+
wordWrap( myDetailString, myDetailMetrics, theOption.rect.width() - myTextStartX );
177+
QStringListIterator myLineWrapIterator(myList);
178+
while (myLineWrapIterator.hasNext())
179+
{
180+
QString myLine = myLineWrapIterator.next();
181+
thepPainter->drawText( myTextStartX,
182+
myTextStartY,
183+
myLine);
184+
myTextStartY += myDetailMetrics.height() - myVerticalSpacer;
185+
}
140186
thepPainter->restore();
141187
}
142188
}
@@ -152,14 +198,70 @@ QSize QgsDetailedItemDelegate::sizeHint(
152198
else // fall back to hand calculated & hand drawn item
153199
{
154200
QFont myFont = theOption.font;
155-
QFont myBoldFont = myFont;
156-
myBoldFont.setBold(true);
157-
myBoldFont.setPointSize(myFont.pointSize() + 3);
158-
QFontMetrics myMetrics(myBoldFont);
201+
QFont myTitleFont = myFont;
202+
myTitleFont.setBold(true);
203+
myTitleFont.setPointSize(myFont.pointSize() + 3);
204+
QFontMetrics myTitleMetrics(myTitleFont);
205+
QFontMetrics myDetailMetrics(myFont);
159206
int myVerticalSpacer = 3; //spacing between title and description
160207
int myHorizontalSpacer = 5; //spacing between checkbox / icon and description
161-
int myHeight = myMetrics.height() + myVerticalSpacer;
162-
return QSize(50,
163-
myHeight *2 + myVerticalSpacer);
208+
int myHeight = myTitleMetrics.height() + myVerticalSpacer;
209+
QString myDetailString = theIndex.model()->data(theIndex, Qt::UserRole).toString();
210+
QStringList myList = wordWrap( myDetailString,
211+
myDetailMetrics,
212+
theOption.rect.width() - (mpCheckBox->width() + myHorizontalSpacer));
213+
myHeight += (myList.count() + 1) * (myDetailMetrics.height() - myVerticalSpacer);
214+
#ifdef Q_OS_MACX
215+
//for some reason itmes are non selectable if using rect.width() on osx
216+
return QSize(50, myHeight + myVerticalSpacer);
217+
#else
218+
return QSize(theOption.rect.width(), myHeight + myVerticalSpacer);
219+
#endif
220+
}
221+
}
222+
223+
QStringList QgsDetailedItemDelegate::wordWrap(QString theString,
224+
QFontMetrics theMetrics,
225+
int theWidth) const
226+
{
227+
if ( theString.isEmpty() ) return QStringList();
228+
if ( 50 >= theWidth ) return QStringList() << theString;
229+
QString myDebug = QString("Word wrapping: %1 into %2 pixels").arg(theString).arg(theWidth);
230+
qDebug(myDebug.toLocal8Bit());
231+
//iterate the string
232+
QStringList myList;
233+
QString myCumulativeLine="";
234+
QString myStringToPreviousSpace="";
235+
int myPreviousSpacePos=0;
236+
for (int i=0; i < theString.count(); ++i)
237+
{
238+
QChar myChar = theString.at(i);
239+
if (myChar == QChar(' '))
240+
{
241+
myStringToPreviousSpace = myCumulativeLine;
242+
myPreviousSpacePos=i;
243+
}
244+
myCumulativeLine += myChar;
245+
if (theMetrics.width(myCumulativeLine) >= theWidth)
246+
{
247+
//time to wrap
248+
//@todo deal with long strings that have no spaces
249+
//forcing a break at current pos...
250+
myList << myStringToPreviousSpace.trimmed();
251+
i = myPreviousSpacePos;
252+
myStringToPreviousSpace = "";
253+
myCumulativeLine = "";
254+
}
255+
}//end of i loop
256+
//add whatever is left in the string to the list
257+
if (!myCumulativeLine.trimmed().isEmpty())
258+
{
259+
myList << myCumulativeLine.trimmed();
164260
}
261+
262+
//qDebug("Wrapped legend entry:");
263+
//qDebug(theString);
264+
//qDebug(myList.join("\n").toLocal8Bit());
265+
return myList;
266+
165267
}

src/gui/qgsdetaileditemdelegate.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
class QCheckBox;
2525
class QgsDetailedItemWidget;
26+
class QFontMetrics;
2627

2728
class GUI_EXPORT QgsDetailedItemDelegate :
2829
public QAbstractItemDelegate
@@ -37,6 +38,9 @@ class GUI_EXPORT QgsDetailedItemDelegate :
3738
QSize sizeHint( const QStyleOptionViewItem & theOption,
3839
const QModelIndex & theIndex ) const;
3940
private:
41+
QStringList wordWrap(QString theString,
42+
QFontMetrics theMetrics,
43+
int theWidth) const;
4044
QgsDetailedItemWidget * mpWidget;
4145
QCheckBox * mpCheckBox;
4246
};

src/gui/qgsdetaileditemwidget.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ QgsDetailedItemWidget::~QgsDetailedItemWidget()
3131
void QgsDetailedItemWidget::setData(QgsDetailedItemData theData)
3232
{
3333
lblTitle->setText(theData.title());
34-
tbDetail->setText(theData.detail());
34+
lblDetail->setText(theData.detail());
35+
cbx->setVisible(theData.isCheckable());
36+
cbx->setChecked(theData.isChecked());
37+
lblIcon->setPixmap(theData.icon());
3538
}
3639

3740
void QgsDetailedItemWidget::setChecked(bool theFlag)

0 commit comments

Comments
 (0)