Implemented word wrap in manually draw detailed item delegate and other related cleanups

git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@8520 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
timlinux 2008-05-26 14:17:44 +00:00
parent 9581b29b23
commit e3660744a3
5 changed files with 176 additions and 28 deletions

View File

@ -35,6 +35,19 @@ void QgsDetailedItemData::setDetail(QString theDetail)
mDetail=theDetail;
}
void QgsDetailedItemData::setIcon(QPixmap theIcon)
{
mPixmap = theIcon;
}
void QgsDetailedItemData::setCheckable(bool theFlag)
{
mCheckableFlag = theFlag;
}
void QgsDetailedItemData::setChecked(bool theFlag)
{
mCheckedFlag = theFlag;
}
QString QgsDetailedItemData::title()
{
return mTitle;
@ -44,3 +57,18 @@ QString QgsDetailedItemData::detail()
{
return mDetail;
}
QPixmap QgsDetailedItemData::icon()
{
return mPixmap;
}
bool QgsDetailedItemData::isCheckable()
{
return mCheckableFlag;
}
bool QgsDetailedItemData::isChecked()
{
return mCheckedFlag;
}

View File

@ -21,6 +21,7 @@
#include <QMetaType>
#include <QString>
#include <QPixmap>
/** This class is the data only representation of a
* QgsDetailedItemWidget, designed to be used in custom views.
@ -32,13 +33,23 @@ class QgsDetailedItemData
~QgsDetailedItemData();
void setTitle(QString theTitle);
void setDetail(QString theDetail);
void setIcon(QPixmap theIcon);
void setCheckable(bool theFlag);
void setChecked(bool theFlag);
QString title();
QString detail();
QPixmap icon();
bool isCheckable();
bool isChecked();
private:
QString mTitle;
QString mDetail;
QString mLibraryName;
bool mCheckBoxEnabled;
QPixmap mPixmap;
bool mCheckableFlag;
bool mCheckedFlag;
};
// Make QVariant aware of this data type (see qtdocs star

View File

@ -32,6 +32,7 @@ QgsDetailedItemDelegate::QgsDetailedItemDelegate(QObject * parent) :
mpCheckBox(new QCheckBox())
{
//mpWidget->setFixedHeight(80);
mpCheckBox->resize(16,16);
}
@ -86,21 +87,24 @@ void QgsDetailedItemDelegate::paint(QPainter * thepPainter,
QString myDetailString = theIndex.model()->data(theIndex, Qt::UserRole).toString();
bool myCheckState = theIndex.model()->data(theIndex, Qt::CheckStateRole).toBool();
mpCheckBox->setChecked(myCheckState);
QPixmap myPixmap(mpCheckBox->size());
mpCheckBox->render(&myPixmap); //we will draw this onto the widget further down
QPixmap myCbxPixmap(mpCheckBox->size());
mpCheckBox->render(&myCbxPixmap); //we will draw this onto the widget further down
QPixmap myDecoPixmap;
//
// Calculate the widget height and other metrics
//
QFont myFont = theOption.font;
QFont myBoldFont = myFont;
myBoldFont.setBold(true);
myBoldFont.setPointSize(myFont.pointSize() + 3);
QFontMetrics myMetrics(myBoldFont);
QFont myTitleFont = myFont;
myTitleFont.setBold(true);
myTitleFont.setPointSize(myFont.pointSize() + 3);
QFontMetrics myTitleMetrics(myTitleFont);
QFontMetrics myDetailMetrics(myFont);
int myVerticalSpacer = 3; //spacing between title and description
int myHorizontalSpacer = 5; //spacing between checkbox / icon and description
int myTextStartX = theOption.rect.x() + myPixmap.width() + myHorizontalSpacer;
int myHeight = myMetrics.height() + myVerticalSpacer;
int myTextStartX = theOption.rect.x() + myHorizontalSpacer;
int myTextStartY= theOption.rect.y() + myVerticalSpacer;
int myHeight = myTitleMetrics.height() + myVerticalSpacer;
//
// Draw the item background with a gradient if its highlighted
@ -110,7 +114,7 @@ void QgsDetailedItemDelegate::paint(QPainter * thepPainter,
QColor myColor1 = theOption.palette.highlight();
QColor myColor2 = myColor1;
myColor2 = myColor2.lighter(110); //10% lighter
int myHeight = myMetrics.height() + myVerticalSpacer;
int myHeight = myTitleMetrics.height() + myVerticalSpacer;
QLinearGradient myGradient(QPointF(0,theOption.rect.y()),
QPointF(0,theOption.rect.y() + myHeight*2));
myGradient.setColorAt(0, myColor1);
@ -124,19 +128,61 @@ void QgsDetailedItemDelegate::paint(QPainter * thepPainter,
//
// Draw the checkbox
//
thepPainter->drawPixmap(theOption.rect.x(),
theOption.rect.y() + mpCheckBox->height(),
myPixmap);
bool myCheckableFlag = true;
if (theIndex.flags() == Qt::ItemIsUserCheckable)
{
myCheckableFlag = false;
}
if (myCheckableFlag)
{
thepPainter->drawPixmap(theOption.rect.x(),
theOption.rect.y() + mpCheckBox->height(),
myCbxPixmap);
myTextStartX = theOption.rect.x() + myCbxPixmap.width() + myHorizontalSpacer;
}
//
// Draw the title and description
// Draw the decoration (pixmap)
//
bool myIconFlag = false;
if (!theIndex.model()->data(theIndex, Qt::DecorationRole).isNull())
{
myDecoPixmap = theIndex.model()->data(theIndex, Qt::DecorationRole).value<QPixmap>();
thepPainter->drawPixmap(myTextStartX,
myTextStartY + (myDecoPixmap.height() / 2),
myDecoPixmap);
myTextStartX += myDecoPixmap.width() + myHorizontalSpacer;
}
//
// Draw the title
//
myTextStartY += myHeight/2;
thepPainter->setFont(myTitleFont);
thepPainter->drawText( myTextStartX ,
myTextStartY ,
myString);
//
// Draw the description with word wrapping if needed
//
thepPainter->setFont(myBoldFont);
thepPainter->drawText( myTextStartX ,theOption.rect.y() + myHeight, myString);
thepPainter->setFont(myFont); //return to original font set by client
thepPainter->drawText( myTextStartX,
theOption.rect.y() + (myHeight *2) - myVerticalSpacer,
myDetailString);
if (myIconFlag)
{
myTextStartY += myVerticalSpacer;
}
else
{
myTextStartY += myDetailMetrics.height() + myVerticalSpacer;
}
QStringList myList =
wordWrap( myDetailString, myDetailMetrics, theOption.rect.width() - myTextStartX );
QStringListIterator myLineWrapIterator(myList);
while (myLineWrapIterator.hasNext())
{
QString myLine = myLineWrapIterator.next();
thepPainter->drawText( myTextStartX,
myTextStartY,
myLine);
myTextStartY += myDetailMetrics.height() - myVerticalSpacer;
}
thepPainter->restore();
}
}
@ -152,14 +198,70 @@ QSize QgsDetailedItemDelegate::sizeHint(
else // fall back to hand calculated & hand drawn item
{
QFont myFont = theOption.font;
QFont myBoldFont = myFont;
myBoldFont.setBold(true);
myBoldFont.setPointSize(myFont.pointSize() + 3);
QFontMetrics myMetrics(myBoldFont);
QFont myTitleFont = myFont;
myTitleFont.setBold(true);
myTitleFont.setPointSize(myFont.pointSize() + 3);
QFontMetrics myTitleMetrics(myTitleFont);
QFontMetrics myDetailMetrics(myFont);
int myVerticalSpacer = 3; //spacing between title and description
int myHorizontalSpacer = 5; //spacing between checkbox / icon and description
int myHeight = myMetrics.height() + myVerticalSpacer;
return QSize(50,
myHeight *2 + myVerticalSpacer);
int myHeight = myTitleMetrics.height() + myVerticalSpacer;
QString myDetailString = theIndex.model()->data(theIndex, Qt::UserRole).toString();
QStringList myList = wordWrap( myDetailString,
myDetailMetrics,
theOption.rect.width() - (mpCheckBox->width() + myHorizontalSpacer));
myHeight += (myList.count() + 1) * (myDetailMetrics.height() - myVerticalSpacer);
#ifdef Q_OS_MACX
//for some reason itmes are non selectable if using rect.width() on osx
return QSize(50, myHeight + myVerticalSpacer);
#else
return QSize(theOption.rect.width(), myHeight + myVerticalSpacer);
#endif
}
}
QStringList QgsDetailedItemDelegate::wordWrap(QString theString,
QFontMetrics theMetrics,
int theWidth) const
{
if ( theString.isEmpty() ) return QStringList();
if ( 50 >= theWidth ) return QStringList() << theString;
QString myDebug = QString("Word wrapping: %1 into %2 pixels").arg(theString).arg(theWidth);
qDebug(myDebug.toLocal8Bit());
//iterate the string
QStringList myList;
QString myCumulativeLine="";
QString myStringToPreviousSpace="";
int myPreviousSpacePos=0;
for (int i=0; i < theString.count(); ++i)
{
QChar myChar = theString.at(i);
if (myChar == QChar(' '))
{
myStringToPreviousSpace = myCumulativeLine;
myPreviousSpacePos=i;
}
myCumulativeLine += myChar;
if (theMetrics.width(myCumulativeLine) >= theWidth)
{
//time to wrap
//@todo deal with long strings that have no spaces
//forcing a break at current pos...
myList << myStringToPreviousSpace.trimmed();
i = myPreviousSpacePos;
myStringToPreviousSpace = "";
myCumulativeLine = "";
}
}//end of i loop
//add whatever is left in the string to the list
if (!myCumulativeLine.trimmed().isEmpty())
{
myList << myCumulativeLine.trimmed();
}
//qDebug("Wrapped legend entry:");
//qDebug(theString);
//qDebug(myList.join("\n").toLocal8Bit());
return myList;
}

View File

@ -23,6 +23,7 @@
class QCheckBox;
class QgsDetailedItemWidget;
class QFontMetrics;
class GUI_EXPORT QgsDetailedItemDelegate :
public QAbstractItemDelegate
@ -37,6 +38,9 @@ class GUI_EXPORT QgsDetailedItemDelegate :
QSize sizeHint( const QStyleOptionViewItem & theOption,
const QModelIndex & theIndex ) const;
private:
QStringList wordWrap(QString theString,
QFontMetrics theMetrics,
int theWidth) const;
QgsDetailedItemWidget * mpWidget;
QCheckBox * mpCheckBox;
};

View File

@ -31,7 +31,10 @@ QgsDetailedItemWidget::~QgsDetailedItemWidget()
void QgsDetailedItemWidget::setData(QgsDetailedItemData theData)
{
lblTitle->setText(theData.title());
tbDetail->setText(theData.detail());
lblDetail->setText(theData.detail());
cbx->setVisible(theData.isCheckable());
cbx->setChecked(theData.isChecked());
lblIcon->setPixmap(theData.icon());
}
void QgsDetailedItemWidget::setChecked(bool theFlag)