Skip to content

Commit

Permalink
Implemented word wrap in manually draw detailed item delegate and oth…
Browse files Browse the repository at this point in the history
…er related cleanups

git-svn-id: http://svn.osgeo.org/qgis/trunk@8520 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
timlinux committed May 26, 2008
1 parent 8d292c1 commit 4334234
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 28 deletions.
28 changes: 28 additions & 0 deletions src/gui/qgsdetaileditemdata.cpp
Expand Up @@ -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;
Expand All @@ -44,3 +57,18 @@ QString QgsDetailedItemData::detail()
{
return mDetail;
}

QPixmap QgsDetailedItemData::icon()
{
return mPixmap;
}

bool QgsDetailedItemData::isCheckable()
{
return mCheckableFlag;
}

bool QgsDetailedItemData::isChecked()
{
return mCheckedFlag;
}
13 changes: 12 additions & 1 deletion src/gui/qgsdetaileditemdata.h
Expand Up @@ -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.
Expand All @@ -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
Expand Down
154 changes: 128 additions & 26 deletions src/gui/qgsdetaileditemdelegate.cpp
Expand Up @@ -32,6 +32,7 @@ QgsDetailedItemDelegate::QgsDetailedItemDelegate(QObject * parent) :
mpCheckBox(new QCheckBox())

{
//mpWidget->setFixedHeight(80);
mpCheckBox->resize(16,16);
}

Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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 decoration (pixmap)
//
// Draw the title and description
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();
}
}
Expand All @@ -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;

}
4 changes: 4 additions & 0 deletions src/gui/qgsdetaileditemdelegate.h
Expand Up @@ -23,6 +23,7 @@

class QCheckBox;
class QgsDetailedItemWidget;
class QFontMetrics;

class GUI_EXPORT QgsDetailedItemDelegate :
public QAbstractItemDelegate
Expand All @@ -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;
};
Expand Down
5 changes: 4 additions & 1 deletion src/gui/qgsdetaileditemwidget.cpp
Expand Up @@ -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)
Expand Down

0 comments on commit 4334234

Please sign in to comment.