Re: Thumbnail Bar

"Ilya Konkov" <[email protected]> Thu, 20 Mar 2008 18:57:52 +0500
Newsgroups gmane.comp.kde.gwenview
Message-ID <[email protected]>
Hello.

New patch. Summary:
1. Delegate now uses stylesheet style to paint background/border.
2. There is no speedbar and save button code. If you want, I can add
save button back.
3. Stylesheet is generated in ThumbnailBarView using system colors.
4. OxygenStyle draws QListView's borders around viewport, not around
whole widget like other styles that I've tried do:
http://img523.imageshack.us/img523/7441/oxygendiffgu4.png
Left is Oxygen.
So to ensure common look I used QWindowsStyle. However drop and
context menus don't look native because of that =(
5. Thumnail bar was moved to part container in document view, so it
doesn't cover image. I am not sure about the code that adds the bar to
partContainer's layout, it looks ugly.

Also don't know how to add actions (toggle and probably shrink/enlarge
thumbnails) from main window to mDocument's status bar.

I think directories should be hidden in thumbnail bar. How to filter
them out using an existing proxy model class?
If you want to keep dirs, I should probably add text to delegate.

That's probably all, if I haven't forgot anything.

--
Ilya Konkov

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

_______________________________________________
Gwenview-general mailing list
Gwenview-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/gwenview-general
gwenview.patch (text/x-patch, 20 KB)
Index: app/thumbnailbarview.h
===================================================================
--- app/thumbnailbarview.h	(revision 0)
+++ app/thumbnailbarview.h	(revision 0)
@@ -0,0 +1,76 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+Gwenview: an image viewer
+Copyright 2008 Aurélien Gâteau <[email protected]>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+#ifndef THUMBNAILBARVIEW_H
+#define THUMBNAILBARVIEW_H
+
+// Qt
+#include <QAbstractItemDelegate>
+
+// KDE
+
+// Local
+#include <lib/thumbnailview/thumbnailview.h>
+
+namespace Gwenview {
+
+
+class ThumbnailBarItemDelegatePrivate;
+
+class ThumbnailBarItemDelegate : public QAbstractItemDelegate {
+	Q_OBJECT
+public:
+	ThumbnailBarItemDelegate(ThumbnailView*);
+	~ThumbnailBarItemDelegate();
+
+	virtual void paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
+	virtual QSize sizeHint( const QStyleOptionViewItem & /*option*/, const QModelIndex & /*index*/ ) const;
+
+private Q_SLOTS:
+	void setThumbnailSize(int);
+
+protected:
+	virtual bool eventFilter(QObject*, QEvent*);
+
+private:
+	ThumbnailBarItemDelegatePrivate* const d;
+	friend class ThumbnailBarItemDelegatePrivate;
+};
+
+
+class ThumbnailBarView : public ThumbnailView {
+	Q_OBJECT
+public:
+	ThumbnailBarView(QWidget *);
+	~ThumbnailBarView();
+	
+	QSize sizeHint() const;
+
+public Q_SLOTS:
+	void showContextMenu();
+	QString defaultStyleSheet() const;
+	
+private:
+	QStyle* style;
+};
+
+} // namespace
+
+#endif /* THUMBNAILBARVIEW_H */
Index: app/CMakeLists.txt
===================================================================
--- app/CMakeLists.txt	(revision 787947)
+++ app/CMakeLists.txt	(working copy)
@@ -23,6 +23,7 @@
 	savebar.cpp
 	sidebar.cpp
 	thumbnailviewhelper.cpp
+	thumbnailbarview.cpp
 	)
 
 if (Nepomuk_FOUND)
Index: app/thumbnailbarview.cpp
===================================================================
--- app/thumbnailbarview.cpp	(revision 0)
+++ app/thumbnailbarview.cpp	(revision 0)
@@ -0,0 +1,329 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+Gwenview: an image viewer
+Copyright 2008 Aurélien Gâteau <[email protected]>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+// Self
+#include "thumbnailbarview.moc"
+
+// Qt
+#include <QApplication>
+#include <QHelpEvent>
+#include <QScrollBar>
+#include <QPainter>
+#include <QWindowsStyle>
+#include <QToolTip>
+// KDE
+
+// Local
+#include "lib/paintutils.h"
+#include "lib/thumbnailview/abstractthumbnailviewhelper.h"
+
+namespace Gwenview {
+
+/**
+ * Space between the item outer rect and the content, and between the
+ * thumbnail and the caption
+ */
+const int ITEM_MARGIN = 5;
+
+/** How dark is the shadow, 0 is invisible, 255 is as dark as possible */
+const int SHADOW_STRENGTH = 127;
+
+/** How many pixels around the thumbnail are shadowed */
+const int SHADOW_SIZE = 3;
+
+
+static QString rgba(const QColor &color) {
+	QString rgba("rgba(%1, %2, %3, %4)");
+	return rgba.arg(QString::number(color.red()), QString::number(color.green()), QString::number(color.red()), QString::number(color.alpha()));
+}
+
+
+struct ThumbnailBarItemDelegatePrivate {
+	// Key is height * 1000 + width
+	typedef QMap<int, QPixmap> ShadowCache;
+	mutable ShadowCache mShadowCache;
+
+	ThumbnailBarItemDelegate* mDelegate;
+	ThumbnailView* mView;
+	int mThumbnailSize;
+	QColor borderColor;
+
+	void showToolTip(QHelpEvent* helpEvent) {
+		QModelIndex index = mView->indexAt(helpEvent->pos());
+		if (!index.isValid()) {
+			return;
+		}
+		QString fullText = index.data().toString();
+		QRect rect = mView->visualRect(index);
+		QPoint pos = QCursor::pos();
+		QToolTip::showText(pos, fullText, mView);
+	}
+
+	void drawShadow(QPainter* painter, const QRect& rect) const {
+		const QPoint shadowOffset(-SHADOW_SIZE, -SHADOW_SIZE + 1);
+
+		int key = rect.height() * 1000 + rect.width();
+
+		ShadowCache::Iterator it = mShadowCache.find(key);
+		if (it == mShadowCache.end()) {
+			QSize size = QSize(rect.width() + 2*SHADOW_SIZE, rect.height() + 2*SHADOW_SIZE);
+			QColor color(0, 0, 0, SHADOW_STRENGTH);
+			QPixmap shadow = PaintUtils::generateFuzzyRect(size, color, SHADOW_SIZE);
+			it = mShadowCache.insert(key, shadow);
+		}
+		painter->drawPixmap(rect.topLeft() + shadowOffset, it.value());
+	}
+};
+
+
+ThumbnailBarItemDelegate::ThumbnailBarItemDelegate(ThumbnailView* view)
+: d(new ThumbnailBarItemDelegatePrivate) {
+	d->mDelegate = this;
+	d->mView = view;
+	view->viewport()->installEventFilter(this);
+	setThumbnailSize(view->thumbnailSize());
+
+	QWidget* viewport = view->viewport();
+	QColor bgColor = viewport->palette().color(viewport->backgroundRole());
+
+	if (bgColor.value() < 128) {
+		d->borderColor = bgColor.darker(200);
+	} else {
+		d->borderColor = bgColor.lighter(200);
+	}
+	d->borderColor = PaintUtils::adjustedHsv(d->borderColor, 0, - d->borderColor.saturation(), 0);
+
+	connect(view, SIGNAL(thumbnailSizeChanged(int)),
+		SLOT(setThumbnailSize(int)) );
+}
+
+
+QSize ThumbnailBarItemDelegate::sizeHint( const QStyleOptionViewItem & /*option*/, const QModelIndex & /*index*/) const {
+	return d->mView->gridSize();
+}
+
+
+void ThumbnailBarItemDelegate::setThumbnailSize(int value) {
+	d->mThumbnailSize = value;
+	d->mView->setGridSize(QSize(value + ITEM_MARGIN*2 + 1, value + ITEM_MARGIN*2 + 1));
+}
+
+
+bool ThumbnailBarItemDelegate::eventFilter(QObject*, QEvent* event) {
+	if (event->type() == QEvent::ToolTip) {
+		QHelpEvent* helpEvent = static_cast<QHelpEvent*>(event);
+		d->showToolTip(helpEvent);
+		return true;
+
+	} else if (event->type() == QEvent::Wheel) {
+		QScrollBar* hsb = d->mView->horizontalScrollBar();
+		QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(event);
+		hsb->setValue(hsb->value() - wheelEvent->delta());
+		return true;
+	}
+
+	return false;
+}
+
+
+void ThumbnailBarItemDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const {
+	ThumbnailView::Thumbnail thumbnail = d->mView->thumbnailForIndex(index);
+	QPixmap thumbnailPix = thumbnail.mPixmap;
+	QSize thumbnailSize = d->mView->gridSize() - QSize(ITEM_MARGIN*2 + 1, ITEM_MARGIN*3 + 1);
+	if (thumbnailPix.width() > thumbnailSize.width() || thumbnailPix.height() > thumbnailSize.height()) {
+		thumbnailPix = thumbnailPix.scaled(thumbnailSize, Qt::KeepAspectRatio);
+	}
+	QRect rect = option.rect;
+
+	QStyleOptionViewItemV4 opt = option;
+	const QWidget* widget = opt.widget;
+	QStyle* style = widget ? widget->style() : QApplication::style();
+	style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
+
+	// Draw thumbnail
+	if (!thumbnailPix.isNull()) {
+		QRect thumbnailRect = QRect(
+			rect.left() + (rect.width() - thumbnailPix.width())/2,
+			rect.top() + (rect.height() - thumbnailPix.height())/2 ,
+		    thumbnailPix.width(),
+		    thumbnailPix.height());
+
+		if (/*!(option.state & QStyle::State_Selected) && */ thumbnail.mOpaque) {
+			d->drawShadow(painter, thumbnailRect);
+		}
+
+		if (thumbnail.mOpaque) {
+			painter->setPen(d->borderColor);
+			painter->setRenderHint(QPainter::Antialiasing, false);
+			QRect borderRect = thumbnailRect.adjusted(-1, -1, 0, 0);
+			painter->drawRect(borderRect);
+		}
+		painter->drawPixmap(thumbnailRect.left(), thumbnailRect.top(), thumbnailPix);
+	}
+}
+
+
+ThumbnailBarItemDelegate::~ThumbnailBarItemDelegate() {
+	delete d;
+}
+
+
+ThumbnailBarView::ThumbnailBarView(QWidget* parent)
+: ThumbnailView(parent) {
+	setObjectName("thumbnailBarView");
+	setUniformItemSizes(true);
+	setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+	setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+	setWrapping(false);
+	setThumbnailSize(80);
+	
+	setStyle(style = new QWindowsStyle);
+	setStyleSheet(defaultStyleSheet());
+	
+	// Since QWindowsStyle is used context menu won't be painted by system style. Avoid it by this hack:
+	ThumbnailView::disconnect(SIGNAL(customContextMenuRequested(const QPoint&)));
+	connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
+	    SLOT(showContextMenu()) );
+}
+
+
+ThumbnailBarView::~ThumbnailBarView() {
+	delete style;
+}
+
+
+void ThumbnailBarView::showContextMenu() {
+	// Using parentWidget as parent of menu to paint it by system style.
+	thumbnailViewHelper()->showContextMenu(parentWidget());
+}
+
+
+QSize ThumbnailBarView::sizeHint() const {
+	QSize hint = ThumbnailView::sizeHint();
+	int size = gridSize().height();
+	int hsbExt = horizontalScrollBar()->sizeHint().height();
+	int f = 2 * frameWidth();
+	hint.setHeight(size + f + hsbExt);
+	return hint;
+}
+
+
+QString ThumbnailBarView::defaultStyleSheet() const {
+	QColor bgColor, bgSelColor;
+	bgSelColor = viewport()->palette().color(QPalette::Normal, QPalette::Highlight);
+	bgColor = viewport()->palette().color(viewport()->backgroundRole());
+
+	// Avoid dark and bright colors
+	bgColor.setHsv(bgColor.hue(), bgColor.saturation(), (128 * 2 + bgColor.value()) / 3);
+	bgSelColor.setHsv(bgSelColor.hue(), bgSelColor.saturation(), (128 * 2 + bgSelColor.value()) / 3);
+
+
+	QString itemCss =
+		"QListView::item {"
+		"	background-color:"
+		"		qlineargradient(x1:0, y1:0, x2:0, y2:1,"
+		"		stop: 0 black, stop: 0.05 %1, stop:1 %2);"
+		"	border-left: 1px solid "
+		"		qlineargradient(x1:0, y1:0, x2:0, y2:1,"
+		"		stop: 0 black, stop: 0.05 %3, stop:1 %4);"
+		"	border-right: 1px solid "
+		"		qlineargradient(x1:0, y1:0, x2:0, y2:1,"
+		"		stop: 0 black, stop: 0.05 %4, stop:1 %5);"
+		"}";
+	itemCss = itemCss.arg(
+		bgColor.lighter(125).name(),
+		bgColor.darker(125).name(),
+		bgColor.lighter(170).name(),
+		bgColor.name(),
+		bgColor.darker(170).name());
+
+	QString viewCss =
+		"#thumbnailBarView {"
+		"	background-color:"
+		"		qlineargradient(x1:0, y1:0, x2:0, y2:1,"
+		"		stop: 0 black, stop: 0.05 %1, stop:1 %2);"
+		"	border: 1px solid #444;"
+		"}";
+	viewCss = viewCss.arg(bgColor.darker(125).name(), bgColor.name());
+
+	QColor borderSelColor(0, 0, 0, 127);
+	QString itemSelCss =
+		"QListView::item:selected {"
+		"	background-color:"
+		"		qlineargradient(x1:0, y1:0, x2:0, y2:1,"
+		"		stop: 0 black, stop: 0.05 %1, stop:1 %2);"
+		"	border-left: 1px solid %3;"
+		"	border-right: 1px solid %3;"
+		"}";
+	itemSelCss = itemSelCss.arg(
+	    bgSelColor.lighter(125).name(),
+	    bgSelColor.darker(125).name(),
+	    rgba(borderSelColor));
+
+	QString scrollbarCss =
+		"QScrollBar:horizontal {"
+		"	background-color:"
+		"		qlineargradient(x1:0, y1:0, x2:0, y2:1,"
+		"		stop: 0 black, stop: 0.4 %1, stop: 1 %2);"
+		"	height: 8px;"
+		"	border-top: 1px solid black;"
+		"}";
+	scrollbarCss = scrollbarCss.arg(bgColor.darker(200).name(), bgColor.darker(175).name());
+
+	QString handle =
+		"background:"
+		"	qlineargradient(x1:0, y1:0, x2:0, y2:1,"
+		"	stop: 0 %1, stop: 0.17 %2,"
+		"	stop: 0.2 %3, stop: 0.8 %4,"
+		"	stop: 0.83 %2, stop: 1 %1);"
+		"border: 1px solid"
+		"	qlineargradient(x1:0, y1:0, x2:0, y2:1,"
+		"	stop: 0 #242424, stop: 0.2 %2,"
+		"	stop: 0.70 %2, stop: 1 #242424);"
+		"border-top: 0px;"
+		"border-bottom: 0px;"
+		"}";
+
+	QColor handleBase = QColor::fromHsv(bgColor.hue(), bgColor.saturation() / 2, (bgColor.value() + 255) / 2);
+	QColor handleSelBase = handleBase.lighter(110);
+	QString handleCss =
+		"QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal, QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {"
+		"	width: 0;"
+		"	border: 0;"
+		"}"
+		"QScrollBar::handle:horizontal {"
+		"	min-width: 20px;" +
+		handle.arg(
+			handleBase.darker(170).name(),
+			handleBase.darker(125).name(),
+			handleBase.darker(140).name(),
+			handleBase.lighter(115).name()) +
+		"QScrollBar::handle:hover {" +
+		handle.arg(
+			handleSelBase.darker(170).name(),
+			handleSelBase.darker(125).name(),
+			handleSelBase.darker(140).name(),
+			handleSelBase.lighter(115).name());
+
+	return viewCss + itemCss + itemSelCss + scrollbarCss + handleCss;
+}
+
+
+} // namespace
Index: app/mainwindow.cpp
===================================================================
--- app/mainwindow.cpp	(revision 787947)
+++ app/mainwindow.cpp	(working copy)
@@ -73,6 +73,7 @@
 #include "savebar.h"
 #include "sidebar.h"
 #include "thumbnailviewhelper.h"
+#include "thumbnailbarview.h"
 #include <lib/archiveutils.h>
 #include <lib/cropsidebar.h>
 #include <lib/document/documentfactory.h>
@@ -148,6 +149,7 @@
 	FullScreenBar* mFullScreenBar;
 	SaveBar* mSaveBar;
 	SlideShow* mSlideShow;
+	QFrame* mThumbnailBar;
 
 	QActionGroup* mViewModeActionGroup;
 	QAction* mBrowseAction;
@@ -167,6 +169,7 @@
 	QAction* mToggleSlideShowAction;
 	KToggleAction* mShowMenuBarAction;
 	KToggleAction* mShowFilterBar;
+	KToggleAction* mToggleThumbnailBarAction;
 
 	SortedDirModel* mDirModel;
 	ContextManager* mContextManager;
@@ -201,6 +204,7 @@
 			mWindow, SLOT(goToPrevious()) );
 		connect(mDocumentView, SIGNAL(nextImageRequested()),
 			mWindow, SLOT(goToNext()) );
+		setupThumbnailBar(mCentralSplitter);
 
 		mSideBarContainer = new QStackedWidget(mCentralSplitter);
 		mSideBar = new SideBar(mSideBarContainer);
@@ -274,7 +278,32 @@
 		layout->addWidget(mFilterBar);
 		layout->addWidget(statusBar);
 	}
+	
+	void setupThumbnailBar(QWidget* parent) {
+		mThumbnailBar = new QFrame(parent);
+		mThumbnailBar->setObjectName("thumbnailBar");
 
+		ThumbnailBarView* view = new ThumbnailBarView(mThumbnailBar);
+		ThumbnailBarItemDelegate* delegate = new ThumbnailBarItemDelegate(view);
+		view->setModel(mDirModel);
+		view->setThumbnailViewHelper(mThumbnailViewHelper);
+		view->setItemDelegate(delegate);
+		view->setSelectionModel(mThumbnailView->selectionModel());
+
+		QVBoxLayout* layout = new QVBoxLayout(mThumbnailBar);
+		layout->setMargin(0);
+		layout->setSpacing(0);
+		layout->addWidget(view);
+
+		if (QWidget* w = mDocumentView->statusBar()->parentWidget()) {
+			if (QVBoxLayout* l = qobject_cast<QVBoxLayout*>(w->layout())) {
+				int index = l->indexOf(mDocumentView->statusBar());
+				l->insertWidget(index, mThumbnailBar);
+			}
+		}
+		mThumbnailBar->hide();
+	}
+
 	void setupFilterBar() {
 		mFilterBar = new QWidget(mThumbnailViewPanel);
 		mFilterBar->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
@@ -420,6 +449,11 @@
 		mShowFilterBar->setShortcut(Qt::CTRL | Qt::Key_I);
 		connect(mShowFilterBar, SIGNAL(triggered(bool)), mWindow, SLOT(toggleFilterBarVisibility(bool)));
 
+		mToggleThumbnailBarAction = actionCollection->add<KToggleAction>("toggle_thumbnailbar");
+		mToggleThumbnailBarAction->setText(i18n("Show Thumbnail Bar"));
+		mToggleThumbnailBarAction->setShortcut(Qt::CTRL | Qt::Key_T);
+		connect(mToggleThumbnailBarAction, SIGNAL(triggered(bool)), mThumbnailBar, SLOT(setVisible(bool)));
+
 		KStandardAction::keyBindings(mWindow->guiFactory(),
 			SLOT(configureShortcuts()), actionCollection);
 
@@ -567,7 +601,8 @@
 		mFullScreenBar->addWidget(mSlideShow->intervalWidget());
 		mFullScreenBar->addWidget(mSlideShow->optionsWidget());
 
-		mFullScreenBar->addWidget(mInformationLabel);
+		QLayout* layout = mFullScreenBar->findChild<QFrame*>("fullScreenBar")->layout();
+		layout->addWidget(mInformationLabel);
 
 		mFullScreenBar->resize(mFullScreenBar->sizeHint());
 	}
@@ -1100,9 +1135,10 @@
 		d->mStateBeforeFullScreen.mSideBarVisible = d->mSideBarContainer->isVisible();
 		d->mStateBeforeFullScreen.mWindowState = windowState();
 
+		// Ensure mDocumentView is active before setting its background color.
+		d->mViewAction->trigger();
+
 		d->mDocumentView->setViewBackgroundColor(Qt::black);
-
-		d->mViewAction->trigger();
 		d->mSideBarContainer->hide();
 
 		setWindowState(windowState() | Qt::WindowFullScreen);
@@ -1113,6 +1149,9 @@
 		if (!d->mFullScreenBar) {
 			d->createFullScreenBar();
 		}
+		d->mToggleThumbnailBarAction->setEnabled(false);
+		d->mThumbnailBar->show();
+		d->mFullScreenBar->layout()->addWidget(d->mThumbnailBar);
 		d->mFullScreenBar->setActivated(true);
 		updateFullScreenInformation();
 	} else {
@@ -1128,6 +1167,15 @@
 		d->mDocumentView->setStatusBarVisible(true);
 		menuBar()->setVisible(d->mShowMenuBarAction->isChecked());
 		toolBar()->show();
+
+		d->mToggleThumbnailBarAction->setEnabled(true);
+		d->mThumbnailBar->setVisible(d->mToggleThumbnailBarAction->isChecked());
+		if (QWidget* w = d->mDocumentView->statusBar()->parentWidget()) {
+			if (QVBoxLayout* l = qobject_cast<QVBoxLayout*>(w->layout())) {
+				int index = l->indexOf(d->mDocumentView->statusBar());
+				l->insertWidget(index, d->mThumbnailBar);
+			}
+		}
 	}
 	setUpdatesEnabled(true);
 }
Index: lib/fullscreenbar.h
===================================================================
--- lib/fullscreenbar.h	(revision 787947)
+++ lib/fullscreenbar.h	(working copy)
@@ -48,6 +48,7 @@
 	void addSeparator();
 	void addWidget(QWidget*);
 
+	QSize sizeHint() const;
 public Q_SLOTS:
 	void slideIn();
 	void slideOut();
Index: lib/fullscreenbar.cpp
===================================================================
--- lib/fullscreenbar.cpp	(revision 787947)
+++ lib/fullscreenbar.cpp	(working copy)
@@ -23,6 +23,7 @@
 
 // Qt
 #include <QApplication>
+#include <QDesktopWidget>
 #include <QBitmap>
 #include <QEvent>
 #include <QHBoxLayout>
@@ -65,20 +66,41 @@
 FullScreenBar::FullScreenBar(QWidget* parent)
 : QFrame(parent)
 , d(new FullScreenBarPrivate) {
-	d->mLayout = new QHBoxLayout(this);
+	QFrame* container = new QFrame(this);
+	QVBoxLayout* containerLayout = new QVBoxLayout(container);
+	containerLayout->setMargin(0);
+	containerLayout->setSpacing(0);
+	d->mLayout = new QHBoxLayout();
 	d->mLayout->setMargin(0);
 	d->mLayout->setSpacing(0);
-	setObjectName("fullScreenBar");
+	containerLayout->addLayout(d->mLayout);
+	container->setObjectName("fullScreenBar");
+
+	QHBoxLayout* layout = new QHBoxLayout(this);
+	layout->setMargin(0);
+	layout->setSpacing(0);
+	layout->addWidget(container);
+	layout->setAlignment(container, Qt::AlignTop);
+
+
 	setStyleSheet(
 		"#fullScreenBar {"
 		"	background-color:"
 		"		qlineargradient(x1:0, y1:0, x2:0, y2:1,"
 		"		stop:0 #444, stop: 0.6 black, stop:1 black);"
-		"	border-right: 1px solid #ccc;"
-		"	border-bottom: 1px solid #ccc;"
-		"	padding-right: 2px;"
-		"	padding-bottom: 2px;"
+		"	border: 0px;"
+		"	border-bottom: 1px solid gray;"
+		"	padding: 2px;"
+		"	padding-top: 0px;"
+		"}"
+
+	    "#thumbnailBar {"
+		"	background-color: black;"
+		"	border: 1px solid gray;"
+		"	border-top: 0px;"
+		"	border-bottom-left-radius: 4px;"
 		"	border-bottom-right-radius: 4px;"
+		"	min-width: 300px;"
 		"}"
 
 		"QToolButton {"
@@ -117,6 +139,10 @@
 	delete d;
 }
 
+QSize FullScreenBar::sizeHint() const {
+	int width = QApplication::desktop()->screenGeometry(this).width();
+	return QSize(width, QFrame::sizeHint().height());
+}
 
 void FullScreenBar::moveBar(qreal value) {
 	move(0, -height() + int(value * height()) );
@@ -176,7 +202,7 @@
 		if (y() == 0) {
 			// The bar is fully visible, restart timer
 			d->mAutoHideTimer->start();
-		} else {
+		} else if (d->mTimeLine->direction() != QTimeLine::Forward || d->mTimeLine->state() != QTimeLine::Running) {
 			// The bar is not fully visible, bring it in
 			slideIn();
 		}