added theme preview
[xcurtheme.git] / previewwidget.cpp
blob617d4e1f1000c0c914fc7e2f5250979bc63e066a
1 /*
2 * Copyright © 2003-2007 Fredrik Höglund <fredrik@kde.org>
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License version 2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 * Boston, MA 02110-1301, USA.
18 #include <QDebug>
20 #include <QPainter>
21 #include <QMouseEvent>
23 #include "previewwidget.h"
25 #include <X11/Xlib.h>
26 #include <X11/Xcursor/Xcursor.h>
28 #include "crtheme.h"
31 namespace {
32 // Preview cursors
33 const char *const cursorNames[] = {
34 "left_ptr",
35 "left_ptr_watch",
36 "wait",
37 "pointing_hand",
38 "whats_this",
39 "ibeam",
40 "size_all",
41 "size_fdiag",
42 "cross",
43 "split_h",
44 "size_ver",
45 "size_hor",
46 "size_bdiag",
47 "split_v",
50 const int numCursors = 9; // The number of cursors from the above list to be previewed
51 const int previewSize = 24; // The nominal cursor size to be used in the preview widget
52 const int cursorSpacing = 20; // Spacing between preview cursors
53 const int widgetMinWidth = 10; // The minimum width of the preview widget
54 const int widgetMinHeight = 48; // The minimum height of the preview widget
58 ///////////////////////////////////////////////////////////////////////////////
59 class PreviewCursor {
60 public:
61 PreviewCursor (const XCursorTheme &theme, const QString &name);
62 ~PreviewCursor () {}
64 const QPixmap &pixmap () const { return mPixmap; }
65 Cursor handle () const { return mCursor.handle(); }
66 int width () const { return mPixmap.width(); }
67 int height () const { return mPixmap.height(); }
68 inline QRect rect () const;
69 void setPosition (const QPoint &p) { mPos = p; }
70 void setPosition (int x, int y) { mPos = QPoint(x, y); }
71 QPoint position () const { return mPos; }
72 operator const QCursor& () const { return mCursor; }
73 operator const QPixmap& () const { return pixmap(); }
75 private:
76 QPixmap mPixmap;
77 QCursor mCursor;
78 QPoint mPos;
82 ///////////////////////////////////////////////////////////////////////////////
83 PreviewCursor::PreviewCursor (const XCursorTheme &theme, const QString &name) {
84 // Create the preview pixmap
85 QImage image = theme.loadImage(name, previewSize);
86 if (image.isNull()) return;
87 int maxSize = previewSize*2;
88 if (image.height() > maxSize || image.width() > maxSize)
89 image = image.scaled(maxSize, maxSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
90 mPixmap = QPixmap::fromImage(image);
91 // load the cursor
92 mCursor = theme.loadCursor(name, previewSize);
96 QRect PreviewCursor::rect () const {
97 return QRect(mPos, mPixmap.size()).adjusted(-(cursorSpacing/2), -(cursorSpacing/2), cursorSpacing/2, cursorSpacing/2);
101 ///////////////////////////////////////////////////////////////////////////////
102 PreviewWidget::PreviewWidget (QWidget *parent) : QWidget(parent) {
103 setMouseTracking(true);
104 current = NULL;
108 PreviewWidget::~PreviewWidget () {
109 qDeleteAll(list);
110 list.clear();
114 QSize PreviewWidget::sizeHint () const {
115 int totalWidth = 0;
116 int maxHeight = 0;
117 foreach (const PreviewCursor *c, list) {
118 totalWidth += c->width();
119 maxHeight = qMax(c->height(), maxHeight);
121 totalWidth += (list.count()-1)*cursorSpacing;
122 maxHeight = qMax(maxHeight, widgetMinHeight);
123 return QSize(qMax(totalWidth, widgetMinWidth), qMax(height(), maxHeight));
127 void PreviewWidget::layoutItems () {
128 if (!list.isEmpty()) {
129 QSize size = sizeHint();
130 int cursorWidth = size.width()/list.count();
131 int nextX = (width()-size.width())/2;
132 foreach (PreviewCursor *c, list) {
133 c->setPosition(nextX+(cursorWidth-c->width())/2, (height()-c->height())/2);
134 nextX += cursorWidth;
137 needLayout = false;
141 void PreviewWidget::setTheme (const XCursorTheme &theme) {
142 qDeleteAll(list);
143 list.clear();
144 for (int i = 0; i < numCursors; i++) list << new PreviewCursor(theme, cursorNames[i]);
145 needLayout = true;
146 updateGeometry();
147 current = NULL;
148 update();
152 void PreviewWidget::paintEvent (QPaintEvent *) {
153 QPainter p(this);
154 if (needLayout) layoutItems();
155 foreach (const PreviewCursor *c, list) {
156 if (c->pixmap().isNull()) continue;
157 p.drawPixmap(c->position(), *c);
162 void PreviewWidget::mouseMoveEvent (QMouseEvent *e) {
163 if (needLayout) layoutItems();
164 foreach (const PreviewCursor *c, list) {
165 if (c->rect().contains(e->pos())) {
166 if (c != current) {
167 setCursor(*c);
168 current = c;
170 return;
173 setCursor(Qt::ArrowCursor);
174 current = NULL;
178 void PreviewWidget::resizeEvent (QResizeEvent *) {
179 if (!list.isEmpty()) needLayout = true;