summaryrefslogtreecommitdiff
authorzecke <zecke>2004-08-24 13:38:23 (UTC)
committer zecke <zecke>2004-08-24 13:38:23 (UTC)
commit0a141c4a9719aa273867ad45c4293208545489b1 (patch) (side-by-side diff)
tree4059ae180d00d33cc31dd9083d38a14b946253a2
parent102bb2b65c71da12c4f9f1ce7a5d1b37b6eb50ee (diff)
downloadopie-0a141c4a9719aa273867ad45c4293208545489b1.zip
opie-0a141c4a9719aa273867ad45c4293208545489b1.tar.gz
opie-0a141c4a9719aa273867ad45c4293208545489b1.tar.bz2
Add RightOn Hold Visual Feedback and integrate it
into QPEApplication Icons and Config Option will be comitted by WIMPIE
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--library/backend/rohfeedback.cpp125
-rw-r--r--library/backend/rohfeedback.h62
-rw-r--r--library/qpeapplication.cpp32
3 files changed, 216 insertions, 3 deletions
diff --git a/library/backend/rohfeedback.cpp b/library/backend/rohfeedback.cpp
new file mode 100644
index 0000000..ff76a36
--- a/dev/null
+++ b/library/backend/rohfeedback.cpp
@@ -0,0 +1,125 @@
+#include <rohfeedback.h>
+
+
+#include <stdio.h>
+#include <qpeapplication.h>
+#include <qevent.h>
+#include <resource.h>
+#include <qpixmap.h>
+#include <qbitmap.h>
+
+#define SPEED 600
+#define DELAY 500
+
+namespace Opie {
+namespace Internal {
+/*
+
+ RightOnHold feedback
+
+*/
+
+QPixmap * RoHFeedback::Imgs[NOOFICONS] = { 0, 0, 0, 0, 0 };
+QBitmap * RoHFeedback::Masks[NOOFICONS];
+int RoHFeedback::IconWidth;
+int RoHFeedback::IconHeight;
+
+RoHFeedback::RoHFeedback() :
+ QLabel( 0, 0, Qt::WType_Popup ), Timer() {
+
+ Receiver = 0l;
+ connect( &Timer, SIGNAL( timeout() ), this, SLOT( iconShow() ) );
+
+ if( Imgs[0] == 0 ) {
+ QString S;
+
+
+ for( int i = 0; i < NOOFICONS ; i ++ ) {
+ Imgs[i] = new QPixmap( Resource::loadPixmap("RoH/star/"+
+ QString::number(i+1) +
+ ".png" ));
+ Masks[i] = new QBitmap();
+ (*Masks[i]) = Resource::loadPixmap("RoH/star/"+QString::number(i+1) +
+ ".png" );
+ }
+ }
+
+ IconWidth = Imgs[0]->size().width();
+ IconHeight = Imgs[0]->size().height();
+
+ resize( IconWidth, IconHeight );
+}
+
+int RoHFeedback::delay( void ) {
+ return DELAY+SPEED+50;
+}
+
+RoHFeedback::~RoHFeedback() {
+ for ( int i = 0; i < NOOFICONS; ++i ) {
+ delete Imgs [i];
+ delete Masks[i];
+ }
+}
+
+void RoHFeedback::init( const QPoint & P, QWidget* wid ) {
+ if( ! IconWidth )
+ return;
+
+ Receiver = wid;
+ IconNr = -1;
+ move( P.x()-IconWidth/2, P.y() - IconHeight/2 );
+ // to initialize
+ Timer.start( DELAY - SPEED/NOOFICONS );
+}
+
+void RoHFeedback::stop( void ) {
+ IconNr = -2; // stop
+ hide();
+ Timer.stop();
+}
+
+bool RoHFeedback::event( QEvent * E ) {
+
+ if( E->type() >= QEvent::MouseButtonPress &&
+ E->type() <= QEvent::MouseMove ) {
+ // pass the event to the receiver with translated coord
+ QMouseEvent QME( ((QMouseEvent *)E)->type(),
+ Receiver->mapFromGlobal(
+ ((QMouseEvent *)E)->globalPos() ),
+ ((QMouseEvent *)E)->globalPos(),
+ ((QMouseEvent *)E)->button(),
+ ((QMouseEvent *)E)->state()
+ );
+ return QPEApplication::sendEvent( Receiver, &QME );
+ }
+
+ // first let the label treat the event
+ return QLabel::event( E );
+}
+
+void RoHFeedback::iconShow( void ) {
+ switch( IconNr ) {
+ case FeedbackTimerStart:
+ IconNr = 0;
+ Timer.start( SPEED/NOOFICONS );
+ break;
+ case FeedbackStopped:
+ // stopped
+ IconNr = FeedbackTimerStart;
+ hide();
+ break;
+ case FeedbackShow: // first
+ show();
+ // FT
+ default :
+ // show
+
+ setPixmap( *(Imgs[IconNr]) );
+ setMask( *(Masks[IconNr]) );
+ IconNr = (IconNr+1)%NOOFICONS; // rotate
+ break;
+ }
+}
+
+}
+} \ No newline at end of file
diff --git a/library/backend/rohfeedback.h b/library/backend/rohfeedback.h
new file mode 100644
index 0000000..f38a095
--- a/dev/null
+++ b/library/backend/rohfeedback.h
@@ -0,0 +1,62 @@
+#ifndef ROHFEEDBACK_H
+#define ROHFEEDBACK_H
+
+/*
+
+ RightOnHold feedback show
+
+*/
+
+#define NOOFICONS 5
+
+#include <qlabel.h>
+#include <qtimer.h>
+
+class QEvent;
+class QPixmap;
+class QBitmap;
+class QMouseEvent;
+
+namespace Opie {
+namespace Internal {
+
+class RoHFeedback : public QLabel {
+
+ Q_OBJECT
+
+ enum Actions {
+ FeedbackStopped = -2,
+ FeedbackTimerStart = -1,
+ FeedbackShow = 0
+ };
+public :
+
+ RoHFeedback();
+ ~RoHFeedback();
+
+
+ void init( const QPoint & P, QWidget* wid );
+ void stop( void );
+ int delay( void );
+
+public slots :
+
+ void iconShow( void );
+
+protected :
+
+ bool event( QEvent * E );
+
+ QTimer Timer;
+ int IconNr;
+ QWidget * Receiver;
+
+ static int IconWidth;
+ static int IconHeight;
+ static QPixmap * Imgs[NOOFICONS];
+ static QBitmap * Masks[NOOFICONS];
+};
+}
+}
+
+#endif
diff --git a/library/qpeapplication.cpp b/library/qpeapplication.cpp
index 59ca61b..acad81d 100644
--- a/library/qpeapplication.cpp
+++ b/library/qpeapplication.cpp
@@ -52,125 +52,130 @@
#include <qtooltip.h>
#include <qsignal.h>
#include <qmainwindow.h>
#include <qwidgetlist.h>
#include <qpixmapcache.h>
#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
#define QTOPIA_INTERNAL_INITAPP
#include "qpeapplication.h"
#include "qpestyle.h"
#include "styleinterface.h"
#if QT_VERSION >= 300
#include <qstylefactory.h>
#else
#include <qplatinumstyle.h>
#include <qwindowsstyle.h>
#include <qmotifstyle.h>
#include <qmotifplusstyle.h>
#include "lightstyle.h"
#include <qpe/qlibrary.h>
#endif
#include "global.h"
#include "resource.h"
#if QT_VERSION <= 230 && defined(QT_NO_CODECS)
#include "qutfcodec.h"
#endif
#include "config.h"
#include "network.h"
#ifdef QWS
#include "fontmanager.h"
#include "fontdatabase.h"
#endif
#include "alarmserver.h"
#include "applnk.h"
#include "qpemenubar.h"
#include "textcodecinterface.h"
#include "imagecodecinterface.h"
#include <unistd.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#ifndef QT_NO_SOUND
#include <sys/soundcard.h>
#endif
#include "qt_override_p.h"
+#include <qpe/rohfeedback.h>
+
+
static bool useBigPixmaps = 0;
+
class HackWidget : public QWidget
{
public:
bool needsOk()
{ return (getWState() & WState_Reserved1 ); }
QRect normalGeometry()
{ return topData()->normalGeometry; };
};
class QPEApplicationData
{
public:
QPEApplicationData ( )
: presstimer( 0 ), presswidget( 0 ), rightpressed( false ), kbgrabbed( false ),
notbusysent( false ), preloaded( false ), forceshow( false ), nomaximize( false ),
keep_running( true ), qcopQok( false ),
fontFamily( "Vera" ), fontSize( 10 ), smallIconSize( 14 ),
bigIconSize( 32 ), qpe_main_widget( 0 )
{
Config cfg( "qpe" );
cfg.setGroup( "Appearance" );
useBigPixmaps = cfg.readBoolEntry( "useBigPixmaps", false );
fontFamily = cfg.readEntry( "FontFamily", "Vera" );
fontSize = cfg.readNumEntry( "FontSize", 10 );
smallIconSize = cfg.readNumEntry( "SmallIconSize", 14 );
bigIconSize = cfg.readNumEntry( "BigIconSize", 32 );
+ RoH = 0;
}
int presstimer;
QWidget* presswidget;
QPoint presspos;
bool rightpressed : 1;
bool kbgrabbed : 1;
bool notbusysent : 1;
bool preloaded : 1;
bool forceshow : 1;
bool nomaximize : 1;
bool keep_running : 1;
bool qcopQok : 1;
QCString fontFamily;
int fontSize;
int smallIconSize;
int bigIconSize;
QStringList langs;
QString appName;
struct QCopRec
{
QCopRec( const QCString &ch, const QCString &msg,
const QByteArray &d ) :
channel( ch ), message( msg ), data( d )
{ }
QCString channel;
QCString message;
QByteArray data;
};
QWidget* qpe_main_widget;
QGuardedPtr<QWidget> lastraised;
QQueue<QCopRec> qcopq;
QString styleName;
QString decorationName;
void enqueueQCop( const QCString &ch, const QCString &msg,
const QByteArray &data )
{
qcopq.enqueue( new QCopRec( ch, msg, data ) );
}
void sendQCopQ()
{
if (!qcopQok )
return;
@@ -447,96 +452,98 @@ static void qpe_show_dialog( QDialog* d, bool nomax )
if ( dir. exists ( ))
list = dir.entryList();
QStringList::Iterator it;
for ( it = list.begin(); it != list.end(); ++it ) {
TextCodecInterface *iface = 0;
QLibrary *lib = new QLibrary( path + "/" + *it );
if ( lib->queryInterface( IID_QtopiaTextCodec, (QUnknownInterface**)&iface ) == QS_OK && iface ) {
QValueList<int> mibs = iface->mibEnums();
for (QValueList<int>::ConstIterator i = mibs.begin(); i != mibs.end(); ++i) {
(void)iface->createForMib(*i);
// ### it exists now; need to remember if we can delete it
}
}
else {
lib->unload();
delete lib;
}
}
}
void loadImageCodecs()
{
QString path = QPEApplication::qpeDir() + "/plugins/imagecodecs";
#ifdef Q_OS_MACX
QDir dir( path, "lib*.dylib" );
#else
QDir dir( path, "lib*.so" );
#endif
QStringList list;
if ( dir. exists ( ))
list = dir.entryList();
QStringList::Iterator it;
for ( it = list.begin(); it != list.end(); ++it ) {
ImageCodecInterface *iface = 0;
QLibrary *lib = new QLibrary( path + "/" + *it );
if ( lib->queryInterface( IID_QtopiaImageCodec, (QUnknownInterface**)&iface ) == QS_OK && iface ) {
QStringList formats = iface->keys();
for (QStringList::ConstIterator i = formats.begin(); i != formats.end(); ++i) {
(void)iface->installIOHandler(*i);
// ### it exists now; need to remember if we can delete it
}
}
else {
lib->unload();
delete lib;
}
}
}
+
+ Opie::Internal::RoHFeedback * RoH;
};
class ResourceMimeFactory : public QMimeSourceFactory
{
public:
ResourceMimeFactory() : resImage( 0 )
{
setFilePath( Global::helpPath() );
setExtensionType( "html", "text/html;charset=UTF-8" );
}
~ResourceMimeFactory() {
delete resImage;
}
const QMimeSource* data( const QString& abs_name ) const
{
const QMimeSource * r = QMimeSourceFactory::data( abs_name );
if ( !r ) {
int sl = abs_name.length();
do {
sl = abs_name.findRev( '/', sl - 1 );
QString name = sl >= 0 ? abs_name.mid( sl + 1 ) : abs_name;
int dot = name.findRev( '.' );
if ( dot >= 0 )
name = name.left( dot );
QImage img = Resource::loadImage( name );
if ( !img.isNull() ) {
delete resImage;
resImage = new QImageDrag( img );
r = resImage;
}
}
while ( !r && sl > 0 );
}
return r;
}
private:
mutable QImageDrag *resImage;
};
static int& hack(int& i)
{
#if QT_VERSION <= 230 && defined(QT_NO_CODECS)
// These should be created, but aren't in Qt 2.3.0
(void)new QUtf8Codec;
(void)new QUtf16Codec;
#endif
return i;
@@ -1160,97 +1167,97 @@ bool QPEApplication::qwsEventFilter( QWSEvent * e )
e << int( ke-> simpleData.keycode ) << int( ke-> simpleData. is_press ) << int( ke-> simpleData.is_auto_repeat );
}
}
return true;
}
}
if ( e->type == QWSEvent::Focus ) {
QWSFocusEvent * fe = ( QWSFocusEvent* ) e;
if ( !fe->simpleData.get_focus ) {
QWidget * active = activeWindow();
while ( active && active->isPopup() ) {
active->close();
active = activeWindow();
}
}
else {
// make sure our modal widget is ALWAYS on top
QWidget *topm = activeModalWidget();
if ( topm && static_cast<int>( topm->winId() ) != fe->simpleData.window) {
topm->raise();
}
}
if ( fe->simpleData.get_focus && inputMethodDict ) {
InputMethodHint m = inputMethodHint( QWidget::find( e->window() ) );
if ( m == AlwaysOff )
Global::hideInputMethod();
if ( m == AlwaysOn )
Global::showInputMethod();
}
}
return QApplication::qwsEventFilter( e );
}
#endif
/*!
Destroys the QPEApplication.
*/
QPEApplication::~QPEApplication()
{
ungrabKeyboard();
#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
// Need to delete QCopChannels early, since the display will
// be gone by the time we get to ~QObject().
delete sysChannel;
delete pidChannel;
#endif
-
+ delete d->RoH;
delete d;
}
/*!
Returns <tt>$OPIEDIR/</tt>.
*/
QString QPEApplication::qpeDir()
{
const char * base = getenv( "OPIEDIR" );
if ( base )
return QString( base ) + "/";
return QString( "../" );
}
/*!
Returns the user's current Document directory. There is a trailing "/".
.. well, it does now,, and there's no trailing '/'
*/
QString QPEApplication::documentDir()
{
const char* base = getenv( "HOME");
if ( base )
return QString( base ) + "/Documents";
return QString( "../Documents" );
}
static int deforient = -1;
/*!
\internal
*/
int QPEApplication::defaultRotation()
{
if ( deforient < 0 ) {
QString d = getenv( "QWS_DISPLAY" );
if ( d.contains( "Rot90" ) ) {
deforient = 90;
}
else if ( d.contains( "Rot180" ) ) {
deforient = 180;
}
else if ( d.contains( "Rot270" ) ) {
deforient = 270;
}
else {
deforient = 0;
@@ -1978,166 +1985,185 @@ QPEApplication::StylusMode QPEApplication::stylusOperation( QWidget* w )
\enum QPEApplication::StylusMode
\value LeftOnly the stylus only generates LeftButton
events (the default).
\value RightOnHold the stylus generates RightButton events
if the user uses the press-and-hold gesture.
\sa setStylusOperation() stylusOperation()
*/
/*!
Causes widget \a w to receive mouse events according to the stylus
\a mode.
\sa stylusOperation() StylusMode
*/
void QPEApplication::setStylusOperation( QWidget * w, StylusMode mode )
{
createDict();
if ( mode == LeftOnly ) {
stylusDict->remove
( w );
w->removeEventFilter( qApp );
}
else {
stylusDict->insert( w, ( void* ) mode );
connect( w, SIGNAL( destroyed() ), qApp, SLOT( removeSenderFromStylusDict() ) );
w->installEventFilter( qApp );
}
}
/*!
\reimp
*/
bool QPEApplication::eventFilter( QObject *o, QEvent *e )
{
if ( !o->isWidgetType() )
return FALSE;
if ( stylusDict && e->type() >= QEvent::MouseButtonPress && e->type() <= QEvent::MouseMove ) {
QMouseEvent * me = ( QMouseEvent* ) e;
StylusMode mode = (StylusMode)(int)stylusDict->find(o);
switch (mode) {
case RightOnHold:
switch ( me->type() ) {
case QEvent::MouseButtonPress:
if ( me->button() == LeftButton ) {
- if (!d->presstimer )
- d->presstimer = startTimer(500); // #### pref.
d->presswidget = (QWidget*)o;
d->presspos = me->pos();
d->rightpressed = FALSE;
+ // just for the time being
+ static int pref = 500;
+#ifdef WITHROHFEEDBACK
+ if( ! d->RoH )
+ d->RoH = new Opie::Internal::RoHFeedback;
+
+ d->RoH->init( me->globalPos(), d->presswidget );
+ pref = d->RoH->delay();
+#endif
+ if (!d->presstimer )
+ d->presstimer = startTimer( pref ); // #### pref.
+
}
break;
case QEvent::MouseMove:
if (d->presstimer && (me->pos() - d->presspos).manhattanLength() > 8) {
killTimer(d->presstimer);
+#ifdef WITHROHFEEDBACK
+ if( d->RoH )
+ d->RoH->stop( );
+#endif
d->presstimer = 0;
}
break;
case QEvent::MouseButtonRelease:
if ( me->button() == LeftButton ) {
if ( d->presstimer ) {
killTimer(d->presstimer);
+#ifdef WITHROHFEEDBACK
+ if( d->RoH )
+ d->RoH->stop( );
+#endif
d->presstimer = 0;
}
if ( d->rightpressed && d->presswidget ) {
// Right released
postEvent( d->presswidget,
new QMouseEvent( QEvent::MouseButtonRelease, me->pos(),
RightButton, LeftButton + RightButton ) );
// Left released, off-widget
postEvent( d->presswidget,
new QMouseEvent( QEvent::MouseMove, QPoint( -1, -1),
LeftButton, LeftButton ) );
postEvent( d->presswidget,
new QMouseEvent( QEvent::MouseButtonRelease, QPoint( -1, -1),
LeftButton, LeftButton ) );
d->rightpressed = FALSE;
return TRUE; // don't send the real Left release
}
}
break;
default:
break;
}
break;
default:
;
}
}
else if ( e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease ) {
QKeyEvent *ke = (QKeyEvent *)e;
if ( ke->key() == Key_Enter ) {
if ( o->isA( "QRadioButton" ) || o->isA( "QCheckBox" ) ) {
postEvent( o, new QKeyEvent( e->type(), Key_Space, ' ',
ke->state(), " ", ke->isAutoRepeat(), ke->count() ) );
return TRUE;
}
}
}
return FALSE;
}
/*!
\reimp
*/
void QPEApplication::timerEvent( QTimerEvent *e )
{
if ( e->timerId() == d->presstimer && d->presswidget ) {
// Right pressed
postEvent( d->presswidget,
new QMouseEvent( QEvent::MouseButtonPress, d->presspos,
RightButton, LeftButton ) );
killTimer( d->presstimer );
d->presstimer = 0;
d->rightpressed = TRUE;
+ d->RoH->stop();
}
}
void QPEApplication::removeSenderFromStylusDict()
{
stylusDict->remove
( ( void* ) sender() );
if ( d->presswidget == sender() )
d->presswidget = 0;
}
/*!
\internal
*/
bool QPEApplication::keyboardGrabbed() const
{
return d->kbgrabbed;
}
/*!
Reverses the effect of grabKeyboard(). This is called automatically
on program exit.
*/
void QPEApplication::ungrabKeyboard()
{
((QPEApplication *) qApp )-> d-> kbgrabbed = false;
}
/*!
Grabs the physical keyboard keys, e.g. the application's launching
keys. Instead of launching applications when these keys are pressed
the signals emitted are sent to this application instead. Some games
programs take over the launch keys in this way to make interaction
easier.
\sa ungrabKeyboard()
*/
void QPEApplication::grabKeyboard()
{
((QPEApplication *) qApp )-> d-> kbgrabbed = true;
}
/*!
\reimp
*/
int QPEApplication::exec()
{