]> cloud.milkyroute.net Git - dolphin.git/blob - src/ktreeview.cpp
fix crash in Folder Panel (= treeview) when Dolphin gets closed before the panel...
[dolphin.git] / src / ktreeview.cpp
1 /***************************************************************************
2 * Copyright (C) 2008 by <haraldhv (at) stud.ntnu.no> *
3 * Copyright (C) 2008 by <peter.penz@gmx.at> *
4 * *
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. *
9 * *
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. *
14 * *
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 ***************************************************************************/
20
21 #include "ktreeview.h"
22 #include "ktreeview_p.h"
23
24 #include <KGlobalSettings>
25
26 #include <QEvent>
27 #include <QItemSelectionModel>
28 #include <QScrollBar>
29 #include <QTimer>
30 #include <QTimeLine>
31
32 KTreeView::KTreeViewPrivate::KTreeViewPrivate(KTreeView *parent) :
33 parent(parent),
34 autoHorizontalScroll(false),
35 timeLine(0),
36 startScrollTimer(0)
37 {
38 startScrollTimer = new QTimer(this);
39 startScrollTimer->setSingleShot(true);
40 startScrollTimer->setInterval(300);
41
42 timeLine = new QTimeLine(300, this);
43 }
44
45 void KTreeView::KTreeViewPrivate::connectScrollTimers()
46 {
47 connect(startScrollTimer, SIGNAL(timeout()),
48 this, SLOT(startScrolling()));
49
50 connect(timeLine, SIGNAL(frameChanged(int)),
51 this, SLOT(updateVerticalScrollBar(int)));
52
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()));
61 }
62
63 void KTreeView::KTreeViewPrivate::startScrolling()
64 {
65 QModelIndex index;
66
67 const int viewportHeight = parent->viewport()->height();
68
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
76 // scroll target
77 index = selectedIndex;
78 }
79 }
80
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()) {
85 return;
86 }
87
88 index = visibleIndex;
89 int minimum = parent->width();
90 do {
91 const QRect rect = parent->visualRect(visibleIndex);
92 if (rect.top() > viewportHeight) {
93 // the current index and all successors are not visible anymore
94 break;
95 }
96 if (rect.left() < minimum) {
97 minimum = rect.left();
98 index = visibleIndex;
99 }
100 visibleIndex = parent->indexBelow(visibleIndex);
101 } while (visibleIndex.isValid());
102 }
103
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);
107
108 QScrollBar *scrollBar = parent->horizontalScrollBar();
109 const int oldScrollBarPos = scrollBar->value();
110
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;
117 }
118
119 if (scrollBarPos != oldScrollBarPos) {
120 timeLine->setFrameRange(oldScrollBarPos, scrollBarPos);
121 timeLine->start();
122 }
123 }
124
125 void KTreeView::KTreeViewPrivate::updateVerticalScrollBar(int value)
126 {
127 QScrollBar *scrollBar = parent->horizontalScrollBar();
128 scrollBar->setValue(value);
129 startScrollTimer->stop();
130 }
131
132 // ************************************************
133
134 KTreeView::KTreeView(QWidget *parent) :
135 QTreeView(parent),
136 d(new KTreeViewPrivate(this))
137 {
138 if (KGlobalSettings::graphicEffectsLevel() >= KGlobalSettings::SimpleAnimationEffects) {
139 setAutoHorizontalScroll(true);
140 }
141 }
142
143 KTreeView::~KTreeView()
144 {
145 }
146
147 void KTreeView::setAutoHorizontalScroll(bool value)
148 {
149 d->autoHorizontalScroll = value;
150 }
151
152 bool KTreeView::autoHorizontalScroll() const
153 {
154 return d->autoHorizontalScroll;
155 }
156
157 void KTreeView::setSelectionModel(QItemSelectionModel *selectionModel)
158 {
159 QTreeView::setSelectionModel(selectionModel);
160 connect(selectionModel,
161 SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
162 d->startScrollTimer, SLOT(start()));
163 }
164
165 void KTreeView::scrollTo(const QModelIndex& index, ScrollHint hint)
166 {
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);
173 } else {
174 QTreeView::scrollTo(index, hint);
175 }
176 }
177
178 bool KTreeView::event(QEvent* event)
179 {
180 if (event->type() == QEvent::Polish) {
181 d->connectScrollTimers();
182 }
183 return QTreeView::event(event);
184 }
185
186 #include "ktreeview.moc"
187 #include "ktreeview_p.moc"