[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-devel
Subject:    Re: Fwd: Announcing KShortcutAssistant
From:       "Ulrik Mikaelsson" <ulrik.mikaelsson () gmail ! com>
Date:       2007-08-26 18:47:35
Message-ID: 15c1dfa0708261147v24d4acecw3f801843925619ea () mail ! gmail ! com
[Download RAW message or body]

On 8/26/07, Andreas Pakulat <apaku@gmx.de> wrote:
> It would have been nice if you could've provided some more information
> how that class/code works specifically. What changes did you do?

Certainly, although the important part is not the code itself. The
code is trivial and probably not optimal (re-generating the
KShortcutAssistant-panel on each display, for instance). What's
important here is how it affects usability, and if the direction of
development is desired.

Anyways, the attached patch should pretty much be self-explanatory,
but the current concept is;

- Create a new core-widget that displays a centered panel containing
all available shortcut-actions.
  + Currently, the available actions are inferred by examining the
menu of the current KMainWindow. (This happens on each display, room
for improvements)
  + Actions are currently grouped by where in the menu they occur.
Probably not desireable, at least they should be grouped by what the
complete key-combo looks like (look how it's done in the article.)
- Hook up the widget in the main application event-loop (the only
place if found where I are guaranteed to see all keydown-events for
the ctrl-key.)

Don't hesitate to ask for further questions. (Note the attached patch
will probably not apply cleanly to current trunk. I've had some
merging-issues I'm still trying to sort out.)

Regards
/ Ulrik

["kshortcutassistant.patch" (text/x-patch)]

=== added file 'kdeui/kernel/kshortcutassistant.cpp'
--- kdeui/kernel/kshortcutassistant.cpp	1970-01-01 00:00:00 +0000
+++ kdeui/kernel/kshortcutassistant.cpp	2007-08-18 18:08:04 +0000
@@ -0,0 +1,156 @@
+/* This file is part of the KDE libraries
+    Copyright (C) 2007, Ulrik Mikaelsson (rawler@users.sf.net)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public \
License +    along with this library; see the file COPYING.LIB.  If not, \
write to +    the Free Software Foundation, Inc., 51 Franklin Street, \
Fifth Floor, +    Boston, MA 02110-1301, USA.
+*/
+
+#undef QT_NO_TRANSLATION
+#include "kshortcutassistant.h"
+#define QT_NO_TRANSLATION
+
+#include <math.h>
+
+#include <QtCore/QList>
+#include <QtGui/QDesktopWidget>
+#include <QtGui/QFont>
+#include <QtGui/QGridLayout>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QKeySequence>
+#include <QtGui/QLabel>
+#include <QtGui/QVBoxLayout>
+
+#include "kapplication.h"
+#include "kdebug.h"
+#include "kmainwindow.h"
+#include "kmenubar.h"
+
+class KShortcutAssistant::Private
+{
+public:
+    QGridLayout * grid;
+
+    Private()
+    {
+        makeGrid();
+    }
+
+    void makeGrid()
+    {
+        grid = new QGridLayout();
+        grid->setSpacing(30);
+    }
+};
+
+KShortcutAssistant::KShortcutAssistant() :
+    QWidget(NULL, Qt::Window | Qt::WindowStaysOnTopHint | \
Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint), // Need portable support \
for avoiding the keyboard-stuff +    p(new Private)
+{
+    move(20,20);
+    resize(800,800);
+    setLayout(p->grid);
+}
+
+KShortcutAssistant::~KShortcutAssistant()
+{
+
+}
+
+QLayout * KShortcutAssistant::buildGroup(QMenu * sourceMenu)
+{
+    QVBoxLayout *retVal = new QVBoxLayout();
+    retVal->setSpacing(5);
+
+    QLabel * title = new QLabel(sourceMenu->title().remove('&'), this);
+    title->setFont(QFont("Helvetica", 12, QFont::Bold));
+    retVal->addWidget(title);
+    retVal->addSpacing(5);
+
+    foreach (QAction * action, sourceMenu->actions()) {
+        if (!action->shortcut().isEmpty())
+        {
+            QHBoxLayout * actionLayout = new QHBoxLayout();
+            QLabel * iconLabel = new QLabel(this);
+            iconLabel->setPixmap(action->icon().pixmap(16));
+            QLabel * nameLabel = new QLabel(action->text().remove('&'), \
this); +            nameLabel->setAlignment(Qt::AlignLeft);
+            QLabel * shortcutLabel = new \
QLabel(action->shortcut().toString(), this); +            \
shortcutLabel->setAlignment(Qt::AlignRight); +            \
actionLayout->addWidget(iconLabel); +            \
actionLayout->addWidget(nameLabel); +            \
actionLayout->addWidget(shortcutLabel); +            \
retVal->addLayout(actionLayout); +        }
+    }
+
+    return retVal;
+}
+
+void KShortcutAssistant::buildGrid(QMenuBar * sourceMenu)
+{
+    QList<QLayout*> actionGroupLayouts;
+    int cols;
+    int x=0,y=0;
+
+    foreach (QAction * action, sourceMenu->actions()) {
+        if (action->menu()) {
+            QLayout * l = buildGroup(action->menu());
+
+            if (l)
+                actionGroupLayouts << l;
+        }
+    }
+
+    cols = (int)ceil(sqrt(actionGroupLayouts.count()));
+
+    foreach (QLayout *l, actionGroupLayouts) {
+        p->grid->addLayout(l, y, x);
+        x = (x + 1) % cols;
+        if (x == 0)
+            y += 1;
+    }
+}
+
+void KShortcutAssistant::show()
+{
+    QMainWindow * activeWindow = \
qobject_cast<QMainWindow*>(KApplication::kApplication()->activeWindow()); \
+    QMenuBar * activeMenu = activeWindow ? activeWindow->menuBar() : \
NULL; +
+    if (activeMenu) { // Focus is in a window that has a menu-structure
+        buildGrid(activeMenu); // Build a helper-pane for the menu
+        resize(p->grid->minimumSize());
+
+        QRect screen = \
KApplication::kApplication()->desktop()->screenGeometry(KApplication::kApplication()->focusWidget());
 +        QRect selfRect = geometry();
+        selfRect.setSize(p->grid->minimumSize());
+        selfRect.moveCenter(screen.center());
+        setGeometry(selfRect);
+
+        QWidget::show();
+    }
+}
+
+void KShortcutAssistant::hide()
+{
+    // Destroy internal widget-stuff
+    QWidget::hide();
+
+    while (QLayoutItem * child = p->grid->takeAt(0)) { // Empty the \
grid-layout +        p->grid->removeItem(child);
+        delete(child);
+    }
+    foreach (QWidget* child, findChildren<QWidget*>()) // Remove the \
child-widgets +        delete(child);
+}

=== added file 'kdeui/kernel/kshortcutassistant.h'
--- kdeui/kernel/kshortcutassistant.h	1970-01-01 00:00:00 +0000
+++ kdeui/kernel/kshortcutassistant.h	2007-08-18 16:23:30 +0000
@@ -0,0 +1,49 @@
+/* This file is part of the KDE libraries
+    Copyright (C) 2007, Ulrik Mikaelsson (rawler@users.sf.net)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public \
License +    along with this library; see the file COPYING.LIB.  If not, \
write to +    the Free Software Foundation, Inc., 51 Franklin Street, \
Fifth Floor, +    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KSHORTCUTASSISTANT_H
+#define KSHORTCUTASSISTANT_H
+
+// Version macros. Never put this further down.
+#include "kdeversion.h"
+#include <kdeui_export.h>
+
+#include <QtGui/QMenu>
+#include <QtGui/QMenuBar>
+#include <QtGui/QLayout>
+
+class KDEUI_EXPORT KShortcutAssistant : public QWidget
+{
+  Q_OBJECT
+public:
+  explicit KShortcutAssistant();
+  virtual ~KShortcutAssistant();
+
+  virtual void show();
+  virtual void hide();
+
+private:
+  QLayout* buildGroup(QMenu* sourceMenu);
+  void buildGrid(QMenuBar* sourceMenu);
+
+  class Private;
+  Private * const p;
+};
+
+#endif

=== modified file 'kdeui/CMakeLists.txt'
--- kdeui/CMakeLists.txt	2007-08-13 21:05:47 +0000
+++ kdeui/CMakeLists.txt	2007-08-18 16:23:30 +0000
@@ -111,6 +111,7 @@
  kernel/kclipboard.cpp
  kernel/kuniqueapplication.cpp
  kernel/ksessionmanager.cpp
+ kernel/kshortcutassistant.cpp
  kernel/kstartupinfo.cpp
  kernel/kglobalsettings.cpp
  paged/kpagedialog.cpp
@@ -363,6 +364,7 @@
  kernel/kapplication.h
  kernel/kuniqueapplication.h
  kernel/ksessionmanager.h
+ kernel/kshortcutassistant.h
  kernel/kstartupinfo.h
  kernel/kglobalsettings.h
  paged/kpagedialog.h

=== modified file 'kdeui/kernel/kapplication.cpp'
--- kdeui/kernel/kapplication.cpp	2007-08-05 07:49:38 +0000
+++ kdeui/kernel/kapplication.cpp	2007-08-18 16:33:47 +0000
@@ -53,6 +53,7 @@
 #include "ksessionmanager.h"
 #include "kstandarddirs.h"
 #include "kstandardshortcut.h"
+#include "kshortcutassistant.h"
 #include "ktoolinvocation.h"
 #include "kgesturemap.h"
 #include "kurl.h"
@@ -160,6 +161,7 @@
   Private(const QByteArray &cName)
       : componentData(cName),
       checkAccelerators(0),
+      shortcutAssistant(0),
       startup_id("0"),
       app_started_timer(0),
       session_save(false)
@@ -176,6 +178,7 @@
   Private(const KComponentData &cData)
       : componentData(cData),
       checkAccelerators(0),
+      shortcutAssistant(0),
       startup_id("0"),
       app_started_timer(0),
       session_save(false)
@@ -192,6 +195,7 @@
   Private()
       : componentData(KCmdLineArgs::aboutData()),
       checkAccelerators(0),
+      shortcutAssistant(0),
       startup_id( "0" ),
       app_started_timer( 0 ),
       session_save( false )
@@ -211,6 +215,7 @@
 
   KComponentData componentData;
   KCheckAccelerators* checkAccelerators;
+  KShortcutAssistant* shortcutAssistant;
   QByteArray startup_id;
   QTimer* app_started_timer;
   bool session_save;
@@ -277,6 +282,7 @@
 bool KApplication::notify(QObject *receiver, QEvent *event)
 {
     QEvent::Type t = event->type();
+    QKeyEvent *ke;
     if( t == QEvent::Show && receiver->isWidgetType())
     {
         QWidget* w = static_cast< QWidget* >( receiver );
@@ -296,7 +302,13 @@
                 d->app_started_timer->start( 0 );
             }
         }
+    } else if ( (ke = dynamic_cast<QKeyEvent*>(event)) && ke->key() == \
Qt::Key_Control ) { +        if (t == QEvent::KeyPress)
+            d->shortcutAssistant->show();
+        else if (t == QEvent::KeyRelease)
+            d->shortcutAssistant->hide();
     }
+    
     return QApplication::notify(receiver, event);
 }
 
@@ -577,6 +589,7 @@
     KMessage::setMessageHandler( new KMessageBoxMessageHandler(0) );
 
     d->checkAccelerators = new KCheckAccelerators( this );
+    d->shortcutAssistant = new KShortcutAssistant();
     KGestureMap::self()->installEventFilterOnMe( this );
 
     connect(KToolInvocation::self(), \
SIGNAL(kapplication_hook(QStringList&, QByteArray&)), 




>> Visit http://mail.kde.org/mailman/listinfo/kde-devel#unsub to unsubscribe <<


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic