1 /***************************************************************************
2 * Copyright (C) 2007-2009 by Peter Penz <peter.penz@gmx.at> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
18 ***************************************************************************/
20 #include "dolphincolumnviewcontainer.h"
22 #include "dolphincolumnview.h"
23 #include "dolphincontroller.h"
24 #include "dolphinsortfilterproxymodel.h"
25 #include "settings/dolphinsettings.h"
26 #include "zoomlevelinfo.h"
28 #include "dolphin_columnmodesettings.h"
30 #include <kfilepreviewgenerator.h>
36 DolphinColumnViewContainer::DolphinColumnViewContainer(QWidget
* parent
, DolphinController
* controller
) :
38 m_controller(controller
),
47 Q_ASSERT(controller
!= 0);
50 setFocusPolicy(Qt::NoFocus
);
51 setFrameShape(QFrame::NoFrame
);
52 setLayoutDirection(Qt::LeftToRight
);
54 connect(this, SIGNAL(viewportEntered()),
55 controller
, SLOT(emitViewportEntered()));
56 connect(controller
, SIGNAL(zoomLevelChanged(int)),
57 this, SLOT(setZoomLevel(int)));
58 connect(controller
, SIGNAL(activationChanged(bool)),
59 this, SLOT(updateColumnsBackground(bool)));
61 connect(horizontalScrollBar(), SIGNAL(valueChanged(int)),
62 this, SLOT(moveContentHorizontally(int)));
64 m_animation
= new QTimeLine(500, this);
65 connect(m_animation
, SIGNAL(frameChanged(int)), horizontalScrollBar(), SLOT(setValue(int)));
67 DolphinColumnView
* column
= new DolphinColumnView(viewport(), this, m_controller
->url());
68 m_columns
.append(column
);
69 setActiveColumnIndex(0);
71 m_emptyViewport
= new QFrame(viewport());
72 m_emptyViewport
->setFrameStyle(QFrame::StyledPanel
| QFrame::Sunken
);
74 updateColumnsBackground(true);
77 DolphinColumnViewContainer::~DolphinColumnViewContainer()
81 void DolphinColumnViewContainer::setNameFilter(const QString
& nameFilter
)
83 if (nameFilter
!= m_nameFilter
) {
84 m_nameFilter
= nameFilter
;
85 foreach (DolphinColumnView
* column
, m_columns
) {
86 DolphinSortFilterProxyModel
* proxyModel
= static_cast<DolphinSortFilterProxyModel
*>(column
->model());
87 proxyModel
->setFilterRegExp(nameFilter
);
92 QString
DolphinColumnViewContainer::nameFilter() const
97 KUrl
DolphinColumnViewContainer::rootUrl() const
99 return m_columns
[0]->url();
102 QAbstractItemView
* DolphinColumnViewContainer::activeColumn() const
104 return m_columns
[m_index
];
107 bool DolphinColumnViewContainer::showColumn(const KUrl
& url
)
109 if (!rootUrl().isParentOf(url
)) {
111 m_columns
[0]->setUrl(url
);
116 foreach (DolphinColumnView
* column
, m_columns
) {
117 if (column
->url() == url
) {
118 // the column represents already the requested URL, hence activate it
119 requestActivation(column
);
122 } else if (!column
->url().isParentOf(url
)) {
123 // the column is no parent of the requested URL, hence
124 // just delete all remaining columns
125 if (columnIndex
> 0) {
126 QList
<DolphinColumnView
*>::iterator start
= m_columns
.begin() + columnIndex
;
127 QList
<DolphinColumnView
*>::iterator end
= m_columns
.end();
128 for (QList
<DolphinColumnView
*>::iterator it
= start
; it
!= end
; ++it
) {
131 m_columns
.erase(start
, end
);
133 const int maxIndex
= m_columns
.count() - 1;
134 Q_ASSERT(maxIndex
>= 0);
135 if (m_index
> maxIndex
) {
144 // Create missing columns. Assuming that the path is "/home/peter/Temp/" and
145 // the target path is "/home/peter/Temp/a/b/c/", then the columns "a", "b" and
146 // "c" will be created.
147 const int lastIndex
= m_columns
.count() - 1;
148 Q_ASSERT(lastIndex
>= 0);
150 const KUrl
& activeUrl
= m_columns
[lastIndex
]->url();
151 Q_ASSERT(activeUrl
.isParentOf(url
));
152 Q_ASSERT(activeUrl
!= url
);
154 QString path
= activeUrl
.url(KUrl::AddTrailingSlash
);
155 const QString targetPath
= url
.url(KUrl::AddTrailingSlash
);
157 columnIndex
= lastIndex
;
158 int slashIndex
= path
.count('/');
159 bool hasSubPath
= (slashIndex
>= 0);
161 const QString subPath
= targetPath
.section('/', slashIndex
, slashIndex
);
162 if (subPath
.isEmpty()) {
165 path
+= subPath
+ '/';
168 const KUrl childUrl
= KUrl(path
);
169 m_columns
[columnIndex
]->setChildUrl(childUrl
);
172 DolphinColumnView
* column
= new DolphinColumnView(viewport(), this, childUrl
);
173 if (!m_nameFilter
.isEmpty()) {
174 DolphinSortFilterProxyModel
* proxyModel
= static_cast<DolphinSortFilterProxyModel
*>(column
->model());
175 proxyModel
->setFilterRegExp(m_nameFilter
);
177 column
->setActive(false);
179 m_columns
.append(column
);
181 // Before invoking layoutColumns() the column must be set visible temporary.
182 // To prevent a flickering the initial geometry is set to a hidden position.
183 column
->setGeometry(QRect(-1, -1, 1, 1));
190 // set the last column as active column without modifying the controller
191 // and hence the history
192 m_columns
[m_index
]->setActive(false);
193 m_index
= columnIndex
;
194 m_columns
[m_index
]->setActive(true);
195 assureVisibleActiveColumn();
200 void DolphinColumnViewContainer::mousePressEvent(QMouseEvent
* event
)
202 m_controller
->requestActivation();
203 QScrollArea::mousePressEvent(event
);
206 void DolphinColumnViewContainer::resizeEvent(QResizeEvent
* event
)
208 QScrollArea::resizeEvent(event
);
211 assureVisibleActiveColumn();
214 void DolphinColumnViewContainer::wheelEvent(QWheelEvent
* event
)
216 // let Ctrl+wheel events propagate to the DolphinView for icon zooming
217 if ((event
->modifiers() & Qt::ControlModifier
) == Qt::ControlModifier
) {
220 QScrollArea::wheelEvent(event
);
224 void DolphinColumnViewContainer::setZoomLevel(int level
)
226 const int size
= ZoomLevelInfo::iconSizeForZoomLevel(level
);
227 ColumnModeSettings
* settings
= DolphinSettings::instance().columnModeSettings();
229 const bool showPreview
= m_controller
->dolphinView()->showPreview();
231 settings
->setPreviewSize(size
);
233 settings
->setIconSize(size
);
237 void DolphinColumnViewContainer::moveContentHorizontally(int x
)
239 m_contentX
= isRightToLeft() ? +x
: -x
;
243 void DolphinColumnViewContainer::updateColumnsBackground(bool active
)
245 if (active
== m_active
) {
251 // dim the background of the viewport
252 const QPalette::ColorRole role
= viewport()->backgroundRole();
253 QColor background
= viewport()->palette().color(role
);
254 background
.setAlpha(0); // make background transparent
256 QPalette palette
= viewport()->palette();
257 palette
.setColor(role
, background
);
258 viewport()->setPalette(palette
);
260 foreach (DolphinColumnView
* column
, m_columns
) {
261 column
->updateBackground();
265 void DolphinColumnViewContainer::setActiveColumnIndex(int index
)
267 if (m_index
== index
) {
271 const bool hasActiveColumn
= (m_index
>= 0);
272 if (hasActiveColumn
) {
273 m_columns
[m_index
]->setActive(false);
277 m_columns
[m_index
]->setActive(true);
279 assureVisibleActiveColumn();
282 void DolphinColumnViewContainer::layoutColumns()
286 ColumnModeSettings
* settings
= DolphinSettings::instance().columnModeSettings();
287 const int columnWidth
= settings
->columnWidth();
289 QRect emptyViewportRect
;
290 if (isRightToLeft()) {
291 int x
= viewport()->width() - columnWidth
+ m_contentX
;
292 foreach (DolphinColumnView
* column
, m_columns
) {
293 column
->setGeometry(QRect(x
, 0, columnWidth
- gap
, viewport()->height()));
296 emptyViewportRect
= QRect(0, 0, x
+ columnWidth
- gap
, viewport()->height());
299 foreach (DolphinColumnView
* column
, m_columns
) {
300 column
->setGeometry(QRect(x
, 0, columnWidth
- gap
, viewport()->height()));
303 emptyViewportRect
= QRect(x
, 0, viewport()->width() - x
- gap
, viewport()->height());
306 if (emptyViewportRect
.isValid()) {
307 m_emptyViewport
->show();
308 m_emptyViewport
->setGeometry(emptyViewportRect
);
310 m_emptyViewport
->hide();
314 void DolphinColumnViewContainer::updateScrollBar()
316 ColumnModeSettings
* settings
= DolphinSettings::instance().columnModeSettings();
317 const int contentWidth
= m_columns
.count() * settings
->columnWidth();
319 horizontalScrollBar()->setPageStep(contentWidth
);
320 horizontalScrollBar()->setRange(0, contentWidth
- viewport()->width());
323 void DolphinColumnViewContainer::assureVisibleActiveColumn()
325 const int viewportWidth
= viewport()->width();
326 const int x
= activeColumn()->x();
328 ColumnModeSettings
* settings
= DolphinSettings::instance().columnModeSettings();
329 const int width
= settings
->columnWidth();
331 if (x
+ width
> viewportWidth
) {
332 const int newContentX
= m_contentX
- x
- width
+ viewportWidth
;
333 if (isRightToLeft()) {
334 m_animation
->setFrameRange(m_contentX
, newContentX
);
336 m_animation
->setFrameRange(-m_contentX
, -newContentX
);
338 if (m_animation
->state() != QTimeLine::Running
) {
339 m_animation
->start();
342 const int newContentX
= m_contentX
- x
;
343 if (isRightToLeft()) {
344 m_animation
->setFrameRange(m_contentX
, newContentX
);
346 m_animation
->setFrameRange(-m_contentX
, -newContentX
);
348 if (m_animation
->state() != QTimeLine::Running
) {
349 m_animation
->start();
354 void DolphinColumnViewContainer::requestActivation(DolphinColumnView
* column
)
356 m_controller
->setItemView(column
);
357 if (column
->isActive()) {
358 assureVisibleActiveColumn();
361 foreach (DolphinColumnView
* currColumn
, m_columns
) {
362 if (currColumn
== column
) {
363 setActiveColumnIndex(index
);
371 void DolphinColumnViewContainer::removeAllColumns()
373 QList
<DolphinColumnView
*>::iterator start
= m_columns
.begin() + 1;
374 QList
<DolphinColumnView
*>::iterator end
= m_columns
.end();
375 for (QList
<DolphinColumnView
*>::iterator it
= start
; it
!= end
; ++it
) {
378 m_columns
.erase(start
, end
);
380 m_columns
[0]->setActive(true);
381 assureVisibleActiveColumn();
384 QPoint
DolphinColumnViewContainer::columnPosition(DolphinColumnView
* column
, const QPoint
& point
) const
386 const QPoint topLeft
= column
->frameGeometry().topLeft();
387 return QPoint(point
.x() - topLeft
.x(), point
.y() - topLeft
.y());
390 void DolphinColumnViewContainer::deleteColumn(DolphinColumnView
* column
)
393 if (m_controller
->itemView() == column
) {
394 m_controller
->setItemView(0);
396 // deleteWhenNotDragSource(column) does not necessarily delete column,
397 // and we want its preview generator destroyed immediately.
398 column
->m_previewGenerator
->deleteLater();
399 column
->m_previewGenerator
= 0;
401 // Prevent automatic destruction of column when this DolphinColumnViewContainer
403 column
->setParent(0);
404 column
->disconnect();
405 emit
requestColumnDeletion(column
);
409 #include "dolphincolumnviewcontainer.moc"