[kde-doc-english] [kde-workspace] kcontrol/input/xcursor: Make mouse coursor size configurable
Lukas Sommer
sommerluk at gmail.com
Wed Nov 9 22:32:00 UTC 2011
Git commit 617b08f5f6652bb9d918abc963954723caca59d2 by Lukas Sommer.
Committed on 09/11/2011 at 23:27.
Pushed by sommer into branch 'master'.
Make mouse coursor size configurable
Enable systemsettings to change the size of the mouse cursor.
FEATURE: 90444
FIXED-IN: 4.8
REVIEW: 101701
GUI:
DIGEST:
M +18 -6 kcontrol/input/xcursor/cursortheme.cpp
M +22 -6 kcontrol/input/xcursor/cursortheme.h
M +2 -2 kcontrol/input/xcursor/legacytheme.h
M +6 -12 kcontrol/input/xcursor/previewwidget.cpp
M +1 -1 kcontrol/input/xcursor/previewwidget.h
M +166 -31 kcontrol/input/xcursor/themepage.cpp
M +32 -3 kcontrol/input/xcursor/themepage.h
M +33 -7 kcontrol/input/xcursor/themepage.ui
M +68 -4 kcontrol/input/xcursor/xcursortheme.cpp
M +6 -3 kcontrol/input/xcursor/xcursortheme.h
http://commits.kde.org/kde-workspace/617b08f5f6652bb9d918abc963954723caca59d2
diff --git a/kcontrol/input/xcursor/cursortheme.cpp b/kcontrol/input/xcursor/cursortheme.cpp
index 92abea5..2c8c260 100644
--- a/kcontrol/input/xcursor/cursortheme.cpp
+++ b/kcontrol/input/xcursor/cursortheme.cpp
@@ -110,24 +110,36 @@ QPixmap CursorTheme::createIcon() const
int cursorSize = nominalCursorSize(iconSize);
QSize size = QSize(iconSize, iconSize);
+ QPixmap pixmap = createIcon(cursorSize);
+
+ if (!pixmap.isNull())
+ {
+ // Scale the pixmap if it's larger than the preferred icon size
+ if (pixmap.width() > size.width() || pixmap.height() > size.height())
+ pixmap = pixmap.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ }
+
+ return pixmap;
+}
+
+
+QPixmap CursorTheme::createIcon(int size) const
+{
QPixmap pixmap;
- QImage image = loadImage(sample(), cursorSize);
+ QImage image = loadImage(sample(), size);
if (image.isNull() && sample() != "left_ptr")
- image = loadImage("left_ptr", cursorSize);
+ image = loadImage("left_ptr", size);
if (!image.isNull())
{
- // Scale the image if it's larger than the preferred icon size
- if (image.width() > size.width() || image.height() > size.height())
- image = image.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
-
pixmap = QPixmap::fromImage(image);
}
return pixmap;
}
+
void CursorTheme::setCursorName(QCursor &cursor, const QString &name) const
{
#ifdef HAVE_XFIXES
diff --git a/kcontrol/input/xcursor/cursortheme.h b/kcontrol/input/xcursor/cursortheme.h
index 586ccba..672239b 100644
--- a/kcontrol/input/xcursor/cursortheme.h
+++ b/kcontrol/input/xcursor/cursortheme.h
@@ -62,6 +62,11 @@ class CursorTheme
const QString sample() const { return m_sample; }
const QString name() const { return m_name; }
const QString path() const { return m_path; }
+ /** @returns A list of the available sizes in this cursor theme,
+ @warning This list may be empty if the engine doesn't support
+ the recognition of the size. */
+ const QList<int> availableSizes() const
+ { return m_availableSizes; }
bool isWritable() const { return m_writable; }
bool isHidden() const { return m_hidden; }
QPixmap icon() const;
@@ -72,16 +77,27 @@ class CursorTheme
/// Loads the cursor image @p name, with the nominal size @p size.
/// The image should be autocropped to the smallest possible size.
/// If the theme doesn't have the cursor @p name, it should return a null image.
- virtual QImage loadImage(const QString &name, int size = -1) const = 0;
+ virtual QImage loadImage(const QString &name, int size = 0) const = 0;
/// Convenience function. Default implementation calls
/// QPixmap::fromImage(loadImage());
- virtual QPixmap loadPixmap(const QString &name, int size = -1) const;
+ virtual QPixmap loadPixmap(const QString &name, int size = 0) const;
/// Loads the cursor @p name, with the nominal size @p size.
/// If the theme doesn't have the cursor @p name, it should return
/// the default cursor from the active theme instead.
- virtual QCursor loadCursor(const QString &name, int size = -1) const = 0;
+ virtual QCursor loadCursor(const QString &name, int size = 0) const = 0;
+
+ /** Creates the icon returned by @ref icon(). Don't use this function
+ directly but use @ref icon() instead, because @ref icon() caches
+ the icon.
+ @returns A pixmap with a cursor (usually left_ptr) that can
+ be used as icon for this theme. The size is adopted to
+ standard icon sizes.*/
+ virtual QPixmap createIcon() const;
+ /** @returns A pixmap with a cursor (usually left_ptr) that can
+ be used as icon for this theme. */
+ virtual QPixmap createIcon(int size) const;
protected:
void setTitle( const QString &title ) { m_title = title; }
@@ -89,13 +105,12 @@ class CursorTheme
void setSample( const QString &sample ) { m_sample = sample; }
inline void setName( const QString &name );
void setPath( const QString &path ) { m_path = path; }
+ void setAvailableSizes( const QList<int> &availableSizes )
+ { m_availableSizes = availableSizes; }
void setIcon( const QPixmap &icon ) { m_icon = icon; }
void setIsWritable( bool val ) { m_writable = val; }
void setIsHidden( bool val ) { m_hidden = val; }
- /// Creates the icon returned by @ref icon().
- virtual QPixmap createIcon() const;
-
/// Convenience function for cropping an image.
QImage autoCropImage( const QImage &image ) const;
@@ -105,6 +120,7 @@ class CursorTheme
QString m_title;
QString m_description;
QString m_path;
+ QList<int> m_availableSizes;
QString m_sample;
mutable QPixmap m_icon;
bool m_writable:1;
diff --git a/kcontrol/input/xcursor/legacytheme.h b/kcontrol/input/xcursor/legacytheme.h
index 846bf9b..bd3c33d 100644
--- a/kcontrol/input/xcursor/legacytheme.h
+++ b/kcontrol/input/xcursor/legacytheme.h
@@ -41,8 +41,8 @@ class LegacyTheme : public CursorTheme
LegacyTheme();
virtual ~LegacyTheme();
- QImage loadImage(const QString &name, int size = -1) const;
- QCursor loadCursor(const QString &name, int size = - 1) const;
+ QImage loadImage(const QString &name, int size = 0) const;
+ QCursor loadCursor(const QString &name, int size = 0) const;
protected:
LegacyTheme(const QString &title, const QString &description = QString())
diff --git a/kcontrol/input/xcursor/previewwidget.cpp b/kcontrol/input/xcursor/previewwidget.cpp
index 3c264fc..aff149b 100644
--- a/kcontrol/input/xcursor/previewwidget.cpp
+++ b/kcontrol/input/xcursor/previewwidget.cpp
@@ -50,7 +50,6 @@ namespace {
};
const int numCursors = 9; // The number of cursors from the above list to be previewed
- const int previewSize = 24; // The nominal cursor size to be used in the preview widget
const int cursorSpacing = 20; // Spacing between preview cursors
const int widgetMinWidth = 10; // The minimum width of the preview widget
const int widgetMinHeight = 48; // The minimum height of the preview widget
@@ -60,7 +59,7 @@ namespace {
class PreviewCursor
{
public:
- PreviewCursor( const CursorTheme *theme, const QString &name );
+ PreviewCursor( const CursorTheme *theme, const QString &name, int size );
~PreviewCursor() {}
const QPixmap &pixmap() const { return m_pixmap; }
@@ -81,23 +80,18 @@ class PreviewCursor
};
-PreviewCursor::PreviewCursor(const CursorTheme *theme, const QString &name)
+PreviewCursor::PreviewCursor(const CursorTheme *theme, const QString &name, int size)
{
// Create the preview pixmap
- QImage image = theme->loadImage(name, previewSize);
+ QImage image = theme->loadImage(name, size);
if (image.isNull())
return;
- int maxSize = previewSize * 2;
- if (image.height() > maxSize || image.width() > maxSize)
- image = image.scaled(maxSize, maxSize, Qt::KeepAspectRatio,
- Qt::SmoothTransformation);
-
m_pixmap = QPixmap::fromImage(image);
// Load the cursor
- m_cursor = theme->loadCursor(name, previewSize);
+ m_cursor = theme->loadCursor(name, size);
// ### perhaps we should tag the cursor so it doesn't get
// replaced when a new theme is applied
}
@@ -168,7 +162,7 @@ void PreviewWidget::layoutItems()
}
-void PreviewWidget::setTheme(const CursorTheme *theme)
+void PreviewWidget::setTheme(const CursorTheme *theme, const int size)
{
qDeleteAll(list);
list.clear();
@@ -176,7 +170,7 @@ void PreviewWidget::setTheme(const CursorTheme *theme)
if (theme)
{
for (int i = 0; i < numCursors; i++)
- list << new PreviewCursor(theme, cursor_names[i]);
+ list << new PreviewCursor(theme, cursor_names[i], size);
needLayout = true;
updateGeometry();
diff --git a/kcontrol/input/xcursor/previewwidget.h b/kcontrol/input/xcursor/previewwidget.h
index f4d2c4e..4a11e2d 100644
--- a/kcontrol/input/xcursor/previewwidget.h
+++ b/kcontrol/input/xcursor/previewwidget.h
@@ -30,7 +30,7 @@ class PreviewWidget : public QWidget
PreviewWidget(QWidget *parent);
~PreviewWidget();
- void setTheme(const CursorTheme *theme);
+ void setTheme(const CursorTheme *theme, const int size);
void setUseLables(bool);
QSize sizeHint() const;
diff --git a/kcontrol/input/xcursor/themepage.cpp b/kcontrol/input/xcursor/themepage.cpp
index 6c9f29a..0f678ed 100644
--- a/kcontrol/input/xcursor/themepage.cpp
+++ b/kcontrol/input/xcursor/themepage.cpp
@@ -73,6 +73,7 @@ ThemePage::ThemePage(QWidget *parent)
proxy->setFilterCaseSensitivity(Qt::CaseSensitive);
proxy->sort(NameColumn, Qt::AscendingOrder);
+ // Get the icon size for QListView
int size = style()->pixelMetric(QStyle::PM_LargeIconSize);
view->setModel(proxy);
@@ -85,6 +86,16 @@ ThemePage::ThemePage(QWidget *parent)
SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
SLOT(selectionChanged()));
+ // Make sure we find out about size changes
+ connect(sizeComboBox,
+ SIGNAL(currentIndexChanged(int)),
+ SLOT(sizeChanged()));
+
+ // Make sure we find out about user activity
+ connect(sizeComboBox,
+ SIGNAL(activated(int)),
+ SLOT(preferredSizeChanged()));
+
// Disable the install button if we can't install new themes to ~/.icons,
// or Xcursor isn't set up to look for cursor themes there.
if (!model->searchPaths().contains(QDir::homePath() + "/.icons") || !iconsIsWritable()) {
@@ -113,6 +124,114 @@ bool ThemePage::iconsIsWritable() const
}
+void ThemePage::updateSizeComboBox()
+{
+ // clear the combo box
+ sizeComboBox->clear();
+
+ // refill the combo box and adopt its icon size
+ QModelIndex selected = selectedIndex();
+ int maxIconWidth = 0;
+ int maxIconHeight = 0;
+ if (selected.isValid())
+ {
+ const CursorTheme *theme = proxy->theme(selected);
+ const QList<int> sizes = theme->availableSizes();
+ QIcon m_icon;
+ if (sizes.size() > 1) // only refill the combobox if there is more that 1 size
+ {
+ int i;
+ QList<int> comboBoxList;
+ QPixmap m_pixmap;
+
+ // insert the items
+ m_pixmap = theme->createIcon(0);
+ if (m_pixmap.width() > maxIconWidth)
+ maxIconWidth = m_pixmap.width();
+ if (m_pixmap.height() > maxIconHeight)
+ maxIconHeight = m_pixmap.height();
+ sizeComboBox->addItem(
+ QIcon(m_pixmap),
+ i18nc("@item:inlistbox size", "resolution dependent"),
+ 0);
+ comboBoxList << 0;
+ foreach (i, sizes)
+ {
+ m_pixmap = theme->createIcon(i);
+ if (m_pixmap.width() > maxIconWidth)
+ maxIconWidth = m_pixmap.width();
+ if (m_pixmap.height() > maxIconHeight)
+ maxIconHeight = m_pixmap.height();
+ sizeComboBox->addItem(QIcon(m_pixmap), QString::number(i), i);
+ comboBoxList << i;
+ };
+
+ // select an item
+ int selectItem = comboBoxList.indexOf(preferredSize);
+ if (selectItem < 0) // preferredSize not available for this theme
+ {
+ /* Search the value next to preferredSize. The first entry (0)
+ is ignored. (If preferredSize would have been 0, then we
+ would had found it yet. As preferredSize is not 0, we won't
+ default to "automatic size".)*/
+ int j;
+ int distance;
+ int smallestDistance;
+ selectItem = 1;
+ j = comboBoxList.value(selectItem);
+ smallestDistance = j < preferredSize ? preferredSize - j : j - preferredSize;
+ for (int i = 2; i < comboBoxList.size(); ++i)
+ {
+ j = comboBoxList.value(i);
+ distance = j < preferredSize ? preferredSize - j : j - preferredSize;
+ if (distance < smallestDistance || (distance == smallestDistance && j > preferredSize))
+ {
+ smallestDistance = distance;
+ selectItem = i;
+ };
+ }
+ };
+ sizeComboBox->setCurrentIndex(selectItem);
+ };
+ };
+ sizeComboBox->setIconSize(QSize(maxIconWidth, maxIconHeight));
+
+ // enable or disable the combobox
+ KConfig c("kcminputrc");
+ KConfigGroup cg(&c, "Mouse");
+ if (cg.isEntryImmutable("cursorSize")) {
+ sizeComboBox->setEnabled(false);
+ sizeLabel->setEnabled(false);
+ } else {
+ sizeComboBox->setEnabled(sizeComboBox->count() > 0);
+ sizeLabel->setEnabled(sizeComboBox->count() > 0);
+ };
+}
+
+
+int ThemePage::selectedSize() const
+{
+ if (sizeComboBox->isEnabled() && sizeComboBox->currentIndex() >= 0)
+ return sizeComboBox->itemData(sizeComboBox->currentIndex(), Qt::UserRole).toInt();
+ return 0;
+}
+
+
+void ThemePage::updatePreview()
+{
+ QModelIndex selected = selectedIndex();
+
+ if (selected.isValid()) {
+ const CursorTheme *theme = proxy->theme(selected);
+ preview->setTheme(theme, selectedSize());
+ removeButton->setEnabled(theme->isWritable());
+ } else {
+ preview->setTheme(NULL, 0);
+ removeButton->setEnabled(false);
+ };
+}
+
+
bool ThemePage::haveXfixes()
{
bool result = false;
@@ -131,12 +250,15 @@ bool ThemePage::haveXfixes()
}
-bool ThemePage::applyTheme(const CursorTheme *theme)
+bool ThemePage::applyTheme(const CursorTheme *theme, const int size)
{
// Require the Xcursor version that shipped with X11R6.9 or greater, since
// in previous versions the Xfixes code wasn't enabled due to a bug in the
// build system (freedesktop bug #975).
#if HAVE_XFIXES && XFIXES_MAJOR >= 2 && XCURSOR_LIB_VERSION >= 10105
+ if (!theme)
+ return false;
+
if (!haveXfixes())
return false;
@@ -173,7 +295,7 @@ bool ThemePage::applyTheme(const CursorTheme *theme)
foreach (const QString &name, names)
{
- QCursor cursor = theme->loadCursor(name);
+ QCursor cursor = theme->loadCursor(name, size);
XFixesChangeCursorByName(x11Info().display(), cursor.handle(), QFile::encodeName(name));
}
@@ -187,17 +309,20 @@ bool ThemePage::applyTheme(const CursorTheme *theme)
void ThemePage::save()
{
- if (appliedIndex == selectedIndex() || !selectedIndex().isValid())
- return;
-
- const CursorTheme *theme = proxy->theme(selectedIndex());
+ const CursorTheme *theme = selectedIndex().isValid() ? proxy->theme(selectedIndex()) : NULL;
+ const int size = selectedSize();
KConfig config("kcminputrc");
KConfigGroup c(&config, "Mouse");
- c.writeEntry("cursorTheme", theme->name());
+ if (theme)
+ {
+ c.writeEntry("cursorTheme", theme->name());
+ };
+ c.writeEntry("cursorSize", size);
+ preferredSize = size;
c.sync();
- if (!applyTheme(theme))
+ if (!applyTheme(theme, size))
{
KMessageBox::information(this,
i18n("You have to restart KDE for these changes to take effect."),
@@ -205,6 +330,7 @@ void ThemePage::save()
}
appliedIndex = selectedIndex();
+ appliedSize = size;
}
@@ -233,16 +359,26 @@ void ThemePage::load()
removeButton->setEnabled(false);
}
+ // Load cursor size
+ int size = cg.readEntry("cursorSize", 0);
+ if (size <= 0)
+ preferredSize = 0;
+ else
+ preferredSize = size;
+ updateSizeComboBox(); // This handles also the kiosk mode
+
+ appliedSize = size;
+
const CursorTheme *theme = proxy->theme(appliedIndex);
if (appliedIndex.isValid())
{
// Select the current theme
- selectRow(appliedIndex);
+ view->setCurrentIndex(appliedIndex);
view->scrollTo(appliedIndex, QListView::PositionAtCenter);
// Update the preview widget as well
- preview->setTheme(theme);
+ preview->setTheme(theme, size);
}
if (!theme || !theme->isWritable())
@@ -255,33 +391,17 @@ void ThemePage::defaults()
view->selectionModel()->clear();
QModelIndex defaultIndex = proxy->findIndex("Oxygen_Black");
view->setCurrentIndex(defaultIndex);
-}
-
-
-void ThemePage::selectRow(int row) const
-{
- // Create a selection that stretches across all columns
- QModelIndex from = proxy->index(row, 0);
- QModelIndex to = proxy->index(row, model->columnCount() - 1);
- QItemSelection selection(from, to);
-
- view->selectionModel()->select(selection, QItemSelectionModel::Select);
+ preferredSize = 0;
+ updateSizeComboBox();
}
void ThemePage::selectionChanged()
{
- QModelIndex selected = selectedIndex();
+ updateSizeComboBox();
+ updatePreview();
- if (selected.isValid())
- {
- const CursorTheme *theme = proxy->theme(selected);
- preview->setTheme(theme);
- removeButton->setEnabled(theme->isWritable());
- } else
- preview->setTheme(NULL);
-
- emit changed(appliedIndex != selected);
+ emit changed(appliedIndex != selectedIndex());
}
QModelIndex ThemePage::selectedIndex() const
@@ -293,6 +413,21 @@ QModelIndex ThemePage::selectedIndex() const
return QModelIndex();
}
+void ThemePage::sizeChanged()
+{
+ updatePreview();
+ emit changed(selectedSize() != appliedSize);
+}
+
+void ThemePage::preferredSizeChanged()
+{
+ int index = sizeComboBox->currentIndex();
+ if (index >= 0)
+ preferredSize = sizeComboBox->itemData(index, Qt::UserRole).toInt();
+ else
+ preferredSize = 0;
+}
+
void ThemePage::getNewClicked()
{
KNS3::DownloadDialog dialog("xcursor.knsrc", this);
diff --git a/kcontrol/input/xcursor/themepage.h b/kcontrol/input/xcursor/themepage.h
index 38ca893..3b21dd9 100644
--- a/kcontrol/input/xcursor/themepage.h
+++ b/kcontrol/input/xcursor/themepage.h
@@ -48,21 +48,50 @@ class ThemePage : public QWidget, private Ui::ThemePage
private slots:
void selectionChanged();
+ /** Updates the preview. If the size has changed, it also emits changed() */
+ void sizeChanged();
+ /** Sets #preferredSize to the item that is currently selected in sizeComboBox.
+ If none is selected, it is set to 0. */
+ void preferredSizeChanged();
+ /** Updates the size combo box. It loads the size list of the selected cursor
+ theme with the corresponding icons and chooses an appropriate entry. It
+ enables the combo box and the label if the theme provides more than one
+ size, otherwise it disables it. If the size setting is looked in kiosk
+ mode, it stays always disabled. */
+ void updateSizeComboBox();
void getNewClicked();
void installClicked();
void removeClicked();
private:
- void selectRow(int) const;
- void selectRow(const QModelIndex &index) const { selectRow(index.row()); }
+ /** @returns 0 if in the UI "automatic size" is selected, otherwise
+ returns the custom size. */
+ int selectedSize() const;
+ /** Holds the last size that was choosen by the user. Example: The user chooses
+ theme1 which provides the sizes 24 and 36. He chooses 36. preferredSize gets
+ set to 36. Now, he switchs to theme2 which provides the sizes 30 and 40.
+ preferredSize still is 36, so the UI will default to 40, which is next to 36.
+ Now, he chooses theme3 which provides the sizes 34 and 44. preferredSize is
+ still 36, so the UI defaults to 34. Now the user changes manually to 44. This
+ will also change preferredSize. */
+ int preferredSize;
+ void updatePreview();
QModelIndex selectedIndex() const;
bool installThemes(const QString &file);
- bool applyTheme(const CursorTheme *theme);
+ /** Applies a given theme, using XFixes, XCursor and KGlobalSettings.
+ @param theme The cursor theme to be applied. It is save to pass 0 here
+ (will result in \e false as return value).
+ @param size The size hint that is used to select the cursor size.
+ @returns If the changes could be applied. Will return \e false if \e theme is
+ 0 or if the XFixes and XCursor libraries aren't available in the required
+ version, otherwise returns \e true. */
+ bool applyTheme(const CursorTheme *theme, const int size);
bool iconsIsWritable() const;
CursorThemeModel *model;
SortProxyModel *proxy;
+ int appliedSize;
// This index refers to the CursorThemeModel, not the proxy or the view
QPersistentModelIndex appliedIndex;
};
diff --git a/kcontrol/input/xcursor/themepage.ui b/kcontrol/input/xcursor/themepage.ui
index 2e38054..be73663 100644
--- a/kcontrol/input/xcursor/themepage.ui
+++ b/kcontrol/input/xcursor/themepage.ui
@@ -6,19 +6,19 @@
<rect>
<x>0</x>
<y>0</y>
- <width>542</width>
+ <width>541</width>
<height>360</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0" colspan="4">
+ <item row="0" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>Select the cursor theme you want to use (hover preview to test cursor):</string>
</property>
</widget>
</item>
- <item row="1" column="0" colspan="4">
+ <item row="1" column="0" rowspan="3" colspan="2">
<widget class="PreviewWidget" name="preview" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@@ -34,7 +34,7 @@
</property>
</widget>
</item>
- <item row="2" column="0" rowspan="5" colspan="3">
+ <item row="4" column="0" rowspan="5" colspan="2">
<widget class="QListView" name="view">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
@@ -50,7 +50,7 @@
</property>
</widget>
</item>
- <item row="2" column="3">
+ <item row="4" column="2">
<widget class="KPushButton" name="installKnsButton">
<property name="toolTip">
<string>Get new color schemes from the Internet</string>
@@ -60,20 +60,46 @@
</property>
</widget>
</item>
- <item row="3" column="3">
+ <item row="5" column="2">
<widget class="KPushButton" name="installButton">
<property name="text">
<string>Install From File...</string>
</property>
</widget>
</item>
- <item row="4" column="3">
+ <item row="6" column="2">
<widget class="KPushButton" name="removeButton">
<property name="text">
<string>Remove Theme</string>
</property>
</widget>
</item>
+ <item row="2" column="2">
+ <widget class="QComboBox" name="sizeComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="sizeAdjustPolicy">
+ <enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="sizeLabel">
+ <property name="text">
+ <string comment="@label:listbox cursor size">Size:</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
<customwidgets>
diff --git a/kcontrol/input/xcursor/xcursortheme.cpp b/kcontrol/input/xcursor/xcursortheme.cpp
index 2ecb9ba..2fc7504 100644
--- a/kcontrol/input/xcursor/xcursortheme.cpp
+++ b/kcontrol/input/xcursor/xcursortheme.cpp
@@ -45,6 +45,39 @@ XCursorTheme::XCursorTheme(const QDir &themeDir)
if (themeDir.exists("index.theme"))
parseIndexFile();
+
+ QString cursorFile = path() + "/cursors/left_ptr";
+ QList<int> sizeList;
+ XcursorImages *images = XcursorFilenameLoadAllImages(qPrintable(cursorFile));
+ if (images)
+ {
+ for (int i = 0; i < images->nimage; ++i)
+ {
+ if (!sizeList.contains(images->images[i]->size))
+ sizeList.append(images->images[i]->size);
+ };
+ XcursorImagesDestroy(images);
+ qSort(sizeList.begin(), sizeList.end());
+ m_availableSizes = sizeList;
+ };
+ if (!sizeList.isEmpty())
+ {
+ QString sizeListString = QString::number(sizeList.takeFirst());
+ while (!sizeList.isEmpty())
+ {
+ sizeListString.append(", ");
+ sizeListString.append(QString::number(sizeList.takeFirst()));
+ };
+ QString tempString = i18nc(
+ "@info/plain The argument is the list of available sizes (in pixel). Example: "
+ "'Available sizes: 24' or 'Available sizes: 24, 36, 48'",
+ "(Available sizes: %1)",
+ sizeListString);
+ if (m_description.isEmpty())
+ m_description = tempString;
+ else
+ m_description = m_description + ' ' + tempString;
+ };
}
@@ -116,10 +149,41 @@ XcursorImages *XCursorTheme::xcLoadImages(const QString &image, int size) const
}
+int XCursorTheme::autodetectCursorSize() const
+{
+ /* This code is basically borrowed from display.c of the XCursor library
+ We can't use "int XcursorGetDefaultSize(Display *dpy)" because if
+ previously the cursor size was set to a custom value, it would return
+ this custom value. */
+ int size = 0;
+ int dpi = 0;
+ Display *dpy = QX11Info::display();
+ // The string "v" is owned and will be destroyed by Xlib
+ char *v = XGetDefault(dpy, "Xft", "dpi");
+ if (v)
+ dpi = atoi(v);
+ if (dpi)
+ size = dpi * 16 / 72;
+ if (size == 0)
+ {
+ int dim;
+ if (DisplayHeight(dpy, DefaultScreen(dpy)) <
+ DisplayWidth(dpy, DefaultScreen(dpy)))
+ {
+ dim = DisplayHeight(dpy, DefaultScreen(dpy));
+ } else {
+ dim = DisplayWidth(dpy, DefaultScreen(dpy));
+ };
+ size = dim / 48;
+ }
+ return size;
+}
+
+
QCursor XCursorTheme::loadCursor(const QString &name, int size) const
{
- if (size == -1)
- size = XcursorGetDefaultSize(QX11Info::display());
+ if (size <= 0)
+ size = autodetectCursorSize();
// Load the cursor images
XcursorImages *images = xcLoadImages(name, size);
@@ -143,8 +207,8 @@ QCursor XCursorTheme::loadCursor(const QString &name, int size) const
QImage XCursorTheme::loadImage(const QString &name, int size) const
{
- if (size == -1)
- size = XcursorGetDefaultSize(QX11Info::display());
+ if (size <= 0)
+ size = autodetectCursorSize();
// Load the image
XcursorImage *xcimage = xcLoadImage(name, size);
diff --git a/kcontrol/input/xcursor/xcursortheme.h b/kcontrol/input/xcursor/xcursortheme.h
index b474086..b4b6c53 100644
--- a/kcontrol/input/xcursor/xcursortheme.h
+++ b/kcontrol/input/xcursor/xcursortheme.h
@@ -45,9 +45,9 @@ class XCursorTheme : public LegacyTheme
XCursorTheme(const QDir &dir);
virtual ~XCursorTheme() {}
- const QStringList inherits() const { return m_inherits; }
- QImage loadImage(const QString &name, int size = -1) const;
- QCursor loadCursor(const QString &name, int size = -1) const;
+ const QStringList inherits() const { return m_inherits; }
+ QImage loadImage(const QString &name, int size = 0) const;
+ QCursor loadCursor(const QString &name, int size = 0) const;
protected:
XCursorTheme(const QString &title, const QString &desc)
@@ -59,6 +59,9 @@ class XCursorTheme : public LegacyTheme
XcursorImages *xcLoadImages(const QString &name, int size) const;
void parseIndexFile();
QString findAlternative(const QString &name) const;
+ /** Returns the size that the XCursor library would use if no
+ cursor size is given. This depends mainly on Xft.dpi. */
+ int autodetectCursorSize() const;
QStringList m_inherits;
static QHash<QString, QString> alternatives;
More information about the kde-doc-english
mailing list