From: pavelpa Date: Tue, 12 Jan 2010 08:15:42 +0000 (+0000) Subject: modified model-view X-Git-Tag: 0.5.0~318 X-Git-Url: https://git.toastfreeware.priv.at/toast/confclerk.git/commitdiff_plain/66327a09223edea0c2ff159ff965fe394747ab42 modified model-view - created own delegate to display TreeView items - contains also 'controls' - which are clickable (handled in TreeView) - created own TreeView inherited from QTreeView - to handle control-clicks of the Delegate - minor modifications to MainWindow UI - QTreeView replaced by own TreeView - autoresizing of TreeView - icons added --- diff --git a/src/app/app.pro b/src/app/app.pro index 48d12f6..c14f1e6 100644 --- a/src/app/app.pro +++ b/src/app/app.pro @@ -11,3 +11,5 @@ TARGETDEPS += $$DESTDIR/libmodel.a $$DESTDIR/libgui.a SOURCES += main.cpp +RESOURCES += ../icons.qrc + diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index bf48d91..b2f091c 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -4,6 +4,7 @@ #include #include +#include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) @@ -15,6 +16,11 @@ MainWindow::MainWindow(QWidget *parent) setupUi(this); //TODO Palo: continue - //treeView->setModel(new QDirModel); + treeView->setHeaderHidden(true); + treeView->setRootIsDecorated(false); + treeView->setIndentation(0); + treeView->setAnimated(true); treeView->setModel(new EventModel()); + treeView->setItemDelegate(new Delegate(treeView)); } + diff --git a/src/gui/mainwindow.ui b/src/gui/mainwindow.ui index bdce5c7..5447986 100644 --- a/src/gui/mainwindow.ui +++ b/src/gui/mainwindow.ui @@ -5,60 +5,69 @@ 0 0 - 800 - 600 + 856 + 558 MainWindow - - - - 0 - 0 - 791 - 551 - - - - 0 - - - - Tab 1 - - - - - 0 - 0 - 781 - 521 - + + + + + 0 + + + Tab 1 + + + + + + + + + 16777215 + 16777215 + + + + + + + + + + + Tab 2 + + - - - - Tab 2 - - - + + 0 0 - 800 - 25 + 856 + 22 + + + TreeView + QTreeView +
../model/treeview.h
+
+
diff --git a/src/icons.qrc b/src/icons.qrc new file mode 100644 index 0000000..3579279 --- /dev/null +++ b/src/icons.qrc @@ -0,0 +1,10 @@ + + + icons/favourite-on.png + icons/favourite-off.png + icons/alarm-on.png + icons/alarm-off.png + icons/expand.png + icons/collapse.png + + diff --git a/src/icons/alarm-off.png b/src/icons/alarm-off.png new file mode 100644 index 0000000..acb7b5c Binary files /dev/null and b/src/icons/alarm-off.png differ diff --git a/src/icons/alarm-on.png b/src/icons/alarm-on.png new file mode 100644 index 0000000..4ecff7b Binary files /dev/null and b/src/icons/alarm-on.png differ diff --git a/src/icons/collapse.png b/src/icons/collapse.png new file mode 100644 index 0000000..b3a0825 Binary files /dev/null and b/src/icons/collapse.png differ diff --git a/src/icons/expand.png b/src/icons/expand.png new file mode 100644 index 0000000..4dfcdc6 Binary files /dev/null and b/src/icons/expand.png differ diff --git a/src/icons/favourite-off.png b/src/icons/favourite-off.png new file mode 100644 index 0000000..1b42daf Binary files /dev/null and b/src/icons/favourite-off.png differ diff --git a/src/icons/favourite-on.png b/src/icons/favourite-on.png new file mode 100644 index 0000000..4b569ce Binary files /dev/null and b/src/icons/favourite-on.png differ diff --git a/src/model/delegate.cpp b/src/model/delegate.cpp new file mode 100644 index 0000000..95ab7b1 --- /dev/null +++ b/src/model/delegate.cpp @@ -0,0 +1,220 @@ +#include "delegate.h" +#include "eventmodel.h" + +#include +#include + +const int RADIUS = 10; +const int SPACER = RADIUS; + +Delegate::Delegate(QTreeView *aParent) + : QItemDelegate(aParent) + , mViewPtr(aParent) +{ + mControls.clear(); + defineControls(); +} + +Delegate::~Delegate() +{ + QListIterator i(mControls.keys()); + while (i.hasNext()) + { + delete mControls[i.next()]->image(); + } +} + +void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + if(!mViewPtr) + return; + + painter->save(); + + QColor bkgrColor = Qt::cyan; + QPen borderPen(bkgrColor.darker()); + if(hasParent(index)) + { + if(isLast(index)) + { + QLinearGradient lastGradient(option.rect.topLeft(), option.rect.bottomLeft()); + lastGradient.setColorAt(0.0, Qt::white); + lastGradient.setColorAt(0.5, bkgrColor); + lastGradient.setColorAt(1.0, Qt::white); + + QPainterPath endPath; + endPath.moveTo(option.rect.topLeft()); + endPath.lineTo(option.rect.bottomLeft()-QPoint(0, RADIUS)); + endPath.arcTo(option.rect.left(), option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 180, 90); + endPath.lineTo(option.rect.bottomRight()-QPoint(RADIUS, 0)); + endPath.arcTo(option.rect.right()-2*RADIUS, option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 270, 90); + endPath.lineTo(option.rect.topRight()); + + //painter->setBrush( bkgrColor ); + painter->setBrush(lastGradient); + painter->setPen(borderPen); + painter->drawPath(endPath); + + painter->setFont(option.font); + } + else // middle elements + { + + QLinearGradient middleGradient(option.rect.topLeft(), option.rect.bottomLeft()); + middleGradient.setColorAt(0.0, Qt::white); + middleGradient.setColorAt(0.25, bkgrColor); + middleGradient.setColorAt(0.5, Qt::white); + middleGradient.setColorAt(0.75, bkgrColor); + middleGradient.setColorAt(1.0, Qt::white); + + //painter->setBrush( bkgrColor ); + painter->setBrush(middleGradient); + painter->setPen(Qt::NoPen); + painter->drawRect(option.rect); + + painter->setPen(borderPen); + // vertical lines + painter->drawLine(option.rect.topLeft(), option.rect.bottomLeft()); + painter->drawLine(option.rect.topRight(), option.rect.bottomRight()); + // horizontal lines + painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight()); + + painter->setFont(option.font); + } + + // draw Controls + painter->drawImage(mControls[FavouriteControl]->drawPoint(option.rect),*mControls[FavouriteControl]->image()); + painter->drawImage(mControls[AlarmControl]->drawPoint(option.rect),*mControls[AlarmControl]->image()); + } + else // doesn't have parent - time-groups' elements (top items) + { + QLinearGradient titleGradient(option.rect.topLeft(), option.rect.topRight()); + //titleGradient.setColorAt(0.0, Qt::white); + titleGradient.setColorAt(0.0, bkgrColor); + titleGradient.setColorAt(0.5, Qt::white); + titleGradient.setColorAt(1.0, bkgrColor); + + QPainterPath titlePath; + if(isExpanded(index)) + { + titlePath.moveTo(option.rect.bottomLeft()); + titlePath.lineTo(option.rect.topLeft()+QPoint(0, RADIUS)); + titlePath.arcTo(option.rect.left(), option.rect.top(), 2*RADIUS, 2*RADIUS, 180, -90); + titlePath.lineTo(option.rect.topRight()-QPoint(RADIUS, 0)); + titlePath.arcTo(option.rect.right()-2*RADIUS, option.rect.top(), 2*RADIUS, 2*RADIUS, 90, -90); + titlePath.lineTo(option.rect.bottomRight()); + titlePath.closeSubpath(); + } + else + { + titlePath.lineTo(option.rect.topLeft()+QPoint(0, RADIUS)); + titlePath.arcTo(option.rect.left(), option.rect.top(), 2*RADIUS, 2*RADIUS, 180, -90); + titlePath.lineTo(option.rect.topRight()-QPoint(RADIUS, 0)); + titlePath.arcTo(option.rect.right()-2*RADIUS, option.rect.top(), 2*RADIUS, 2*RADIUS, 90, -90); + titlePath.lineTo(option.rect.bottomRight()-QPoint(0, RADIUS)); + titlePath.arcTo(option.rect.right()-2*RADIUS, option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 0, -90); + titlePath.lineTo(option.rect.bottomLeft()+QPoint(RADIUS, 0)); + titlePath.arcTo(option.rect.left(), option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 270, -90); + titlePath.closeSubpath(); + } + + painter->setBrush(titleGradient); + painter->setPen(borderPen); + painter->drawPath(titlePath); + + QFont font = option.font; + font.setBold(true); + painter->setFont(font); + } + + //// HIGHLIGHTING SELECTED ITEM + //if (option.state & QStyle::State_Selected) + //painter->fillRect(option.rect, option.palette.highlight()); + + // draw title + QPointF titlePointF(option.rect.x(),option.rect.y()+option.rect.height()-10); + QString text = qVariantValue(index.data()); + painter->drawText(titlePointF,text); + + painter->restore(); +} + +QSize Delegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + Q_UNUSED(option) + + if (index.internalId() == 0) // time group + { + return QSize(30,30); + } + else // event + { + return QSize(100,100); + } +} + +bool Delegate::hasParent( const QModelIndex &index ) const +{ + if( index.parent().isValid() ) + return true; + else + return false; +} + +bool Delegate::isLast( const QModelIndex &index ) const +{ + if(!hasParent(index)) + return false; // what should be returned here? + + if(index.row() >= (index.model()->rowCount(index.parent())-1)) + return true; + else + return false; +} + +bool Delegate::isExpanded( const QModelIndex &index ) const +{ + if( !mViewPtr ) + return false; + else + return mViewPtr->isExpanded( index ); +} + +Delegate::ControlId Delegate::whichControlClicked(const QModelIndex &aIndex, const QPoint &aPoint) const +{ + if(!hasParent(aIndex)) // time-group item (root item) + return ControlNone; + + QListIterator i(mControls.keys()); + while (i.hasNext()) + { + ControlId id = i.next(); + if(mControls[id]->drawRect(static_cast(parent())->visualRect(aIndex)).contains(aPoint)) + return id; + } + + return ControlNone; +} + +void Delegate::defineControls() +{ + Control *control; + // FAVOURITE ICON + control = new Control(FavouriteControl,QString(":icons/favourite-on.png")); + control->setDrawPoint(QPoint(-control->image()->width()-SPACER,SPACER)); + mControls.insert(FavouriteControl,control); + + // ALARM ICON + control = new Control(AlarmControl,QString(":icons/alarm-on.png")); + control->setDrawPoint(QPoint(-mControls[FavouriteControl]->image()->width()-control->image()->width()-2*SPACER,SPACER)); + mControls.insert(AlarmControl,control); +} + +bool Delegate::isPointFromRect(const QPoint &aPoint, const QRect &aRect) const +{ + if( (aPoint.x()>=aRect.left() && aPoint.x()<=aRect.right()) && (aPoint.y()>=aRect.top() && aPoint.y()<=aRect.bottom()) ) + return true; + + return false; +} + diff --git a/src/model/delegate.h b/src/model/delegate.h new file mode 100644 index 0000000..657994d --- /dev/null +++ b/src/model/delegate.h @@ -0,0 +1,66 @@ +#ifndef DELEGATE_H +#define DELEGATE_H + +#include +#include +#include + +class Delegate : public QItemDelegate +{ + Q_OBJECT + + public: + + enum ControlId + { + ControlNone = 0, + FavouriteControl, + AlarmControl + }; + + class Control + { + public: + Control(ControlId aControlId, const QString &aImageName) + : mId(aControlId) + , mImage(new QImage(aImageName)) + , mDrawPoint(QPoint(0,0)) + { } + inline QImage *image() const { return mImage; } + inline void setDrawPoint(const QPoint &aPoint) { mDrawPoint = aPoint; } + inline QPoint drawPoint(const QRect &aRect) const // for painter to draw Control + { + return QPoint(aRect.x()+aRect.width(),aRect.y()) + mDrawPoint; + } + inline QRect drawRect(const QRect &aRect) const // helper for determining if Control was clicked + { + return QRect(drawPoint(aRect), drawPoint(aRect)+QPoint(mImage->size().width(),mImage->size().height())); + } + private: + ControlId mId; + QImage *mImage; + QPoint mDrawPoint; // relative 'start-drawing' position (may hold negative values) + }; + + Delegate(QTreeView *aParent); // the delegate 'owner' has to be specified in the constructor - it's used to obtain visualRect of selected item/index + ~Delegate(); + + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; + // + Delegate::ControlId whichControlClicked(const QModelIndex &aIndex, const QPoint &aPoint) const; + bool isPointFromRect(const QPoint &aPoint, const QRect &aRect) const; + + private: + bool hasParent( const QModelIndex &index ) const; + bool isLast( const QModelIndex &index ) const; + bool isExpanded( const QModelIndex &index ) const; + void defineControls(); + + private: + QPointer mViewPtr; + QMap mControls; +}; + +#endif /* DELEGATE_H */ + diff --git a/src/model/model.pro b/src/model/model.pro index c8e0b62..1a80365 100644 --- a/src/model/model.pro +++ b/src/model/model.pro @@ -12,8 +12,12 @@ TARGETDEPS += $$DESTDIR/liborm.a HEADERS += \ event.h \ - eventmodel.h + delegate.h \ + eventmodel.h \ + treeview.h SOURCES += \ event.cpp \ - eventmodel.cpp + delegate.cpp \ + eventmodel.cpp \ + treeview.cpp diff --git a/src/model/treeview.cpp b/src/model/treeview.cpp new file mode 100644 index 0000000..80fbd28 --- /dev/null +++ b/src/model/treeview.cpp @@ -0,0 +1,52 @@ +#include + +#include "treeview.h" +#include "delegate.h" + +#include + +TreeView::TreeView(QWidget *aParent) + : QTreeView(aParent) +{ +} + +void TreeView::mouseReleaseEvent(QMouseEvent *aEvent) +{ + QModelIndex index = currentIndex(); + QPoint point = aEvent->pos(); + + testForControlClicked(index,point); + + // pass the event to the Base class, so item clicks/events are handled correctly + QTreeView::mouseReleaseEvent(aEvent); +} + +void TreeView::testForControlClicked(const QModelIndex &aIndex, const QPoint &aPoint) +{ + if(!aIndex.isValid()) + return; + + QRect rect = visualRect(aIndex); // visual QRect of selected/clicked item in the list + Delegate *delegate = static_cast(itemDelegate(aIndex)); + switch(delegate->whichControlClicked(aIndex,aPoint)) + { + case Delegate::FavouriteControl: + { + // handle Favourite Control clicked + qDebug() << "FAVOURITE CLICKED: " << qVariantValue(aIndex.data()); + } + break; + case Delegate::AlarmControl: + { + // handle Alarm Control clicked + qDebug() << "ALARM CLICKED: " << qVariantValue(aIndex.data()); + } + break; + case Delegate::ControlNone: + default: + { + // item was clicked, but not a control + } + }; +} + diff --git a/src/model/treeview.h b/src/model/treeview.h new file mode 100644 index 0000000..2a81907 --- /dev/null +++ b/src/model/treeview.h @@ -0,0 +1,17 @@ +#ifndef TREEVIEW_H +#define TREEVIEW_H + +#include + +class TreeView : public QTreeView +{ +public: + TreeView(QWidget *aParent = NULL); + ~TreeView() {} +private: + void mouseReleaseEvent(QMouseEvent *aEvent); + void testForControlClicked(const QModelIndex &aIndex, const QPoint &aPoint); +}; + +#endif /* TREEVIEW_H */ +