combjs
changeset 1:dd02002227a2
- added a few commandline arguments to combjs
- trying to make a gui frontend
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 14 Jul 2011 15:40:20 +0300 |
parents | 15293518d92b |
children | 4e8f2bbe8426 |
files | Makefile combjs.c gui/Makefile gui/combjs-gui.cc gui/combjs.h gui/droplist.cc gui/droplist.h gui/gui.cc gui/gui.h gui/main.ui |
diffstat | 10 files changed, 733 insertions(+), 37 deletions(-) [+] |
line diff
1.1 --- a/Makefile Wed Jul 13 07:12:57 2011 +0300 1.2 +++ b/Makefile Thu Jul 14 15:40:20 2011 +0300 1.3 @@ -1,3 +1,5 @@ 1.4 +PREFIX = /usr/local 1.5 + 1.6 src = $(wildcard *.c) 1.7 obj = $(src:.c=.o) 1.8 bin = combjs 1.9 @@ -11,3 +13,14 @@ 1.10 .PHONY: clean 1.11 clean: 1.12 rm -f $(obj) $(bin) 1.13 + 1.14 +.PHONY: install 1.15 +install: $(bin) 1.16 + mkdir -p $(PREFIX)/bin 1.17 + cp $(bin) $(PREFIX)/bin/$(bin) 1.18 + chown root $(PREFIX)/bin/$(bin) 1.19 + chmod 4775 $(PREFIX)/bin/$(bin) 1.20 + 1.21 +.PHONY: uninstall 1.22 +uninstall: 1.23 + rm -f $(PREFIX)/bin/$(bin)
2.1 --- a/combjs.c Wed Jul 13 07:12:57 2011 +0300 2.2 +++ b/combjs.c Thu Jul 14 15:40:20 2011 +0300 2.3 @@ -24,6 +24,7 @@ 2.4 #include <signal.h> 2.5 #include <unistd.h> 2.6 #include <fcntl.h> 2.7 +#include <dirent.h> 2.8 #include <sys/select.h> 2.9 #include <sys/ioctl.h> 2.10 #include <linux/joystick.h> 2.11 @@ -33,6 +34,7 @@ 2.12 #define DBG_MAX_BN 32 2.13 2.14 struct joystick { 2.15 + char *devfile; 2.16 char *name; 2.17 int fd; 2.18 int num_bn, num_axes; 2.19 @@ -45,16 +47,22 @@ 2.20 int create_virt_js(const char *uinput_dev, const char *devname); 2.21 int handle_event(struct joystick *js, struct js_event *ev); 2.22 int add_joystick(const char *devfile); 2.23 +struct joystick *open_joystick(const char *devfile); 2.24 +void close_joystick(struct joystick *js); 2.25 +void print_joystick(struct joystick *js, int verbose); 2.26 +int list_devices(void); 2.27 +int cmp_jsp(const void *a, const void *b); 2.28 void sig_handler(int sig); 2.29 int proc_cmdline(int argc, char **argv); 2.30 void print_usage(const char *argv0); 2.31 2.32 2.33 int vfd = -1; 2.34 -const char *virt_dev_name = "combjs - virtual multi-joystick combiner"; 2.35 -const char *uinput_dev_name = "/dev/uinput"; 2.36 +const char *virt_name = "combjs - virtual multi-joystick combiner"; 2.37 +const char *uinput_dev = "/dev/uinput"; 2.38 struct joystick *jslist, *jstail; 2.39 int num_vaxes, num_vbn; 2.40 +int verbose = 1; 2.41 2.42 2.43 int main(int argc, char **argv) 2.44 @@ -67,11 +75,16 @@ 2.45 return 1; 2.46 } 2.47 2.48 - if((vfd = create_virt_js(uinput_dev_name, virt_dev_name)) == -1) { 2.49 + if((vfd = create_virt_js(uinput_dev, virt_name)) == -1) { 2.50 cleanup(); 2.51 return 1; 2.52 } 2.53 2.54 + /* if we where running suid-root, drop root priviledges */ 2.55 + if(geteuid() == 0) { 2.56 + setuid(getuid()); 2.57 + } 2.58 + 2.59 for(;;) { 2.60 fd_set rdset; 2.61 struct joystick *js = jslist; 2.62 @@ -207,35 +220,9 @@ 2.63 int add_joystick(const char *devfile) 2.64 { 2.65 struct joystick *js; 2.66 - char buf[512]; 2.67 2.68 - if(!(js = calloc(1, sizeof *js))) { 2.69 - perror("failed to allocate memory"); 2.70 - goto err; 2.71 - } 2.72 - 2.73 - if((js->fd = open(devfile, O_RDONLY | O_NONBLOCK)) == -1) { 2.74 - fprintf(stderr, "failed to open %s: %s\n", devfile, strerror(errno)); 2.75 - goto err; 2.76 - } 2.77 - 2.78 - if(ioctl(js->fd, JSIOCGNAME(sizeof buf), buf) == -1) { 2.79 - fprintf(stderr, "failed to get joystick name for %s: %s\n", devfile, strerror(errno)); 2.80 - strcpy(buf, "<unknown>"); 2.81 - } 2.82 - if(!(js->name = malloc(strlen(buf) + 1))) { 2.83 - perror("failed to allocate memory"); 2.84 - goto err; 2.85 - } 2.86 - strcpy(js->name, buf); 2.87 - 2.88 - if(ioctl(js->fd, JSIOCGBUTTONS, &js->num_bn) == -1) { 2.89 - fprintf(stderr, "failed to get joystick %s's number of buttons: %s\n", devfile, strerror(errno)); 2.90 - goto err; 2.91 - } 2.92 - if(ioctl(js->fd, JSIOCGAXES, &js->num_axes) == -1) { 2.93 - fprintf(stderr, "failed to get joystick %s's number of axes: %s\n", devfile, strerror(errno)); 2.94 - goto err; 2.95 + if(!(js = open_joystick(devfile))) { 2.96 + return -1; 2.97 } 2.98 2.99 if(!jstail) { 2.100 @@ -250,18 +237,141 @@ 2.101 num_vaxes = js->axis_offset + js->num_axes; 2.102 num_vbn = js->bn_offset + js->num_bn; 2.103 2.104 - printf("added joystick %s: %s\n", devfile, js->name); 2.105 - printf(" - %d axes (offset: %d)\n", js->num_axes, js->axis_offset); 2.106 - printf(" - %d buttons (offset: %d)\n", js->num_bn, js->bn_offset); 2.107 + if(verbose) { 2.108 + printf("added "); 2.109 + print_joystick(js, 1); 2.110 + } 2.111 return 0; 2.112 +} 2.113 2.114 -err: 2.115 +struct joystick *open_joystick(const char *devfile) 2.116 +{ 2.117 + struct joystick *js; 2.118 + char buf[512]; 2.119 + 2.120 + if(!(js = calloc(1, sizeof *js))) { 2.121 + perror("failed to allocate memory"); 2.122 + close_joystick(js); 2.123 + return 0; 2.124 + } 2.125 + 2.126 + if(!(js->devfile = malloc(strlen(devfile) + 1))) { 2.127 + perror("failed to allocate memory"); 2.128 + close_joystick(js); 2.129 + return 0; 2.130 + } 2.131 + strcpy(js->devfile, devfile); 2.132 + 2.133 + if((js->fd = open(devfile, O_RDONLY | O_NONBLOCK)) == -1) { 2.134 + fprintf(stderr, "failed to open %s: %s\n", devfile, strerror(errno)); 2.135 + close_joystick(js); 2.136 + return 0; 2.137 + } 2.138 + 2.139 + if(ioctl(js->fd, JSIOCGNAME(sizeof buf), buf) == -1) { 2.140 + fprintf(stderr, "failed to get joystick name for %s: %s\n", devfile, strerror(errno)); 2.141 + strcpy(buf, "<unknown>"); 2.142 + } 2.143 + if(!(js->name = malloc(strlen(buf) + 1))) { 2.144 + perror("failed to allocate memory"); 2.145 + close_joystick(js); 2.146 + return 0; 2.147 + } 2.148 + strcpy(js->name, buf); 2.149 + 2.150 + if(ioctl(js->fd, JSIOCGBUTTONS, &js->num_bn) == -1) { 2.151 + fprintf(stderr, "failed to get joystick %s's number of buttons: %s\n", devfile, strerror(errno)); 2.152 + close_joystick(js); 2.153 + return 0; 2.154 + } 2.155 + if(ioctl(js->fd, JSIOCGAXES, &js->num_axes) == -1) { 2.156 + fprintf(stderr, "failed to get joystick %s's number of axes: %s\n", devfile, strerror(errno)); 2.157 + close_joystick(js); 2.158 + return 0; 2.159 + } 2.160 + return js; 2.161 +} 2.162 + 2.163 +void close_joystick(struct joystick *js) 2.164 +{ 2.165 if(js) { 2.166 close(js->fd); 2.167 free(js->name); 2.168 free(js); 2.169 } 2.170 - return -1; 2.171 +} 2.172 + 2.173 +void print_joystick(struct joystick *js, int verbose) 2.174 +{ 2.175 + if(verbose) { 2.176 + printf("joystick %s: %s\n", js->devfile, js->name); 2.177 + printf(" - %d axes (offset: %d)\n", js->num_axes, js->axis_offset); 2.178 + printf(" - %d buttons (offset: %d)\n", js->num_bn, js->bn_offset); 2.179 + } else { 2.180 + printf("%s: \"%s\", axes: %d, buttons: %d\n", js->devfile, js->name, js->num_axes, js->num_bn); 2.181 + } 2.182 +} 2.183 + 2.184 +int list_devices(void) 2.185 +{ 2.186 + DIR *dir; 2.187 + struct dirent *dent; 2.188 + char buf[PATH_MAX]; 2.189 + struct joystick **jsp_arr, *js; 2.190 + int i, num_js = 0; 2.191 + 2.192 + /* we don't need root priviledges for this */ 2.193 + if(geteuid() == 0) { 2.194 + setuid(getuid()); 2.195 + } 2.196 + 2.197 + if(!(dir = opendir("/dev/input"))) { 2.198 + perror("failed to open /dev/input"); 2.199 + return -1; 2.200 + } 2.201 + 2.202 + while((dent = readdir(dir))) { 2.203 + if(strstr(dent->d_name, "js") == dent->d_name) { 2.204 + sprintf(buf, "/dev/input/%s", dent->d_name); 2.205 + 2.206 + if(!(js = open_joystick(buf))) { 2.207 + continue; 2.208 + } 2.209 + 2.210 + if(jslist) { 2.211 + js->next = jslist; 2.212 + } 2.213 + jslist = js; 2.214 + num_js++; 2.215 + } 2.216 + } 2.217 + closedir(dir); 2.218 + 2.219 + if(!(jsp_arr = malloc(num_js * sizeof *jsp_arr))) { 2.220 + perror("failed to allocate memory"); 2.221 + return -1; 2.222 + } 2.223 + 2.224 + js = jslist; 2.225 + for(i=0; i<num_js; i++) { 2.226 + jsp_arr[i] = js; 2.227 + js = js->next; 2.228 + } 2.229 + 2.230 + qsort(jsp_arr, num_js, sizeof *jsp_arr, cmp_jsp); 2.231 + 2.232 + for(i=0; i<num_js; i++) { 2.233 + print_joystick(jsp_arr[i], 0); 2.234 + close_joystick(jsp_arr[i]); 2.235 + } 2.236 + free(jsp_arr); 2.237 + 2.238 + return 0; 2.239 +} 2.240 + 2.241 +int cmp_jsp(const void *a, const void *b) 2.242 +{ 2.243 + return strcmp((*(struct joystick**)a)->devfile, (*(struct joystick**)b)->devfile); 2.244 } 2.245 2.246 void sig_handler(int sig) 2.247 @@ -278,6 +388,24 @@ 2.248 if(argv[i][0] == '-') { 2.249 if(argv[i][2] == 0) { 2.250 switch(argv[i][1]) { 2.251 + case 'd': 2.252 + uinput_dev = argv[++i]; 2.253 + break; 2.254 + 2.255 + case 'n': 2.256 + virt_name = argv[++i]; 2.257 + break; 2.258 + 2.259 + case 'l': 2.260 + if(list_devices() == -1) { 2.261 + exit(1); 2.262 + } 2.263 + exit(0); 2.264 + 2.265 + case 's': 2.266 + verbose = 0; 2.267 + break; 2.268 + 2.269 case 'h': 2.270 print_usage(argv[0]); 2.271 exit(0); 2.272 @@ -309,5 +437,11 @@ 2.273 2.274 void print_usage(const char *argv0) 2.275 { 2.276 - printf("usage: %s <dev 0> [dev1] ... [dev n]\n", argv0); 2.277 + printf("usage: %s [options] <dev 0> [dev1] ... [dev n]\n", argv0); 2.278 + printf("options:\n"); 2.279 + printf(" -d: uinput device file (default: /dev/uinput)\n"); 2.280 + printf(" -n: name for the virtual combined joystick\n"); 2.281 + printf(" -s: silent (reduces verbosity)\n"); 2.282 + printf(" -l: print a list of all the joystick devices and exit\n"); 2.283 + printf(" -h: print usage information and exit\n"); 2.284 }
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/gui/Makefile Thu Jul 14 15:40:20 2011 +0300 3.3 @@ -0,0 +1,29 @@ 3.4 +src = $(wildcard *.cc) moc_gui.cc moc_droplist.cc 3.5 +obj = $(src:.cc=.o) 3.6 +dep = $(obj:.o=.d) 3.7 +bin = combjs-gui 3.8 + 3.9 +uihdr = ui_main.h 3.10 + 3.11 +CXX = g++ 3.12 +CXXFLAGS = -Wall -g `pkg-config --cflags QtGui QtDesigner` 3.13 +LDFLAGS = `pkg-config --libs QtGui QtDesigner` 3.14 +MOC = moc 3.15 +UIC = uic 3.16 + 3.17 +$(bin): $(uihdr) $(obj) 3.18 + $(CXX) -o $@ $(obj) $(LDFLAGS) 3.19 + 3.20 +moc_%.cc: %.h 3.21 + moc -o $@ $< 3.22 + 3.23 +ui_%.h: %.ui 3.24 + uic -o $@ $< 3.25 + 3.26 +.PHONY: clean 3.27 +clean: 3.28 + rm -f $(obj) $(bin) ui_*.h moc_*.cc 3.29 + 3.30 +.PHONY: cleandep 3.31 +cleandep: 3.32 + rm -f $(dep)
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/gui/combjs-gui.cc Thu Jul 14 15:40:20 2011 +0300 4.3 @@ -0,0 +1,66 @@ 4.4 +#include <stdio.h> 4.5 +#include <QApplication> 4.6 +#include <QMessageBox> 4.7 +#include "combjs.h" 4.8 +#include "gui.h" 4.9 + 4.10 +MainWindow *main_win; 4.11 + 4.12 +int main(int argc, char **argv) 4.13 +{ 4.14 + QApplication app(argc, argv); 4.15 + 4.16 + main_win = new MainWindow; 4.17 + main_win->show(); 4.18 + 4.19 + return app.exec(); 4.20 +} 4.21 + 4.22 +int enum_joysticks(std::vector<Joystick> *jsvec) 4.23 +{ 4.24 + jsvec->clear(); 4.25 + 4.26 + FILE *pipe = popen("combjs -l", "r"); 4.27 + if(!pipe) { 4.28 + QMessageBox::critical(main_win, "Critical error", 4.29 + "Failed to execute combjs, make sure it's installed in the path."); 4.30 + exit(1); 4.31 + } 4.32 + 4.33 + char line[512]; 4.34 + while(fgets(line, sizeof line, pipe)) { 4.35 + Joystick js; 4.36 + char *ptr, *end; 4.37 + 4.38 + if(!(ptr = strchr(line, ':'))) { 4.39 + goto inval; 4.40 + } 4.41 + *ptr++ = 0; 4.42 + 4.43 + js.dev = line; 4.44 + 4.45 + if(!(ptr = strchr(ptr, '"')) || !(end = strchr(ptr + 1, '"'))) { 4.46 + goto inval; 4.47 + } 4.48 + *end = 0; 4.49 + 4.50 + js.name = ptr + 1; 4.51 + ptr = end + 1; 4.52 + 4.53 + if(sscanf(ptr, ", axes: %d, buttons: %d", &js.num_axes, &js.num_bn) != 2) { 4.54 + goto inval; 4.55 + } 4.56 + 4.57 + js.isvirt = false; 4.58 + jsvec->push_back(js); 4.59 + } 4.60 + pclose(pipe); 4.61 + 4.62 + return jsvec->size(); 4.63 + 4.64 +inval: 4.65 + QMessageBox::critical(main_win, "Invalid combjs output", 4.66 + "The output from combjs is in an unexpected format, version missmatch?"); 4.67 + exit(1); 4.68 + return -1; /* unreachable (duh) */ 4.69 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/gui/combjs.h Thu Jul 14 15:40:20 2011 +0300 5.3 @@ -0,0 +1,16 @@ 5.4 +#ifndef COMBJS_H_ 5.5 +#define COMBJS_H_ 5.6 + 5.7 +#include <vector> 5.8 +#include <string> 5.9 + 5.10 +struct Joystick { 5.11 + std::string dev; 5.12 + std::string name; 5.13 + int num_axes, num_bn; 5.14 + bool isvirt; 5.15 +}; 5.16 + 5.17 +int enum_joysticks(std::vector<Joystick> *jsvec); 5.18 + 5.19 +#endif /* COMBJS_H_ */
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/gui/droplist.cc Thu Jul 14 15:40:20 2011 +0300 6.3 @@ -0,0 +1,51 @@ 6.4 +#include <stdio.h> 6.5 +#include <QDragMoveEvent> 6.6 +#include "droplist.h" 6.7 + 6.8 +DropList::DropList(QWidget *parent) 6.9 + : QListWidget(parent) 6.10 +{ 6.11 + /*setDragEnabled(true); 6.12 + viewport()->setAcceptDrops(true); 6.13 + setDragDropMode(QAbstractItemView::DragDrop);*/ 6.14 +} 6.15 + 6.16 +void DropList::dragMoveEvent(QDragMoveEvent *ev) 6.17 +{ 6.18 + printf("%s\n", __func__); 6.19 + /*if(ev->source() == this) { 6.20 + ev->ignore(); 6.21 + return; 6.22 + }*/ 6.23 + 6.24 + /* check if duplicate and then ... */ 6.25 + ev->accept(); 6.26 +} 6.27 + 6.28 +void DropList::dragEnterEvent(QDragEnterEvent *ev) 6.29 +{ 6.30 + printf("%s\n", __func__); 6.31 + if(ev->source() == this) { 6.32 + ev->setDropAction(Qt::MoveAction); 6.33 + ev->accept(); 6.34 + } else { 6.35 + ev->acceptProposedAction(); 6.36 + } 6.37 +} 6.38 + 6.39 +void DropList::dropEvent(QDropEvent *ev) 6.40 +{ 6.41 + const QMimeData *mdata = ev->mimeData(); 6.42 + if(mdata->hasText()) { 6.43 + printf("%s: %s\n", __func__, mdata->text().toAscii().data()); 6.44 + } else { 6.45 + printf("%s\n", __func__); 6.46 + } 6.47 + 6.48 + if(ev->source() == this) { 6.49 + ev->setDropAction(Qt::MoveAction); 6.50 + ev->accept(); 6.51 + } else { 6.52 + ev->acceptProposedAction(); 6.53 + } 6.54 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/gui/droplist.h Thu Jul 14 15:40:20 2011 +0300 7.3 @@ -0,0 +1,18 @@ 7.4 +#ifndef DROPLIST_H_ 7.5 +#define DROPLIST_H_ 7.6 + 7.7 +#include <QListWidget> 7.8 + 7.9 +/* a custom drop-target list for the virtual joystick creation */ 7.10 +class DropList : public QListWidget { 7.11 + Q_OBJECT 7.12 +protected: 7.13 + void dragMoveEvent(QDragMoveEvent *ev); 7.14 + void dragEnterEvent(QDragEnterEvent *ev); 7.15 + void dropEvent(QDropEvent *ev); 7.16 + 7.17 +public: 7.18 + DropList(QWidget *parent); 7.19 +}; 7.20 + 7.21 +#endif /* DROPLIST_H_ */
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/gui/gui.cc Thu Jul 14 15:40:20 2011 +0300 8.3 @@ -0,0 +1,55 @@ 8.4 +#include <stdio.h> 8.5 +#include <stdlib.h> 8.6 +#include <QMessageBox> 8.7 +#include <QCloseEvent> 8.8 +#include "gui.h" 8.9 +#include "combjs.h" 8.10 + 8.11 +static std::vector<Joystick> jsvec; 8.12 + 8.13 +MainWindow::MainWindow(QWidget *parent) 8.14 + : QMainWindow(parent) 8.15 +{ 8.16 + setupUi(this); 8.17 + 8.18 + int num_js = enum_joysticks(&jsvec); 8.19 + 8.20 + list_js->clear(); 8.21 + for(int i=0; i<num_js; i++) { 8.22 + QListWidgetItem *item = new QListWidgetItem(jsvec[i].name.c_str()); 8.23 + item->setData(Qt::UserRole, i); 8.24 + item->setToolTip(jsvec[i].dev.c_str()); 8.25 + 8.26 + list_js->addItem(item); 8.27 + } 8.28 + 8.29 + connect(list_js, SIGNAL(itemSelectionChanged()), this, SLOT(jslist_select())); 8.30 +} 8.31 + 8.32 + 8.33 +void MainWindow::closeEvent(QCloseEvent *ev) 8.34 +{ 8.35 + /*const char *msg_text = "Are you sure you want to quit?\n" 8.36 + "Quitting this application will destroy any virtual joystick devices you created!" 8.37 + "If this wasn't your intention, press cancel and minimize instead of quitting."; 8.38 + 8.39 + if(QMessageBox::question(this, "Quit?", msg_text, QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) { 8.40 + ev->accept(); 8.41 + } else { 8.42 + ev->ignore(); 8.43 + }*/ 8.44 + ev->accept(); 8.45 +} 8.46 + 8.47 +/* slots */ 8.48 +void MainWindow::jslist_select() 8.49 +{ 8.50 + QList<QListWidgetItem*> sel_list = list_js->selectedItems(); 8.51 + QListWidgetItem *item = sel_list.isEmpty() ? 0 : sel_list.first(); 8.52 + 8.53 + if(item && jsvec[item->data(Qt::UserRole).toInt()].isvirt) { 8.54 + bn_del_virt->setEnabled(true); 8.55 + } else { 8.56 + bn_del_virt->setEnabled(false); 8.57 + } 8.58 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/gui/gui.h Thu Jul 14 15:40:20 2011 +0300 9.3 @@ -0,0 +1,18 @@ 9.4 +#ifndef GUI_H_ 9.5 +#define GUI_H_ 9.6 + 9.7 +#include "ui_main.h" 9.8 + 9.9 +class MainWindow : public QMainWindow, private Ui::MainWindow { 9.10 + Q_OBJECT 9.11 +private slots: 9.12 + void jslist_select(); 9.13 + 9.14 +private: 9.15 + void closeEvent(QCloseEvent *ev); 9.16 + 9.17 +public: 9.18 + MainWindow(QWidget *parent = 0); 9.19 +}; 9.20 + 9.21 +#endif /* GUI_H_ */
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/gui/main.ui Thu Jul 14 15:40:20 2011 +0300 10.3 @@ -0,0 +1,296 @@ 10.4 +<?xml version="1.0" encoding="UTF-8"?> 10.5 +<ui version="4.0"> 10.6 + <class>MainWindow</class> 10.7 + <widget class="QMainWindow" name="MainWindow"> 10.8 + <property name="geometry"> 10.9 + <rect> 10.10 + <x>0</x> 10.11 + <y>0</y> 10.12 + <width>796</width> 10.13 + <height>612</height> 10.14 + </rect> 10.15 + </property> 10.16 + <property name="windowTitle"> 10.17 + <string>Joystick Combiner</string> 10.18 + </property> 10.19 + <widget class="QWidget" name="centralwidget"> 10.20 + <layout class="QVBoxLayout" name="verticalLayout_4"> 10.21 + <item> 10.22 + <widget class="QSplitter" name="splitter_3"> 10.23 + <property name="orientation"> 10.24 + <enum>Qt::Horizontal</enum> 10.25 + </property> 10.26 + <widget class="QSplitter" name="splitter_2"> 10.27 + <property name="orientation"> 10.28 + <enum>Qt::Vertical</enum> 10.29 + </property> 10.30 + <widget class="QGroupBox" name="groupBox"> 10.31 + <property name="title"> 10.32 + <string>Joystick devices</string> 10.33 + </property> 10.34 + <layout class="QVBoxLayout" name="verticalLayout_3"> 10.35 + <item> 10.36 + <widget class="QListWidget" name="list_js"> 10.37 + <property name="dragEnabled"> 10.38 + <bool>true</bool> 10.39 + </property> 10.40 + <property name="dragDropMode"> 10.41 + <enum>QAbstractItemView::DragDrop</enum> 10.42 + </property> 10.43 + </widget> 10.44 + </item> 10.45 + <item> 10.46 + <layout class="QHBoxLayout" name="horizontalLayout_3"> 10.47 + <item> 10.48 + <spacer name="horizontalSpacer_2"> 10.49 + <property name="orientation"> 10.50 + <enum>Qt::Horizontal</enum> 10.51 + </property> 10.52 + <property name="sizeHint" stdset="0"> 10.53 + <size> 10.54 + <width>40</width> 10.55 + <height>20</height> 10.56 + </size> 10.57 + </property> 10.58 + </spacer> 10.59 + </item> 10.60 + <item> 10.61 + <widget class="QPushButton" name="bn_del_virt"> 10.62 + <property name="enabled"> 10.63 + <bool>false</bool> 10.64 + </property> 10.65 + <property name="text"> 10.66 + <string>Delete virtual device</string> 10.67 + </property> 10.68 + </widget> 10.69 + </item> 10.70 + </layout> 10.71 + </item> 10.72 + </layout> 10.73 + </widget> 10.74 + <widget class="QGroupBox" name="groupBox_2"> 10.75 + <property name="title"> 10.76 + <string>New virtual device</string> 10.77 + </property> 10.78 + <layout class="QVBoxLayout" name="verticalLayout_2"> 10.79 + <item> 10.80 + <layout class="QHBoxLayout" name="horizontalLayout"> 10.81 + <item> 10.82 + <widget class="QLabel" name="label"> 10.83 + <property name="text"> 10.84 + <string>Name</string> 10.85 + </property> 10.86 + </widget> 10.87 + </item> 10.88 + <item> 10.89 + <widget class="QLineEdit" name="tx_devname"/> 10.90 + </item> 10.91 + </layout> 10.92 + </item> 10.93 + <item> 10.94 + <widget class="DropList" name="list_newdev"> 10.95 + <property name="acceptDrops"> 10.96 + <bool>true</bool> 10.97 + </property> 10.98 + <property name="dragEnabled"> 10.99 + <bool>true</bool> 10.100 + </property> 10.101 + <property name="dragDropOverwriteMode"> 10.102 + <bool>true</bool> 10.103 + </property> 10.104 + <property name="dragDropMode"> 10.105 + <enum>QAbstractItemView::DragDrop</enum> 10.106 + </property> 10.107 + <property name="defaultDropAction"> 10.108 + <enum>Qt::CopyAction</enum> 10.109 + </property> 10.110 + <property name="alternatingRowColors"> 10.111 + <bool>false</bool> 10.112 + </property> 10.113 + <property name="modelColumn"> 10.114 + <number>0</number> 10.115 + </property> 10.116 + </widget> 10.117 + </item> 10.118 + <item> 10.119 + <layout class="QHBoxLayout" name="horizontalLayout_2"> 10.120 + <item> 10.121 + <widget class="QPushButton" name="pushButton_3"> 10.122 + <property name="enabled"> 10.123 + <bool>false</bool> 10.124 + </property> 10.125 + <property name="text"> 10.126 + <string>Create</string> 10.127 + </property> 10.128 + </widget> 10.129 + </item> 10.130 + <item> 10.131 + <spacer name="horizontalSpacer"> 10.132 + <property name="orientation"> 10.133 + <enum>Qt::Horizontal</enum> 10.134 + </property> 10.135 + <property name="sizeHint" stdset="0"> 10.136 + <size> 10.137 + <width>40</width> 10.138 + <height>20</height> 10.139 + </size> 10.140 + </property> 10.141 + </spacer> 10.142 + </item> 10.143 + <item> 10.144 + <widget class="QPushButton" name="pushButton_2"> 10.145 + <property name="enabled"> 10.146 + <bool>false</bool> 10.147 + </property> 10.148 + <property name="text"> 10.149 + <string>Remove</string> 10.150 + </property> 10.151 + </widget> 10.152 + </item> 10.153 + </layout> 10.154 + </item> 10.155 + </layout> 10.156 + </widget> 10.157 + </widget> 10.158 + <widget class="QSplitter" name="splitter"> 10.159 + <property name="orientation"> 10.160 + <enum>Qt::Vertical</enum> 10.161 + </property> 10.162 + <widget class="QGroupBox" name="groupBox_3"> 10.163 + <property name="sizePolicy"> 10.164 + <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> 10.165 + <horstretch>0</horstretch> 10.166 + <verstretch>0</verstretch> 10.167 + </sizepolicy> 10.168 + </property> 10.169 + <property name="minimumSize"> 10.170 + <size> 10.171 + <width>0</width> 10.172 + <height>347</height> 10.173 + </size> 10.174 + </property> 10.175 + <property name="title"> 10.176 + <string>Joystick information</string> 10.177 + </property> 10.178 + <layout class="QVBoxLayout" name="verticalLayout"> 10.179 + <item> 10.180 + <widget class="QListWidget" name="list_joyinfo"/> 10.181 + </item> 10.182 + </layout> 10.183 + </widget> 10.184 + <widget class="QGroupBox" name="groupBox_4"> 10.185 + <property name="sizePolicy"> 10.186 + <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> 10.187 + <horstretch>0</horstretch> 10.188 + <verstretch>0</verstretch> 10.189 + </sizepolicy> 10.190 + </property> 10.191 + <property name="title"> 10.192 + <string>Joystick test</string> 10.193 + </property> 10.194 + <layout class="QVBoxLayout" name="verticalLayout_5"> 10.195 + <item> 10.196 + <widget class="QScrollArea" name="test_area"> 10.197 + <property name="widgetResizable"> 10.198 + <bool>true</bool> 10.199 + </property> 10.200 + <widget class="QWidget" name="scrollAreaWidgetContents"> 10.201 + <property name="geometry"> 10.202 + <rect> 10.203 + <x>0</x> 10.204 + <y>0</y> 10.205 + <width>360</width> 10.206 + <height>158</height> 10.207 + </rect> 10.208 + </property> 10.209 + </widget> 10.210 + </widget> 10.211 + </item> 10.212 + </layout> 10.213 + </widget> 10.214 + </widget> 10.215 + </widget> 10.216 + </item> 10.217 + </layout> 10.218 + </widget> 10.219 + <widget class="QMenuBar" name="menubar"> 10.220 + <property name="geometry"> 10.221 + <rect> 10.222 + <x>0</x> 10.223 + <y>0</y> 10.224 + <width>796</width> 10.225 + <height>24</height> 10.226 + </rect> 10.227 + </property> 10.228 + <widget class="QMenu" name="menuFile"> 10.229 + <property name="title"> 10.230 + <string>Joystick</string> 10.231 + </property> 10.232 + <addaction name="action_combine"/> 10.233 + <addaction name="action_delete"/> 10.234 + <addaction name="action_quit"/> 10.235 + </widget> 10.236 + <widget class="QMenu" name="menuHelp"> 10.237 + <property name="title"> 10.238 + <string>Help</string> 10.239 + </property> 10.240 + <addaction name="action_usage"/> 10.241 + <addaction name="action_about"/> 10.242 + </widget> 10.243 + <addaction name="menuFile"/> 10.244 + <addaction name="menuHelp"/> 10.245 + </widget> 10.246 + <widget class="QStatusBar" name="statusbar"/> 10.247 + <action name="action_usage"> 10.248 + <property name="text"> 10.249 + <string>Usage</string> 10.250 + </property> 10.251 + </action> 10.252 + <action name="action_about"> 10.253 + <property name="text"> 10.254 + <string>About</string> 10.255 + </property> 10.256 + </action> 10.257 + <action name="action_combine"> 10.258 + <property name="text"> 10.259 + <string>Combine</string> 10.260 + </property> 10.261 + </action> 10.262 + <action name="action_delete"> 10.263 + <property name="text"> 10.264 + <string>Delete</string> 10.265 + </property> 10.266 + </action> 10.267 + <action name="action_quit"> 10.268 + <property name="text"> 10.269 + <string>Quit</string> 10.270 + </property> 10.271 + </action> 10.272 + </widget> 10.273 + <customwidgets> 10.274 + <customwidget> 10.275 + <class>DropList</class> 10.276 + <extends>QListWidget</extends> 10.277 + <header>droplist.h</header> 10.278 + </customwidget> 10.279 + </customwidgets> 10.280 + <resources/> 10.281 + <connections> 10.282 + <connection> 10.283 + <sender>action_quit</sender> 10.284 + <signal>triggered()</signal> 10.285 + <receiver>MainWindow</receiver> 10.286 + <slot>close()</slot> 10.287 + <hints> 10.288 + <hint type="sourcelabel"> 10.289 + <x>-1</x> 10.290 + <y>-1</y> 10.291 + </hint> 10.292 + <hint type="destinationlabel"> 10.293 + <x>397</x> 10.294 + <y>305</y> 10.295 + </hint> 10.296 + </hints> 10.297 + </connection> 10.298 + </connections> 10.299 +</ui>