From 66327a09223edea0c2ff159ff965fe394747ab42 Mon Sep 17 00:00:00 2001 From: pavelpa Date: Tue, 12 Jan 2010 08:15:42 +0000 Subject: [PATCH] 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 --- src/app/app.pro | 2 + src/gui/mainwindow.cpp | 8 +- src/gui/mainwindow.ui | 79 +++++++------ src/icons.qrc | 10 ++ src/icons/alarm-off.png | Bin 0 -> 403 bytes src/icons/alarm-on.png | Bin 0 -> 795 bytes src/icons/collapse.png | Bin 0 -> 475 bytes src/icons/expand.png | Bin 0 -> 484 bytes src/icons/favourite-off.png | Bin 0 -> 360 bytes src/icons/favourite-on.png | Bin 0 -> 627 bytes src/model/delegate.cpp | 220 ++++++++++++++++++++++++++++++++++++ src/model/delegate.h | 66 +++++++++++ src/model/model.pro | 8 +- src/model/treeview.cpp | 52 +++++++++ src/model/treeview.h | 17 +++ 15 files changed, 424 insertions(+), 38 deletions(-) create mode 100644 src/icons.qrc create mode 100644 src/icons/alarm-off.png create mode 100644 src/icons/alarm-on.png create mode 100644 src/icons/collapse.png create mode 100644 src/icons/expand.png create mode 100644 src/icons/favourite-off.png create mode 100644 src/icons/favourite-on.png create mode 100644 src/model/delegate.cpp create mode 100644 src/model/delegate.h create mode 100644 src/model/treeview.cpp create mode 100644 src/model/treeview.h 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 0000000000000000000000000000000000000000..acb7b5c8727f8df6f33a0ab8b51029993094c33e GIT binary patch literal 403 zcmV;E0c`$>P)Llsr(%}XPb`(LJTQ^77Ix6}HT<5CbS_}v+E_RUy#6h7n zF(57u2BAZfG(GPnDE;8w_wnA3yN@&dTd)+5vuNn*=AbC|q+I=*myGck%CZ1!&&QEb zbv(}l#hD&6GG-V8K>+mH6<7@)aw~#u+vs@$?Pdi+0A#R#-oKL#sL3={X{MBvGVc^U zW@L;wj-AcpPrZbRBr6tTr|2;wW9kDNYb%In1yt15c7E5Qm(KV7J>2wEgm`pQli~9ew6g_5Sj5JMe=06{}xawo@@{ZXYxj55fM#ij_ xMlE~;kCAmSd<_p5KU}LL%E5K5gx0SB0{{reumGaoN-O{X002ovPDHLkV1ks-rAz<- literal 0 HcmV?d00001 diff --git a/src/icons/alarm-on.png b/src/icons/alarm-on.png new file mode 100644 index 0000000000000000000000000000000000000000..4ecff7b4c1c3bce457024c07e7bb09d88e9be6e4 GIT binary patch literal 795 zcmV+$1LXXPP)HE&v4l{b;;r-70KF{-g?|1kZ&oHv1hoGBa ziok-y;UK6dc#`HRvHB8_BoEEf&eu+ftfiPRB$00it*3hqTBAM6q1<#G%;KQzBk{M! z4sGWeYQ^(|1$liprxyR~lVI4`Z}gN^n}J;iK94*F#{n_16r?|LC!Z8c)##S%<}FR{m9o2kQx-KIl3UOr;SZSy=BF$kv< zuyz=7J^1nQ}HYm4l**^C1I0j`(~I9=j4xY_tX~fnE@ePnYmpSZkjI zYv22DBoZlazIX!H&6N-jlw-TyZaEuHDu%S@54B@(nuk7LA0FvyKn`srlS!Uo7+81% zk}0T29Vp1IQ4Zx&4b`$~1LWpv!4>IcQYO}aC?j0Ts!_riV_aj1!GUL4Gqr zp^$L)xL8cNlfmVB)xhiZ!e+BUOP*>nX&4p+;U+;NY4Mr2L&qn0rHy!R*leEe%vgT~ Z7yuDdOA@OlFfRZA002ovPDHLkV1ha>YSjP$ literal 0 HcmV?d00001 diff --git a/src/icons/collapse.png b/src/icons/collapse.png new file mode 100644 index 0000000000000000000000000000000000000000..b3a08254f75b7de96d0cc0898676dffcc0732e4a GIT binary patch literal 475 zcmV<10VMv3P)ge@i#*BK5C0CPS9O3j}l$F+V{^!Nw(Pdf)kC zV-O0pf#V(b-Q9b4-xs5*DthEI&|va8nXx}*3)#|NY63RJ_P%^w&Yln{%W~?vE>6W3 zXurbQ^noEq`?!##K~WT89LF>q4&kdj&nrIZd_If8*D-}0v^m3(T$DU|H66^I)XygI>0vO{2&Y8UW8slN23~$7_S_ zc1xfcIqUUW)mo^Ps2sMefNCI86`ZKz=Q%yT{?$2=4Axj}a!Auzv`~``#n8o$= z?s(6p;#3VBcklb|?j?6$gp?9)c?30>ea~Wyy-V)me0fu{cv|=m6rD~d&vji!%d!N^ zvc$E^kdw&qVYAurh1}qHJVIU9Oyqe^=1r&5q*=XQuerc9P0%&xPZ)j;WxwBts;Xcz znLwJR#Q7L=6FgIKtT~;#d)|qb?$&O%1$sY?H2ZLd%+F5uibzBOoz{dfAboD a1Q-Cs*a@%U2aAjV0000f4v7|ftIx;YR|DNig)WpGT%PfAtr%uP&B4N6T+sVqF1Y6DdC%hSa%q~cc21jDXF4ic^Rc`mX# z2C;~}iOH1_$a(9-_mFW7tFCT1f5P&)>K}wWm(T5;V8SSv6DBPvHi^S3|HLLonTj*B z-~a!gc(0?P_xjfp<$*1q>e!|J-thRna_zANFSuolPXAlJ<$u{N<$y1&eA>Pb--r25 zUvN#5;pIsYS<{AR_2)T`q&2#iOE8Da=TCo|xI4#*rTBx{{(J8heJVWqR^8<5tL2CC zlOAul|LMg^6~_gp*7C|zyd_upo$Z*{WBSeGuUp2~eNxl*ePruA0~U#>%(}i&ze7oZ zM^He6b^BGLPTzoy^JciIDbC3B{VZ|kr>o4Dc}zSE$;uh)=WsSE14Dtq)78&qol`;+ E02sEDNB{r; literal 0 HcmV?d00001 diff --git a/src/icons/favourite-on.png b/src/icons/favourite-on.png new file mode 100644 index 0000000000000000000000000000000000000000..4b569ce09d88ded983318e5bfd761f5032a62bc2 GIT binary patch literal 627 zcmV-(0*w8MP)zMGIDwi$y_Cg+^@&-LA7c&NmyQlQ!bOW4?Lc``*rvZ`np2{~DqC?(_DEp?Yxm1y;1o6X>Mq2Y z%kmQUJ_Erg{MWEf0@)LIeJ>A#bJSkm$yaCQFM&lJ#C#V3O(~u)7Jq zyM>gIgGk%>u)LJ)VC9z5I1>J>TY(6^U}v)pzPF>lcXkY8Qw1>VINtdUqFjk)O6~yV zMbVVA`}Ubkqz}Q!WM#pq4#`oDG^Fj-KpD`OKj$h!@NdXuGcYYn196li4QbWU{x*2} z$ag5tWq!akhO}tUCI+gJ){jwBIMb)bVX!VnaN_GAk7M4YsC^xgYo@P;Y3!*+mn3uv`e zkz1)G28{-s6+iHcMW9ef{(*ig*RKQTZwfrQ(eKEbgg2yx_Gx|zFaXm!`w}4OjYj|g N002ovPDHLkV1lZ&8V&#e literal 0 HcmV?d00001 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 */ + -- 2.39.5