1 /***************************************************************************
2 * Copyright (C) 2008 by <haraldhv (at) stud.ntnu.no> *
3 * Copyright (C) 2008 by <peter.penz@gmx.at> *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
19 ***************************************************************************/
21 #include "ktreeview.h"
22 #include "ktreeview_p.h"
24 #include <KGlobalSettings>
27 #include <QItemSelectionModel>
32 KTreeView::KTreeViewPrivate::KTreeViewPrivate(KTreeView
*parent
) :
34 autoHorizontalScroll(false),
38 startScrollTimer
= new QTimer(this);
39 startScrollTimer
->setSingleShot(true);
40 startScrollTimer
->setInterval(300);
42 timeLine
= new QTimeLine(300, this);
45 void KTreeView::KTreeViewPrivate::connectScrollTimers()
47 connect(startScrollTimer
, SIGNAL(timeout()),
48 this, SLOT(startScrolling()));
50 connect(timeLine
, SIGNAL(frameChanged(int)),
51 this, SLOT(updateVerticalScrollBar(int)));
53 connect(parent
->verticalScrollBar(), SIGNAL(rangeChanged(int, int)),
54 startScrollTimer
, SLOT(start()));
55 connect(parent
->verticalScrollBar(), SIGNAL(valueChanged(int)),
56 startScrollTimer
, SLOT(start()));
57 connect(parent
, SIGNAL(collapsed(const QModelIndex
&)),
58 startScrollTimer
, SLOT(start()));
59 connect(parent
, SIGNAL(expanded(const QModelIndex
&)),
60 startScrollTimer
, SLOT(start()));
63 void KTreeView::KTreeViewPrivate::startScrolling()
67 const int viewportHeight
= parent
->viewport()->height();
69 // check whether there is a selected index which is partly visible
70 const QModelIndexList selectedIndexes
= parent
->selectionModel()->selectedIndexes();
71 if (selectedIndexes
.count() == 1) {
72 QModelIndex selectedIndex
= selectedIndexes
.first();
73 const QRect rect
= parent
->visualRect(selectedIndex
);
74 if ((rect
.bottom() >= 0) && (rect
.top() <= viewportHeight
)) {
75 // the selected index is (at least partly) visible, use it as
77 index
= selectedIndex
;
81 if (!index
.isValid()) {
82 // no partly selected index is visible, determine the most left visual index
83 QModelIndex visibleIndex
= parent
->indexAt(QPoint(0, 0));
84 if (!visibleIndex
.isValid()) {
89 int minimum
= parent
->width();
91 const QRect rect
= parent
->visualRect(visibleIndex
);
92 if (rect
.top() > viewportHeight
) {
93 // the current index and all successors are not visible anymore
96 if (rect
.left() < minimum
) {
97 minimum
= rect
.left();
100 visibleIndex
= parent
->indexBelow(visibleIndex
);
101 } while (visibleIndex
.isValid());
104 // start the horizontal scrolling to assure that the item indicated by 'index' gets fully visible
105 Q_ASSERT(index
.isValid());
106 const QRect rect
= parent
->visualRect(index
);
108 QScrollBar
*scrollBar
= parent
->horizontalScrollBar();
109 const int oldScrollBarPos
= scrollBar
->value();
111 const int itemRight
= oldScrollBarPos
+ rect
.left() + rect
.width() - 1;
112 const int availableWidth
= parent
->viewport()->width();
113 int scrollBarPos
= itemRight
- availableWidth
;
114 const int scrollBarPosMax
= oldScrollBarPos
+ rect
.left() - parent
->indentation();
115 if (scrollBarPos
> scrollBarPosMax
) {
116 scrollBarPos
= scrollBarPosMax
;
119 if (scrollBarPos
!= oldScrollBarPos
) {
120 timeLine
->setFrameRange(oldScrollBarPos
, scrollBarPos
);
125 void KTreeView::KTreeViewPrivate::updateVerticalScrollBar(int value
)
127 QScrollBar
*scrollBar
= parent
->horizontalScrollBar();
128 scrollBar
->setValue(value
);
129 startScrollTimer
->stop();
132 // ************************************************
134 KTreeView::KTreeView(QWidget
*parent
) :
136 d(new KTreeViewPrivate(this))
138 if (KGlobalSettings::graphicEffectsLevel() >= KGlobalSettings::SimpleAnimationEffects
) {
139 setAutoHorizontalScroll(true);
143 KTreeView::~KTreeView()
147 void KTreeView::setAutoHorizontalScroll(bool value
)
149 d
->autoHorizontalScroll
= value
;
152 bool KTreeView::autoHorizontalScroll() const
154 return d
->autoHorizontalScroll
;
157 void KTreeView::setSelectionModel(QItemSelectionModel
*selectionModel
)
159 QTreeView::setSelectionModel(selectionModel
);
160 connect(selectionModel
,
161 SIGNAL(selectionChanged(const QItemSelection
&, const QItemSelection
&)),
162 d
->startScrollTimer
, SLOT(start()));
165 void KTreeView::scrollTo(const QModelIndex
& index
, ScrollHint hint
)
167 if (d
->autoHorizontalScroll
) {
168 // assure that the value of the horizontal scrollbar stays on its current value,
169 // KTreeView will adjust the value manually
170 const int value
= horizontalScrollBar()->value();
171 QTreeView::scrollTo(index
, hint
);
172 horizontalScrollBar()->setValue(value
);
174 QTreeView::scrollTo(index
, hint
);
178 bool KTreeView::event(QEvent
* event
)
180 if (event
->type() == QEvent::Polish
) {
181 d
->connectScrollTimers();
183 return QTreeView::event(event
);
186 #include "ktreeview.moc"
187 #include "ktreeview_p.moc"