Add Icon and IconLoader
authorManuel Nickschas <sputnick@quassel-irc.org>
Mon, 22 Sep 2008 22:33:33 +0000 (00:33 +0200)
committerManuel Nickschas <sputnick@quassel-irc.org>
Mon, 22 Sep 2008 22:37:20 +0000 (00:37 +0200)
The former is a very thin wrapper around QIcon that will use the latter to locate an icon
in the current theme (harcoded to Oxygen for now), either in the file system or in a resource.
This will allow us to make icon resources optional, and also to seamlessly integrate with KDE's
icon theming later.
Note that we don't provide proper theming support now, as IconLoader is _very_ rudimentary for
now and assumes Oxygen to be present.

src/qtui/mainwin.cpp
src/qtui/qtuiapplication.cpp
src/uisupport/CMakeLists.txt
src/uisupport/icon.cpp [new file with mode: 0644]
src/uisupport/icon.h [new file with mode: 0644]
src/uisupport/iconloader.cpp [new file with mode: 0644]
src/uisupport/iconloader.h [new file with mode: 0644]

index 8896893..d2363e6 100644 (file)
@@ -36,6 +36,7 @@
 #include "clientbacklogmanager.h"
 #include "coreinfodlg.h"
 #include "coreconnectdlg.h"
+#include "icon.h"
 #include "msgprocessorstatuswidget.h"
 #include "qtuimessageprocessor.h"
 #include "qtuiapplication.h"
@@ -92,7 +93,6 @@ MainWin::MainWin(QWidget *parent)
   if(style != "") {
     QApplication::setStyle(style);
   }
-
   ui.setupUi(this);
   setWindowTitle("Quassel IRC");
   setWindowIcon(offlineTrayIcon);
index 7a6f097..80cc4d4 100644 (file)
@@ -27,6 +27,8 @@
 #include "qtui.h"
 #include "sessionsettings.h"
 
+#include "iconloader.h"
+
 QtUiApplication::QtUiApplication(int &argc, char **argv) : QApplication(argc, argv), Quassel() {
   setRunMode(Quassel::ClientOnly);
 
@@ -45,6 +47,10 @@ bool QtUiApplication::init() {
     // QTimer::singleShot(0, gui, SLOT(init()));
     gui->init();
     resumeSessionIfPossible();
+
+    // DEBUG
+    QPixmap pix = IconLoader::global()->loadIcon("network-connect", IconLoader::Small);
+    qDebug() << pix;
     return true;
   }
   return false;
index f60c8ca..19befca 100644 (file)
@@ -14,9 +14,11 @@ set(SOURCES
     clearablelineedit.cpp
     clickablelabel.cpp
     colorbutton.cpp
-    nickviewfilter.cpp
+    icon.cpp
+    iconloader.cpp
     inputline.cpp
     nickview.cpp
+    nickviewfilter.cpp
     settingspage.cpp
     tabcompleter.cpp
     uisettings.cpp
@@ -32,13 +34,15 @@ set(MOC_HDRS
     clearablelineedit.h
     clickablelabel.h
     colorbutton.h
-    nickviewfilter.h
+    iconloader.h
     inputline.h
     nickview.h
+    nickviewfilter.h
     settingspage.h
     tabcompleter.h)
 
 set(HEADERS
+    icon.h
     uisettings.h
     uistyle.h)
 
diff --git a/src/uisupport/icon.cpp b/src/uisupport/icon.cpp
new file mode 100644 (file)
index 0000000..729a88b
--- /dev/null
@@ -0,0 +1,26 @@
+/***************************************************************************
+ *   Copyright (C) 2005-08 by the Quassel IRC Team                         *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   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) version 3.                                           *
+ *                                                                         *
+ *   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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include "icon.h"
+#include "iconloader.h"
+
+Icon::Icon(const QString &name) : QIcon() {
+  addPixmap(IconLoader::global()->loadIcon(name, IconLoader::Desktop));
+}
diff --git a/src/uisupport/icon.h b/src/uisupport/icon.h
new file mode 100644 (file)
index 0000000..7ca1844
--- /dev/null
@@ -0,0 +1,38 @@
+/***************************************************************************
+ *   Copyright (C) 2005-08 by the Quassel IRC Team                         *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   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) version 3.                                           *
+ *                                                                         *
+ *   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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef ICON_H_
+#define ICON_H_
+
+#include <QIcon>
+
+/// A very thin wrapper around QIcon
+/** This wrapper class allows us to load an icon by its theme name rather than its full file name.
+ *  The overloaded ctor uses IconLoader to locate an icon with this basename in the current theme
+ *  or in Qt Resources.
+ */
+class Icon : public QIcon {
+
+  public:
+    //explicit Icon();
+    explicit Icon(const QString &iconName);
+};
+
+#endif
diff --git a/src/uisupport/iconloader.cpp b/src/uisupport/iconloader.cpp
new file mode 100644 (file)
index 0000000..0fff1e8
--- /dev/null
@@ -0,0 +1,112 @@
+/***************************************************************************
+ *   Copyright (C) 2005-08 by the Quassel IRC Team                         *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   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) version 3.                                           *
+ *                                                                         *
+ *   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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include <QDebug>
+#include <QDir>
+#include <QFile>
+
+#include "iconloader.h"
+
+IconLoader IconLoader::_iconLoader;
+int IconLoader::_groupSize[] = { 48, 22, 22, 16, 32, 22 };  // default sizes taken from Oxygen
+
+IconLoader *IconLoader::global() {
+  return &_iconLoader;
+}
+
+IconLoader::IconLoader(QObject *parent) : QObject(parent) {
+
+  setTheme("oxygen");
+}
+
+IconLoader::~IconLoader() {
+
+}
+
+void IconLoader::setTheme(const QString &theme) {
+  _theme = theme;
+  // check which dirs could contain themed icons
+  _themedIconDirNames.clear();
+  _plainIconDirNames.clear();
+  QString path;
+  QStringList dataDirNames = QString(qgetenv("XDG_DATA_DIRS")).split(':');
+
+  // System theme in $data/icons/$theme
+  foreach(QString dir, dataDirNames) {
+    path = QString("%1/icons/%2").arg(dir, theme);
+    if(QFile::exists(path))
+      _themedIconDirNames.append(path);
+  }
+  // Resource for system theme :/icons/$theme
+  path = QString(":/icons/%2");
+  if(QFile::exists(path))
+    _themedIconDirNames.append(path);
+
+  // Own icons in $data/apps/quassel/icons/hicolor and :/icons/hicolor
+  // Also, plain icon dirs $data/apps/quassel/pics and :/pics
+  dataDirNames.append(":");
+  foreach(QString dir, dataDirNames) {
+    path = QString("%1/apps/quassel/icons/hicolor");
+    if(QFile::exists(path))
+      _themedIconDirNames.append(path);
+    path = QString("%1/apps/quassel/pics");
+    if(QFile::exists(path))
+      _plainIconDirNames.append(path);
+  }
+}
+
+// TODO: optionally implement cache (speed/memory tradeoff?)
+QPixmap IconLoader::loadIcon(const QString &name, IconLoader::Group group, int size) {
+  if(group < 0 || group >= LastGroup) {
+    qWarning() << "Invalid icon group!";
+    return QPixmap();
+  }
+  if(size == 0)
+    size = _groupSize[group];
+
+  QString path = findIconPath(name, size);
+  if(path.isEmpty()) return QPixmap();
+
+  // load the icon
+  return QPixmap(path);
+}
+
+QString IconLoader::findIconPath(const QString &name, int size) {
+  QString fname = QString("%1.png").arg(name);  // we only support PNG so far
+  // First, look for a themed icon... we don't do anything fancy here, only exact match for both name and size
+  foreach(QString basedir, _themedIconDirNames) {
+    QDir sizedir(QString("%1/%2x%2").arg(basedir).arg(QString::number(size)));
+    if(sizedir.exists()) {
+      // ignore context, i.e. scan all subdirs
+      QStringList contextdirs = sizedir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
+      foreach(QString dir, contextdirs) {
+        QString path = QString("%1/%2/%3").arg(sizedir.absolutePath(), dir, fname);
+        if(QFile::exists(path)) return path;
+      }
+    }
+  }
+  // Now check the plain dirs
+  foreach(QString dir, _plainIconDirNames) {
+    QString path = QString("%1/%2").arg(dir, name);
+    if(QFile::exists(path)) return path;
+  }
+
+  return QString();
+}
diff --git a/src/uisupport/iconloader.h b/src/uisupport/iconloader.h
new file mode 100644 (file)
index 0000000..165aa9b
--- /dev/null
@@ -0,0 +1,105 @@
+/***************************************************************************
+ *   Copyright (C) 2005-08 by the Quassel IRC Team                         *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   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) version 3.                                           *
+ *                                                                         *
+ *   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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************
+ * Based in part on KDE's kiconloader.h                                    *
+ * This declares a subset of that API.                                     *
+ ***************************************************************************/
+
+#ifndef ICONLOADER_H_
+#define ICONLOADER_H_
+
+#include <QPixmap>
+
+/// Provides basic facilities to load icons from standard locations or resources
+/** This implements a (very) basic subset of KIconLoader's API, such that we can use those classes
+ *  interchangeably in Quassel.
+ *
+ *  We currently (unless somebody does a more fancy implementation ;-)) assume the Oxygen icon theme
+ *  to be used. In particular, this means that we do assume its directory layout and existing icons to
+ *  be present. Though it should be easy to switch to a different theme name, we don't currently support
+ *  any fallback mechanism if this other theme misses an icon for a given size. Also, we only support PNG.
+ *
+ *  Since we do support integrating the required part of Oxygen into the binary via Qt Resources, this
+ *  should work for everyone for now.
+ *
+ *  - $XDG_DATA_DIRS/icons/$theme (in order)
+ *  - :/icons/$theme (fallback in case we use Qt Resources)
+ *  - $XDG_DATA_DIRS/apps/quassel/icons/hicolor (our own unthemed icons)
+ *  - :/icons/hicolor
+ *  - $XDG_DATA_DIRS/apps/quassel/pics
+ *  - :/pics
+ *
+ *  We don't search for size/context dirs in /pics, i.e. for a given $name, we expect pics/$name.png.
+ */
+class IconLoader : public QObject {
+  Q_OBJECT
+
+public:
+  enum Group {
+    NoGroup = -1,   ///< No group
+    Desktop = 0,    ///< Desktop icons
+    Toolbar,        ///< Toolbar icons
+    MainToolbar,    ///< Main toolbar icons
+    Small,          ///< Small icons, e.g. for buttons
+    Panel,          ///< Panel icons
+    Dialog,         ///< Icons for use in dialog title etc.
+    LastGroup
+  };
+
+  /// Standard icon sizes
+  enum StdSizes {
+    SizeSmall=16,         ///< Small icons for menu entries
+    SizeSmallMedium=22,   ///< Slightly larger small icons for toolbars, panels, etc
+    SizeMedium=32,        ///< Medium-sized icons for the desktop
+    SizeLarge=48,         ///< Large icons for the panel
+    SizeHuge=64,          ///< Huge icons for iconviews
+    SizeEnormous=128      ///< Enormous icons for iconviews
+  };
+
+  explicit IconLoader(QObject *parent = 0);
+  ~IconLoader();
+
+  static IconLoader *global();
+
+  /// Load a pixmap for the given name and group
+  QPixmap loadIcon(const QString& name, IconLoader::Group group, int size = 0);
+
+  inline QString theme() const;
+  void setTheme(const QString &name);
+
+private:
+  QString findIconPath(const QString &name, int size);
+
+  static IconLoader _iconLoader;
+  QString _theme;
+  QStringList _themedIconDirNames;
+  QStringList _plainIconDirNames;
+  static int _groupSize[];
+};
+
+// convenience
+QPixmap DesktopIcon(const QString& name, int size = 0);
+QPixmap BarIcon(const QString& name, int size = 0);
+QPixmap MainbarIcon(const QString& name, int size = 0);
+QPixmap SmallIcon(const QString& name, int size = 0);
+//QPixmap SmallMediumIcon(const QString &name, int size = 0);  // not part of KIconLoader
+
+QString IconLoader::theme() const { return _theme; }
+
+#endif