finishing up repo migration

git-svn-id: svn://svn.code.sf.net/p/qjoypad/code/trunk@80 c05e91a0-76c8-4ec0-b377-ef19ce7cc080
This commit is contained in:
John Toman
2009-05-26 00:45:05 +00:00
committed by virtuoussin13
commit 1cc6e9087e
59 changed files with 6563 additions and 0 deletions

30
src/.kdbgrc.qjoypad Normal file
View File

@ -0,0 +1,30 @@
[Breakpoint 0]
Enabled=true
File=layout.cpp
Line=263
Temporary=false
[Breakpoint 1]
Enabled=true
File=moc_layout_edit.cpp
Line=58
Temporary=false
[Breakpoint 2]
Enabled=true
File=layout_edit.cpp
Line=107
Temporary=false
[General]
DebuggerCmdStr=
DriverName=GDB
FileVersion=1
OptionsSelected=
ProgramArgs=
TTYLevel=7
WorkingDirectory=
[Memory]
ColumnWidths=80,0
NumExprs=0

590
src/Makefile Normal file
View File

@ -0,0 +1,590 @@
#############################################################################
# Makefile for building: qjoypad
# Generated by qmake (2.01a) (Qt 4.5.1) on: Mon May 25 00:43:37 2009
# Project: qjoypad.pro
# Template: app
# Command: /usr/bin/qmake -unix -o Makefile qjoypad.pro
#############################################################################
####### Compiler, tools and options
CC = gcc
CXX = g++
DEFINES = -DDEVDIR="" -DICON24="/share/pixmaps/qjoypad/icon24.png" -DICON64="/share/pixmaps/qjoypad/icon64.png" -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED
CFLAGS = -pipe -march=i686 -mtune=generic -O2 -pipe -Wall -W -D_REENTRANT $(DEFINES)
CXXFLAGS = -pipe -march=i686 -mtune=generic -O2 -pipe -Wall -W -D_REENTRANT $(DEFINES)
INCPATH = -I/usr/share/qt/mkspecs/linux-g++ -I. -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include -I. -Itrayicon -I. -I.
LINK = g++
LFLAGS = -Wl,-O1 -Wl,-rpath,/usr/lib
LIBS = $(SUBLIBS) -L/usr/lib -lXtst -lQtGui -L/usr/lib -L/usr/X11R6/lib -pthread -lpng -lfreetype -lgobject-2.0 -lSM -lICE -pthread -pthread -lXrender -lfontconfig -lXext -lX11 -lQtCore -lz -lm -pthread -lgthread-2.0 -lrt -lglib-2.0 -ldl -lpthread
AR = ar cqs
RANLIB =
QMAKE = /usr/bin/qmake
TAR = tar -cf
COMPRESS = gzip -9f
COPY = cp -f
SED = sed
COPY_FILE = $(COPY)
COPY_DIR = $(COPY) -r
INSTALL_FILE = install -m 644 -p
INSTALL_DIR = $(COPY_DIR)
INSTALL_PROGRAM = install -m 755 -p
DEL_FILE = rm -f
SYMLINK = ln -sf
DEL_DIR = rmdir
MOVE = mv -f
CHK_DIR_EXISTS= test -d
MKDIR = mkdir -p
####### Output directory
OBJECTS_DIR = ./
####### Files
SOURCES = axis.cpp \
axis_edit.cpp \
axisw.cpp \
button.cpp \
button_edit.cpp \
buttonw.cpp \
event.cpp \
flash.cpp \
icon.cpp \
joypad.cpp \
joypadw.cpp \
joyslider.cpp \
keycode.cpp \
layout.cpp \
layout_edit.cpp \
main.cpp \
quickset.cpp \
getkey.cpp \
trayicon/trayicon.cpp \
trayicon/trayicon_x11.cpp moc_axis.cpp \
moc_axis_edit.cpp \
moc_button.cpp \
moc_button_edit.cpp \
moc_flash.cpp \
moc_icon.cpp \
moc_joypad.cpp \
moc_joypadw.cpp \
moc_keycode.cpp \
moc_layout.cpp \
moc_getkey.cpp \
moc_trayicon.cpp
OBJECTS = axis.o \
axis_edit.o \
axisw.o \
button.o \
button_edit.o \
buttonw.o \
event.o \
flash.o \
icon.o \
joypad.o \
joypadw.o \
joyslider.o \
keycode.o \
layout.o \
layout_edit.o \
main.o \
quickset.o \
getkey.o \
trayicon.o \
trayicon_x11.o \
moc_axis.o \
moc_axis_edit.o \
moc_button.o \
moc_button_edit.o \
moc_flash.o \
moc_icon.o \
moc_joypad.o \
moc_joypadw.o \
moc_keycode.o \
moc_layout.o \
moc_getkey.o \
moc_trayicon.o
DIST = /usr/share/qt/mkspecs/common/g++.conf \
/usr/share/qt/mkspecs/common/unix.conf \
/usr/share/qt/mkspecs/common/linux.conf \
/usr/share/qt/mkspecs/qconfig.pri \
/usr/share/qt/mkspecs/features/qt_functions.prf \
/usr/share/qt/mkspecs/features/qt_config.prf \
/usr/share/qt/mkspecs/features/exclusive_builds.prf \
/usr/share/qt/mkspecs/features/default_pre.prf \
/usr/share/qt/mkspecs/features/release.prf \
/usr/share/qt/mkspecs/features/default_post.prf \
/usr/share/qt/mkspecs/features/warn_on.prf \
/usr/share/qt/mkspecs/features/qt.prf \
/usr/share/qt/mkspecs/features/unix/thread.prf \
/usr/share/qt/mkspecs/features/moc.prf \
/usr/share/qt/mkspecs/features/resources.prf \
/usr/share/qt/mkspecs/features/uic.prf \
/usr/share/qt/mkspecs/features/yacc.prf \
/usr/share/qt/mkspecs/features/lex.prf \
/usr/share/qt/mkspecs/features/include_source_dir.prf \
qjoypad.pro
QMAKE_TARGET = qjoypad
DESTDIR =
TARGET = qjoypad
first: all
####### Implicit rules
.SUFFIXES: .o .c .cpp .cc .cxx .C
.cpp.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
.cc.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
.cxx.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
.C.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
.c.o:
$(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<"
####### Build rules
all: Makefile $(TARGET)
$(TARGET): $(OBJECTS)
$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)
Makefile: qjoypad.pro /usr/share/qt/mkspecs/linux-g++/qmake.conf /usr/share/qt/mkspecs/common/g++.conf \
/usr/share/qt/mkspecs/common/unix.conf \
/usr/share/qt/mkspecs/common/linux.conf \
/usr/share/qt/mkspecs/qconfig.pri \
/usr/share/qt/mkspecs/features/qt_functions.prf \
/usr/share/qt/mkspecs/features/qt_config.prf \
/usr/share/qt/mkspecs/features/exclusive_builds.prf \
/usr/share/qt/mkspecs/features/default_pre.prf \
/usr/share/qt/mkspecs/features/release.prf \
/usr/share/qt/mkspecs/features/default_post.prf \
/usr/share/qt/mkspecs/features/warn_on.prf \
/usr/share/qt/mkspecs/features/qt.prf \
/usr/share/qt/mkspecs/features/unix/thread.prf \
/usr/share/qt/mkspecs/features/moc.prf \
/usr/share/qt/mkspecs/features/resources.prf \
/usr/share/qt/mkspecs/features/uic.prf \
/usr/share/qt/mkspecs/features/yacc.prf \
/usr/share/qt/mkspecs/features/lex.prf \
/usr/share/qt/mkspecs/features/include_source_dir.prf \
/usr/lib/libQtGui.prl \
/usr/lib/libQtCore.prl
$(QMAKE) -unix -o Makefile qjoypad.pro
/usr/share/qt/mkspecs/common/g++.conf:
/usr/share/qt/mkspecs/common/unix.conf:
/usr/share/qt/mkspecs/common/linux.conf:
/usr/share/qt/mkspecs/qconfig.pri:
/usr/share/qt/mkspecs/features/qt_functions.prf:
/usr/share/qt/mkspecs/features/qt_config.prf:
/usr/share/qt/mkspecs/features/exclusive_builds.prf:
/usr/share/qt/mkspecs/features/default_pre.prf:
/usr/share/qt/mkspecs/features/release.prf:
/usr/share/qt/mkspecs/features/default_post.prf:
/usr/share/qt/mkspecs/features/warn_on.prf:
/usr/share/qt/mkspecs/features/qt.prf:
/usr/share/qt/mkspecs/features/unix/thread.prf:
/usr/share/qt/mkspecs/features/moc.prf:
/usr/share/qt/mkspecs/features/resources.prf:
/usr/share/qt/mkspecs/features/uic.prf:
/usr/share/qt/mkspecs/features/yacc.prf:
/usr/share/qt/mkspecs/features/lex.prf:
/usr/share/qt/mkspecs/features/include_source_dir.prf:
/usr/lib/libQtGui.prl:
/usr/lib/libQtCore.prl:
qmake: FORCE
@$(QMAKE) -unix -o Makefile qjoypad.pro
dist:
@$(CHK_DIR_EXISTS) .tmp/qjoypad1.0.0 || $(MKDIR) .tmp/qjoypad1.0.0
$(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/qjoypad1.0.0/ && $(COPY_FILE) --parents axis.h axis_edit.h axisw.h button.h button_edit.h buttonw.h constant.h device.h error.h event.h flash.h icon.h joypad.h joypadw.h joyslider.h keycode.h layout.h getkey.h layout_edit.h quickset.h trayicon/trayicon.h .tmp/qjoypad1.0.0/ && $(COPY_FILE) --parents axis.cpp axis_edit.cpp axisw.cpp button.cpp button_edit.cpp buttonw.cpp event.cpp flash.cpp icon.cpp joypad.cpp joypadw.cpp joyslider.cpp keycode.cpp layout.cpp layout_edit.cpp main.cpp quickset.cpp getkey.cpp trayicon/trayicon.cpp trayicon/trayicon_x11.cpp .tmp/qjoypad1.0.0/ && (cd `dirname .tmp/qjoypad1.0.0` && $(TAR) qjoypad1.0.0.tar qjoypad1.0.0 && $(COMPRESS) qjoypad1.0.0.tar) && $(MOVE) `dirname .tmp/qjoypad1.0.0`/qjoypad1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/qjoypad1.0.0
clean:compiler_clean
-$(DEL_FILE) $(OBJECTS)
-$(DEL_FILE) *~ core *.core
####### Sub-libraries
distclean: clean
-$(DEL_FILE) $(TARGET)
-$(DEL_FILE) Makefile
mocclean: compiler_moc_header_clean compiler_moc_source_clean
mocables: compiler_moc_header_make_all compiler_moc_source_make_all
compiler_moc_header_make_all: moc_axis.cpp moc_axis_edit.cpp moc_button.cpp moc_button_edit.cpp moc_flash.cpp moc_icon.cpp moc_joypad.cpp moc_joypadw.cpp moc_keycode.cpp moc_layout.cpp moc_getkey.cpp moc_trayicon.cpp
compiler_moc_header_clean:
-$(DEL_FILE) moc_axis.cpp moc_axis_edit.cpp moc_button.cpp moc_button_edit.cpp moc_flash.cpp moc_icon.cpp moc_joypad.cpp moc_joypadw.cpp moc_keycode.cpp moc_layout.cpp moc_getkey.cpp moc_trayicon.cpp
moc_axis.cpp: constant.h \
axis.h
/usr/bin/moc $(DEFINES) $(INCPATH) axis.h -o moc_axis.cpp
moc_axis_edit.cpp: axis.h \
constant.h \
joyslider.h \
keycode.h \
axis_edit.h
/usr/bin/moc $(DEFINES) $(INCPATH) axis_edit.h -o moc_axis_edit.cpp
moc_button.cpp: keycode.h \
constant.h \
button.h
/usr/bin/moc $(DEFINES) $(INCPATH) button.h -o moc_button.cpp
moc_button_edit.cpp: button.h \
keycode.h \
constant.h \
button_edit.h
/usr/bin/moc $(DEFINES) $(INCPATH) button_edit.h -o moc_button_edit.cpp
moc_flash.cpp: flash.h
/usr/bin/moc $(DEFINES) $(INCPATH) flash.h -o moc_flash.cpp
moc_icon.cpp: constant.h \
icon.h
/usr/bin/moc $(DEFINES) $(INCPATH) icon.h -o moc_icon.cpp
moc_joypad.cpp: button.h \
keycode.h \
constant.h \
axis.h \
joypadw.h \
axisw.h \
flash.h \
axis_edit.h \
joyslider.h \
joypad.h \
error.h \
buttonw.h \
button_edit.h \
quickset.h \
joypad.h
/usr/bin/moc $(DEFINES) $(INCPATH) joypad.h -o moc_joypad.cpp
moc_joypadw.cpp: axisw.h \
axis.h \
constant.h \
flash.h \
axis_edit.h \
joyslider.h \
keycode.h \
joypad.h \
button.h \
joypadw.h \
buttonw.h \
button_edit.h \
quickset.h \
error.h \
joypadw.h
/usr/bin/moc $(DEFINES) $(INCPATH) joypadw.h -o moc_joypadw.cpp
moc_keycode.cpp: constant.h \
keycode.h
/usr/bin/moc $(DEFINES) $(INCPATH) keycode.h -o moc_keycode.cpp
moc_layout.cpp: joypad.h \
button.h \
keycode.h \
constant.h \
axis.h \
joypadw.h \
axisw.h \
flash.h \
axis_edit.h \
joyslider.h \
buttonw.h \
button_edit.h \
quickset.h \
error.h \
device.h \
trayicon/trayicon.h \
icon.h \
layout_edit.h \
layout.h \
layout.h
/usr/bin/moc $(DEFINES) $(INCPATH) layout.h -o moc_layout.cpp
moc_getkey.cpp: constant.h \
getkey.h
/usr/bin/moc $(DEFINES) $(INCPATH) getkey.h -o moc_getkey.cpp
moc_trayicon.cpp: trayicon/trayicon.h
/usr/bin/moc $(DEFINES) $(INCPATH) trayicon/trayicon.h -o moc_trayicon.cpp
compiler_rcc_make_all:
compiler_rcc_clean:
compiler_image_collection_make_all: qmake_image_collection.cpp
compiler_image_collection_clean:
-$(DEL_FILE) qmake_image_collection.cpp
compiler_moc_source_make_all:
compiler_moc_source_clean:
compiler_uic_make_all:
compiler_uic_clean:
compiler_yacc_decl_make_all:
compiler_yacc_decl_clean:
compiler_yacc_impl_make_all:
compiler_yacc_impl_clean:
compiler_lex_make_all:
compiler_lex_clean:
compiler_clean: compiler_moc_header_clean
####### Compile
axis.o: axis.cpp axis.h \
constant.h \
event.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o axis.o axis.cpp
axis_edit.o: axis_edit.cpp axis_edit.h \
axis.h \
constant.h \
joyslider.h \
keycode.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o axis_edit.o axis_edit.cpp
axisw.o: axisw.cpp axisw.h \
axis.h \
constant.h \
flash.h \
axis_edit.h \
joyslider.h \
keycode.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o axisw.o axisw.cpp
button.o: button.cpp button.h \
keycode.h \
constant.h \
event.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o button.o button.cpp
button_edit.o: button_edit.cpp button_edit.h \
button.h \
keycode.h \
constant.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o button_edit.o button_edit.cpp
buttonw.o: buttonw.cpp buttonw.h \
button.h \
keycode.h \
constant.h \
button_edit.h \
flash.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o buttonw.o buttonw.cpp
event.o: event.cpp event.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o event.o event.cpp
flash.o: flash.cpp flash.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o flash.o flash.cpp
icon.o: icon.cpp icon.h \
constant.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o icon.o icon.cpp
joypad.o: joypad.cpp joypad.h \
button.h \
keycode.h \
constant.h \
axis.h \
joypadw.h \
axisw.h \
flash.h \
axis_edit.h \
joyslider.h \
buttonw.h \
button_edit.h \
quickset.h \
error.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o joypad.o joypad.cpp
joypadw.o: joypadw.cpp joypadw.h \
axisw.h \
axis.h \
constant.h \
flash.h \
axis_edit.h \
joyslider.h \
keycode.h \
joypad.h \
button.h \
error.h \
buttonw.h \
button_edit.h \
quickset.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o joypadw.o joypadw.cpp
joyslider.o: joyslider.cpp joyslider.h \
constant.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o joyslider.o joyslider.cpp
keycode.o: keycode.cpp keycode.h \
constant.h \
getkey.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o keycode.o keycode.cpp
layout.o: layout.cpp layout.h \
joypad.h \
button.h \
keycode.h \
constant.h \
axis.h \
joypadw.h \
axisw.h \
flash.h \
axis_edit.h \
joyslider.h \
buttonw.h \
button_edit.h \
quickset.h \
error.h \
device.h \
trayicon/trayicon.h \
icon.h \
layout_edit.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o layout.o layout.cpp
layout_edit.o: layout_edit.cpp layout_edit.h \
flash.h \
layout.h \
joypad.h \
button.h \
keycode.h \
constant.h \
axis.h \
joypadw.h \
axisw.h \
axis_edit.h \
joyslider.h \
buttonw.h \
button_edit.h \
quickset.h \
error.h \
device.h \
trayicon/trayicon.h \
icon.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o layout_edit.o layout_edit.cpp
main.o: main.cpp layout.h \
joypad.h \
button.h \
keycode.h \
constant.h \
axis.h \
joypadw.h \
axisw.h \
flash.h \
axis_edit.h \
joyslider.h \
buttonw.h \
button_edit.h \
quickset.h \
error.h \
device.h \
trayicon/trayicon.h \
icon.h \
layout_edit.h \
event.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o main.o main.cpp
quickset.o: quickset.cpp quickset.h \
joypad.h \
button.h \
keycode.h \
constant.h \
axis.h \
joypadw.h \
axisw.h \
flash.h \
axis_edit.h \
joyslider.h \
buttonw.h \
button_edit.h \
error.h \
getkey.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o quickset.o quickset.cpp
getkey.o: getkey.cpp getkey.h \
constant.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o getkey.o getkey.cpp
trayicon.o: trayicon/trayicon.cpp trayicon/trayicon.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o trayicon.o trayicon/trayicon.cpp
trayicon_x11.o: trayicon/trayicon_x11.cpp trayicon/trayicon.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o trayicon_x11.o trayicon/trayicon_x11.cpp
moc_axis.o: moc_axis.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_axis.o moc_axis.cpp
moc_axis_edit.o: moc_axis_edit.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_axis_edit.o moc_axis_edit.cpp
moc_button.o: moc_button.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_button.o moc_button.cpp
moc_button_edit.o: moc_button_edit.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_button_edit.o moc_button_edit.cpp
moc_flash.o: moc_flash.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_flash.o moc_flash.cpp
moc_icon.o: moc_icon.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_icon.o moc_icon.cpp
moc_joypad.o: moc_joypad.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_joypad.o moc_joypad.cpp
moc_joypadw.o: moc_joypadw.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_joypadw.o moc_joypadw.cpp
moc_keycode.o: moc_keycode.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_keycode.o moc_keycode.cpp
moc_layout.o: moc_layout.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_layout.o moc_layout.cpp
moc_getkey.o: moc_getkey.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_getkey.o moc_getkey.cpp
moc_trayicon.o: moc_trayicon.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_trayicon.o moc_trayicon.cpp
####### Install
install_target: first FORCE
@$(CHK_DIR_EXISTS) $(INSTALL_ROOT)/bin/ || $(MKDIR) $(INSTALL_ROOT)/bin/
-$(INSTALL_PROGRAM) "$(QMAKE_TARGET)" "$(INSTALL_ROOT)/bin/$(QMAKE_TARGET)"
-strip "$(INSTALL_ROOT)/bin/$(QMAKE_TARGET)"
uninstall_target: FORCE
-$(DEL_FILE) "$(INSTALL_ROOT)/bin/$(QMAKE_TARGET)"
-$(DEL_DIR) $(INSTALL_ROOT)/bin/
install_icons: first FORCE
@$(CHK_DIR_EXISTS) $(INSTALL_ROOT)/share/pixmaps/qjoypad/ || $(MKDIR) $(INSTALL_ROOT)/share/pixmaps/qjoypad/
cp ../icons/* /share/pixmaps/qjoypad; cd /share/pixmaps/qjoypad; ln -sf gamepad4-24x24.png icon24.png; ln -sf gamepad3-64x64.png icon64.png; chmod -R a+r /share/pixmaps/qjoypad
install_doc: first FORCE
@$(CHK_DIR_EXISTS) $(INSTALL_ROOT)/doc/qjoypad3/ || $(MKDIR) $(INSTALL_ROOT)/doc/qjoypad3/
cp ../README.txt ../LICENSE.txt /doc/qjoypad3
install: install_target install_icons install_doc FORCE
uninstall: uninstall_target FORCE
FORCE:

335
src/axis.cpp Normal file
View File

@ -0,0 +1,335 @@
#include "axis.h"
#include "event.h"
#define sqr(a) ((a)*(a))
Axis::Axis( int i ) {
index = i;
isOn = false;
isDown = false;
state = 0;
gradient = false;
toDefault();
tick = 0;
timer = new QTimer(this);
}
Axis::~Axis() {
release();
delete timer;
}
bool Axis::read( QTextStream* stream ) {
// At this point, toDefault has just been called.
//read in a line from the stream, and split it up into individual words
QString input = stream->readLine().toLower();
QRegExp regex("[\\s,]+");
QStringList words = input.split(regex);
//used to assure QString->int conversions worked
bool ok;
//int to store values derived from strings
int val;
//step through each word, check if it's a token we recognize
for ( QStringList::Iterator it = words.begin(); it != words.end(); ++it ) {
if (*it == "maxspeed") {
++it; //move to the next word, which should be the maximum speed.
//if no value was given, there's an error in the file, stop reading.
if (it == words.end()) return false;
//try to convert the value.
val = (*it).toInt(&ok);
//if that worked and the maximum speed is in range, set it.
if (ok && val >= 0 && val <= MAXMOUSESPEED) maxSpeed = val;
//otherwise, faulty input, give up.
else return false;
}
//pretty much the same process for getting the dead zone
else if (*it == "dzone") {
++it;
if (it == words.end()) return false;
val = (*it).toInt(&ok);
if (ok && val >= 0 && val <= JOYMAX) dZone = val;
else return false;
}
//and again for the extreme zone,
else if (*it == "xzone") {
++it;
if (it == words.end()) return false;
val = (*it).toInt(&ok);
if (ok && val >= 0 && val <= JOYMAX) xZone = val;
else return false;
}
//and for the positive keycode,
else if (*it == "+key") {
++it;
if (it == words.end()) return false;
val = (*it).toInt(&ok);
if (ok && val >= 0 && val <= MAXKEY) pkeycode = val;
else return false;
}
//and finally for the negative keycode.
else if (*it == "-key") {
++it;
if (it == words.end()) return false;
val = (*it).toInt(&ok);
if (ok && val >= 0 && val <= MAXKEY) nkeycode = val;
else return false;
}
//the rest of the options are keywords without integers
else if (*it == "gradient") {
gradient = true;
}
else if (*it == "throttle+") {
throttle = 1;
}
else if (*it == "throttle-") {
throttle = -1;
}
else if (*it == "mouse+v") {
mode = mousepv;
}
else if (*it == "mouse-v") {
mode = mousenv;
}
else if (*it == "mouse+h") {
mode = mouseph;
}
else if (*it == "mouse-h") {
mode = mousenh;
}
//we ignore unrecognized words to be friendly and allow for additions to
//the format in later versions. Note, this means that typos will not get
//the desired effect OR produce an error message.
}
//assume that xZone, dZone, or maxSpeed has changed, for simplicity.
//do a few floating point calculations.
adjustGradient();
//if we parsed through all of the words, yay! All done.
return true;
}
void Axis::timerCalled() {
timerTick(++tick);
}
void Axis::write( QTextStream* stream ) {
*stream << "\t" << getName() << ": ";
if (gradient) *stream << "gradient, ";
if (throttle > 0) *stream << "throttle+, ";
else if (throttle < 0) *stream << "throttle-, ";
if (dZone != DZONE) *stream << "dZone " << dZone << ", ";
if (xZone != XZONE) *stream << "xZone " << xZone << ", ";
if (mode == keybd) {
*stream << "+key " << pkeycode << ", "
<< "-key " << nkeycode << "\n";
}
else {
if (gradient) *stream << "maxSpeed " << maxSpeed << ", ";
*stream << "mouse";
if (mode == mousepv)
*stream << "+v\n";
else if (mode == mousenv)
*stream << "-v\n";
else if (mode == mouseph)
*stream << "+h\n";
else if (mode == mousenh)
*stream << "-h\n";
}
}
void Axis::release() {
//if we're pressing a key, let it go.
if (isDown) {
move(false);
isDown = false;
}
}
void Axis::jsevent( int value ) {
//adjust real value to throttle value
if (throttle == 0)
state = value;
else if (throttle == -1)
state = (value + JOYMIN) / 2;
else
state = (value + JOYMAX) / 2;
//set isOn, deal with state changing.
//if was on but now should be off:
if (isOn && abs(state) <= dZone) {
isOn = false;
if (gradient) {
release();
timer->stop();
tick = 0;
}
}
//if was off but now should be on:
else if (!isOn && abs(state) >= dZone) {
isOn = true;
if (gradient) {
duration = (abs(state) * FREQ) / JOYMAX;
connect(timer, SIGNAL(timeout()), this, SLOT(timerCalled()));
timer->start(MSEC);
}
}
//otherwise, state doesn't change! Don't touch it.
else return;
//gradient will trigger movement on its own via timer().
//non-gradient needs to be told to move.
if (!gradient) {
move(isOn);
}
}
void Axis::toDefault() {
release();
gradient = false;
throttle = 0;
maxSpeed = 100;
dZone = DZONE;
tick = 0;
xZone = XZONE;
mode = keybd;
pkeycode = 0;
nkeycode = 0;
downkey = 0;
state = 0;
adjustGradient();
}
bool Axis::isDefault() {
return (gradient == false) &&
(throttle == 0) &&
(maxSpeed == 100) &&
(dZone == DZONE) &&
(xZone == XZONE) &&
(mode == keybd) &&
(pkeycode == 0) &&
(nkeycode == 0);
}
bool Axis::inDeadZone( int val ) {
int value;
if (throttle == 0)
value = val;
else if (throttle == -1)
value = (val + JOYMIN) / 2;
else
value = (val + JOYMAX) / 2;
return (abs(value) < dZone);
}
QString Axis::status() {
QString result = getName() + " : [";
if (mode == keybd) {
if (throttle == 0)
result += "KEYBOARD";
else result += "THROTTLE";
}
else result += "MOUSE";
return result + "]";
}
void Axis::setKey(bool positive, int value) {
if (positive)
pkeycode = value;
else
nkeycode = value;
}
void Axis::timerTick( int tick ) {
if (isOn) {
if (mode == keybd) {
if (tick % FREQ == 0) {
if (duration == FREQ) {
if (!isDown) move(true);
duration = (abs(state) * FREQ) / JOYMAX;
return;
}
move(true);
}
if (tick % FREQ == duration) {
move(false);
duration = (abs(state) * FREQ) / JOYMAX;
}
}
else {
move(true);
}
}
}
void Axis::adjustGradient() {
//create a nice quadratic curve fitting it to the points
//(dZone,0) and (xZone,MaxSpeed)
a = (double) (maxSpeed) / sqr(xZone - dZone);
b = -2 * a * dZone;
c = a * sqr(dZone);
//actual equation for curve is: y = ax^2 + b
//where x is the state of the axis and y is the distance the mouse should move.
}
void Axis::move( bool press ) {
xevent e;
if (mode == keybd) {
//prevent KeyPress-KeyPress and KeyRelease-KeyRelease pairs.
//this would only happen in odd circumstances involving the setup
//dialog being open and blocking events from happening.
if (isDown == press) return;
isDown = press;
if (press) {
e.type = KPRESS;
downkey = (state > 0)?pkeycode:nkeycode;
}
else {
e.type = KREL;
}
e.value1 = downkey;
e.value2 = 0;
}
//if using the mouse
else if (press) {
int dist;
if (gradient) {
//calculate our mouse speed curve based on calculations made in
//adjustGradient()
int absState = abs(state);
if (absState >= xZone) dist = maxSpeed;
else if (absState <= dZone) dist = 0;
else dist = (int) (a*sqr(absState) + b*absState + c);
}
//if not gradient, always go full speed.
else dist = maxSpeed;
//if we're on the negative side of the axis, must compensate for
//squaring and make distance negative.
if (state < 0) dist = -dist;
e.type = WARP;
if (mode == mousepv) {
e.value1 = 0;
e.value2 = dist;
}
else if (mode == mousenv) {
e.value1 = 0;
e.value2 = -dist;
}
else if (mode == mouseph) {
e.value1 = dist;
e.value2 = 0;
}
else if (mode == mousenh) {
e.value1 = -dist;
e.value2 = 0;
}
}
//actually create the event
sendevent(e);
}

94
src/axis.h Normal file
View File

@ -0,0 +1,94 @@
#ifndef AXIS_H
#define AXIS_H
//abs()
#include <stdlib.h>
#include <QTimer>
#include <QTextStream>
#include <QRegExp>
#include <QStringList>
#include "constant.h"
//default and arbitrary values for dZone and xZone
#define DZONE 3000
#define XZONE 30000
//each axis can create a key press or move the mouse in one of four directions.
enum AxisMode {keybd, mousepv, mousenv, mouseph, mousenh};
//represents one joystick axis
class Axis : public QObject {
Q_OBJECT
//so AxisEdit can manipulate fields directly.
friend class AxisEdit;
public:
Axis( int i );
~Axis();
//read axis settings from a stream
bool read( QTextStream* stream );
//write axis settings to a stream
void write( QTextStream* stream );
//releases any pushed buttons and returns to a neutral state
void release();
//pass a message from the joystick device to this axis object
void jsevent( int value );
//revert to default settings
void toDefault();
//True iff currently at defaults
bool isDefault();
QString getName() { return "Axis " + QString::number(index+1);};
//true iff the given value is in the dead zone for this axis.
bool inDeadZone( int val );
//a descriptive string used as a label for the button representing this axis
QString status();
//set the key code for this axis. Used by quickset.
void setKey(bool positive, int value);
//happens every MSEC milliseconds (constant.h)
//uses tick to decide if key events should be generated
void timerTick( int tick );
//recalculates the gradient curve. This should be run every time
//maxSpeed, xZone, or dZone are changed.
void adjustGradient();
protected:
int tick;
//This axis is logically depressed (positive or negative)
//if the axis is gradient, this is true even if it is not
//currently generating a keypress at the instant.
bool isOn;
//which joystick this actually is
int index;
//actually sends key events. Press is true iff the key
//is to be depressed as opposed to released.
virtual void move( bool press );
//is a key currently depressed?
bool isDown;
//variables for calculating quadratic used for gradient mouse axes
double a,b,c;
//actual axis settings:
bool gradient;
int maxSpeed; //0..MAXMOUSESPEED
int throttle; //-1 (nkey), 0 (no throttle), 1 (pkey)
int dZone;//-32767 .. 32767
int xZone;//-32767 .. 32767
AxisMode mode;
//positive keycode
int pkeycode;
//negative keycode
int nkeycode;
//the key that is currently pressed
int downkey;
//the position of the axis, as from jsevent
int state;
//how long a key should stay down when in gradient mode
//note, the key is still clicked at the same pace no matter what,
//this just decides how long it stays down each cycle.
int duration;
QTimer *timer;
public slots:
void timerCalled();
};
#endif

150
src/axis_edit.cpp Normal file
View File

@ -0,0 +1,150 @@
#include "axis_edit.h"
AxisEdit::AxisEdit( Axis* ax )
:QDialog() {
//build the dialog, display current axis settings :)
axis = ax;
setWindowTitle("Set " + axis->getName());
setWindowIcon(QPixmap(ICON24));
//h, v, and v2 are all references to layouts. They are used to refer to
//various layouts as the dialog is built and are not pointing to the same
//thing throughout. This is just because I don't care about the layouts
//after I have placed the widgets within them and there's no reasno to
//keep track of them.
QVBoxLayout* v = new QVBoxLayout(this);
v->setMargin(5);
v->setSpacing(5);
QHBoxLayout* h = new QHBoxLayout();
QVBoxLayout* v2 = new QVBoxLayout();
v2->setMargin(5);
v2->setSpacing(5);
CGradient = new QCheckBox("Gradient", this);
CGradient->setChecked(axis->gradient);
v2->addWidget(CGradient);
CMode = new QComboBox(this);
CMode->insertItem((int)keybd, QString("Keyboard"), QVariant(NULL));
CMode->insertItem((int) mousepv,QString("Mouse (Vert.)"),QVariant(NULL));
CMode->insertItem((int) mousenv, QString("Mouse (Vert. Rev.)"), QVariant(NULL));
CMode->insertItem((int) mouseph, "Mouse (Hor.)", QVariant(NULL));
CMode->insertItem((int)mousenh, QString("Mouse (Hor. Rev.)"), NULL);
CMode->setCurrentIndex( axis->mode );
connect(CMode, SIGNAL(activated(int)), this, SLOT( CModeChanged( int )));
v2->addWidget(CMode);
h->addLayout(v2);
MouseBox = new QFrame(this);
MouseBox->setFrameStyle( QFrame::Box | QFrame::Sunken );
v2 = new QVBoxLayout(MouseBox);
v2->setSpacing(5);
v2->setMargin(5);
//v2->setAutoAdd(true);
QLabel *mouseLabel = new QLabel("Mouse Speed", MouseBox);
v2->addWidget(mouseLabel);
SSpeed = new QSpinBox(MouseBox);
SSpeed->setRange(0,MAXMOUSESPEED);
SSpeed->setSingleStep(1);
SSpeed->setValue(axis->maxSpeed);
v2->addWidget(SSpeed);
h->addWidget(MouseBox);
v->addLayout(h);
Slider = new JoySlider(axis->dZone, axis->xZone, axis->state, this);
v->addWidget(Slider);
KeyBox = new QFrame(this);
KeyBox->setFrameStyle( QFrame::Box | QFrame::Sunken );
h = new QHBoxLayout(KeyBox);
h->setSpacing(5);
h->setMargin(5);
//h->setAutoAdd(true);
BNeg = new KeyButton(axis->getName(),axis->nkeycode,KeyBox);
CThrottle = new QComboBox(KeyBox);
CThrottle->insertItem(0,"Neg. Throttle",QVariant(NULL));
CThrottle->insertItem(1,"No Throttle",QVariant(NULL));
CThrottle->insertItem(2,"Pos. Throttle",QVariant(NULL));
CThrottle->setCurrentIndex(axis->throttle + 1);
connect( CThrottle, SIGNAL( activated( int )), this, SLOT( CThrottleChanged( int )));
BPos = new KeyButton(axis->getName(),axis->pkeycode,KeyBox);
h->addWidget(BNeg);
h->addWidget(CThrottle);
h->addWidget(BPos);
v->addWidget( KeyBox );
h = new QHBoxLayout();
BOkay = new QPushButton("Okay", this);
connect(BOkay, SIGNAL( clicked() ), this, SLOT( accept()));
h->addWidget(BOkay);
BCancel = new QPushButton("Cancel", this);
connect(BCancel, SIGNAL( clicked() ), this, SLOT( reject()));
h->addWidget(BCancel);
v->addLayout(h);
CModeChanged( axis->mode );
CThrottleChanged( axis->throttle + 1 );
}
void AxisEdit::show() {
QDialog::show();
setFixedSize(size());
}
void AxisEdit::setState( int val ) {
Slider->setValue( val );
}
void AxisEdit::CModeChanged( int index ) {
if (index == keybd) {
MouseBox->setEnabled(false);
KeyBox->setEnabled(true);
}
else {
MouseBox->setEnabled(true);
KeyBox->setEnabled(false);
}
}
void AxisEdit::CThrottleChanged( int index ) {
switch (index) {
case 0:
BNeg->setEnabled(true);
BPos->setEnabled(false);
break;
case 1:
BNeg->setEnabled(true);
BPos->setEnabled(true);
break;
case 2:
BNeg->setEnabled(false);
BPos->setEnabled(true);
break;
}
Slider->setThrottle( index - 1 );
}
void AxisEdit::accept() {
//if the gradient status has changed, either request a timer or turn it down.
/*if (axis->gradient) {
if (!CGradient->isChecked()) tossTimer(axis);
}
else {
if (CGradient->isChecked()) takeTimer(axis);
}*/
axis->gradient = CGradient->isChecked();
axis->maxSpeed = SSpeed->value();
axis->throttle = CThrottle->currentIndex() - 1;
axis->dZone = Slider->dZone();
axis->xZone = Slider->xZone();
axis->mode = (AxisMode) CMode->currentIndex();
axis->pkeycode = BPos->getValue();
axis->nkeycode = BNeg->getValue();
axis->adjustGradient();
QDialog::accept();
}

41
src/axis_edit.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef AXIS_EDIT_H
#define AXIS_EDIT_H
//to refer to the axis we're editing
//for building up the dialog we need
#include "axis.h"
#include <QComboBox>
#include <QSpinBox>
#include <QCheckBox>
#include <QLabel>
//for my home-brewed widgets
#include "joyslider.h"
#include "keycode.h"
class AxisEdit : public QDialog {
Q_OBJECT
public:
AxisEdit(Axis* ax);
//show the dialog (modal)
void show();
//set the current state of the axis (adjusts the JoySlider for real time
//notification of the state to the user)
void setState( int val );
protected slots:
//slots for GUI events
void CModeChanged( int index );
void CThrottleChanged( int index );
void accept();
protected:
//the associated Axis that needs to be set.
Axis *axis;
//the important parts of the dialog:
QCheckBox *CGradient;
QComboBox *CMode, *CThrottle;
QFrame *MouseBox, *KeyBox;
QSpinBox *SSpeed;
KeyButton *BNeg, *BPos;
JoySlider *Slider;
QPushButton *BOkay, *BCancel;
};
#endif

38
src/axisw.cpp Normal file
View File

@ -0,0 +1,38 @@
#include "axisw.h"
AxisWidget::AxisWidget( Axis* a, QWidget* parent )
: FlashButton( "",parent) {
axis = a;
ae = NULL;
update();
on = false;
}
void AxisWidget::jsevent( int val ) {
bool newOn = !axis->inDeadZone(val);
if (on != newOn) {
on = newOn;
flash();
}
if (ae != NULL) ae->setState(val);
}
void AxisWidget::update() {
setText( axis->status());
}
void AxisWidget::mouseReleaseEvent( QMouseEvent* e ) {
//create the edit dialog,
ae = new AxisEdit(axis);
//get its input
ae->exec();
//now that it's done, destroy it!
delete ae;
//and remember that it's gone.
ae = NULL;
update();
//release the button. Waiting to do this until the very end has the nice
//effect of keeping the button depressed while the dialog is shown.
FlashButton::mouseReleaseEvent( e );
}

31
src/axisw.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef AXIS_WIDGET_H
#define AXIS_WIDGET_H
#include <QMouseEvent>
//so we can interact with the axis this refers to
#include "axis.h"
//for the FlashButton widget
#include "flash.h"
//so we can edit this axis when the user clicks the button
#include "axis_edit.h"
class AxisWidget : public FlashButton {
public:
AxisWidget( Axis* a, QWidget* parent );
//this is notified on a jsevent so it can flash if necesary.
void jsevent( int val );
//change the text on this button to reflect the axis' current state.
void update();
private:
//to deal with clicking (by creating an AxisEdit dialog)
void mouseReleaseEvent( QMouseEvent* e );
//is this button currently blue?
bool on;
//the axis this refers to
Axis* axis;
//the edit dialog that we pop up on request.
AxisEdit* ae;
};
#endif

178
src/button.cpp Normal file
View File

@ -0,0 +1,178 @@
#include "button.h"
#include "event.h"
Button::Button( int i ) {
index = i;
isButtonPressed = false;
isDown = false;
rapidfire = false;
timer = new QTimer(this);
toDefault();
tick = 0;
}
Button::~Button() {
release();
//delete timer;
}
bool Button::read( QTextStream* stream ) {
// at this point, toDefault() has just been called.
//read in a line of text and break it into words
QString input = stream->readLine().toLower();
QRegExp regex("[\\s,]+");
QStringList words = input.split(regex);
//used to assure correct conversion of QStrings -> ints
bool ok;
//used to receive converted ints from QStrings.
int val;
//go through every word on the line describing this button.
for ( QStringList::Iterator it = words.begin(); it != words.end(); ++it ) {
if (*it == "mouse") {
++it;
if (it == words.end()) return false;
val = (*it).toInt(&ok);
if (ok && val >= 0 && val <= MAXKEY) {
useMouse = true;
mousecode = val;
}
else return false;
}
else if (*it == "key") {
++it;
if (it == words.end()) return false;
val = (*it).toInt(&ok);
if (ok && val >= 0 && val <= MAXKEY) {
useMouse = false;
keycode = val;
}
else return false;
}
else if (*it == "rapidfire") {
rapidfire = true;
}
else if (*it == "sticky") {
sticky = true;
}
}
return true;
}
void Button::write( QTextStream* stream ) {
*stream << "\t" << getName() << ": ";
if (rapidfire) *stream << "rapidfire, ";
if (sticky) *stream << "sticky, ";
*stream << (useMouse?"mouse ":"key ") << (useMouse?mousecode:keycode) << "\n";
}
void Button::release() {
if (isDown) {
click(false);
isDown = true;
}
}
void Button::jsevent( int value ) {
bool newval = (value == 1);
if (sticky) {
//the state of a sticky key only changes on button press, not button release.
if (value == 1) {
isButtonPressed = !isButtonPressed;
}
else return;
}
//if the received event indicates a change in state,
else if (newval != isButtonPressed) {
isButtonPressed = newval; //change state
if (isButtonPressed && rapidfire) {
tick = 0;
connect(timer, SIGNAL(timeout()), this, SLOT(timerCalled()));
timer->start(MSEC);
}
if (!isButtonPressed && rapidfire) {
timer->stop();
if(isDown) {
click(false);
}
tick = 0;
}
}
//otherwise... we don't care. This shouldn't happen.
else return;
//if rapidfire is on, then timer() will do its job. Otherwise we must
//manually triger the key event.
if (!rapidfire) {
click(isButtonPressed);
}
}
void Button::toDefault() {
rapidfire = false;
sticky = false;
useMouse = false;
keycode = 0;
mousecode = 0;
timer->stop();
}
bool Button::isDefault() {
return (rapidfire == false) &&
(sticky == false) &&
(useMouse == false) &&
(keycode == 0) &&
(mousecode == 0);
}
QString Button::status() {
if (useMouse) {
return getName() + " : Mouse " + QString::number(mousecode);
}
else {
return getName() + " : " + QString(ktos(keycode));
}
}
void Button::setKey( bool mouse, int value ) {
if (mouse) {
mousecode = value;
useMouse = true;
}
else {
keycode = value;
useMouse = false;
}
}
void Button::timerTick( int tick ) {
if (isButtonPressed) {
//originally I just clicked true and then false right after, but this
//was not recognized by some programs. I need a delay in between.
if (tick % FREQ == 0) {
click(true);
}
if (tick % FREQ == FREQ / 2) {
click(false);
}
}
}
void Button::click( bool press ) {
if (isDown == press) return;
isDown = press;
xevent click;
//determine which of the four possible events we're sending.
if (press) click.type = useMouse?BPRESS:KPRESS;
else click.type = useMouse?BREL:KREL;
//set up the event,
click.value1 = useMouse?mousecode:keycode;
click.value2 = 0;
//and send it.
sendevent( click );
}
void Button::timerCalled() {
timerTick(++tick);
}

60
src/button.h Normal file
View File

@ -0,0 +1,60 @@
#ifndef BUTTON_H
#define BUTTON_H
#include <QTimer>
#include <QTextStream>
//for getting a key name in status()
#include "keycode.h"
//note that the Button class, unlike the axis class, does not need a release
//function because it releases the key as soon as it is pressed.
class Button : public QObject {
Q_OBJECT
friend class ButtonEdit;
public:
Button( int i );
~Button();
//read from stream
bool read( QTextStream* stream );
//write to stream
void write( QTextStream* stream );
//releases any pushed buttons and returns to a neutral state
void release();
//process an event from the actual joystick device
void jsevent( int value );
//reset default settings
void toDefault();
//True iff is currently using default settings
bool isDefault();
//returns a string representation of this button.
QString getName() { return "Button " + QString::number(index+1);};
//a descriptive string used as a label for the button representing this axis
QString status();
//set the key code for this axis. Used by quickset.
void setKey(bool mouse, int value);
//happens every MSEC (constant.h) milliseconds
void timerTick( int tick );
protected:
//true iff this button is physically depressed.
bool isButtonPressed;
//the index of this button on the joystick
int index;
//actually sends a key press/release
virtual void click( bool press );
//is a simulated key currently depressed?
bool isDown;
int tick;
//button settings
bool rapidfire;
bool sticky;
bool useMouse;
int keycode;
int mousecode; //like keycode, only mousebutton ;)
QTimer *timer;
public slots:
void timerCalled();
};
#endif

66
src/button_edit.cpp Normal file
View File

@ -0,0 +1,66 @@
#include "button_edit.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
ButtonEdit::ButtonEdit(Button* butt)
:QDialog(0) {
setModal(true);
//build the dialog!
button = butt;
setWindowTitle("Set " + button->getName());
setWindowIcon(QPixmap(ICON24));
QVBoxLayout* v = new QVBoxLayout(this);
v->setMargin(5);
v->setSpacing(5);
BKKey = new KeyButton( button->getName(), button->useMouse?button->mousecode:button->keycode, this, true, button->useMouse);
v->addWidget(BKKey);
QHBoxLayout* h = new QHBoxLayout();
CSticky = new QCheckBox("Sticky", this);
CSticky->setChecked(button->sticky);
h->addWidget(CSticky);
CRapid = new QCheckBox("Rapid Fire", this);
CRapid->setChecked(button->rapidfire);
h->addWidget(CRapid);
v->addLayout(h);
h = new QHBoxLayout();
BOkay = new QPushButton("Okay", this);
connect(BOkay, SIGNAL( clicked() ), this, SLOT( accept()));
h->addWidget(BOkay);
BCancel = new QPushButton("Cancel", this);
connect(BCancel, SIGNAL( clicked() ), this, SLOT( reject()));
h->addWidget(BCancel);
v->addLayout(h);
}
void ButtonEdit::show() {
QDialog::show();
setFixedSize(size());
}
void ButtonEdit::accept() {
//if the rapidfire status has changed, either request a timer or turn it down.
/*if (button->rapidfire) {
if (!CRapid->isChecked()) tossTimer(button);
}
else {
if (CRapid->isChecked()) takeTimer(button);
}*/
button->rapidfire = CRapid->isChecked();
button->sticky = (CSticky->isChecked());
//if the user chose a mouse button...
if (BKKey->choseMouse()) {
button->useMouse = true;
button->mousecode = BKKey->getValue();
}
else {
button->useMouse = false;
button->keycode = BKKey->getValue();
}
QDialog::accept();
}

30
src/button_edit.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef BUTTON_EDIT_H
#define BUTTON_EDIT_H
#include <QPushButton>
#include <QCheckBox>
//we need to edit a Button
#include "button.h"
//to get a new key for the button.
#include "keycode.h"
class ButtonEdit : public QDialog {
Q_OBJECT
public:
ButtonEdit(Button* butt);
void show();
protected slots:
void accept();
protected:
Button *button;
KeyButton *BKKey;
QPushButton *BKey, *BMouse, *BOkay, *BCancel;
QPushButton **BMKey;
QCheckBox *CSticky, *CRapid;
};
#endif

30
src/buttonw.cpp Normal file
View File

@ -0,0 +1,30 @@
#include "buttonw.h"
ButtonWidget::ButtonWidget( Button* b, QWidget* parent )
: FlashButton( "", parent) {
button = b;
update();
on = false;
}
void ButtonWidget::jsevent( int val ) {
bool newOn = (val == 1);
if (on != newOn) {
on = newOn;
flash();
}
}
void ButtonWidget::update() {
setText( button->status());
}
void ButtonWidget::mouseReleaseEvent( QMouseEvent* e ) {
ButtonEdit* be = new ButtonEdit(button);
be->exec();
delete be;
update();
FlashButton::mouseReleaseEvent( e );
}

28
src/buttonw.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef BUTTON_WIDGET_H
#define BUTTON_WIDGET_H
//this represents a Button
#include "button.h"
//this can set a button using a ButtonEdit
#include "button_edit.h"
//this IS a FlashButton
#include "flash.h"
#ifdef Bool
#undef Bool
#endif
#include <QMouseEvent>
class ButtonWidget : public FlashButton {
public:
ButtonWidget( Button* b, QWidget* parent);
void jsevent( int val );
//reset the label to match the respective Button's current state.
void update();
private:
void mouseReleaseEvent( QMouseEvent* e );
bool on;
Button* button;
};
#endif

80
src/config Executable file
View File

@ -0,0 +1,80 @@
#!/bin/bash
devdir="/dev/input"
prefix="/usr/local"
plain_keys=""
for arg in $*
do
case $arg in
--help) echo "
Usage: ./config [--devdir=\"dir\"] [--prefix=\"prefix\"] [--help]
Options:
--devdir=DIR Set the path where QJoyPad will look for your joystick
devices to be DIR. If your devices are /dev/js0, /dev/js1,
etc., this should be just \"/dev\". By default, this is
/dev/input.
--prefix=DIR Set the path where QJoyPad and its components will be
installed. By default, this is /usr/local.
--plain_keys Force QJoyPad to use standard XWindows keynames without
filtering them for appearance. This will make displays
less attractive and readable, but will save processor power
and ensure that you see the right names for keys you press.
--help Show this message.
"; exit 0;;
--devdir=*) devdir=${arg##*=}
if [[ ! -d $devdir ]]
then
echo "Invalid device directory given: $devdir"
exit 1
fi ;;
--prefix=*) prefix=${arg##*=}
if [[ ! -d $prefix ]]
then
echo "Invalid prefix directory given: $prefix"
exit 1
fi ;;
--plain_keys) plain_keys="PLAIN_KEYS";;
*) echo "Unrecognized argument: \"$arg\". Try ./config --help for help."
esac
done
arg1="DEVDIR=$devdir"
arg2="PREFIX=$prefix"
arg3="DEFINES += $plain_keys"
qmake -makefile "$arg1" "$arg2" "$arg3" qjoypad.pro
echo "
Configuring QJoyPad installation...
------------------------------------------------------------
Device directory: $devdir
-- Devices will be looked for in:
$devdir/js0
$devdir/js1
etc.
Prefix directory: $prefix
-- Files to be installed in:
$prefix/bin
$prefix/doc
$prefix/share/pixmaps"
if [[ -n $plain_keys ]]; then
echo "
-- Using regular XWindows key names.";
fi
echo "
---------------------------------------------------------
If these settings are okay, go ahead and run 'make' and
then 'make install'.
To make changes, run ./config --help for details.
"

29
src/constant.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef JCONST_H
#define JCONST_H
//How many cycles there are per click.
#define FREQ 10
//How many milliseconds per cycle.
#define MSEC 5
//events will be generated every FREQ * MSEC milliseconds. The duration of the
//event can be anywhere between 0 * MSEC and FREQ * MSEC. This means there will
//be FREQ + 1 levels of gradation.
//maximum range of values from joystick driver
#define JOYMAX 32767
#define JOYMIN -32767
//maximum number of defined keys
#define MAXKEY 122
//fastest the mouse can go. Completely arbitrary.
#define MAXMOUSESPEED 5000
#define NAME "QJoyPad 3.4"
#define MOUSE_OFFSET 400
#endif

16
src/device.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef JOY_DEVICE_H
#define JOY_DEVICE_H
#include "joypad.h"
//the purpose of this file is to make device information available to what
//needs it.
//a collection of joysticks currently available on this computer
extern QHash<int, JoyPad*> available;
//a collection of joypad objects representing all the available joysticks
//as well as the ones defined in a layout buy not currently plugged in.
extern QHash<int, JoyPad*> joypads;
#endif

13
src/error.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef JOY_ERROR_H
#define JOY_ERROR_H
#include <qmessagebox.h>
//a nice simple way of throwing up an error message if something goes wrong.
static void error(QString type, QString message ) {
QMessageBox::warning(0,NAME" - " + type,
message, QMessageBox::Ok, Qt::NoButton);
}
#endif

21
src/event.cpp Normal file
View File

@ -0,0 +1,21 @@
#include "event.h"
//this should be initialized by main.cpp as soon as the program starts.
Display* display;
//actually creates an XWindows event :)
void sendevent( xevent e ) {
if (e.value1 == 0 && e.value2 == 0) return;
if (e.type == WARP) {
XTestFakeRelativeMotionEvent(display, e.value1, e.value2, 0);
}
else {
if (e.type == KREL || e.type == KPRESS) {
XTestFakeKeyEvent(display, e.value1, (e.type == KPRESS), 0);
}
else if (e.type == BREL || e.type == BPRESS) {
XTestFakeButtonEvent(display, e.value1, (e.type == BPRESS), 0);
}
}
XFlush(display);
}

22
src/event.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef JEVENT_H
#define JEVENT_H
//for the functions we need to generate keypresses / mouse actions
#include <X11/extensions/XTest.h>
//types of events QJoyPad can create.
//KeyRelease, KeyPress, ButtonRelease, ButtonPress, and MouseMove
enum eventType {KREL, KPRESS, BREL, BPRESS, WARP};
//a simplified event structure that can handle buttons and mouse movements
struct xevent {
eventType type;
int value1; //button, keycode, or x
int value2; //y
};
void sendevent( xevent e );
#endif

99
src/flash.cpp Normal file
View File

@ -0,0 +1,99 @@
#include "flash.h"
//Added by qt3to4:
//Modified here (and in .h) to not have default arguments for 2 and 3.
//This caused an error with a development version of g++ on a Mandrake system
//in Sweden.
FlashButton::FlashButton( QString text, QWidget* parent, QString name )
:QPushButton( text, parent )
{
this->setObjectName(name);
//record the base palette for posterity.
Normal = palette();
//define the palette the button will have when it flashes.
QPalette cg = this->palette();
cg.setCurrentColorGroup(QPalette::Inactive);
cg.setColor(QPalette::Button, HIGHLIGHT);
cg.setColor(QPalette::Light, HIGHLIGHT.light(150));
cg.setColor(QPalette::Midlight, HIGHLIGHT.light(125));
cg.setColor(QPalette::Dark, HIGHLIGHT.dark(200));
cg.setColor(QPalette::Mid, HIGHLIGHT.dark(150));
Flash = cg;
isflash=false;
setAutoDefault( false );
setFocusPolicy(Qt::NoFocus);
}
void FlashButton::flash()
{
emit( flashed( !isflash ) );
if (isflash)
{
setPalette( Normal );
isflash = false;
}
else
{
setPalette( Flash );
isflash = true;
}
}
FlashRadioArray::FlashRadioArray( int count, QString names[], bool horizontal, QWidget* parent)
:QWidget( parent )
{
if (horizontal) {
LMain = new QHBoxLayout( this);
LMain->setMargin(5);
LMain->setSpacing(5);
} else {
LMain = new QVBoxLayout( this);
LMain->setMargin(5);
LMain->setSpacing(5);
}
Buttons = new FlashButton*[count];
for (int i = 0; i < count; i++)
{
Buttons[i] = new FlashButton( names[i], this, "" );
//when any of the buttons is clicked, it calls the same function on this.
connect( Buttons[i], SIGNAL( clicked() ), this, SLOT( clicked() ));
LMain->addWidget(Buttons[i]);
}
Count = count;
State = 0;
Buttons[0]->setDown( true );
}
int FlashRadioArray::getState()
{
return State;
}
void FlashRadioArray::flash( int index )
{
Buttons[index]->flash();
}
void FlashRadioArray::clicked()
{
//go through each button. If it wasn't the button that was just clicked,
//then make sure that it is up. If it WAS the button that was clicked,
//remember that index as the new state.
for (int i = 0; i < Count; i++)
{
if ( Buttons[i] != sender() )
Buttons[i]->setDown( false );
else
{
State = i;
Buttons[i]->setDown( true );
}
}
emit changed( State );
}

77
src/flash.h Normal file
View File

@ -0,0 +1,77 @@
#ifndef FLASH_H
#define FLASH_H
//The color the buttons flash! Feel free to change this.
//The three numbers are all you need to touch, and they
//represent the red, green, and blue values of the color,
//respectively.
#define HIGHLIGHT QColor( 0,0,255 )
//--- --- --- --- End of editable code.
#include <QPushButton>
#include <QPalette>
#include <QBoxLayout>
//A QPushButton that can flash a color
//The color it flashes is defined by HIGHLIGHT
//A FlashButton can now also be set dark
//in the same way that it can flash, but
//a FlashButton can not be dark and flash at the same time.
class FlashButton : public QPushButton
{
Q_OBJECT
public:
FlashButton( QString text, QWidget* parent, QString name = "" );
public slots:
//make the button turn blue if it was gray, or visa versa.
void flash();
signals:
//let the world know when flash() happens!
void flashed( bool on );
private:
//is this currently "flashed" (ie, colored blue)?
bool isflash;
//the normal, unflashed palette
QPalette Normal;
//the colorful flashed palette
QPalette Flash;
};
//An array of flashing mutually-exclusive toggle buttons.
class FlashRadioArray : public QWidget
{
Q_OBJECT
public:
FlashRadioArray( int count, QString names[], bool horizontal, QWidget* parent);
//returns an integer returning the currently selected button.
//First button is 0.
int getState();
public slots:
//flash the button at the given index
void flash( int );
private slots:
//this is what happens when one of the buttons in the array is clicked.
void clicked();
signals:
//happens when the state changes. The int is the new state.
void changed( int );
private:
//how many buttons
int Count;
//which is currently down
int State;
//the array of buttons
FlashButton** Buttons;
//the main layout.
QBoxLayout* LMain;
};
#endif

58
src/getkey.cpp Normal file
View File

@ -0,0 +1,58 @@
#include "getkey.h"
GetKey::GetKey( QString button, bool m )
:QDialog( 0 )
{
//prepare the dialog
mouse = m;
setWindowTitle( "Choose a key" );
setWindowIcon(QIcon(ICON24));
//I'd use a QLabel, but that steals x11Events!
//So, I'll draw the text directly. That means
//I need to resolve the size of the dialog by hand:
Text = "Choose a new key ";
if (mouse) Text += "or mouse button ";
Text += "for " + button;
QRect rect = fontMetrics().boundingRect( Text );
//I calculate the size based on the first line of text, which is longer.
//The fontMetrics function is dumb and would treat the string with a
//newline in it as a continues flow of characters if I did the whole string
//at once.
Text += "\n(Ctrl-X for no key)";
//now I add 20 pixels of padding and double the height to make room for
//two lines.
setFixedSize( QSize( rect.width() + 20, rect.height()*2 + 20 ) );
}
bool GetKey::x11Event( XEvent* e )
{
//keep Qt from closing the dialog upon seeing Esc pressed.
if (e->type == KeyPress) return true;
//On a key press, return the key and quit
//Ctrl+X == [No Key]
if (e->type == KeyRelease) {
if (XKeycodeToKeysym(display,e->xkey.keycode,0) == XK_x ) {
if (e->xkey.state & ControlMask) done( 0 );
else done( e->xkey.keycode );
}
else done( e->xkey.keycode );
return true;
}
//if we're accepting mouse clicks and a mouse button was clicked...
if (mouse && e->type == ButtonRelease) {
done ( e->xbutton.button + MOUSE_OFFSET);
return true;
}
//any other events we will pass on to the dialog. This allows for closing
//the window and easy redrawing :)
return false;
}
void GetKey::paintEvent ( QPaintEvent * ) {
//whenever we need to repaint, draw in our text.
QPainter paint( this );
paint.drawText( rect(), Qt::AlignCenter, Text );
}

28
src/getkey.h Normal file
View File

@ -0,0 +1,28 @@
#include <QDialog>
#include <QPainter>
#include <QPixmap>
#include <QIcon>
#include "constant.h"
#include <X11/Xlib.h>
//The KeySym for "x"
#define XK_x 0x078
extern Display *display;
//a keycode dialog box
class GetKey : public QDialog {
Q_OBJECT
public:
GetKey( QString button, bool m = false );
protected:
//to filter through every event this thing sees, before QT does.
bool x11Event( XEvent* e );
//to avoid focus issues, there is only the dialog widget, all the
//rest is painted on. So, I need to know when to repaint.
void paintEvent ( QPaintEvent * );
private:
//the dialog's message
QString Text;
//does this dialog accept mouse clicks?
bool mouse;
};

33
src/icon.cpp Normal file
View File

@ -0,0 +1,33 @@
#include "icon.h"
FloatingIcon::FloatingIcon( const QPixmap &icon, QMenu *popup, QWidget *parent, const char *name)
: QDialog( parent ) {
this->setObjectName(name);
setWindowTitle(NAME);
QPalette palette;
palette.setBrush(backgroundRole(), QBrush(icon));
setPalette(palette);
//setPaletteBackgroundPixmap(icon);
pop = popup;
setFixedSize(64,64);
}
void FloatingIcon::mousePressEvent( QMouseEvent* e ) {
//if it was the right mouse button,
if (e->button() == Qt::RightButton) {
//bring up the popup menu.
pop->popup( e->globalPos() );
e->accept();
}
else {
//otherwise, treat it as a regular click.
emit clicked();
}
}
void FloatingIcon::closeEvent( QCloseEvent* e ) {
emit closed();
e->accept();
}

25
src/icon.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef JOY_ICON_H
#define JOY_ICON_H
#include <QDialog>
#include <QMenu>
#include <QPixmap>
#include <QMouseEvent>
#include <QCloseEvent>
#include "constant.h"
class FloatingIcon : public QDialog {
Q_OBJECT
public:
FloatingIcon( const QPixmap &icon, QMenu *popup = 0, QWidget *parent = 0, const char *name = 0);
signals:
void closed();
void clicked();
protected:
void mousePressEvent( QMouseEvent* e );
void closeEvent( QCloseEvent* e );
QMenu* pop;
};
#endif

270
src/joypad.cpp Normal file
View File

@ -0,0 +1,270 @@
#include "unistd.h"
#include "joypad.h"
#include <stdio.h>
#include <fcntl.h>
#include <poll.h>
#include <QApplication>
JoyPad::JoyPad( int i, int dev ) {
//remember the index,
index = i;
//load data from the joystick device, if available.
joydevFileHandle = NULL;
if(dev > 0) {
resetToDev(dev);
joydevFileHandle = new QSocketNotifier(dev, QSocketNotifier::Read, this);
connect(joydevFileHandle, SIGNAL(activated(int)), this, SLOT(handleJoyEvents(int)));
}
//there is no JoyPadWidget yet.
jpw = NULL;
}
void JoyPad::resetToDev(int dev ) {
//remember the device file descriptor
joydev = dev;
//read in the number of axes / buttons
axes = 0;
ioctl (joydev, JSIOCGAXES, &axes);
buttons = 0;
ioctl (joydev, JSIOCGBUTTONS, &buttons);
//make sure that we have the axes we need.
//if one that we need doesn't yet exist, add it in.
//Note: if the current layout has a key assigned to an axis that did not
//have a real joystick axis mapped to it, and this function suddenly brings
//that axis into use, the key assignment will not be lost because the axis
//will already exist and no new axis will be created.
for (int i = 0; i < axes; i++) {
if (Axes[i] == 0) Axes.insert(i, new Axis( i ));
}
for (int i = 0; i < buttons; i++) {
if (Buttons[i] == 0) Buttons.insert(i, new Button( i ));
}
struct pollfd read_struct;
read_struct.fd = joydev;
read_struct.events = POLLIN;
char buf[10];
while(poll(&read_struct, 1, 2)!=0) {
printf("reading junk data\n");
read(joydev, buf, 10);
}
setupJoyDeviceListener(dev);
}
void JoyPad::setupJoyDeviceListener(int dev) {
if(joydevFileHandle != NULL) {
delete joydevFileHandle;
}
joydevFileHandle = new QSocketNotifier(dev, QSocketNotifier::Read, this);
connect(joydevFileHandle, SIGNAL(activated(int)), this, SLOT(handleJoyEvents(int)));
}
void JoyPad::toDefault() {
//to reset the whole, reset all the parts.
do
{
QHashIterator<int, Axis*> it( Axes );
while (it.hasNext())
{
it.next();
it.value()->toDefault();
}
} while (0);
do
{
QHashIterator<int, Button*> it( Buttons );
while (it.hasNext())
{
it.next();
it.value()->toDefault();
}
} while (0);
}
bool JoyPad::isDefault() {
//if any of the parts are not at default, then the whole isn't either.
do {
QHashIterator<int, Axis*> it( Axes );
while (it.hasNext())
{
it.next();
if (!it.value()->isDefault()) return false;
}
} while (0);
do {
QHashIterator<int, Button*> it( Buttons );
while (it.hasNext())
{
it.next();
if (!it.value()->isDefault()) return false;
}
} while (0);
return true;
}
bool JoyPad::readConfig( QTextStream* stream ) {
toDefault();
QString word;
QChar dump;
int num;
*stream >> word;
while (word != NULL && word != "}") {
word = word.toLower();
if (word == "button") {
*stream >> num;
if (num > 0) {
*stream >> dump;
if (dump != ':') {
error("Layout file error", "Expected ':', found '" + QString(dump) + "'.");
return false;
}
if (Buttons[num-1] == 0) {
Buttons.insert(num-1,new Button(num-1));
}
if (!Buttons[num-1]->read( stream )) {
error("Layout file error", "Error reading Button " + QString::number(num));
return false;
}
}
else {
stream->readLine();
}
}
else if (word == "axis") {
*stream >> num;
if (num > 0) {
*stream >> dump;
if (dump != ':') {
error("Layout file error", "Expected ':', found '" + QString(dump) + "'.");
return false;
}
if (Axes[num-1] == 0) {
Axes.insert(num-1,new Axis(num-1));
}
if (!Axes[num-1]->read(stream)) {
error("Layout file error", "Error reading Axis " + QString::number(num));
return false;
}
}
}
else {
error( "Layout file error", "Error while reading layout. Unrecognized word: " + word );
return false;
}
*stream >> word;
}
return true;
}
//only actually writes something if this JoyPad is NON DEFAULT.
void JoyPad::write( QTextStream* stream ) {
int i = 0; //use to test if this is default or not.
QString result;
QTextStream* s = new QTextStream(&result, QIODevice::WriteOnly);
*s << getName() << " {\n";
do {
QHashIterator<int, Axis*> it( Axes );
while (it.hasNext()) {
it.next();
if (!it.value()->isDefault()) {
it.value()->write( s );
++i;
}
}
} while (0);
QHashIterator<int, Button*> it( Buttons );
while (it.hasNext()) {
it.next();
if (!it.value()->isDefault()) {
it.value()->write( s );
++i;
}
}
if (i > 0) {
*stream << result << "}\n\n";
}
}
void JoyPad::release() {
do {
QHashIterator<int, Axis*> it( Axes );
while (it.hasNext()) {
it.next();
it.value()->release();
}
} while (0);
do {
QHashIterator<int, Button*> it( Buttons );
while (it.hasNext()) {
it.next();
it.value()->release();
}
} while (0);
}
void JoyPad::jsevent( js_event msg ) {
//if there is a JoyPadWidget around, ie, if the joypad is being edited
if (jpw != NULL) {
//tell the dialog there was an event. It will use this to flash
//the appropriate button, if necesary.
jpw->jsevent(msg);
return;
}
//if the dialog is open, stop here. We don't want to signal ourselves with
//the input we generate.
if (qApp->activeWindow() != 0 && qApp->activeModalWidget() != 0) return;
//otherwise, lets create us a fake event! Pass on the event to whichever
//Button or Axis was pressed and let them decide what to do with it.
if (msg.type & JS_EVENT_AXIS) {
printf("passing on an axis event\n");
printf("DEBUG: %d %d\n", msg.number, msg.value);
Axes[msg.number]->jsevent(msg.value);
}
else {
printf("passing on a button event\n");
printf("DEBUG: %d %d\n", msg.number, msg.value);
Buttons[msg.number]->jsevent(msg.value);
}
}
JoyPadWidget* JoyPad::widget( QWidget* parent, int i) {
//create the widget and remember it.
jpw = new JoyPadWidget(this, i, parent);
return jpw;
}
void JoyPad::handleJoyEvents(int fd) {
js_event msg;
int len;
len = read( joydev, &msg, sizeof(js_event));
//if there was a real event waiting,
if (len == (int) sizeof(js_event)) {
//pass that event on to the joypad!
jsevent(msg);
} else {
printf("NOOOOOOO\n");
}
//sleep for a moment. This is just to keep us from throwing all the
//available processer power into madly checking for new events.
//usleep(10000);
}
void JoyPad::releaseWidget() {
//this is how we know that there is no longer a JoyPadWidget around.
jpw = NULL;
}
void JoyPad::unsetDev() {
close(joydev);
joydev = -1;
if(joydevFileHandle != NULL) {
delete joydevFileHandle;
}
}

80
src/joypad.h Normal file
View File

@ -0,0 +1,80 @@
#ifndef JOYPAD_H
#define JOYPAD_H
//parts of the joypad
#include "button.h"
#include "axis.h"
//the widget that will edit this
#include "joypadw.h"
//for raising errors
#include "error.h"
//for actually interacting with the joystick devices
#include <linux/joystick.h>
#include <fcntl.h>
#include <unistd.h>
#include <QTextStream>
#include <QHash>
#include <QSocketNotifier>
class JoyPadWidget;
//represents an actual joystick device
class JoyPad : public QObject{
Q_OBJECT
friend class JoyPadWidget;
friend class QuickSet;
public:
void setupJoyDeviceListener(int dev);
JoyPad( int i, int dev );
//read from a stream
bool readConfig( QTextStream* stream );
//write to a stream
void write( QTextStream* stream );
//release any pushed buttons and return to a neutral state
void release();
//handle an event from the joystick device this is associated with
void jsevent( js_event msg );
//reset to default settings
void toDefault();
//true iff this is currently at default settings
bool isDefault();
//release the connection to the real joystick
void unsetDev();
//read the dimensions on the real joystick and use them
void resetToDev( int dev );
//generates a name ("Joystick 1")
QString getName() { return "Joystick " + QString::number(index+1);};
//it's just easier to have these publicly available.
int joydev; //the actual file descriptor to the joystick device
int axes; //the number of axes available on this device
int buttons; //the number of buttons
//request the joypad to make a JoyPadWidget. We create them this way
//so that the joypad is always aware when it has a widget active.
JoyPadWidget* widget(QWidget* parent, int i);
//called when the joypad is no longer being edited.
void releaseWidget();
protected:
//lookup axes and buttons. These are dictionaries to support
//layouts with different numbers of axes/buttons than the current
//devices. Note that with the current layout settings, the defined
//buttons that don't actually exist on the device may not be contiguous.
QHash<int, Axis*> Axes;
QHash<int, Button*> Buttons;
//the index of this device (devicenum)
int index;
//the widget that edits this. Mainly I keep track of this to know if
//the joypad is currently being edited.
JoyPadWidget* jpw;
QSocketNotifier *joydevFileHandle;
public slots:
void handleJoyEvents(int fd);
};
#endif

102
src/joypadw.cpp Normal file
View File

@ -0,0 +1,102 @@
#include "joypadw.h"
//Added by qt3to4:
JoyPadWidget::JoyPadWidget( JoyPad* jp, int i, QWidget* parent )
: QWidget(parent) {
//initialize things, build the dialog
joypad = jp;
index = i;
/* This was in below, no idea what it does :( ...
* (joypad->axes+1)/2 +(joypad->buttons+1)/2 + 2
*/
LMain = new QGridLayout(this);
LMain->setSpacing(5);
LMain->setMargin(5);
flashcount = 0;
int insertCounter = 0;
quickset = NULL;
Axes = new AxisWidget*[joypad->axes];
for (int i = 0; i < joypad->axes; i++) {
Axes[i] = new AxisWidget(joypad->Axes[i],this);
connect( Axes[i], SIGNAL( flashed( bool ) ), this, SLOT( flash( bool )));
LMain->addWidget(Axes[i], insertCounter / 2, insertCounter %2);
insertCounter++;
}
Buttons = new ButtonWidget*[joypad->buttons];
for (int i = 0; i < joypad->buttons; i++) {
Buttons[i] = new ButtonWidget(joypad->Buttons[i],this);
connect( Buttons[i], SIGNAL( flashed( bool ) ), this, SLOT( flash( bool )));
LMain->addWidget(Buttons[i], insertCounter/2, insertCounter%2);
insertCounter++;
}
if(insertCounter % 2 == 1) {
insertCounter++;
}
insertCounter+=2;
BClear = new QPushButton("Clear", this);
connect(BClear, SIGNAL(clicked()), this, SLOT(clear()));
LMain->addWidget(BClear, insertCounter / 2, insertCounter %2);
insertCounter++;
BAll = new QPushButton("Quick Set", this);
LMain->addWidget(BAll, insertCounter /2, insertCounter%2);
connect(BAll, SIGNAL(clicked()), this, SLOT(setAll()));
}
JoyPadWidget::~JoyPadWidget() {
//so the joypad knows that we're done.
joypad->releaseWidget();
}
void JoyPadWidget::flash( bool on ) {
//true iff this entire widget was considered "flashed" before
bool wasOn = (flashcount != 0);
//adjust the count based on this new flash
flashcount += (on?1:-1);
//if we were on and should now be off, or visa versa, flash the whole widget
if (wasOn != (flashcount != 0))
emit flashed(index);
}
void JoyPadWidget::update() {
for (int i = 0; i < joypad->axes; i++) {
Axes[i]->update();
}
for (int i = 0; i < joypad->buttons; i++) {
Buttons[i]->update();
}
}
void JoyPadWidget::clear() {
joypad->toDefault();
update();
}
void JoyPadWidget::setAll() {
//quickset is NULL if there is no quickset dialog, and a pointer to the
//dialog otherwise. This is so we can forward jsevents properly.
quickset = new QuickSet(joypad);
quickset->exec();
update();
delete quickset;
quickset = NULL;
}
void JoyPadWidget::jsevent( js_event msg ) {
//notify the component this event applies to. this cannot generate anything
//other than a flash :)
if (msg.type == JS_EVENT_AXIS) {
Axes[msg.number]->jsevent(msg.value);
}
else {
Buttons[msg.number]->jsevent(msg.value);
}
//if we're doing quickset, it needs to know when we do something.
if (quickset != NULL)
quickset->jsevent(msg);
}

65
src/joypadw.h Normal file
View File

@ -0,0 +1,65 @@
#ifndef JOYPAD_WIDGET_H
#define JOYPAD_WIDGET_H
//parts for the widget
//Added by qt3to4:
#include <linux/joystick.h>
#include "axisw.h"
//this all relates to a JoyPad
#include "joypad.h"
//and a JoyPadWidget is composed of AxisWidgets and ButtonWidgets
#include "buttonw.h"
//JoyPadWidget also is what initiates the whole QuickSet procedure :)
#include "quickset.h"
//because of some circularity issues, I need to forward declare these.
class JoyPad;
class QuickSet;
//Widget for editing a JoyPad
class JoyPadWidget : public QWidget {
Q_OBJECT
public:
JoyPadWidget( JoyPad* jp, int i, QWidget* parent);
~JoyPadWidget();
//takes in an event and decides whether or not to flash anything
void jsevent( js_event msg );
public slots:
//called whenever one of the subwidgets flashes... used to determine
//when to emit the flashed() signal.
void flash( bool on );
//update all the components, that is, get the proper labels up on the buttons
void update();
//reset everything
void clear();
//quickset!
void setAll();
signals:
//happens whenever the tab that represents this joypadwidget should flash
//(either on or off) The int is the index of this widget so that this
//signal can be directly connected to FlashRadioArray's flash(int)
void flashed(int);
protected:
//the joypad this is linked to
JoyPad* joypad;
//the index of this widget IN THE WIDGET STACK! This is unique from
//joypad->index and has nothing to do with device number.
int index;
//how many times one of the components has flashed on minus how many
//times one of the components has flashed off. This is how we know when
//none of the components are left lit.
int flashcount;
//the parts of the dialog
QGridLayout *LMain;
AxisWidget **Axes;
ButtonWidget **Buttons;
QPushButton *BClear, *BAll;
//the quickset window, when we create it
QuickSet* quickset;
};
#endif

239
src/joyslider.cpp Normal file
View File

@ -0,0 +1,239 @@
#include "joyslider.h"
//Added by qt3to4:
JoySlider::JoySlider( int dz, int xz, int val, QWidget* parent )
:QWidget( parent )
{
//initialize :)
JoyVal = val;
DeadZone = dz;
XZone = xz;
setMinimumHeight(20);
}
void JoySlider::setValue( int newval )
{
//adjust the new position based on the throttle settings
if (throttle == 0) JoyVal = newval;
else if (throttle < 0) JoyVal = (newval + JOYMIN) / 2;
else JoyVal = (newval + JOYMAX) / 2;
//then redraw!
update();
}
void JoySlider::setThrottle( int newval )
{
//change throttle settings. This WILL quite likely cause minor issues with
//status if the axis is not currently at zero, but these will be corrected
//as soon as the axis moves again.
throttle = newval;
update();
}
int JoySlider::pointFor( int value, bool negative )
{
//complicated... this just finds the pixel the given value should be.
if (throttle == 0) {
int result = ((boxwidth - 4) * value) / JOYMAX;
if (negative) result = lboxstart + boxwidth - 2 - result;
else result += rboxstart + 2;
return result;
}
else {
int result = ((twidth - 4) * value) / JOYMAX;
if (negative) result = lboxstart + twidth - 2 - result;
else result += lboxstart + 2;
return result;
}
}
int JoySlider::valueFrom( int point )
{
//the inverse of above :)
if (throttle == 0) {
if (point <= lboxstart) return JOYMAX;
if (point >= lboxend - 2 && point <= rboxstart + 2) return 0;
if (point >= rboxend - 2) return JOYMAX;
if (point < lboxend - 2) return ((lboxend - point) * JOYMAX) / boxwidth;
if (point > rboxstart) return ((point - rboxstart) * JOYMAX) / boxwidth;
else return 0;
}
else if (throttle > 0) {
if (point <= lboxstart) return 0;
else if (point >= tend) return JOYMAX;
else return ((point - lboxstart) * JOYMAX) / twidth;
}
else {
if (point <= lboxstart - 2) return JOYMAX;
else if (point >= tend) return 0;
else return ((tend - point) * JOYMAX) / twidth;
}
}
void JoySlider::resizeEvent( QResizeEvent* )
{
//when we resize, we need to recalculate a bunch of measurements.
boxwidth = (this->width() - 6) / 2 - 1;
twidth = this->width() - 4;
boxheight = this->height() - 4;
lboxstart = 1;
lboxend = lboxstart + boxwidth - 1;
tend = lboxstart + twidth - 1;
rboxstart = lboxend + 5;
rboxend = rboxstart + boxwidth - 1;
}
void JoySlider::drawBox( int x, int width ) {
//draws a nice, pretty, 3d-styled box. that takes up the full height of the
//widget but is defined by x-coordinate and width
QPainter paint( this );
paint.setPen( (isEnabled())?Qt::white:palette().background().color() );
paint.setBrush( (isEnabled())?Qt::white:palette().background() );
paint.drawRect( x, 1, width, boxheight);
paint.setPen( palette().dark().color() );
paint.drawLine( x, 1 + boxheight, x, 1 );
paint.drawLine( x, 1, x + width - 1, 1);
paint.setPen( palette().shadow().color() );
paint.drawLine( x + 1, 1 + boxheight - 1, x + 1, 2);
paint.drawLine( x + 1, 2, x + width - 2, 2);
paint.setPen( palette().light().color() );
paint.drawLine( x + 2, 1 + boxheight - 1, x + width - 1, 1 + boxheight - 1);
paint.drawLine( x + width - 1, 1 + boxheight - 1, x + width - 1, 2);
paint.setPen( palette().midlight().color() );
paint.drawLine( x + 1, 1 + boxheight, x + width, 1 + boxheight );
paint.drawLine( x + width, 1 + boxheight, x + width, 1 );
}
void JoySlider::paintEvent( QPaintEvent* )
{
//when we need to redraw,
//start by making our boxes
if (throttle == 0) {
drawBox( lboxstart, boxwidth );
drawBox( rboxstart, boxwidth );
}
//or box, if we are in throttle mode.
else {
drawBox( lboxstart, twidth );
}
//if this is disabled, that's enough of that.
if (!isEnabled()) return;
//now we need to draw.
QPainter paint( this );
//prepare to draw a bar of the appropriate color
QColor bar;
if (abs(JoyVal) < DeadZone) bar = Qt::gray;
else if (abs(JoyVal) < XZone) bar = Qt::blue;
else bar = Qt::red;
paint.setPen( bar );
paint.setBrush( bar );
//find out the dimensions of the bar, then draw it
int width = (throttle == 0)?boxwidth:twidth;
int barlen = abs(((width - 4) * JoyVal) / JOYMAX);
if (JoyVal > 0)
paint.drawRect( ((throttle == 0)?rboxstart:lboxstart) + 2, 3, barlen, boxheight - 3 );
else if (JoyVal < 0)
paint.drawRect( lboxstart + width - 2 - barlen, 3, barlen, boxheight - 3 );
//and now draw the tabs! We only need one set if we're doing a throttle mode
//but we need two if we're not. However, it's important to draw the right
//set of tabs depending on the mode! Negative throttle gets negative tabs.
int point;
QPolygon shape;
paint.setPen( Qt::black );
paint.setBrush( Qt::blue );
if (throttle >= 0) {
point = pointFor(DeadZone, false);
shape.putPoints(0,5,
point, boxheight - 4,
point + 3, boxheight - 1,
point + 3, boxheight + 2,
point - 3, boxheight + 2,
point - 3, boxheight - 1);
paint.drawPolygon(shape);
}
if (throttle <= 0) {
point = pointFor(DeadZone, true);
shape.putPoints(0,5,
point, boxheight - 4,
point + 3, boxheight - 1,
point + 3, boxheight + 2,
point - 3, boxheight + 2,
point - 3, boxheight - 1);
paint.drawPolygon(shape);
}
paint.setBrush( Qt::red );
if (throttle >= 0) {
point = pointFor(XZone, false);
shape.putPoints(0,5,
point, boxheight - 4,
point + 3, boxheight - 1,
point + 3, boxheight + 2,
point - 3, boxheight + 2,
point - 3, boxheight - 1);
paint.drawPolygon(shape);
}
if (throttle <= 0) {
point = pointFor(XZone, true);
shape.putPoints(0,5,
point, boxheight - 4,
point + 3, boxheight - 1,
point + 3, boxheight + 2,
point - 3, boxheight + 2,
point - 3, boxheight - 1);
paint.drawPolygon(shape);
}
}
void JoySlider::mousePressEvent( QMouseEvent* e )
{
//store the x coordinate.
int xpt = e->x();
int result = 0;
//see if this happened near one of the tabs. If so, start dragging that tab.
if (throttle <= 0 && abs( xpt - pointFor( XZone, true )) < 5) result = DRAG_XZ;
else if (throttle <= 0 && abs( xpt - pointFor( DeadZone, true )) < 5) result = DRAG_DZ;
else if (throttle >= 0 && abs( xpt - pointFor( XZone, false )) < 5) result = DRAG_XZ;
else if (throttle >= 0 && abs( xpt - pointFor( DeadZone, false )) < 5) result = DRAG_DZ;
dragging = result;
};
void JoySlider::mouseReleaseEvent( QMouseEvent* )
{
//when the mouse releases, all dragging stops.
dragging = 0;
}
void JoySlider::mouseMoveEvent( QMouseEvent* e )
{
//get the x coordinate
int xpt = e->x();
//if we're dragging, move the appropriate tab!
if (dragging == DRAG_XZ)
{
XZone = valueFrom( xpt );
}
else if (dragging == DRAG_DZ)
{
DeadZone = valueFrom( xpt );
}
else return;
//if we moved a tab, redraw!
update();
}

76
src/joyslider.h Normal file
View File

@ -0,0 +1,76 @@
#ifndef Q_JOYSLIDER_H
#define Q_JOYSLIDER_H
//the parent of this
#include <stdlib.h>
#include <QResizeEvent>
#include <QPaintEvent>
#include <QMouseEvent>
#include <QPainter>
#include <QFrame>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QComboBox>
#include <QSpinBox>
#include "constant.h"
//dragging constants.
//When dragging == DRAG_XZ, that means we are currently dragging the xZone mark
#define DRAG_XZ 1
//When dragging == DRAG_DZ, that means we are currently dragging the dZone mark
#define DRAG_DZ 2
class JoySlider : public QWidget
{
public:
JoySlider( int dz, int xz, int val, QWidget* parent );
//set where the axis physically is
void setValue( int );
//change the throttle mode
void setThrottle( int );
//get the current settings
int dZone() { return DeadZone; };
int xZone() { return XZone; };
protected:
//all for getting the widget to look right:
void drawBox( int x, int width );
void paintEvent( QPaintEvent* );
void resizeEvent( QResizeEvent* );
//for working with drag and drop:
void mousePressEvent( QMouseEvent* e );
void mouseReleaseEvent( QMouseEvent* );
void mouseMoveEvent( QMouseEvent* e );
private:
//dimensions of the box to draw!
int boxwidth;
int boxheight;
int rboxstart;
int rboxend;
int lboxstart;
int lboxend;
int twidth;
int tend;
//the throttle mode
int throttle;
//convert from joystick value to pixel position on the widget
//negative refers to whether or not we're on the "negative" end
//of the widget
int pointFor( int value, bool negative );
//convert from pixel position to joystick value
int valueFrom( int point );
//the current drag and drop state
int dragging;
//the axis' position
int JoyVal;
//the dead and extreme zone values
int DeadZone;
int XZone;
};
#endif

104
src/keycode.cpp Normal file
View File

@ -0,0 +1,104 @@
#include "keycode.h"
#include "getkey.h"
const QString ktos( int keycode )
{
if (keycode > MAXKEY || keycode < 0) keycode = 0;
if (keycode == 0) return "[NO KEY]";
QString xname = XKeysymToString(XKeycodeToKeysym(display, keycode,0));
//this section of code converts standard X11 keynames into much nicer names
//which are prettier, fit the dialogs better, and are more readily understandable.
//This is really ugly and I wish I didn't have to do this... that's why there
//is a config option to define PLAIN_KEYS and drop this whole section of code,
//instead using the default names for keys.
#ifndef PLAIN_KEYS
//the following code assumes xname is system independent and always
//in the same exact format.
QRegExp rx;
rx.setPattern("^\\w$");
//"a-z" -> "A-Z"
if (rx.exactMatch(xname)) return xname.toUpper();
rx.setPattern("(.*)_(.*)");
if (rx.exactMatch(xname)) {
QString first = rx.cap(1);
QString second = rx.cap(2);
rx.setPattern("^[RL]$");
//"Control_R" -> "R Control"
if (rx.exactMatch(second)) return second + " " + first;
rx.setPattern("^(Lock|Enter)$");
//"Caps_Lock" -> "Caps Lock"
//"KP_Enter" -> "KP Enter"
if (rx.exactMatch(second)) return first + " " + second;
//the following assumes all number pads are laid out alike.
if (xname == "KP_Home") return "KP 7";
if (xname == "KP_Up") return "KP 8";
if (xname == "KP_Prior") return "KP 9";
if (xname == "KP_Subtract") return "KP -";
if (xname == "KP_Left") return "KP 4";
if (xname == "KP_Begin") return "KP 5";
if (xname == "KP_Right") return "KP 6";
if (xname == "KP_Add") return "KP +";
if (xname == "KP_End") return "KP 1";
if (xname == "KP_Down") return "KP 2";
if (xname == "KP_Next") return "KP 3";
if (xname == "KP_Insert") return "KP 0";
if (xname == "KP_Delete") return "KP .";
if (xname == "KP_Multiply") return "KP *";
if (xname == "KP_Divide") return "KP /";
return xname;
}
if (xname == "minus") return "-";
if (xname == "equal") return "=";
if (xname == "bracketleft") return "[";
if (xname == "bracketright") return "]";
if (xname == "semicolon") return ";";
if (xname == "apostrophe") return "'";
if (xname == "grave") return "`";
if (xname == "backslash") return "\\";
if (xname == "comma") return ",";
if (xname == "period") return ".";
if (xname == "slash") return "/";
if (xname == "space") return "Space";
if (xname == "Prior") return "PageUp";
if (xname == "Next") return "PageDown";
#endif
//if none of that succeeded,
return xname;
}
KeyButton::KeyButton( QString name, int val, QWidget* parent, bool m, bool nowMouse)
:QPushButton(nowMouse?"Mouse " + QString::number(val):QString(ktos(val)), parent) {
mouse = m;
mouseClicked = nowMouse;
buttonname = name;
value = val;
connect( this, SIGNAL( clicked() ), SLOT( onClick() ));
}
void KeyButton::onClick() {
//when clicked, ask for a key!
value = GetKey( buttonname, mouse ).exec();
//if the return value was a mouse click...
if (value > MOUSE_OFFSET) {
mouseClicked = true;
value -= MOUSE_OFFSET;
setText( "Mouse " + QString::number(value));
}
//otherwise, it was a key press!
else {
mouseClicked = false;
setText( ktos(value));
}
}

36
src/keycode.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef KEYCODE_H
#define KEYCODE_H
//To create the "press a key" dialog:
#include <QPushButton>
#include <QDialog>
#include <QPaintEvent>
#include <QPainter>
#include "constant.h"
//Produce a string for any keycode
const QString ktos( int keycode );
//The X11 display, taken from main.cpp
extern Display* display;
//a button that requests a keycode from the user when clicked.
class KeyButton : public QPushButton {
Q_OBJECT
public:
KeyButton(QString name, int val, QWidget* parent, bool m = false, bool nowMouse = false);
int getValue() {return value;};
int choseMouse() {return mouseClicked;};
protected slots:
void onClick();
private:
QString buttonname;
int value;
bool mouse;
bool mouseClicked;
};
#endif

390
src/layout.cpp Normal file
View File

@ -0,0 +1,390 @@
#include "layout.h"
#include <errno.h>
//initialize things and set up an icon :)
LayoutManager::LayoutManager( bool useTrayIcon ) {
//no LayoutEdit yet.
le = NULL;
//prepare the popup first.
Popup = new QMenu();
fillPopup();
connect(Popup,SIGNAL(triggered(QAction*)),this, SLOT(trayMenu(QAction*)));
//make a tray icon
if (useTrayIcon) {
TrayIcon* Tray = new TrayIcon(QPixmap(ICON24),NAME,Popup,0,"tray");
connect(Tray, SIGNAL( clicked(const QPoint&, int)), this, SLOT( trayClick()));
Tray->show();
}
//or make a floating icon
else {
FloatingIcon* Icon = new FloatingIcon(QPixmap(ICON64),Popup,0,"tray");
connect(Icon, SIGNAL( clicked()), this, SLOT( trayClick()));
connect(Icon, SIGNAL( closed()), qApp, SLOT( quit()));
Icon->show();
}
//no layout loaded at start.
setLayoutName(NL);
}
QString LayoutManager::getFileName( QString layoutname ) {
return settingsDir + layoutname + ".lyt";
}
bool LayoutManager::load(const QString& name) {
//it's VERY easy to load NL :)
if (name == NL) {
clear();
return true;
}
QFile file(getFileName(name));
//if the file isn't available,
if (!file.exists()) {
error("Load error","Failed to find a layout named " + name);
return false;
}
//if the file isn't readable,
if (!file.open(QIODevice::ReadOnly)) {
error("Load error","Error reading from file " + file.fileName());
return false;
}
//reset all the joypads.
//note that we don't use available here, but joypads instead. This is so
//if one layout has more joypads than this one does, this won't have the
//extra settings left over after things are supposed to be "cleared"
QHashIterator<int, JoyPad*> it( joypads );
while (it.hasNext())
{
it.next();
it.value()->toDefault();
}
//start reading joypads!
QTextStream stream( &file );
QString input = stream.readLine().toLower();
QRegExp quoted("\"(.*)\"");
bool okay;
int num;
while (input != QString::null) {
QStringList words = input.split(" ");
//if this line is specifying a joystick
if (words[0] == "joystick") {
num = words[1].toInt(&okay);
//make sure the number of the joystick is valid
if (!okay || okay < 1) {
error( "Load error", "Error reading joystick definition. Expected: Joysyick 1 {");
if (name != CurrentLayout) reload();
else clear();
return false;
}
//if there was no joypad defined for this index before, make it now!
if (joypads[num-1] == 0) {
joypads.insert(num-1, new JoyPad(num-1, 0));
}
//try to read the joypad, report error on fail.
if (!joypads[num-1]->readConfig(&stream)) {
error( "Load error", "Error reading definition for joystick " + QString::number(num-1));
//if this was attempting to change to a new layout and it failed,
//revert back to the old layout.
if (name != CurrentLayout) reload();
//to keep from going into an infinite loop, if there is no good
//layout to fall back on, go to NL.
else clear();
return false;
}
}
//read a new line.
input = stream.readLine().toLower();
}
//if loading succeeded, this is our new layout.
setLayoutName(name);
return true;
}
bool LayoutManager::load() {
//try to load the file named "layout" to retrieve the last used layout name
QFile file( settingsDir + "layout");
QString name;
if (file.open(QIODevice::ReadOnly)) {
QTextStream stream(&file);
name = stream.readLine();
file.close();
//if there was no name, don't load.
if (name == "") {
return false;
}
//if there was a name, try to load it! Note, this will still return
//false if the name is invalid ( see load() )
return load(name);
}
//if the file isn't available to open, don't load.
return false;
}
bool LayoutManager::reload() {
return load(CurrentLayout);
}
void LayoutManager::clear() {
//reset all the joypads...
QHashIterator<int, JoyPad*> it (joypads);
while (it.hasNext())
{
it.next();
it.value()->toDefault();
}
//and call our layout NL
setLayoutName(NL);
}
void LayoutManager::save() {
if (CurrentLayout == NL) {
saveAs();
return;
}
//get a filename
QString filename = getFileName( CurrentLayout );
QFile file(filename);
//if it's good, start writing the file
if (file.open(QIODevice::WriteOnly)) {
QTextStream stream( &file );
stream << "# "NAME" Layout File\n\n";
QHashIterator<int, JoyPad*> it (joypads);
while (it.hasNext())
{
it.next();
it.value()->write( &stream );
}
file.close();
}
//if it's not, error.
else
error("Save error", "Could not open file " + filename + ", layout not saved.");
}
void LayoutManager::saveAs() {
bool ok;
//request a new name!
QString name = QInputDialog::getText(0, NAME" - Name new layout","Enter a name for the new layout:", QLineEdit::Normal, QString::null, &ok );
if (!ok) {
return;
}
QFile file(settingsDir + name + ".lyt");
//don't overwrite an existing layout.
if (file.exists()) {
error("Save error", "That name's already taken!");
return;
}
//now that the new layout has a name, that is the name we should use.
setLayoutName(name);
//since we have a new name for this layout now, we can save it normally :)
save();
//add the new name to our lists
fillPopup();
if (le != NULL) {
le->updateLayoutList();
}
printf("returning, user provided input\n");
}
void LayoutManager::saveDefault() {
QFile file( settingsDir + "layout");
if (file.open(QIODevice::WriteOnly)) {
QTextStream stream(&file);
stream << CurrentLayout;
file.close();
}
}
void LayoutManager::remove() {
if (CurrentLayout == NL) return;
if (QMessageBox::warning( 0, NAME" - Delete layout?","Remove layout permanently from your hard drive?", "Yes", "No", 0, 0, 1 ) == 1) return;
QString filename = getFileName( CurrentLayout );
if (!QFile(filename).remove()) {
error("Remove error", "Could not remove file " + filename);
}
fillPopup();
if (le != NULL) {
le->updateLayoutList();
}
clear();
}
QStringList LayoutManager::getLayoutNames() {
//goes through the list of .lyt files and removes the file extensions ;)
QStringList result = QDir(settingsDir).entryList(QStringList("*.lyt"));
for ( QStringList::Iterator it = result.begin(); it != result.end(); ++it ) {
*it = (*it).left((*it).length() - 4);
}
//and, of course, there's always NL.
result.prepend(NL);
return result;
}
void LayoutManager::setLayoutName(QString name) {
CurrentLayout = name;
fillPopup();
if (le != NULL) {
le->setLayout(name);
}
}
void LayoutManager::trayClick() {
//don't show the dialog if there aren't any joystick devices plugged in
if (available.count() == 0) {
error("No joystick devices available","No joystick devices are currently available to configure.\nPlease plug in a gaming device and select\n\"Update Joystick Devices\" from the popup menu.");
return;
}
//otherwise, make a new LayoutEdit dialog and show it.
le = new LayoutEdit(this);
le->setLayout(CurrentLayout);
//note, this will cause the menu to hang. You cannot use the menu while the
//dialog is active. I'd rather it not work out that way, but this makes my
//code MUCH simpler for a small inconvenience that shouldn't matter. For
//instance, I don't have to worry about the current joysticks changing
//while there's a dialog and therefore adjusting the dialog to match.
le->exec();
delete le;
le = NULL;
}
void LayoutManager::trayMenu(QAction *menuItemAction) {
//if they clicked on a Layout name, load it!
//note that the other options are handled with their own special functions
printf("%s\n", qPrintable(menuItemAction->text()));
printf("oh hi\n");
//printf("%d\n", Popup->
if (Popup->actions().indexOf(menuItemAction) > 1 && menuItemAction->text() != "Quit" &&
menuItemAction->text() != "Update lyaout list" &&
menuItemAction->text() != "Update joystick devices") {
load(menuItemAction->text());
}
}
void LayoutManager::fillPopup() {
printf("starting fillPopup\n");
//start with an empty slate
Popup->clear();
//make a list of joystick devices
QString devs = "Joysticks: ";
QHashIterator<int, JoyPad*> it( available );
while (it.hasNext())
{
it.next();
devs += QString::number(it.key() + 1) + " ";
}
QAction *temp = Popup->addAction(devs);
Popup->addSeparator(/*temp*/);
//add in the Update options
QAction *tempAdd = new QAction("Update layout list", this);
connect(tempAdd, SIGNAL(triggered(bool)), this, SLOT(fillPopup()));
Popup->addAction(tempAdd);
tempAdd = new QAction("Update joystick devices", this);
connect(tempAdd, SIGNAL(triggered(bool)), this, SLOT(updateJoyDevs()));
Popup->addAction(tempAdd);
Popup->addSeparator(/*temp*/);
//then add all the layout names
QStringList names = getLayoutNames();
for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it ) {
temp = Popup->addAction(*it);
temp->setCheckable(true);
//put a check by the current one ;)
if (CurrentLayout == (*it)) {
temp->setChecked(true);
}
}
Popup->addSeparator();
//and, at the end, quit!
Popup->addAction("Quit",qApp,SLOT(quit()));
printf("returning from fill popup\n");
}
void LayoutManager::updateJoyDevs() {
printf("entering update JoyDevs\n");
QString devdir = DEVDIR;
//reset all joydevs to sentinal value (-1)
do {
QHashIterator<int, JoyPad*> it( joypads );
while (it.hasNext() ) {
it.next();
it.value()->unsetDev();
}
} while (0);
//clear out the list of previously available joysticks
available.clear();
//set all joydevs anew (create new JoyPad's if necesary)
QDir DeviceDir(devdir);
QStringList devices = DeviceDir.entryList(QStringList("js*"), QDir::System );
QRegExp devicename(".*\\js(\\d+)");
int joydev;
int index;
//for every joystick device in the directory listing...
//(note, with devfs, only available devices are listed)
for (QStringList::Iterator it = devices.begin(); it != devices.end(); ++it) {
//try opening the device.
printf("%s\n", qPrintable(devdir + "/" + (*it)));
joydev = open( qPrintable(devdir + "/" + (*it)), O_RDONLY | O_NONBLOCK);
//if it worked, then we have a live joystick! Make sure it's properly
//setup.
if (joydev > 0) {
printf("joystick found, constructing...\n");
devicename.indexIn(*it);
index = QString(devicename.cap(1)).toInt();
JoyPad* joypad;
//if we've never seen this device before, make a new one!
if (joypads[index] == 0) {
struct pollfd read_struct;
read_struct.fd = joydev;
read_struct.events = POLLIN;
char buf[10];
while(poll(&read_struct, 1, 2)!=0) {
printf("reading junk data\n");
read(joydev, buf, 10);
}
joypad = new JoyPad( index, joydev );
joypads.insert(index,joypad);
}
else {
printf("resetting to dev...\n");
joypad = joypads[index];
joypad->resetToDev(joydev);
}
//make this joystick device available.
available.insert(index,joypad);
}
else {
int errsv = errno;
printf("well fuck!\n");
printf("%s\n", strerror(errsv));
}
}
printf("done rebuilding joystick devices\n");
//when it's all done, rebuild the popup menu so it displays the correct
//information.
fillPopup();
//the actual update process is handled by main.cpp, we just need to signal
//ourselves to do it.
//raise(SIGUSR1);
printf("returning from rebuild function\n");
}

88
src/layout.h Normal file
View File

@ -0,0 +1,88 @@
#ifndef JOY_LAYOUT_H
#define JOY_LAYOUT_H
//to allow for interprocess communications (ie, signaling a running instance of
//qjoypad by running "qjoypad layout-name", etc.) QJoyPad uses signals to
//triger certain events. This is for signaling the main program to update
//the joystick device list.
#include <signal.h>
#include <QAction>
#include <QDir>
#include <QMenu>
#include <QApplication>
#include <QDialog>
#include <QInputDialog>
#include <poll.h>
//a layout handles several joypads
#include "joypad.h"
//for errors
#include "error.h"
//so we know which joypads have RL equivalents
#include "device.h"
//to display the tray icon
#include "trayicon/trayicon.h"
//For displaying a floating icon instead of a tray icon
#include "icon.h"
//So we can know if there is a graphical version of the Layout Manager displayed
#include "layout_edit.h"
//for recognizing when the special empty layout is in use
#define NL "[NO LAYOUT]"
//where QJoyPad saves its settings!
const QString settingsDir(QDir::homePath() + "/.qjoypad3/");
//handles loading, saving, and changing of layouts
class LayoutManager : public QObject {
friend class LayoutEdit;
Q_OBJECT
public:
LayoutManager( bool useTrayIcon);
//produces a list of the names of all the available layout.
QStringList getLayoutNames();
public slots:
//load a layout with a given name
bool load(const QString& name);
//look for the last loaded layout and try to load that.
bool load();
//load the current layout, overwriting any changes made to it.
bool reload();
//reset to a blank, empty layout
void clear();
//save the current layout with its current name
void save();
//save the current layout with a new name
void saveAs();
//save the currently loaded layout so it can be recalled later
void saveDefault();
//get rid of a layout
void remove();
//when the tray icon is clicked
void trayClick();
//when the user selects an item on the tray's popup menu
void trayMenu(QAction* menuItemAction);
//rebuild the popup menu with the current information
void fillPopup();
//update the list of available joystick devices
void updateJoyDevs();
private:
//change to the given layout name and make all the necesary adjustments
void setLayoutName(QString name);
//get the file name for a layout name
QString getFileName( QString layoutname );
//the layout that is currently in use
QString CurrentLayout;
//the popup menu from the tray/floating icon
QMenu* Popup;
//if there is a LayoutEdit open, this points to it. Otherwise, NULL.
LayoutEdit* le;
};
#endif

132
src/layout_edit.cpp Normal file
View File

@ -0,0 +1,132 @@
#include "layout_edit.h"
//build the dialog
LayoutEdit::LayoutEdit( LayoutManager* l ) {
lm = l;
setWindowTitle( NAME );
setWindowIcon(QPixmap(ICON24));
LMain = new QVBoxLayout( this);
LMain->setSpacing(5);
LMain->setMargin(5);
QFrame* frame = new QFrame(this);
frame->setFrameStyle(QFrame::Box | QFrame::Sunken );
QGridLayout* g = new QGridLayout(frame);
g->setMargin(5);
g->setSpacing(5);
CLayouts = new QComboBox(frame);
connect( CLayouts, SIGNAL(activated( const QString& )), lm, SLOT(load(const QString&)));
g->addWidget(CLayouts,0,0,1,4);
//most of these buttons can link directly into slots in the LayoutManager
BAdd = new QPushButton("Add", frame);
connect(BAdd, SIGNAL(clicked()), lm, SLOT(saveAs()));
g->addWidget(BAdd,1,0);
BRem = new QPushButton("Remove", frame);
connect(BRem, SIGNAL(clicked()), lm, SLOT(remove()));
g->addWidget(BRem,1,1);
BUpd = new QPushButton("Update", frame);
connect(BUpd, SIGNAL(clicked()), lm, SLOT(save()));
g->addWidget(BUpd,1,2);
BRev = new QPushButton("Revert", frame);
connect(BRev, SIGNAL(clicked()), lm, SLOT(reload()));
g->addWidget(BRev,1,3);
LMain->addWidget( frame );
//produce a list of names for the FlashRadioArray
//this is only necesary since joystick devices need not always be
//contiguous
int padcount = available.count();
QString names[padcount];
int i = 0;
do
{
QHashIterator<int, JoyPad*> it( available );
while (it.hasNext())
{
it.next();
names[i] = it.value()->getName();
++i;
}
} while (0);
//flash radio array
JoyButtons = new FlashRadioArray(padcount, names, true, this );
LMain->addWidget( JoyButtons );
//we have a WidgetStack to represent the multiple joypads
PadStack = new QStackedWidget( this );
PadStack->setFrameStyle(QFrame::Box | QFrame::Sunken );
LMain->addWidget(PadStack);
//go through each of the available joysticks
i = 0; // i is the current index into PadStack
do
{
QHashIterator<int, JoyPad*> it(available);
while (it.hasNext())
{
it.next();
//add a new JoyPadWidget to the stack
PadStack->insertWidget( i,it.value()->widget(PadStack,i) );
//every time it "flashes", flash the associated tab.
connect( PadStack->widget(i), SIGNAL( flashed( int ) ), JoyButtons, SLOT( flash( int )));
++i;
}
} while (0);
//whenever a new tab is selected, raise the appropriate JoyPadWidget
connect( JoyButtons, SIGNAL( changed( int ) ), PadStack, SLOT( setCurrentIndex( int )));
updateLayoutList();
//add the buttons at the bottom.
QHBoxLayout* h = new QHBoxLayout(0);
h->setMargin(0);
h->setSpacing(5);
QPushButton* close = new QPushButton( "-- Close Dialog --", this );
connect(close, SIGNAL(clicked()), this, SLOT(close()));
h->addWidget(close);
QPushButton* quit = new QPushButton( "-- Quit --", this );
connect( quit, SIGNAL( clicked() ), qApp, SLOT(quit()));
h->addWidget(quit);
LMain->addLayout(h);
blockEvents = false;
}
void LayoutEdit::setLayout(QString layout) {
//change the text,
CLayouts->setItemText(CLayouts->currentIndex(), layout);
//update all the JoyPadWidgets.
for (uint i = 0; i < available.count(); i++) {
((JoyPadWidget*)PadStack->widget(i))->update();
}
}
void LayoutEdit::updateLayoutList() {
//blank the list, then load in new names from the LayoutManager.
CLayouts->clear();
QStringList layouts = lm->getLayoutNames();
//For some reason, insertStringList doesn't want to work for me!
for ( QStringList::Iterator it = layouts.begin(); it != layouts.end(); ++it ) {
CLayouts->insertItem(-1,*it);
}
CLayouts->setItemText(CLayouts->currentIndex(), lm->CurrentLayout);
}
void LayoutEdit::windowActivationChange( bool oldActive ) {
if (oldActive) return;
//whenever the window becomes active, release all pressed buttons! This way
//you don't get any presses without releases to confuse things.
blockEvents = true;
QHashIterator<int, JoyPad*> it( available );
while (it.hasNext())
{
printf("iterating and releasing\n");
it.next();
it.value()->release();
}
printf("done releasing!\n");
blockEvents = false;
}

40
src/layout_edit.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef LAYOUT_EDIT_H
#define LAYOUT_EDIT_H
#include <QStackedWidget>
//for the tab list of joypads
#include "flash.h"
//this is a front end for the non-GUI LayoutManager
class LayoutEdit;
#include "layout.h"
//so we can see the available devices
#include "device.h"
//so we can use the LayoutEditer to edit key layouts :)
#include "joypadw.h"
class LayoutManager;
class LayoutEdit : public QDialog {
public:
LayoutEdit( LayoutManager* l );
//swap to a new layout
void setLayout(QString layout);
//update the list of available layouts
void updateLayoutList();
protected:
//the layout manager this represents
LayoutManager* lm;
//find out when the window is activated.
virtual void windowActivationChange( bool oldActive );
bool blockEvents;
//parts of the dialog:
QVBoxLayout *LMain;
QStackedWidget *PadStack;
FlashRadioArray *JoyButtons;
QComboBox* CLayouts;
QPushButton *BAdd, *BRem, *BUpd, *BRev;
};
#endif

275
src/main.cpp Normal file
View File

@ -0,0 +1,275 @@
#define MAIN
//to create a qapplication
#include <QFile>
//for ouput when there is no GUI going
#include <stdio.h>
//to create and handle signals for various events
#include <signal.h>
//to load layouts
#include "layout.h"
//to give event.h the current X11 display
#include "event.h"
//to update the joystick device list
#include "device.h"
//to produce errors!
#include "error.h"
#include <QX11Info>
#include <poll.h>
#include <cstdlib>
//for making universally available variables
extern Display* display; //from event.h
QHash<int, JoyPad*> available; //to device.h
QHash<int, JoyPad*> joypads; //to device.h
//variables needed in various functions in this file
LayoutManager* lm;
QString devdir = DEVDIR;
//update the joystick devices!
void buildJoyDevices() {
//reset all joydevs to sentinal value (-1)
do {
QHashIterator<int, JoyPad*> it( joypads );
while (it.hasNext() ) {
it.next();
it.value()->unsetDev();
}
} while (0);
//clear out the list of previously available joysticks
available.clear();
//set all joydevs anew (create new JoyPad's if necesary)
QDir DeviceDir(devdir);
QStringList devices = DeviceDir.entryList(QStringList("js*"), QDir::System );
QRegExp devicename(".*\\js(\\d+)");
int joydev;
int index;
//for every joystick device in the directory listing...
//(note, with devfs, only available devices are listed)
for (QStringList::Iterator it = devices.begin(); it != devices.end(); ++it) {
//try opening the device.
joydev = open( (devdir + "/" + (*it)).toStdString().c_str(), O_RDONLY | O_NONBLOCK);
//if it worked, then we have a live joystick! Make sure it's properly
//setup.
if (joydev > 0) {
devicename.indexIn(*it);
index = QString(devicename.cap(1)).toInt();
JoyPad* joypad;
//if we've never seen this device before, make a new one!
if (joypads[index] == 0) {
struct pollfd read_struct;
read_struct.fd = joydev;
read_struct.events = POLLIN;
char buf[10];
while(poll(&read_struct, 1, 2)!=0) {
printf("reading junk data\n");
read(joydev, buf, 10);
}
joypad = new JoyPad( index, joydev );
joypads.insert(index,joypad);
}
else {
joypad = joypads[index];
joypad->resetToDev(joydev);
}
//make this joystick device available.
available.insert(index,joypad);
}
}
printf("done rebuilding joystick devices\n");
//when it's all done, rebuild the popup menu so it displays the correct
//information.
lm->fillPopup();
}
//signal handler for SIGIO
//SIGIO means that a new layout should be loaded. It is saved in
// ~/.qjoypad/layout, where the last used layout is put.
void catchSIGIO( int sig )
{
lm->load();
//remember to catch this signal again next time.
signal( sig, catchSIGIO );
}
//signal handler for SIGUSR1
//SIGUSR1 means that we should update the available joystick device list.
void catchSIGUSR1( int sig ) {
//buildJoyDevices();
lm->updateJoyDevs();
//remember to catch this signal again next time.
signal( sig, catchSIGUSR1 );
}
/* A new feature to add? We'll see.
void catchSIGUSR2( int sig ) {
lm->trayClick();
signal( sig, catchSIGUSR2 );
}
*/
int main( int argc, char **argv )
{
//create a new event loop. This will be captured by the QApplication
//when it gets created
QApplication a( argc, argv );
//where to look for settings. If it does not exist, it will be created
QDir dir(settingsDir);
//if there is no new directory and we can't make it, complain
if (!dir.exists() && !dir.mkdir(settingsDir)) {
printf("Couldn't create the QJoyPad save directory (%s)!", settingsDir.toStdString().c_str());
return 1;
}
//start out with no special layout.
QString layout = "";
//by default, we use a tray icon
bool useTrayIcon = true;
//this execution wasn't made to update the joystick device list.
bool update = false;
//parse command-line options
for (int i = 1; i < a.argc(); i++) {
//if a device directory was specified,
if (QRegExp("-{1,2}device").exactMatch(a.argv()[i])) {
++i;
if (i < a.argc()) {
if (QFile::exists(a.argv()[i])) {
devdir = a.argv()[i];
}
else {
error("Command Line Argument Problems", "No such directory: " + QString(a.argv()[i]));
continue;
}
}
}
//if no-tray mode was requested,
else if (QRegExp("-{1,2}notray").exactMatch(a.argv()[i])) {
useTrayIcon = false;
}
//if this execution is just meant to update the joystick devices,
else if (QRegExp("-{1,2}update").exactMatch(a.argv()[i])) {
update = true;
}
//if help was requested,
else if (QRegExp("-{1,2}h(elp)?").exactMatch(a.argv()[i])) {
printf(NAME"\nUsage: qjoypad [--device \"/device/path\"] [--notray] [\"layout name\"]\n\nOptions:\n --device path Look for joystick devices in \"path\". This should\n be something like \"/dev/input\" if your game\n devices are in /dev/input/js0, /dev/input/js1, etc.\n --notray Do not use a system tray icon. This is useful for\n window managers that don't support this feature.\n --update Force a running instance of QJoyPad to update its\n list of devices and layouts.\n \"layout name\" Load the given layout in an already running\n instance of QJoyPad, or start QJoyPad using the\n given layout.\n");
return 1;
}
//in all other cases, an argument is assumed to be a layout name.
//note: only the last layout name given will be used.
else layout = a.argv()[i];
}
//if the user specified a layout to use,
if (layout != "")
{
//then we try to store that layout in the last-used layout spot, to be
//loaded by default.
QFile file( settingsDir + "layout");
if (file.open(QIODevice::WriteOnly))
{
QTextStream stream( &file );
stream << layout;
file.close();
}
}
//create a pid lock file.
QFile pidFile( "/tmp/qjoypad.pid" );
//if that file already exists, then qjoypad is already running!
if (pidFile.exists())
{
int pid;
if (pidFile.open( QIODevice::ReadOnly ));
{
//try to get that pid...
QTextStream( &pidFile ) >> pid;
pidFile.close();
//if we can signal the pid (ie, if the process is active)
if (kill(pid,0) == 0)
{
//then prevent two instances from running at once.
//however, if we are setting the layout or updating the device
//list, this is not an error and we shouldn't make one!
if (layout == "" && update == false) error("Instance Error","There is already a running instance of QJoyPad; please close\nthe old instance before starting a new one.");
else {
//if one of these is the case, send the approrpriate signal!
if (update == true)
kill(pid,SIGUSR1);
if (layout != "")
kill(pid,SIGIO);
}
//and quit. We don't need two instances.
return 0;
}
}
}
//now we can try to create and write our pid to the lock file.
if (pidFile.open( QIODevice::WriteOnly ))
{
QTextStream( &pidFile ) << getpid();
pidFile.close();
}
//prepare the signal handlers
signal( SIGIO, catchSIGIO );
signal( SIGUSR1, catchSIGUSR1 );
// signal( SIGUSR2, catchSIGUSR2 );
//capture the current display for event.h
display = QX11Info::display();
//create a new LayoutManager with a tray icon / floating icon, depending
//on the user's request
lm = new LayoutManager(useTrayIcon);
//build the joystick device list for the first time,
//buildJoyDevices();
lm->updateJoyDevs();
//load the last used layout (Or the one given as a command-line argument)
lm->load();
//and run the program!
int result = a.exec();
//when everything is done, save the current layout for next time...
lm->saveDefault();
//remove the lock file...
pidFile.remove();
//and terminate!
return result;
}

184
src/portinglog.txt Normal file
View File

@ -0,0 +1,184 @@
Log for qt3to4 on Fri Dec 26 18:59:56 2008. Number of log entries: 101
In file /home/john/qjoypad-3.4.1/src/axis.cpp at line 21 column 28: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/axis.cpp at line 115 column 29: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/axis.cpp: Added the following include directives:
#include <Q3TextStream>
In file /home/john/qjoypad-3.4.1/src/axis_edit.cpp at line 22 column 12: QVBoxLayout -> Q3VBoxLayout
In file /home/john/qjoypad-3.4.1/src/axis_edit.cpp at line 22 column 33: QVBoxLayout -> Q3VBoxLayout
In file /home/john/qjoypad-3.4.1/src/axis_edit.cpp at line 24 column 12: QHBoxLayout -> Q3HBoxLayout
In file /home/john/qjoypad-3.4.1/src/axis_edit.cpp at line 24 column 33: QHBoxLayout -> Q3HBoxLayout
In file /home/john/qjoypad-3.4.1/src/axis_edit.cpp at line 25 column 13: QVBoxLayout -> Q3VBoxLayout
In file /home/john/qjoypad-3.4.1/src/axis_edit.cpp at line 25 column 35: QVBoxLayout -> Q3VBoxLayout
In file /home/john/qjoypad-3.4.1/src/axis_edit.cpp at line 41 column 23: QFrame -> Q3Frame
In file /home/john/qjoypad-3.4.1/src/axis_edit.cpp at line 42 column 33: QFrame -> Q3Frame
In file /home/john/qjoypad-3.4.1/src/axis_edit.cpp at line 42 column 47: QFrame -> Q3Frame
In file /home/john/qjoypad-3.4.1/src/axis_edit.cpp at line 43 column 22: QVBoxLayout -> Q3VBoxLayout
In file /home/john/qjoypad-3.4.1/src/axis_edit.cpp at line 54 column 20: QFrame -> Q3Frame
In file /home/john/qjoypad-3.4.1/src/axis_edit.cpp at line 55 column 30: QFrame -> Q3Frame
In file /home/john/qjoypad-3.4.1/src/axis_edit.cpp at line 55 column 44: QFrame -> Q3Frame
In file /home/john/qjoypad-3.4.1/src/axis_edit.cpp at line 56 column 20: QHBoxLayout -> Q3HBoxLayout
In file /home/john/qjoypad-3.4.1/src/axis_edit.cpp at line 70 column 20: QHBoxLayout -> Q3HBoxLayout
In file /home/john/qjoypad-3.4.1/src/axis_edit.cpp: Added the following include directives:
#include <QPixmap> #include <Q3HBoxLayout> #include <Q3VBoxLayout> #include <QLabel> #include <Q3Frame>
In file /home/john/qjoypad-3.4.1/src/axisw.cpp: Added the following include directives:
#include <QMouseEvent>
In file /home/john/qjoypad-3.4.1/src/button.cpp at line 18 column 30: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/button.cpp at line 64 column 31: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/button.cpp: Added the following include directives:
#include <Q3TextStream>
In file /home/john/qjoypad-3.4.1/src/button_edit.cpp at line 14 column 12: QVBoxLayout -> Q3VBoxLayout
In file /home/john/qjoypad-3.4.1/src/button_edit.cpp at line 14 column 33: QVBoxLayout -> Q3VBoxLayout
In file /home/john/qjoypad-3.4.1/src/button_edit.cpp at line 19 column 12: QHBoxLayout -> Q3HBoxLayout
In file /home/john/qjoypad-3.4.1/src/button_edit.cpp at line 19 column 33: QHBoxLayout -> Q3HBoxLayout
In file /home/john/qjoypad-3.4.1/src/button_edit.cpp at line 28 column 20: QHBoxLayout -> Q3HBoxLayout
In file /home/john/qjoypad-3.4.1/src/button_edit.cpp: Added the following include directives:
#include <Q3VBoxLayout> #include <QPixmap> #include <Q3HBoxLayout>
In file /home/john/qjoypad-3.4.1/src/buttonw.cpp: Added the following include directives:
#include <QMouseEvent>
No changes made to file /home/john/qjoypad-3.4.1/src/event.cpp
In file /home/john/qjoypad-3.4.1/src/flash.cpp at line 56 column 25: QHBoxLayout -> Q3HBoxLayout
In file /home/john/qjoypad-3.4.1/src/flash.cpp at line 58 column 25: QVBoxLayout -> Q3VBoxLayout
In file /home/john/qjoypad-3.4.1/src/flash.cpp: Added the following include directives:
#include <Q3VBoxLayout> #include <Q3HBoxLayout>
In file /home/john/qjoypad-3.4.1/src/icon.cpp at line 7 column 20: qpopupmenu.h -> q3popupmenu.h
In file /home/john/qjoypad-3.4.1/src/icon.cpp at line 9 column 59: QPopupMenu -> Q3PopupMenu
In file /home/john/qjoypad-3.4.1/src/icon.cpp: Added the following include directives:
#include <QPixmap> #include <QCloseEvent> #include <QMouseEvent>
In file /home/john/qjoypad-3.4.1/src/joypad.cpp at line 42 column 26: QIntDictIterator -> Q3IntDictIterator
In file /home/john/qjoypad-3.4.1/src/joypad.cpp at line 44 column 26: QIntDictIterator -> Q3IntDictIterator
In file /home/john/qjoypad-3.4.1/src/joypad.cpp at line 50 column 26: QIntDictIterator -> Q3IntDictIterator
In file /home/john/qjoypad-3.4.1/src/joypad.cpp at line 52 column 26: QIntDictIterator -> Q3IntDictIterator
In file /home/john/qjoypad-3.4.1/src/joypad.cpp at line 57 column 30: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/joypad.cpp at line 114 column 31: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/joypad.cpp at line 117 column 12: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/joypad.cpp at line 117 column 33: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/joypad.cpp at line 117 column 55: IO_WriteOnly -> QIODevice::WriteOnly
In file /home/john/qjoypad-3.4.1/src/joypad.cpp at line 119 column 26: QIntDictIterator -> Q3IntDictIterator
In file /home/john/qjoypad-3.4.1/src/joypad.cpp at line 126 column 26: QIntDictIterator -> Q3IntDictIterator
In file /home/john/qjoypad-3.4.1/src/joypad.cpp at line 139 column 26: QIntDictIterator -> Q3IntDictIterator
In file /home/john/qjoypad-3.4.1/src/joypad.cpp at line 142 column 26: QIntDictIterator -> Q3IntDictIterator
In file /home/john/qjoypad-3.4.1/src/joypad.cpp: Added the following include directives:
#include <Q3TextStream>
In file /home/john/qjoypad-3.4.1/src/joypadw.cpp at line 10 column 24: QGridLayout -> Q3GridLayout
In file /home/john/qjoypad-3.4.1/src/joypadw.cpp: Added the following include directives:
#include <Q3GridLayout>
In file /home/john/qjoypad-3.4.1/src/joyslider.cpp at line 156 column 12: QPointArray -> Q3PointArray
In file /home/john/qjoypad-3.4.1/src/joyslider.cpp: Added the following include directives:
#include <QResizeEvent> #include <Q3PointArray> #include <QMouseEvent> #include <QPaintEvent>
In file /home/john/qjoypad-3.4.1/src/keycode.cpp: Added the following include directives:
#include <QPixmap> #include <QPaintEvent>
In file /home/john/qjoypad-3.4.1/src/layout.cpp at line 13 column 26: QPopupMenu -> Q3PopupMenu
In file /home/john/qjoypad-3.4.1/src/layout.cpp at line 54 column 27: IO_ReadOnly -> QIODevice::ReadOnly
In file /home/john/qjoypad-3.4.1/src/layout.cpp at line 63 column 20: QIntDictIterator -> Q3IntDictIterator
In file /home/john/qjoypad-3.4.1/src/layout.cpp at line 69 column 12: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/layout.cpp at line 115 column 26: IO_ReadOnly -> QIODevice::ReadOnly
In file /home/john/qjoypad-3.4.1/src/layout.cpp at line 116 column 13: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/layout.cpp at line 137 column 22: QIntDictIterator -> Q3IntDictIterator
In file /home/john/qjoypad-3.4.1/src/layout.cpp at line 154 column 27: IO_WriteOnly -> QIODevice::WriteOnly
In file /home/john/qjoypad-3.4.1/src/layout.cpp at line 155 column 13: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/layout.cpp at line 157 column 23: QIntDictIterator -> Q3IntDictIterator
In file /home/john/qjoypad-3.4.1/src/layout.cpp at line 194 column 27: IO_WriteOnly -> QIODevice::WriteOnly
In file /home/john/qjoypad-3.4.1/src/layout.cpp at line 195 column 13: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/layout.cpp at line 276 column 17: QIntDictIterator -> Q3IntDictIterator
In file /home/john/qjoypad-3.4.1/src/layout.cpp: Added the following include directives:
#include <QPixmap> #include <Q3TextStream> #include <Q3PopupMenu>
In file /home/john/qjoypad-3.4.1/src/layout_edit.cpp at line 17 column 24: QVBoxLayout -> Q3VBoxLayout
In file /home/john/qjoypad-3.4.1/src/layout_edit.cpp at line 19 column 7: QFrame -> Q3Frame
In file /home/john/qjoypad-3.4.1/src/layout_edit.cpp at line 19 column 27: QFrame -> Q3Frame
In file /home/john/qjoypad-3.4.1/src/layout_edit.cpp at line 20 column 28: QFrame -> Q3Frame
In file /home/john/qjoypad-3.4.1/src/layout_edit.cpp at line 20 column 42: QFrame -> Q3Frame
In file /home/john/qjoypad-3.4.1/src/layout_edit.cpp at line 21 column 12: QGridLayout -> Q3GridLayout
In file /home/john/qjoypad-3.4.1/src/layout_edit.cpp at line 21 column 33: QGridLayout -> Q3GridLayout
In file /home/john/qjoypad-3.4.1/src/layout_edit.cpp at line 42 column 28: QWidgetStack -> Q3WidgetStack
In file /home/john/qjoypad-3.4.1/src/layout_edit.cpp at line 43 column 31: QFrame -> Q3Frame
In file /home/john/qjoypad-3.4.1/src/layout_edit.cpp at line 43 column 45: QFrame -> Q3Frame
In file /home/john/qjoypad-3.4.1/src/layout_edit.cpp at line 52 column 20: QIntDictIterator -> Q3IntDictIterator
In file /home/john/qjoypad-3.4.1/src/layout_edit.cpp at line 77 column 12: QHBoxLayout -> Q3HBoxLayout
In file /home/john/qjoypad-3.4.1/src/layout_edit.cpp at line 77 column 33: QHBoxLayout -> Q3HBoxLayout
In file /home/john/qjoypad-3.4.1/src/layout_edit.cpp at line 112 column 17: QIntDictIterator -> Q3IntDictIterator
In file /home/john/qjoypad-3.4.1/src/layout_edit.cpp: Added the following include directives:
#include <QPixmap> #include <Q3GridLayout> #include <Q3HBoxLayout> #include <Q3VBoxLayout> #include <Q3Frame>
In file /home/john/qjoypad-3.4.1/src/loop.cpp at line 21 column 17: QIntDictIterator -> Q3IntDictIterator
In file /home/john/qjoypad-3.4.1/src/loop.cpp: Added the following include directives:
#include <QTimerEvent> #include <QEventLoop>
In file /home/john/qjoypad-3.4.1/src/main.cpp at line 34 column 8: QIntDict -> Q3IntDict
In file /home/john/qjoypad-3.4.1/src/main.cpp at line 35 column 8: QIntDict -> Q3IntDict
In file /home/john/qjoypad-3.4.1/src/main.cpp at line 36 column 8: QPtrList -> Q3PtrList
In file /home/john/qjoypad-3.4.1/src/main.cpp at line 56 column 20: QIntDictIterator -> Q3IntDictIterator
In file /home/john/qjoypad-3.4.1/src/main.cpp at line 192 column 28: IO_WriteOnly -> QIODevice::WriteOnly
In file /home/john/qjoypad-3.4.1/src/main.cpp at line 194 column 14: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/main.cpp at line 210 column 33: IO_ReadOnly -> QIODevice::ReadOnly
In file /home/john/qjoypad-3.4.1/src/main.cpp at line 213 column 14: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/main.cpp at line 235 column 31: IO_WriteOnly -> QIODevice::WriteOnly
In file /home/john/qjoypad-3.4.1/src/main.cpp at line 237 column 13: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/main.cpp: Added the following include directives:
#include <Q3TextStream> #include <Q3PtrList>
In file /home/john/qjoypad-3.4.1/src/quickset.cpp at line 12 column 12: QVBoxLayout -> Q3VBoxLayout
In file /home/john/qjoypad-3.4.1/src/quickset.cpp at line 12 column 37: QVBoxLayout -> Q3VBoxLayout
In file /home/john/qjoypad-3.4.1/src/quickset.cpp: Added the following include directives:
#include <Q3VBoxLayout> #include <QLabel>
Log for qt3to4 on Fri Dec 26 19:23:39 2008. Number of log entries: 47
In file /home/john/qjoypad-3.4.1/src/axis.h at line 30 column 24: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/axis.h at line 32 column 25: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/axis.h: Added the following include directives:
#include <Q3TextStream>
In file /home/john/qjoypad-3.4.1/src/axis_edit.h at line 8 column 16: qframe.h -> q3frame.h
In file /home/john/qjoypad-3.4.1/src/axis_edit.h at line 40 column 8: QFrame -> Q3Frame
In file /home/john/qjoypad-3.4.1/src/axisw.h: Added the following include directives:
#include <QMouseEvent>
In file /home/john/qjoypad-3.4.1/src/button.h at line 23 column 24: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/button.h at line 25 column 25: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/button.h: Added the following include directives:
#include <Q3TextStream>
No changes made to file /home/john/qjoypad-3.4.1/src/button_edit.h
In file /home/john/qjoypad-3.4.1/src/buttonw.h: Added the following include directives:
#include <QMouseEvent>
In file /home/john/qjoypad-3.4.1/src/component.h at line 7 column 21: qtextstream.h -> q3textstream.h
In file /home/john/qjoypad-3.4.1/src/component.h at line 21 column 32: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/component.h at line 22 column 33: QTextStream -> Q3TextStream
No changes made to file /home/john/qjoypad-3.4.1/src/constant.h
In file /home/john/qjoypad-3.4.1/src/device.h at line 4 column 18: qintdict.h -> q3intdict.h
In file /home/john/qjoypad-3.4.1/src/device.h at line 11 column 15: QIntDict -> Q3IntDict
In file /home/john/qjoypad-3.4.1/src/device.h at line 15 column 15: QIntDict -> Q3IntDict
In file /home/john/qjoypad-3.4.1/src/error.h at line 10 column 39: QMessageBox -> Qt
No changes made to file /home/john/qjoypad-3.4.1/src/event.h
In file /home/john/qjoypad-3.4.1/src/flash.h at line 75 column 12: QBoxLayout -> Q3BoxLayout
In file /home/john/qjoypad-3.4.1/src/flash.h: Added the following include directives:
#include <Q3BoxLayout>
In file /home/john/qjoypad-3.4.1/src/icon.h at line 16 column 16: QPopupMenu -> Q3PopupMenu
In file /home/john/qjoypad-3.4.1/src/icon.h at line 21 column 47: QPopupMenu -> Q3PopupMenu
In file /home/john/qjoypad-3.4.1/src/icon.h at line 28 column 12: QPopupMenu -> Q3PopupMenu
In file /home/john/qjoypad-3.4.1/src/icon.h: Added the following include directives:
#include <QCloseEvent> #include <Q3PopupMenu> #include <QMouseEvent>
In file /home/john/qjoypad-3.4.1/src/joypad.h at line 7 column 18: qintdict.h -> q3intdict.h
In file /home/john/qjoypad-3.4.1/src/joypad.h at line 38 column 24: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/joypad.h at line 40 column 25: QTextStream -> Q3TextStream
In file /home/john/qjoypad-3.4.1/src/joypad.h at line 71 column 10: QIntDict -> Q3IntDict
In file /home/john/qjoypad-3.4.1/src/joypad.h at line 72 column 10: QIntDict -> Q3IntDict
In file /home/john/qjoypad-3.4.1/src/joypad.h: Added the following include directives:
#include <Q3TextStream>
In file /home/john/qjoypad-3.4.1/src/joypadw.h at line 58 column 13: QGridLayout -> Q3GridLayout
In file /home/john/qjoypad-3.4.1/src/joypadw.h: Added the following include directives:
#include <Q3GridLayout>
In file /home/john/qjoypad-3.4.1/src/joyslider.h: Added the following include directives:
#include <QPaintEvent> #include <QResizeEvent> #include <QMouseEvent>
In file /home/john/qjoypad-3.4.1/src/keycode.h: Added the following include directives:
#include <QPaintEvent>
In file /home/john/qjoypad-3.4.1/src/layout.h at line 7 column 21: qtextstream.h -> q3textstream.h
In file /home/john/qjoypad-3.4.1/src/layout.h at line 18 column 21: qpopupmenu.h -> q3popupmenu.h
In file /home/john/qjoypad-3.4.1/src/layout.h at line 90 column 12: QPopupMenu -> Q3PopupMenu
In file /home/john/qjoypad-3.4.1/src/layout_edit.h at line 10 column 22: qwidgetstack.h -> q3widgetstack.h
In file /home/john/qjoypad-3.4.1/src/layout_edit.h at line 39 column 13: QVBoxLayout -> Q3VBoxLayout
In file /home/john/qjoypad-3.4.1/src/layout_edit.h at line 40 column 14: QWidgetStack -> Q3WidgetStack
In file /home/john/qjoypad-3.4.1/src/layout_edit.h: Added the following include directives:
#include <Q3VBoxLayout>
In file /home/john/qjoypad-3.4.1/src/loop.h at line 39 column 10: QPtrList -> Q3PtrList
In file /home/john/qjoypad-3.4.1/src/loop.h: Added the following include directives:
#include <Q3PtrList> #include <QTimerEvent>
No changes made to file /home/john/qjoypad-3.4.1/src/quickset.h
No changes made to file /home/john/qjoypad-3.4.1/src/timer.h
Log for qt3to4 on Fri Dec 26 19:24:31 2008. Number of log entries: 1
No changes made to file /home/john/qjoypad-3.4.1/src/Makefile

BIN
src/qjoypad Executable file

Binary file not shown.

87
src/qjoypad.pro Normal file
View File

@ -0,0 +1,87 @@
########################################
# #
# QMake project file for QJoyPad #
# #
########################################
##### Setup Targets #####
target.path = $$PREFIX/bin
icons.path = $$PREFIX/share/pixmaps/qjoypad
icons.extra = cp ../icons/* $${icons.path}; cd $${icons.path}; ln -sf gamepad4-24x24.png icon24.png; ln -sf gamepad3-64x64.png icon64.png; chmod -R a+r $${icons.path}
doc.path = $$PREFIX/doc/qjoypad3
doc.extra = cp ../README.txt ../LICENSE.txt $${doc.path}
##### Setup Compile #####
DEFINES += DEVDIR='"$$DEVDIR"'
DEFINES += ICON24='\"$${icons.path}/icon24.png\"'
DEFINES += ICON64='\"$${icons.path}/icon64.png\"'
TEMPLATE = app
DEPENDPATH += trayicon
INCLUDEPATH += . trayicon
QMAKE_LIBS += -lXtst
# Input
HEADERS += axis.h \
axis_edit.h \
axisw.h \
button.h \
button_edit.h \
buttonw.h \
constant.h \
device.h \
error.h \
event.h \
flash.h \
icon.h \
joypad.h \
joypadw.h \
joyslider.h \
keycode.h \
layout.h \
getkey.h \
layout_edit.h \
quickset.h \
trayicon/trayicon.h
SOURCES += axis.cpp \
axis_edit.cpp \
axisw.cpp \
button.cpp \
button_edit.cpp \
buttonw.cpp \
event.cpp \
flash.cpp \
icon.cpp \
joypad.cpp \
joypadw.cpp \
joyslider.cpp \
keycode.cpp \
layout.cpp \
layout_edit.cpp \
main.cpp \
quickset.cpp \
getkey.cpp \
trayicon/trayicon.cpp \
trayicon/trayicon_x11.cpp
##### Install #####
INSTALLS += target icons doc

89
src/qjoypad.pro.backup Normal file
View File

@ -0,0 +1,89 @@
########################################
# #
# QMake project file for QJoyPad #
# #
########################################
##### Setup Targets #####
target.path = $$PREFIX/bin
icons.path = $$PREFIX/share/pixmaps/qjoypad
icons.extra = cp ../icons/* $${icons.path}; cd $${icons.path}; ln -sf gamepad4-24x24.png icon24.png; ln -sf gamepad3-64x64.png icon64.png; chmod -R a+r $${icons.path}
doc.path = $$PREFIX/doc/qjoypad3
doc.extra = cp ../README.txt ../LICENSE.txt $${doc.path}
##### Setup Compile #####
DEFINES += DEVDIR='"$$DEVDIR"'
DEFINES += ICON24='"$${icons.path}/icon24.png"'
DEFINES += ICON64='"$${icons.path}/icon64.png"'
TEMPLATE = app
DEPENDPATH += trayicon
INCLUDEPATH += . trayicon
QMAKE_LIBS += -lXtst
# Input
HEADERS += axis.h \
axis_edit.h \
axisw.h \
button.h \
button_edit.h \
buttonw.h \
component.h \
constant.h \
device.h \
error.h \
event.h \
flash.h \
icon.h \
joypad.h \
joypadw.h \
joyslider.h \
keycode.h \
layout.h \
layout_edit.h \
loop.h \
quickset.h \
timer.h \
trayicon/trayicon.h
SOURCES += axis.cpp \
axis_edit.cpp \
axisw.cpp \
button.cpp \
button_edit.cpp \
buttonw.cpp \
event.cpp \
flash.cpp \
icon.cpp \
joypad.cpp \
joypadw.cpp \
joyslider.cpp \
keycode.cpp \
layout.cpp \
layout_edit.cpp \
loop.cpp \
main.cpp \
quickset.cpp \
trayicon/trayicon.cpp \
trayicon/trayicon_x11.cpp
##### Install #####
INSTALLS += target icons doc

57
src/quickset.cpp Normal file
View File

@ -0,0 +1,57 @@
#include "quickset.h"
#include "getkey.h"
//build the dialog
QuickSet::QuickSet( JoyPad* jp)
: QDialog() {
setting = false;
joypad = jp;
setWindowTitle("Set " + jp->getName());
QVBoxLayout* LMain = new QVBoxLayout(this);
LMain->setMargin(5);
LMain->setSpacing(5);
//LMain->setAutoAdd(true);
new QLabel("Press any button or axis and\nyou will be prompted for a key.",this);
QPushButton* button = new QPushButton("Done",this);
connect( button, SIGNAL(clicked()), this, SLOT(accept()));
}
void QuickSet::jsevent( js_event msg ) {
//ignore any joystick events if we're waiting for a keypress
if (setting) return;
//if a button was pressed on the joystick
if (msg.type == JS_EVENT_BUTTON) {
//capture that button.
Button* button = joypad->Buttons[msg.number];
//go into setting mode and request a key/mousebutton
setting = true;
int code = GetKey(button->getName(), true).exec();
setting = false;
//if a mouse button was used,
if (code > MOUSE_OFFSET)
//then tell it to the Button a mouse button
button->setKey(true, code - MOUSE_OFFSET);
else
//otherwise, tell it to use a keycode.
button->setKey(false, code);
}
else {
//require a signal strength of at least 5000 to consider an axis moved.
if (abs(msg.value) < 5000) return;
//capture the axis that moved
Axis* axis = joypad->Axes[msg.number];
//grab a keycode for that axis and that direction
setting = true;
int code = GetKey(axis->getName() + ", " + QString((msg.value > 0)?"positive":"negative"), false).exec();
setting = false;
//assign the key to the axis.
axis->setKey((msg.value > 0),code);
}
}

33
src/quickset.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef QUICKSET_H
#define QUICKSET_H
//for building the dialog
#include <QLayout>
#include <QLabel>
#include <QPushButton>
#include <linux/joystick.h>
//to request new keycodes
//#include "keycode.h"
//to actually set the joypad
#include "joypad.h"
//because of some circularity issues ;)
class JoyPad;
//a dialog to quickly set a key to a button
class QuickSet : public QDialog {
public:
QuickSet(JoyPad* jp);
//this needs to see js_events so it can capture them directly
void jsevent( js_event msg );
private:
//the joypad that is being configured
JoyPad* joypad;
//when a joystick event has trigered QuickSet, setting is true and it
//is waiting for a keypress or mouse click. Otherwise, setting is false.
bool setting;
};
#endif

275
src/trayicon/trayicon.cpp Normal file
View File

@ -0,0 +1,275 @@
/*
* trayicon.cpp - system-independent trayicon class (adapted from Qt example)
* Copyright (C) 2003 Justin Karneges
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "trayicon.h"
/*!
\class TrayIcon qtrayicon.h
\brief The TrayIcon class implements an entry in the system tray.
*/
/*!
Creates a TrayIcon object. \a parent and \a name are propagated
to the QObject constructor. The icon is initially invisible.
\sa show
*/
TrayIcon::TrayIcon( QObject *parent, const char *name )
: QObject(parent/*, name*/), pop(0), d(0)
{
v_isWMDock = FALSE;
}
/*!
Creates a TrayIcon object displaying \a icon and \a tooltip, and opening
\a popup when clicked with the right mousebutton. \a parent and \a name are
propagated to the QObject constructor. The icon is initially invisible.
\sa show
*/
TrayIcon::TrayIcon( const QPixmap &icon, const QString &tooltip, QMenu *popup, QObject *parent, const char *name )
: QObject(parent/*, name*/), pop(popup), pm(icon), tip(tooltip), d(0)
{
v_isWMDock = FALSE;
}
/*!
Removes the icon from the system tray and frees all allocated resources.
*/
TrayIcon::~TrayIcon()
{
sysRemove();
}
/*!
Sets the context menu to \a popup. The context menu will pop up when the
user clicks the system tray entry with the right mouse button.
*/
void TrayIcon::setPopup( QMenu* popup )
{
pop = popup;
}
/*!
Returns the current popup menu.
\sa setPopup
*/
QMenu* TrayIcon::popup() const
{
return pop;
}
/*!
\property TrayIcon::icon
\brief the system tray icon.
*/
void TrayIcon::setIcon( const QPixmap &icon )
{
//if(!popup()) {
// tip = "";
//}
pm = icon;
sysUpdateIcon();
}
QPixmap TrayIcon::icon() const
{
return pm;
}
/*!
\property TrayIcon::toolTip
\brief the tooltip for the system tray entry
On some systems, the tooltip's length is limited and will be truncated as necessary.
*/
void TrayIcon::setToolTip( const QString &tooltip )
{
tip = tooltip;
sysUpdateToolTip();
}
QString TrayIcon::toolTip() const
{
return tip;
}
/*!
Shows the icon in the system tray.
\sa hide
*/
void TrayIcon::show()
{
sysInstall();
}
/*!
Hides the system tray entry.
*/
void TrayIcon::hide()
{
sysRemove();
}
/*!
\reimp
*/
bool TrayIcon::event( QEvent *e )
{
switch ( e->type() ) {
case QEvent::MouseMove:
mouseMoveEvent( (QMouseEvent*)e );
break;
case QEvent::MouseButtonPress:
mousePressEvent( (QMouseEvent*)e );
break;
case QEvent::MouseButtonRelease:
mouseReleaseEvent( (QMouseEvent*)e );
break;
case QEvent::MouseButtonDblClick:
mouseDoubleClickEvent( (QMouseEvent*)e );
break;
default:
return QObject::event( e );
}
return TRUE;
}
/*!
This event handler can be reimplemented in a subclass to receive
mouse move events for the system tray entry.
\sa mousePressEvent(), mouseReleaseEvent(), mouseDoubleClickEvent(), QMouseEvent
*/
void TrayIcon::mouseMoveEvent( QMouseEvent *e )
{
e->ignore();
}
/*!
This event handler can be reimplemented in a subclass to receive
mouse press events for the system tray entry.
\sa mouseReleaseEvent(), mouseDoubleClickEvent(),
mouseMoveEvent(), QMouseEvent
*/
void TrayIcon::mousePressEvent( QMouseEvent *e )
{
#ifndef Q_WS_WIN
// This is for X11, menus appear on mouse press
// I'm not sure whether Mac should be here or below.. Somebody check?
switch ( e->button() ) {
case Qt::RightButton:
if ( pop ) {
pop->popup( e->globalPos() );
e->accept();
}
break;
case Qt::LeftButton:
case Qt::MidButton:
emit clicked( e->globalPos(), e->button() );
break;
default:
break;
}
#endif
e->ignore();
}
/*!
This event handler can be reimplemented in a subclass to receive
mouse release events for the system tray entry.
The default implementations opens the context menu when the entry
has been clicked with the right mouse button.
\sa setPopup(), mousePressEvent(), mouseDoubleClickEvent(),
mouseMoveEvent(), QMouseEvent
*/
void TrayIcon::mouseReleaseEvent( QMouseEvent *e )
{
#ifdef Q_WS_WIN
// This is for Windows, where menus appear on mouse release
switch ( e->button() ) {
case Qt::RightButton:
if ( pop ) {
// Necessary to make keyboard focus
// and menu closing work on Windows.
pop->setActiveWindow();
pop->popup( e->globalPos() );
pop->setActiveWindow();
e->accept();
}
break;
case Qt::LeftButton:
case Qt::MidButton:
emit clicked( e->globalPos(), e->button() );
break;
default:
break;
}
#endif
e->ignore();
}
/*!
This event handler can be reimplemented in a subclass to receive
mouse double click events for the system tray entry.
Note that the system tray entry gets a mousePressEvent() and a
mouseReleaseEvent() before the mouseDoubleClickEvent().
\sa mousePressEvent(), mouseReleaseEvent(),
mouseMoveEvent(), QMouseEvent
*/
void TrayIcon::mouseDoubleClickEvent( QMouseEvent *e )
{
if ( e->button() == Qt::LeftButton )
emit doubleClicked( e->globalPos() );
e->accept();
}
/*!
\fn void TrayIcon::clicked( const QPoint &p )
This signal is emitted when the user clicks the system tray icon
with the left mouse button, with \a p being the global mouse position
at that moment.
*/
/*!
\fn void TrayIcon::doubleClicked( const QPoint &p )
This signal is emitted when the user double clicks the system tray
icon with the left mouse button, with \a p being the global mouse position
at that moment.
*/
void TrayIcon::gotCloseEvent()
{
closed();
}

96
src/trayicon/trayicon.h Executable file
View File

@ -0,0 +1,96 @@
/*
* trayicon.h - system-independent trayicon class (adapted from Qt example)
* Copyright (C) 2003 Justin Karneges
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef CS_TRAYICON_H
#define CS_TRAYICON_H
#include <qobject.h>
#include <qimage.h>
#include <QPixmap>
#include <QDir>
#include <QMenu>
#include <QMouseEvent>
class TrayIcon : public QObject
{
Q_OBJECT
Q_PROPERTY( QString toolTip READ toolTip WRITE setToolTip )
Q_PROPERTY( QPixmap icon READ icon WRITE setIcon )
public:
TrayIcon( QObject *parent = 0, const char *name = 0 );
TrayIcon( const QPixmap &, const QString &, QMenu *popup = 0, QObject *parent = 0, const char *name = 0 );
~TrayIcon();
// use WindowMaker dock mode. ignored on non-X11 platforms
void setWMDock(bool use) { v_isWMDock = use; }
bool isWMDock() { return v_isWMDock; }
// Set a popup menu to handle RMB
void setPopup( QMenu * );
QMenu* popup() const;
QPixmap icon() const;
QString toolTip() const;
void gotCloseEvent();
public slots:
void setIcon( const QPixmap &icon );
void setToolTip( const QString &tip );
void show();
void hide();
signals:
void clicked( const QPoint&, int);
void doubleClicked( const QPoint& );
void closed();
protected:
bool event( QEvent * );
virtual void mouseMoveEvent( QMouseEvent *e );
virtual void mousePressEvent( QMouseEvent *e );
virtual void mouseReleaseEvent( QMouseEvent *e );
virtual void mouseDoubleClickEvent( QMouseEvent *e );
private:
QMenu *pop;
QPixmap pm;
QString tip;
bool v_isWMDock;
// system-dependant part
public:
class TrayIconPrivate;
private:
TrayIconPrivate *d;
void sysInstall();
void sysRemove();
void sysUpdateIcon();
void sysUpdateToolTip();
friend class TrayIconPrivate;
};
#endif // CS_TRAYICON_H

View File

@ -0,0 +1,374 @@
/*
* trayicon_x11.cpp - X11 trayicon (for use with KDE and GNOME)
* Copyright (C) 2003 Justin Karneges
* GNOME2 Notification Area support: Tomasz Sterna
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "trayicon.h"
#include <QX11Info>
#include <QApplication>
#include <QPainter>
#include<X11/Xlib.h>
#include<X11/Xutil.h>
#include<X11/Xatom.h>
//#if QT_VERSION < 0x030200
//extern Time;// qt_x_time;
//#endif
//----------------------------------------------------------------------------
// common stuff
//----------------------------------------------------------------------------
// for Gnome2 Notification Area
static XErrorHandler old_handler = 0;
static int dock_xerror = 0;
extern "C" int dock_xerrhandler(Display* dpy, XErrorEvent* err)
{
dock_xerror = err->error_code;
return old_handler(dpy, err);
}
static void trap_errors()
{
dock_xerror = 0;
old_handler = XSetErrorHandler(dock_xerrhandler);
}
static bool untrap_errors()
{
XSetErrorHandler(old_handler);
return (dock_xerror == 0);
}
static bool send_message(
Display* dpy, /* display */
Window w, /* sender (tray icon window) */
long message, /* message opcode */
long data1, /* message data 1 */
long data2, /* message data 2 */
long data3 /* message data 3 */
) {
XEvent ev;
memset(&ev, 0, sizeof(ev));
ev.xclient.type = ClientMessage;
ev.xclient.window = w;
ev.xclient.message_type = XInternAtom (dpy, "_NET_SYSTEM_TRAY_OPCODE", False );
ev.xclient.format = 32;
ev.xclient.data.l[0] = CurrentTime;
ev.xclient.data.l[1] = message;
ev.xclient.data.l[2] = data1;
ev.xclient.data.l[3] = data2;
ev.xclient.data.l[4] = data3;
trap_errors();
XSendEvent(dpy, w, False, NoEventMask, &ev);
XSync(dpy, False);
return untrap_errors();
}
#define SYSTEM_TRAY_REQUEST_DOCK 0
#define SYSTEM_TRAY_BEGIN_MESSAGE 1
#define SYSTEM_TRAY_CANCEL_MESSAGE 2
//----------------------------------------------------------------------------
// TrayIcon::TrayIconPrivate
//----------------------------------------------------------------------------
class TrayIcon::TrayIconPrivate : public QWidget
{
public:
TrayIconPrivate(TrayIcon *object, int size);
~TrayIconPrivate() { }
virtual void initWM(WId icon);
virtual void setPixmap(const QPixmap &pm);
virtual void paintEvent(QPaintEvent *);
virtual void enterEvent(QEvent *);
virtual void mouseMoveEvent(QMouseEvent *e);
virtual void mousePressEvent(QMouseEvent *e);
virtual void mouseReleaseEvent(QMouseEvent *e);
virtual void mouseDoubleClickEvent(QMouseEvent *e);
virtual void closeEvent(QCloseEvent *e);
private:
TrayIcon *iconObject;
QPixmap pix;
int size;
};
TrayIcon::TrayIconPrivate::TrayIconPrivate(TrayIcon *object, int _size)
: QWidget(0/*, object->name(), Qt::WRepaintNoErase*/)
{
iconObject = object;
size = _size;
setAttribute(Qt::WA_NoBackground);
setFocusPolicy(Qt::NoFocus);
//setBackgroundMode(X11ParentRelative);
setMinimumSize(size, size);
setMaximumSize(size, size);
}
// This base stuff is required by both FreeDesktop specification and WindowMaker
void TrayIcon::TrayIconPrivate::initWM(WId icon)
{
Display *dsp = x11Info().display();
WId leader = winId();
// set the class hint
XClassHint classhint;
classhint.res_name = (char*)"psidock";
classhint.res_class = (char*)"Psi";
XSetClassHint(dsp, leader, &classhint);
// set the Window Manager hints
XWMHints *hints;
hints = XGetWMHints(dsp, leader); // init hints
hints->flags = WindowGroupHint | IconWindowHint | StateHint; // set the window group hint
hints->window_group = leader; // set the window hint
hints->initial_state = WithdrawnState; // initial state
hints->icon_window = icon; // in WM, this should be winId() of separate widget
hints->icon_x = 0;
hints->icon_y = 0;
XSetWMHints(dsp, leader, hints); // set the window hints for WM to use.
XFree( hints );
}
void TrayIcon::TrayIconPrivate::setPixmap(const QPixmap &pm)
{
pix = pm;
setWindowIcon(pix);
repaint();
}
void TrayIcon::TrayIconPrivate::paintEvent(QPaintEvent *)
{
QPainter p(this);
p.drawPixmap((width() - pix.width())/2, (height() - pix.height())/2, pix);
}
void TrayIcon::TrayIconPrivate::enterEvent(QEvent *e)
{
// Taken from KSystemTray..
//#if QT_VERSION < 0x030200
//if ( !qApp->focusWidget() ) {
XEvent ev;
memset(&ev, 0, sizeof(ev));
ev.xfocus.display = x11Info().display();//qt_xdisplay();
ev.xfocus.type = FocusIn;
ev.xfocus.window = winId();
ev.xfocus.mode = NotifyNormal;
ev.xfocus.detail = NotifyAncestor;
Time time = x11Info().appTime();//qt_x_time;
//qt_x_time = 1;
x11Info().setAppTime(1);
qApp->x11ProcessEvent( &ev );
//qt_x_time = time;
x11Info().setAppTime(time);
//}
//#endif
QWidget::enterEvent(e);
}
void TrayIcon::TrayIconPrivate::mouseMoveEvent(QMouseEvent *e)
{
QApplication::sendEvent(iconObject, e);
}
void TrayIcon::TrayIconPrivate::mousePressEvent(QMouseEvent *e)
{
QApplication::sendEvent(iconObject, e);
}
void TrayIcon::TrayIconPrivate::mouseReleaseEvent(QMouseEvent *e)
{
QApplication::sendEvent(iconObject, e);
}
void TrayIcon::TrayIconPrivate::mouseDoubleClickEvent(QMouseEvent *e)
{
QApplication::sendEvent(iconObject, e);
}
void TrayIcon::TrayIconPrivate::closeEvent(QCloseEvent *e)
{
iconObject->gotCloseEvent();
e->accept();
}
//----------------------------------------------------------------------------
// TrayIconFreeDesktop
//----------------------------------------------------------------------------
class TrayIconFreeDesktop : public TrayIcon::TrayIconPrivate
{
public:
TrayIconFreeDesktop(TrayIcon *object, const QPixmap &pm);
};
TrayIconFreeDesktop::TrayIconFreeDesktop(TrayIcon *object, const QPixmap &pm)
: TrayIconPrivate(object, 22)
{
initWM( winId() );
// initialize NetWM
Display *dsp = x11Info().display();//x11Display();
// dock the widget (adapted from SIM-ICQ)
Screen *screen = XDefaultScreenOfDisplay(dsp); // get the screen
int screen_id = XScreenNumberOfScreen(screen); // and it's number
char buf[32];
snprintf(buf, sizeof(buf), "_NET_SYSTEM_TRAY_S%d", screen_id);
Atom selection_atom = XInternAtom(dsp, buf, false);
XGrabServer(dsp);
Window manager_window = XGetSelectionOwner(dsp, selection_atom);
if ( manager_window != None )
XSelectInput(dsp, manager_window, StructureNotifyMask);
XUngrabServer(dsp);
XFlush(dsp);
if ( manager_window != None )
send_message(dsp, manager_window, SYSTEM_TRAY_REQUEST_DOCK, winId(), 0, 0);
// some KDE mumbo-jumbo... why is it there? anybody?
Atom kwm_dockwindow_atom = XInternAtom(dsp, "KWM_DOCKWINDOW", false);
Atom kde_net_system_tray_window_for_atom = XInternAtom(dsp, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", false);
long data = 0;
XChangeProperty(dsp, winId(), kwm_dockwindow_atom, kwm_dockwindow_atom, 32, PropModeReplace, (uchar*)&data, 1);
XChangeProperty(dsp, winId(), kde_net_system_tray_window_for_atom, XA_WINDOW, 32, PropModeReplace, (uchar*)&data, 1);
setPixmap(pm);
}
//----------------------------------------------------------------------------
// TrayIconWindowMaker
//----------------------------------------------------------------------------
class TrayIconWharf : public TrayIcon::TrayIconPrivate
{
public:
TrayIconWharf(TrayIcon *object, const QPixmap &pm)
: TrayIconPrivate(object, 64)
{
setPixmap(pm);
}
void setPixmap(const QPixmap &_pm)
{
QPixmap pm;
QImage i = _pm.toImage();
i = i.scaled(i.width() * 2, i.height() * 2);
pm = QPixmap::fromImage(i);
TrayIconPrivate::setPixmap(pm);
// thanks to Robert Spier for this:
// for some reason the repaint() isn't being honored, or isn't for
// the icon. So force one on the widget behind the icon
//erase();
QPaintEvent pe( rect() );
paintEvent(&pe);
}
};
class TrayIconWindowMaker : public TrayIcon::TrayIconPrivate
{
public:
TrayIconWindowMaker(TrayIcon *object, const QPixmap &pm);
~TrayIconWindowMaker();
void setPixmap(const QPixmap &pm);
private:
TrayIconWharf *wharf;
};
TrayIconWindowMaker::TrayIconWindowMaker(TrayIcon *object, const QPixmap &pm)
: TrayIconPrivate(object, 32)
{
wharf = new TrayIconWharf(object, pm);
initWM( wharf->winId() );
}
TrayIconWindowMaker::~TrayIconWindowMaker()
{
delete wharf;
}
void TrayIconWindowMaker::setPixmap(const QPixmap &pm)
{
wharf->setPixmap(pm);
}
//----------------------------------------------------------------------------
// TrayIcon
//----------------------------------------------------------------------------
void TrayIcon::sysInstall()
{
if ( d )
return;
if ( v_isWMDock )
d = (TrayIconPrivate *)(new TrayIconWindowMaker(this, pm));
else
d = (TrayIconPrivate *)(new TrayIconFreeDesktop(this, pm));
sysUpdateToolTip();
d->show();
}
void TrayIcon::sysRemove()
{
if ( !d )
return;
delete d;
d = 0;
}
void TrayIcon::sysUpdateIcon()
{
if ( !d )
return;
QPixmap pix = pm;
d->setPixmap(pix);
}
void TrayIcon::sysUpdateToolTip()
{
if ( !d )
return;
if ( tip.isEmpty() ) {
//QToolTip::remove(d);
d->setToolTip(QString());
} else {
//QToolTip::add(d, tip);
d->setToolTip(tip);
}
}