add more spacing
[personal-kdebase.git] / workspace / kcontrol / input / xcursor / previewwidget.cpp
blob3c264fcd69fafb32902275b5c46840beac89dd26
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.
19 #include <QPainter>
20 #include <QMouseEvent>
22 #include "previewwidget.h"
24 #include <X11/Xlib.h>
25 #include <X11/Xcursor/Xcursor.h>
27 #include "cursortheme.h"
31 namespace {
33 // Preview cursors
34 const char * const cursor_names[] =
36 "left_ptr",
37 "left_ptr_watch",
38 "wait",
39 "pointing_hand",
40 "whats_this",
41 "ibeam",
42 "size_all",
43 "size_fdiag",
44 "cross",
45 "split_h",
46 "size_ver",
47 "size_hor",
48 "size_bdiag",
49 "split_v",
52 const int numCursors = 9; // The number of cursors from the above list to be previewed
53 const int previewSize = 24; // The nominal cursor size to be used in the preview widget
54 const int cursorSpacing = 20; // Spacing between preview cursors
55 const int widgetMinWidth = 10; // The minimum width of the preview widget
56 const int widgetMinHeight = 48; // The minimum height of the preview widget
60 class PreviewCursor
62 public:
63 PreviewCursor( const CursorTheme *theme, const QString &name );
64 ~PreviewCursor() {}
66 const QPixmap &pixmap() const { return m_pixmap; }
67 Cursor handle() const { return m_cursor.handle(); }
68 int width() const { return m_pixmap.width(); }
69 int height() const { return m_pixmap.height(); }
70 inline QRect rect() const;
71 void setPosition( const QPoint &p ) { m_pos = p; }
72 void setPosition( int x, int y ) { m_pos = QPoint(x, y); }
73 QPoint position() const { return m_pos; }
74 operator const QCursor& () const { return m_cursor; }
75 operator const QPixmap& () const { return pixmap(); }
77 private:
78 QPixmap m_pixmap;
79 QCursor m_cursor;
80 QPoint m_pos;
84 PreviewCursor::PreviewCursor(const CursorTheme *theme, const QString &name)
86 // Create the preview pixmap
87 QImage image = theme->loadImage(name, previewSize);
89 if (image.isNull())
90 return;
92 int maxSize = previewSize * 2;
93 if (image.height() > maxSize || image.width() > maxSize)
94 image = image.scaled(maxSize, maxSize, Qt::KeepAspectRatio,
95 Qt::SmoothTransformation);
97 m_pixmap = QPixmap::fromImage(image);
99 // Load the cursor
100 m_cursor = theme->loadCursor(name, previewSize);
101 // ### perhaps we should tag the cursor so it doesn't get
102 // replaced when a new theme is applied
106 QRect PreviewCursor::rect() const
108 return QRect(m_pos, m_pixmap.size())
109 .adjusted(-(cursorSpacing / 2), -(cursorSpacing / 2),
110 cursorSpacing / 2, cursorSpacing / 2);
115 // ------------------------------------------------------------------------------
119 PreviewWidget::PreviewWidget(QWidget *parent) : QWidget(parent)
121 setMouseTracking(true);
122 current = NULL;
126 PreviewWidget::~PreviewWidget()
128 qDeleteAll(list);
129 list.clear();
133 QSize PreviewWidget::sizeHint() const
135 int totalWidth = 0;
136 int maxHeight = 0;
138 foreach (const PreviewCursor *c, list)
140 totalWidth += c->width();
141 maxHeight = qMax(c->height(), maxHeight);
144 totalWidth += (list.count() - 1) * cursorSpacing;
145 maxHeight = qMax(maxHeight, widgetMinHeight);
147 return QSize(qMax(totalWidth, widgetMinWidth), qMax(height(), maxHeight));
151 void PreviewWidget::layoutItems()
153 if (!list.isEmpty())
155 QSize size = sizeHint();
156 int cursorWidth = size.width() / list.count();
157 int nextX = (width() - size.width()) / 2;
159 foreach (PreviewCursor *c, list)
161 c->setPosition(nextX + (cursorWidth - c->width()) / 2,
162 (height() - c->height()) / 2);
163 nextX += cursorWidth;
167 needLayout = false;
171 void PreviewWidget::setTheme(const CursorTheme *theme)
173 qDeleteAll(list);
174 list.clear();
176 if (theme)
178 for (int i = 0; i < numCursors; i++)
179 list << new PreviewCursor(theme, cursor_names[i]);
181 needLayout = true;
182 updateGeometry();
185 current = NULL;
186 update();
190 void PreviewWidget::paintEvent(QPaintEvent *)
192 QPainter p(this);
194 if (needLayout)
195 layoutItems();
197 foreach(const PreviewCursor *c, list)
199 if (c->pixmap().isNull())
200 continue;
202 p.drawPixmap(c->position(), *c);
207 void PreviewWidget::mouseMoveEvent(QMouseEvent *e)
209 if (needLayout)
210 layoutItems();
212 foreach (const PreviewCursor *c, list)
214 if (c->rect().contains(e->pos()))
216 if (c != current)
218 setCursor(*c);
219 current = c;
221 return;
225 setCursor(Qt::ArrowCursor);
226 current = NULL;
230 void PreviewWidget::resizeEvent(QResizeEvent *)
232 if (!list.isEmpty())
233 needLayout = true;