From: Konrad Rosenbaum Date: Sun, 19 Jan 2014 18:38:13 +0000 (+0100) Subject: working usb scanner support, missing config widget X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=8d003aef64494dfeccf6c80243109ebeb6fa1308;p=web%2Fkonrad%2Fsmoke.git working usb scanner support, missing config widget --- diff --git a/plugins/bcs-usb/bcs-plugin.cpp b/plugins/bcs-usb/bcs-plugin.cpp new file mode 100644 index 0000000..286c4af --- /dev/null +++ b/plugins/bcs-usb/bcs-plugin.cpp @@ -0,0 +1,149 @@ +// +// C++ Implementation: Barcode Plugin for USB +// +// +// Author: Konrad Rosenbaum , (C) 2013-2014 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "bcs-plugin.h" +#include "configwidget.h" +#include "hidscanner.h" + +#include + +#include +#include +#include + +MHidBarcodePlugin::MHidBarcodePlugin(): QObject() +{ + qDebug()<<"Initializing USB Barcode Plugin"; + misopen = (hid_init()==0); + if(misopen) + qDebug()<<" ...success."; + else{ + qDebug()<<" ...failed to initialize USB-HID."; + return; + } + mdetecttmr=new QTimer(this); + connect(mdetecttmr,SIGNAL(timeout()),this,SLOT(detectScanners())); + mdetecttmr->setSingleShot(false); + restartDetect(); +} + +MHidBarcodePlugin::~MHidBarcodePlugin() +{ + qDebug()<<"Unloading USB Barcode Plugin"; + if(mdetecttmr)mdetecttmr->stop(); + for(MHidBarcodeScanner*sc:mscanners){ + if(sc)delete sc; + } + mscanners.clear(); + if(misopen)hid_exit(); +} + + +void MHidBarcodePlugin::configure(MBarcodeConfiguration* cfg) +{ + //suspend detection until dialog closed + if(mdetecttmr)mdetecttmr->stop(); + //main tab + new MUsbBarcodeConfig(cfg); + QSettings set;set.beginGroup(MUsbBarcodeConfig::settingsGroup); + for(const QString s:set.childGroups()) + new MUsbScannerConfig(cfg,s); + //restart detection + connect(cfg,SIGNAL(destroyed(QObject*)),this,SLOT(restartDetect())); +} + +MHidBarcodePlugin::Config::Config(QSettings& set,QString grp) +{ + set.beginGroup(grp); + isactive=set.value(MUsbBarcodeConfig::activeKey,false).toBool(); + vendor=set.value(MUsbBarcodeConfig::vendorKey,0).toInt(); + product=set.value(MUsbBarcodeConfig::productKey,0).toInt(); + iface=set.value(MUsbBarcodeConfig::interfaceKey,0).toInt(); + useserial=set.value(MUsbBarcodeConfig::useSerialKey,false).toBool(); + serial=set.value(MUsbBarcodeConfig::serialKey).toString(); + group=grp; + set.endGroup(); +} + +void MHidBarcodePlugin::restartDetect() +{ + if(!misopen){ + if(mdetecttmr){ + delete mdetecttmr; + mdetecttmr=0; + } + return; + } + const int interv=QSettings().value(MUsbBarcodeConfig::intervalKey,10).toInt(); + if(interv>0) + mdetecttmr->start(interv*1000); + else + mdetecttmr->stop(); + //re-read config + QSettings set; + set.beginGroup(MUsbBarcodeConfig::settingsGroup); + mconfig.clear(); + for(const QString grp:set.childGroups()){ + Config c(set,grp); + if(!c.isactive){ + continue; + } + mconfig.append(c); + } + //TODO: go through running scanners and kill unknowns +} + +void MHidBarcodePlugin::detectScanners() +{ + if(!misopen)return; + qDebug()<<"scanning for scanners..."; + hid_device_info *info=hid_enumerate(0,0); + for(hid_device_info*dev=info;dev;dev=dev->next){ + //is it known? + Config cfg=findCfgMatch(dev->vendor_id,dev->product_id,dev->interface_number, + QString::fromWCharArray(dev->serial_number)); + if(cfg.vendor<=0)continue; + //is it already open? + MHidBarcodeScanner*scanner=findScanner(dev->path); + if(scanner)continue; + //open it + qDebug()<<"instantiating scanner"; + scanner=new MHidBarcodeScanner(dev->path,cfg.group); + mscanners.append(scanner); + connect(scanner,SIGNAL(destroyed(QObject*)),this,SLOT(removeScanner(QObject*))); + } + hid_free_enumeration(info); +} + +MHidBarcodePlugin::Config MHidBarcodePlugin::findCfgMatch(int vendor, int product, int iface, QString serial) +{ + for(Config c:mconfig){ + if(c.vendor!=vendor || c.product!=product || c.iface!=iface)continue; + if(c.useserial && c.serial!=serial)continue; + return c; + } + return Config(); +} + +MHidBarcodeScanner* MHidBarcodePlugin::findScanner(QString path) +{ + for(MHidBarcodeScanner*scanner:mscanners) + if(scanner->matchPath(path)) + return scanner; + return nullptr; +} + +void MHidBarcodePlugin::removeScanner(QObject* o) +{ + MHidBarcodeScanner*s=qobject_cast< MHidBarcodeScanner* >(o); + if(s) + mscanners.removeAll(s); +} + diff --git a/plugins/bcs-usb/bcs-plugin.h b/plugins/bcs-usb/bcs-plugin.h new file mode 100644 index 0000000..47f97d4 --- /dev/null +++ b/plugins/bcs-usb/bcs-plugin.h @@ -0,0 +1,54 @@ +// +// C++ Interface: plugin for USB barcode scanners +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2013-2014 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_BARCODE_PLUGIN_HID_H +#define MAGICSMOKE_BARCODE_PLUGIN_HID_H + +#include "barcode-plugin.h" + +class QTimer; +class MHidBarcodeScanner; +class QSettings; +class MHidBarcodePlugin:public QObject,public MBarcodePlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID MBarcodePlugin_IID) + Q_INTERFACES(MBarcodePlugin) + public: + MHidBarcodePlugin(); + virtual ~MHidBarcodePlugin(); + virtual void configure(MBarcodeConfiguration*)override; + private slots: + void detectScanners(); + void restartDetect(); + void removeScanner(QObject*); + private: + bool misopen; + QTimer*mdetecttmr=nullptr; + struct Config{ + int vendor=0,product=0,iface=0; + bool useserial=false,isactive=false; + QString serial,group; + Config(){} + Config(const Config&)=default; + Config(Config&&)=default; + Config(QSettings&,QString); + Config& operator=(const Config&)=default; + Config& operator=(Config&&)=default; + }; + QListmconfig; + Config findCfgMatch(int vendor,int product,int iface,QString serial); + QListmscanners; + MHidBarcodeScanner*findScanner(QString path); +}; + +#endif diff --git a/plugins/bcs-usb/bcs-usb.pro b/plugins/bcs-usb/bcs-usb.pro new file mode 100644 index 0000000..61de9c9 --- /dev/null +++ b/plugins/bcs-usb/bcs-usb.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +TARGET = msp-bcs-usb +CONFIG += plugin no_plugin_name_prefix + +include (../../basics.pri) +include (../../src/smoke.pri) +include (hidapi.pri) + +SOURCES += bcs-plugin.cpp configwidget.cpp bcskeyboard.cpp hidscanner.cpp +HEADERS += bcs-plugin.h configwidget.h bcskeyboard.h hidscanner.h + +RESOURCES += layouts.qrc \ No newline at end of file diff --git a/plugins/bcs-usb/bcskeyboard.cpp b/plugins/bcs-usb/bcskeyboard.cpp new file mode 100644 index 0000000..9546563 --- /dev/null +++ b/plugins/bcs-usb/bcskeyboard.cpp @@ -0,0 +1,336 @@ +// +// C++ Implementation: Barcode Plugin for USB: Keyboard Stuff +// +// +// Author: Konrad Rosenbaum , (C) 2013-2014 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "bcskeyboard.h" +#include +#include +#include +#include +#include + +MHidKeyLayout::MHidKeyLayout() +{ + loadLayout("base"); +} + +MHidKeyLayout::MHidKeyLayout(QString name) +{ + loadLayout(name); +} + +QString MHidKeyLayout::layoutCodeName() const +{ + if(mfilename.isEmpty())return QString(); + return QFileInfo(mfilename).baseName(); +} + +void MHidKeyLayout::clearKeyMapping() +{ + mkeymap.clear(); +} + +void MHidKeyLayout::resetLayout() +{ + clearKeyMapping(); + loadLayout("base"); +} + +void MHidKeyLayout::setKeyMapping(unsigned char keycode, const QList &c) +{ + if(!c.isEmpty())mkeymap.insert(keycode,c); + else mkeymap.remove(keycode); +} + +QString MHidKeyLayout::toLayoutDoc() const +{ + QString ret="#This is a generated keyboard layout\n"; + if(!mlname.isEmpty())ret+="title "+mlname+"\n"; + for(unsigned char kc:mkeymap.keys()){ + if(mkeymap[kc].isEmpty())continue; + ret+=QString("0x%1").arg((int)kc,0,16); + for(const MKey&k:mkeymap[kc]) + ret+=QString(" %1").arg(k.toCharName()); + ret+="\n"; + } + return ret; +} + +bool MHidKeyLayout::loadLayout(QString filename) +{ + //no slash: try to find a match + if(!filename.contains('/')){ + if(!filename.endsWith(".kbl"))filename+=".kbl"; + //search for file in app dir + if(QFileInfo(QCoreApplication::applicationDirPath()+"/kbdlayouts/"+filename).exists()) + filename=QCoreApplication::applicationDirPath()+"/kbdlayouts/"+filename; + //search in resources + else if(QFileInfo(":/kbdlayouts/"+filename).exists()) + filename=":/kbdlayouts/"+filename; + else{ + qDebug()<<"Unable to find a match for keyboard layout"<255){ + qDebug()<<"Error: illegal key code"<keys; + for(int i=1;i MHidKeyLayout::findLayouts() +{ + static QMaplaymap; + if(laymap.size()>0)return laymap; + //search all files + for(QString d:QStringList()<<":/kbdlayouts"<=0){ + altseq*=10; + altseq+=d; + } +// qDebug()<<"Alt: "<0) + ret+=QChar::fromLatin1(altseq); +// qDebug()<<"Alt compl:"<0)ret+=QChar::fromLatin1(altseq); + //done + return ret; +} + +void MHidKeyEvent::reduce() +{ + QByteArray r; + for(unsigned char c:mkeys) + if(c>1)r.append(c); + mkeys=r; +} + +qint64 MHidKeySequence::msSinceLastKey() const +{ + if(isEmpty())return 0; + return at(size()-1).timestamp().msecsTo(QDateTime::currentDateTime()); +} diff --git a/plugins/bcs-usb/bcskeyboard.h b/plugins/bcs-usb/bcskeyboard.h new file mode 100644 index 0000000..b9e6d30 --- /dev/null +++ b/plugins/bcs-usb/bcskeyboard.h @@ -0,0 +1,193 @@ +// +// C++ Interface: plugin for USB barcode scanners: Scanner Implementation +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2013-2014 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_BCSUSB_KBD_H +#define MAGICSMOKE_BCSUSB_KBD_H + +#include +#include +#include +#include +#include + +class MKey +{ + public: + enum Modifier { + None = 0, + Ctrl = 1, + Shift = 2, + Alt = 4, + AltGr = 8, + GUI = 16, + }; + Q_DECLARE_FLAGS(Modifiers,Modifier); + + enum KeyType{ + AllKeyRelease = 0, + CharKey = 1, + CapsLock = 2, + NumLock = 3, + Backspace = 4, + Return = 5, + Tabulator = 6, + Space = 7, + ModifierOnly =8, + Escape = 9, + }; + + MKey(){} + MKey(const MKey&k,Modifiers m); + MKey(const MKey&)=default; + MKey(MKey&&)=default; + + MKey(QChar,Modifiers m=None); + MKey(KeyType t,Modifiers m=None):mmod(m),mtype(t){} + + MKey& operator=(const MKey&)=default; + MKey& operator=(MKey&&)=default; + + bool operator==(const MKey&); + bool operator!=(const MKey&k){return !operator==(k);} + + bool isValid()const{return mtype!=AllKeyRelease;} + + Modifiers modifiers()const{return mmod;} + QChar toChar(bool ignoremodifier=false)const; + bool isPrintable(bool ignoremodifier=false)const; + + ///returns the encoded character name as used in layout files + QString toCharName()const; + ///returns a key object matching the encoded character name from a layout file + static MKey fromCharName(QString); + + MKey toLower()const{MKey r(*this);r.mchar=r.mchar.toLower();return r;} + MKey toUpper()const{MKey r(*this);r.mchar=r.mchar.toUpper();return r;} + private: + Modifiers mmod=None; + KeyType mtype=AllKeyRelease; + QChar mchar; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(MKey::Modifiers) + +class MKeySequence:public QList +{ + public: + MKeySequence(){} + MKeySequence(const QList< MKey >& l):QList< MKey >(l){} + MKeySequence(const MKeySequence& other)=default; + MKeySequence(MKeySequence&&)=default; + + MKeySequence& operator=(const QList&l){QList::operator=(l);return *this;} + MKeySequence& operator=(const MKeySequence&)=default; + MKeySequence& operator=(MKeySequence&&)=default; + + QString toString()const; +}; + +class MHidKeyEvent +{ + inline static MKey::Modifiers modconv(unsigned char m){ + MKey::Modifiers r=MKey::None; + if(m&0x11)r=MKey::Ctrl; + if(m&0x22)r|=MKey::Shift; + if(m&0x04)r|=MKey::Alt; + if(m&0x40)r|=MKey::AltGr; + if(m&0x88)r|=MKey::GUI; + return r; + } + public: + + MHidKeyEvent(){} + MHidKeyEvent(unsigned char mod,QByteArray keys):mmod(modconv(mod)),mkeys(keys){reduce();} + MHidKeyEvent(const MHidKeyEvent&)=default; + MHidKeyEvent(MHidKeyEvent&&)=default; + + MHidKeyEvent& operator=(const MHidKeyEvent&)=default; + MHidKeyEvent& operator=(MHidKeyEvent&&)=default; + + MKey::Modifiers modifiers()const{return mmod;} + QByteArray keycodes()const{return mkeys;} + QDateTime timestamp()const{return mtime;} + int lastkeycode()const{if(mkeys.size()>0)return mkeys[mkeys.size()-1];else return 0;} + + private: + QDateTime mtime=QDateTime::currentDateTime(); + MKey::Modifiers mmod=MKey::None; + QByteArray mkeys; + void reduce(); +}; + +class MHidKeySequence:public QList +{ + public: + MHidKeySequence(){} + MHidKeySequence(QList< MHidKeyEvent >& other):QList< MHidKeyEvent >(other){} + MHidKeySequence(const MHidKeySequence&)=default; + MHidKeySequence(MHidKeySequence&&)=default; + + MHidKeySequence& operator=(const MHidKeySequence&)=default; + MHidKeySequence& operator=(MHidKeySequence&&)=default; + + qint64 msSinceLastKey()const; +}; + +class MHidKeyLayout +{ + public: + ///loads the base layout only + MHidKeyLayout(); + ///loads the specified layout + explicit MHidKeyLayout(QString name); + MHidKeyLayout(const MHidKeyLayout&)=default; + MHidKeyLayout(MHidKeyLayout&&)=default; + + MHidKeyLayout& operator=(const MHidKeyLayout&)=default; + MHidKeyLayout& operator=(MHidKeyLayout&&)=default; + + MKeySequence toKeys(const MHidKeySequence&)const; + QString toString(const MHidKeySequence&)const; + + ///attempts to load a layout file, normally the name mentioned + ///should not contain a complete path or the suffix .kbl - the + ///implementation will automatically search for a matching file; + ///if it does contain a slash it is assumed to be a complete file name + bool loadLayout(QString filename); + bool parseLayout(QString content,QString filename=QString()); + void resetLayout(); + + QString toLayoutDoc()const; + + void setKeyMapping(unsigned char keycode,const QList &c); + void clearKeyMapping(); + + ///returns the human readable name of the layout + QString layoutName()const{return mlname;} + ///returns the iso code of the layout (base of the file name) + ///or an empty string if this is a custom layout + QString layoutCodeName()const; + ///returns the full file name of the layout + QString layoutFileName()const{return mfilename;} + + void setLayoutName(QString l){mlname=l;} + + ///returns true if this is a populated layout + bool isValid()const{return mkeymap.size()>0;} + + static QMap findLayouts(); + private: + QString mfilename,mlname; + QMap>mkeymap; +}; + +#endif diff --git a/plugins/bcs-usb/configwidget.cpp b/plugins/bcs-usb/configwidget.cpp new file mode 100644 index 0000000..4a6350d --- /dev/null +++ b/plugins/bcs-usb/configwidget.cpp @@ -0,0 +1,69 @@ +// +// C++ Implementation: Barcode Plugin for USB: Config +// +// +// Author: Konrad Rosenbaum , (C) 2013-2014 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "configwidget.h" + +#include "barcode-plugin.h" +#include +#include +#include + +const QString MUsbBarcodeConfig::settingsGroup="usbBarcodeScanner"; +const QString MUsbBarcodeConfig::intervalKey="interval"; +const QString MUsbBarcodeConfig::timeoutKey="timeoutms"; +const QString MUsbBarcodeConfig::terminatorKey="terminatorkey"; +const QString MUsbBarcodeConfig::layoutKey="kbdlayout"; +const QString MUsbBarcodeConfig::nameKey="name"; +const QString MUsbBarcodeConfig::activeKey="active"; +const QString MUsbBarcodeConfig::vendorKey="vendorid"; +const QString MUsbBarcodeConfig::productKey="productid"; +const QString MUsbBarcodeConfig::serialKey="serial"; +const QString MUsbBarcodeConfig::useSerialKey="useserial"; +const QString MUsbBarcodeConfig::interfaceKey="interfaceid"; + +MUsbBarcodeConfig::MUsbBarcodeConfig(MBarcodeConfiguration* cfg) +{ + QFormLayout *fl; + setLayout(fl=new QFormLayout); + fl->addRow(tr("Detection Interval"),minterval=new QComboBox); + minterval->setEditable(false); + minterval->addItem(tr("Driver Inactive"),0); + minterval->addItem(tr("5 seconds"),5); + minterval->addItem(tr("10 seconds"),10); + minterval->addItem(tr("20 seconds"),20); + minterval->addItem(tr("30 seconds"),30); + QPushButton*p; + fl->addRow(tr("Add Scanner"),p=new QPushButton(tr("add..."))); + connect(p,SIGNAL(clicked(bool)),this,SLOT(addScanner())); + + cfg->addTab(this,tr("USB Settings")); +} + +void MUsbBarcodeConfig::saveConfig() +{ + +} + +void MUsbBarcodeConfig::addScanner() +{ + +} + + +MUsbScannerConfig::MUsbScannerConfig(MBarcodeConfiguration* cfg, QString id) +{ + //TODO: use a better name for the tab + cfg->addTab(this,tr("USB Scanner: %1").arg(id)); +} + +void MUsbScannerConfig::saveConfig() +{ + +} diff --git a/plugins/bcs-usb/configwidget.h b/plugins/bcs-usb/configwidget.h new file mode 100644 index 0000000..b47483b --- /dev/null +++ b/plugins/bcs-usb/configwidget.h @@ -0,0 +1,55 @@ +// +// C++ Interface: plugin for USB barcode scanners +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2013-2014 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_BCSUSB_CONFIG_H +#define MAGICSMOKE_BCSUSB_CONFIG_H + +#include + +class QComboBox; +class MBarcodeConfiguration; +class MUsbBarcodeConfig:public QWidget +{ + Q_OBJECT + public: + MUsbBarcodeConfig(MBarcodeConfiguration*); + + static const QString settingsGroup; + static const QString intervalKey; + static const QString timeoutKey; + static const QString terminatorKey; + static const QString layoutKey; + static const QString nameKey; + static const QString activeKey; + static const QString vendorKey; + static const QString productKey; + static const QString serialKey; + static const QString useSerialKey; + static const QString interfaceKey; + + public slots: + void saveConfig(); + void addScanner(); + private: + QComboBox*minterval; +}; + +class MUsbScannerConfig:public QWidget +{ + Q_OBJECT + public: + MUsbScannerConfig(MBarcodeConfiguration*,QString); + public slots: + void saveConfig(); +}; + +#endif diff --git a/plugins/bcscanner/hidapi.pri b/plugins/bcs-usb/hidapi.pri similarity index 100% rename from plugins/bcscanner/hidapi.pri rename to plugins/bcs-usb/hidapi.pri diff --git a/plugins/bcs-usb/hidscanner.cpp b/plugins/bcs-usb/hidscanner.cpp new file mode 100644 index 0000000..78c5168 --- /dev/null +++ b/plugins/bcs-usb/hidscanner.cpp @@ -0,0 +1,113 @@ +// +// C++ Implementation: Barcode Plugin for USB: Scanner +// +// +// Author: Konrad Rosenbaum , (C) 2013-2014 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "hidscanner.h" +#include "configwidget.h" + +#include +#include +#include + +MHidBarcodeScanner::MHidBarcodeScanner(QString path,QString setGrp, QObject* parent) + : MBarcodeScanner(parent),mpath(path) +{ + qDebug()<<"Trying to open device at"<setSingleShot(false); + mrdtmr->start(20); + connect(mrdtmr,SIGNAL(timeout()),this,SLOT(readData())); + emit activated(); +} + +void MHidBarcodeScanner::deactivate() +{ + if(mrdtmr)delete mrdtmr; + mrdtmr=nullptr; + if(mdev)hid_close(mdev); + mdev=nullptr; + emit deactivated(); +} + +QString MHidBarcodeScanner::readableName() const +{ + return mname; +} + +void MHidBarcodeScanner::readData() +{ + if(mdev==nullptr){ + if(mseq.size()>0)processData(); + return; + } + //read data + unsigned char buf[64]; + memset(buf,0,sizeof(buf)); + while(true){ + const int rs=hid_read(mdev,buf,sizeof(buf)); + if(rs<0){ + qDebug()<<"Error reading from USB device"<=3 bytes, got"<0 && mseq.msSinceLastKey()>=mtimeout) + force=true; + //can we see one of the termination codes? + if(!force && !mterminator.isValid())return; + MKeySequence kseq=mlayout.toKeys(mseq); + if(!force && !kseq.contains(mterminator))return; + //convert + QString bc=kseq.toString(); + mseq.clear(); + //remove superfluous chars + //verify checksum and remove it + //emit barcode + qDebug()<<"scanned barcode"<, (C) 2013-2014 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_BCSUSB_SCANNER_H +#define MAGICSMOKE_BCSUSB_SCANNER_H + +#include + +#include + +#include "bcskeyboard.h" + +class QTimer; +class MHidBarcodeScanner:public MBarcodeScanner +{ + Q_OBJECT + public: + explicit MHidBarcodeScanner(QString path,QString setGrp,QObject* parent = 0); + virtual ~MHidBarcodeScanner(); + + QString readableName()const override; + bool isActive()const override{return mdev!=nullptr;} + + void activate() override; + void deactivate() override; + + bool matchPath(const QString &p){return mpath==p;} + + private slots: + void readData(); + void processData(); + private: + hid_device*mdev=nullptr; + QTimer*mrdtmr=nullptr; + QString mpath,mname; + MHidKeySequence mseq; + MHidKeyLayout mlayout; + int mtimeout=0; + MKey mterminator; +}; + +#endif diff --git a/plugins/bcs-usb/kbdlayouts/base.kbl b/plugins/bcs-usb/kbdlayouts/base.kbl new file mode 100644 index 0000000..7d5fcac --- /dev/null +++ b/plugins/bcs-usb/kbdlayouts/base.kbl @@ -0,0 +1,75 @@ +#basic invisible layout, used by other layouts +0 nokey +1 error + +#top row +0x29 ESC +0x3a F1 +0x3b F2 +0x3c F3 +0x3d F4 +0x3e F5 +0x3f F6 +0x40 F7 +0x41 F8 +0x41 F9 +0x43 F10 +0x44 F11 +0x45 F12 + +0x46 print +0x47 scroll +0x48 pause + + +#numeric row +0x1e 1 +0x1f 2 +0x20 3 +0x21 4 +0x22 5 +0x23 6 +0x24 7 +0x25 8 +0x26 9 +0x27 0 +0x2a backspace + +#stable meta keys +0x2b tab +0x39 caps +0x28 return return +0x2c space space space +#0x65 menu + +#directional blocks +#0x49 ins +#0x4c del +#0x4a home +#0x4d end +#0x4b pgUp +#0x4e pgDown + +#0x52 up +#0x51 down +#0x50 left +#0x4f right + +#numeric keypad +0x62 0 +0x63 . +0x58 return +0x59 1 +0x5a 2 +0x5b 3 +0x5c 4 +0x5d 5 +0x5e 6 +0x5f 7 +0x60 8 +0x61 9 +0x53 num +0x54 / +0x55 * +0x56 minus +0x57 plus diff --git a/plugins/bcs-usb/kbdlayouts/de.kbl b/plugins/bcs-usb/kbdlayouts/de.kbl new file mode 100644 index 0000000..74abd70 --- /dev/null +++ b/plugins/bcs-usb/kbdlayouts/de.kbl @@ -0,0 +1,35 @@ +title German / Deutsch + +include qwertz + +#numeric row +0x35 ^ ° +0x1e 1 ! +0x1f 2 " +0x20 3 § +0x21 4 $ +0x22 5 % +0x23 6 & +0x24 7 / { +0x25 8 ( [ +0x26 9 ) ] +0x27 0 = } +0x2d ß ? \ +0x2e ' ` + + +#special chars on alpha block +0x2f ü +0x30 plus * +0x31 # ' + +0x33 ö +0x34 ä + +0x36 , ; +0x37 . : +0x38 minus _ +0x64 < > | + +#numeric keypad +0x63 , diff --git a/plugins/bcs-usb/kbdlayouts/qwerty.kbl b/plugins/bcs-usb/kbdlayouts/qwerty.kbl new file mode 100644 index 0000000..c2676e0 --- /dev/null +++ b/plugins/bcs-usb/kbdlayouts/qwerty.kbl @@ -0,0 +1,35 @@ +#basic invisible qwerty layout, used by other layouts + +include base + +#top row +0x14 q +0x1a w +0x8 e +0x15 r +0x17 t +0x1c y +0x18 u +0xc i +0x12 o +0x13 p + +#home row +0x4 a +0x16 s +0x7 d +0x9 f +0xa g +0xb h +0xd j +0xe k +0xf l + +#bottom row +0x1d z +0x1b x +0x6 c +0x19 v +0x5 b +0x11 n +0x10 m diff --git a/plugins/bcs-usb/kbdlayouts/qwertz.kbl b/plugins/bcs-usb/kbdlayouts/qwertz.kbl new file mode 100644 index 0000000..36639e7 --- /dev/null +++ b/plugins/bcs-usb/kbdlayouts/qwertz.kbl @@ -0,0 +1,35 @@ +#basic invisible qwertz layout, used by other layouts + +include base + +#top row +0x14 q +0x1a w +0x8 e +0x15 r +0x17 t +0x1c z +0x18 u +0xc i +0x12 o +0x13 p + +#home row +0x4 a +0x16 s +0x7 d +0x9 f +0xa g +0xb h +0xd j +0xe k +0xf l + +#bottom row +0x1d y +0x1b x +0x6 c +0x19 v +0x5 b +0x11 n +0x10 m diff --git a/plugins/bcs-usb/kbdlayouts/us.kbl b/plugins/bcs-usb/kbdlayouts/us.kbl new file mode 100644 index 0000000..855821d --- /dev/null +++ b/plugins/bcs-usb/kbdlayouts/us.kbl @@ -0,0 +1,31 @@ +title US American (Intl) + +include qwerty + +#numeric row +0x35 ` ~ +0x1e 1 ! +0x1f 2 @ +0x20 3 # +0x21 4 $ +0x22 5 % +0x23 6 ^ +0x24 7 & +0x25 8 * +0x26 9 ( +0x27 0 ) +0x2d minus _ +0x2e = plus + +#special chars on alpha block +0x2f [ { +0x30 ] } +0x31 \ | + +0x33 ; : +0x34 ' " + +0x36 , < +0x37 . > +0x38 / ? + diff --git a/plugins/bcs-usb/layouts.qrc b/plugins/bcs-usb/layouts.qrc new file mode 100644 index 0000000..2146333 --- /dev/null +++ b/plugins/bcs-usb/layouts.qrc @@ -0,0 +1,12 @@ + + + + + kbdlayouts/base.kbl + kbdlayouts/qwerty.kbl + kbdlayouts/qwertz.kbl + kbdlayouts/us.kbl + kbdlayouts/de.kbl + + diff --git a/plugins/bcscanner/bcs-plugin.cpp b/plugins/bcscanner/bcs-plugin.cpp deleted file mode 100644 index 5aac522..0000000 --- a/plugins/bcscanner/bcs-plugin.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// -// C++ Implementation: Barcode Plugin Basics -// -// -// Author: Konrad Rosenbaum , (C) 2013 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "bcs-plugin.h" - -MHidBarcodePlugin::~MHidBarcodePlugin() -{ - -} - - -void MHidBarcodePlugin::configure(MBarcodeConfiguration* ) -{ - -} - -QStringList MHidBarcodePlugin::findScanners() -{ - return QStringList(); -} diff --git a/plugins/bcscanner/bcs-plugin.h b/plugins/bcscanner/bcs-plugin.h deleted file mode 100644 index 9271e19..0000000 --- a/plugins/bcscanner/bcs-plugin.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// C++ Interface: plugin base for barcode scanners -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2013 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef MAGICSMOKE_BARCODE_PLUGIN_HID_H -#define MAGICSMOKE_BARCODE_PLUGIN_HID_H - -#include "barcode-plugin.h" - -class MHidBarcodePlugin:public QObject,public MBarcodePlugin -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID MBarcodePlugin_IID) - Q_INTERFACES(MBarcodePlugin) - public: - virtual ~MHidBarcodePlugin(); - virtual QStringList findScanners() override; - virtual void configure(MBarcodeConfiguration*)override; - -}; - -#endif diff --git a/plugins/bcscanner/bcscanner.pro b/plugins/bcscanner/bcscanner.pro deleted file mode 100644 index 1abd988..0000000 --- a/plugins/bcscanner/bcscanner.pro +++ /dev/null @@ -1,10 +0,0 @@ -TEMPLATE = lib -TARGET = msp-bcscanner -CONFIG += plugin - -include (../../basics.pri) -include (../../src/smoke.pri) -include (hidapi.pri) - -SOURCES += bcs-plugin.cpp -HEADERS += bcs-plugin.h diff --git a/plugins/plugins.pro b/plugins/plugins.pro index 0034d33..88a3553 100644 --- a/plugins/plugins.pro +++ b/plugins/plugins.pro @@ -1,2 +1,2 @@ TEMPLATE = subdirs -SUBDIRS = bcscanner \ No newline at end of file +SUBDIRS = bcs-usb \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 5a3e34e..f27abd7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,7 +4,7 @@ // Description: Main Program // // -// Author: Konrad Rosenbaum , (C) 2007-2013 +// Author: Konrad Rosenbaum , (C) 2007-2014 // // Copyright: See README/COPYING.GPL files that come with this distribution // @@ -33,6 +33,7 @@ #include "configdialog.h" #include "debug.h" +#include "barcode-plugin.h" #include "hmac.h" #include "keygen.h" #include "main.h" @@ -390,6 +391,8 @@ void MApplication::initialize() initHelpUrl(); //init updater initUpdater(); + //init plugins + MBarcodeHub::instance()->initialize(); } void MApplication::initUpdater() diff --git a/src/main.h b/src/main.h index df21c91..020a189 100644 --- a/src/main.h +++ b/src/main.h @@ -4,7 +4,7 @@ // Description: // // -// Author: Konrad Rosenbaum , (C) 2007-2011 +// Author: Konrad Rosenbaum , (C) 2007-2014 // // Copyright: See README/COPYING.GPL files that come with this distribution // diff --git a/src/misc/barcode-plugin.cpp b/src/misc/barcode-plugin.cpp index 5f6cc5d..2542a43 100644 --- a/src/misc/barcode-plugin.cpp +++ b/src/misc/barcode-plugin.cpp @@ -2,7 +2,7 @@ // C++ Implementation: Barcode Plugin Basics // // -// Author: Konrad Rosenbaum , (C) 2013 +// Author: Konrad Rosenbaum , (C) 2013-2014 // // Copyright: See README/COPYING.GPL files that come with this distribution // @@ -10,12 +10,110 @@ #include "barcode-plugin.h" +#include +#include +#include +#include +#include +#include +#include +#include + +static QList >allscanners; +static QListallplugins; + MBarcodeConfiguration::MBarcodeConfiguration(QWidget* parent): QDialog(parent) { + setWindowTitle(tr("Configure Barcode Plugins")); + + QVBoxLayout*vl; + QHBoxLayout*hl; + QPushButton*p; + setLayout(vl=new QVBoxLayout); + vl->addWidget(mtab=new QTabWidget,1); + vl->addLayout(hl=new QHBoxLayout); + hl->addStretch(1); + hl->addWidget(p=new QPushButton(tr("&Save"))); + connect(p,SIGNAL(clicked(bool)),this,SLOT(accept())); + hl->addWidget(p=new QPushButton(tr("&Cancel"))); + connect(p,SIGNAL(clicked(bool)),this,SLOT(reject())); + + setSizeGripEnabled(true); + + for(MBarcodePlugin*plug:allplugins) + if(plug)plug->configure(this); +} + +void MBarcodeConfiguration::addTab(QWidget* w, QString t) +{ + mtab->addTab(w,t); +} + + + +MBarcodeHub* MBarcodeHub::instance() +{ + static MBarcodeHub hub; + return &hub; +} +MBarcodeHub::MBarcodeHub(): QObject() +{ + qDebug()<<"instantiating barcode hub"; } -void MBarcodeConfiguration::addTab(QWidget* , QString ) +MBarcodeHub::~MBarcodeHub() { + qDebug()<<"deleting barcode hub"; +} +MBarcodeScanner::MBarcodeScanner(QObject* parent): QObject(parent) +{ +} + +void MBarcodePlugin::registerScanner(MBarcodeScanner* scanner) +{ + if(!scanner)return; + allscanners.append(scanner); + QObject::connect(scanner,SIGNAL(newBarcode(QString)), MBarcodeHub::instance(),SIGNAL(newBarcode(QString))); +} + +MBarcodePlugin::~MBarcodePlugin() +{} + +QList< MBarcodeScanner* > MBarcodeHub::allScanners() +{ + QListret; + for(MBarcodeScanner*s:allscanners) + if(s)ret<(oplug); + if(!plug)continue; + allplugins<(obj)); } diff --git a/src/misc/barcode-plugin.h b/src/misc/barcode-plugin.h index 3f55249..dbeb6b3 100644 --- a/src/misc/barcode-plugin.h +++ b/src/misc/barcode-plugin.h @@ -4,7 +4,7 @@ // Description: // // -// Author: Konrad Rosenbaum , (C) 2013 +// Author: Konrad Rosenbaum , (C) 2013-2014 // // Copyright: See README/COPYING.GPL files that come with this distribution // @@ -22,28 +22,91 @@ #include #include #include +#include class QTabWidget; +///Scanner Configuration Dialog class MAGICSMOKE_EXPORT MBarcodeConfiguration:public QDialog { Q_OBJECT public: + ///instantiates a new config dialog and asks plugins to display their tabs MBarcodeConfiguration(QWidget*parent); public slots: + ///used by plugins to add configuration tabs, + ///tabs should connect to the accepted() and rejected() signals to store data void addTab(QWidget*,QString); private: QTabWidget*mtab; }; +///base class of actual scanner implementations +class MAGICSMOKE_EXPORT MBarcodeScanner:public QObject +{ + Q_OBJECT + public: + explicit MBarcodeScanner(QObject* parent = 0); + + ///returns a human readable name for the scanner + virtual QString readableName()const=0; + + ///returns whether the scanner is currently active + virtual bool isActive()const=0; + + public slots: + ///attempts to activate the scanner + virtual void activate()=0; + ///attempts to de-activate the scanner + virtual void deactivate()=0; + signals: + ///emitted when the scanner becomes active + void activated(); + ///emitted when the scanner becomes inactive + void deactivated(); + ///emitted when a new barcode is available + void newBarcode(QString); +}; + +///base class of barcode scanner plugins class MAGICSMOKE_EXPORT MBarcodePlugin { public: - virtual ~MBarcodePlugin(){} + virtual ~MBarcodePlugin(); - virtual QStringList findScanners()=0; + ///called whenever the user opens a configuration dialog virtual void configure(MBarcodeConfiguration*)=0; + protected: + ///called by plugins to register a new scanner that has come online + static void registerScanner(MBarcodeScanner*); +}; + +///central barcode scanner hub, this is used by widgets that require barcodes, +///plugins report (indirectly) to the hub +class MAGICSMOKE_EXPORT MBarcodeHub:public QObject +{ + Q_OBJECT + public: + ///returns the hub object + static MBarcodeHub*instance(); + + ///initializes plugins (unless already initialized) + void initialize(); + + ///returns all currently active scanners + QListallScanners(); + + signals: + ///this is emitted whenever any of the barcode scanners find a new barcode + void newBarcode(QString); + + private slots: + ///automatically called by when a plugin destructs + void removePlugin(QObject*); + private: + MBarcodeHub(); + virtual ~MBarcodeHub(); }; #define MBarcodePlugin_IID "de.silmor.MagicSmoke.BarcodePlugin/1.0" diff --git a/src/misc/misc.pri b/src/misc/misc.pri index 229639f..565a3d5 100644 --- a/src/misc/misc.pri +++ b/src/misc/misc.pri @@ -2,13 +2,15 @@ HEADERS += \ $$PWD/debug.h \ $$PWD/waitcursor.h \ $$PWD/sclock.h \ - $$PWD/dommodel.h + $$PWD/dommodel.h \ + $$PWD/barcode-plugin.h SOURCES += \ $$PWD/code39.cpp \ $$PWD/debug.cpp \ $$PWD/waitcursor.cpp \ $$PWD/sclock.cpp \ - $$PWD/dommodel.cpp + $$PWD/dommodel.cpp \ + $$PWD/barcode-plugin.cpp INCLUDEPATH += $$PWD diff --git a/src/mwin/entrancetab.cpp b/src/mwin/entrancetab.cpp index 3e4dd74..1feb769 100644 --- a/src/mwin/entrancetab.cpp +++ b/src/mwin/entrancetab.cpp @@ -14,6 +14,7 @@ #include "misc.h" #include "msinterface.h" #include "orderwin.h" +#include "barcodeline.h" #include "entrancetab.h" @@ -45,7 +46,7 @@ MEntranceTab::MEntranceTab(QString pk) entranceevent->setEditable(false); vl->addSpacing(30); vl->addWidget(new QLabel(tr("Enter or scan Ticket-ID:")),0); - vl->addWidget(entrancescan=new QLineEdit,0); + vl->addWidget(entrancescan=new MBarcodeLine,0); connect(entrancescan,SIGNAL(returnPressed()),this,SLOT(entranceValidate())); vl->addWidget(entrancelabel=new QLabel(" "),10); entrancelabel->setAutoFillBackground(true); diff --git a/src/mwin/overview.cpp b/src/mwin/overview.cpp index 114ef24..426a89e 100644 --- a/src/mwin/overview.cpp +++ b/src/mwin/overview.cpp @@ -32,6 +32,8 @@ #include "centbox.h" #include "sclock.h" +#include "barcode-plugin.h" +#include "labeldlg.h" #include "jsengine.h" @@ -57,8 +59,6 @@ #include #include -#include - #include "MTChangeMyPassword" #include "MTReturnTicketVoucher" #include "MTDeductVoucher" @@ -144,6 +144,7 @@ MOverview::MOverview(QString pk,std::functioninitUpdate) m2->addAction(tr("&Display settings..."),this,SLOT(displaySettings())); m2->addAction(tr("&Label Printing settings..."),this,SLOT(labelSettings())); m2->addAction(tr("&OpenOffice settings..."),this,SLOT(openOfficeSettings())); + m2->addAction(tr("&Barcode Scanner settings..."),this,SLOT(barcodeSettings())); //make sure webrequest knows its settings webSettings(false); @@ -631,6 +632,12 @@ void MOverview::openOfficeSettings() c.exec(); } +void MOverview::barcodeSettings() +{ + MBarcodeConfiguration bc(this); + bc.exec(); +} + void MOverview::aclWindow() { MAclWindow::showWindow(this); diff --git a/src/mwin/overview.h b/src/mwin/overview.h index 380c955..d6d4b63 100644 --- a/src/mwin/overview.h +++ b/src/mwin/overview.h @@ -77,6 +77,8 @@ class MOverview:public MTabWin void labelSettings(); ///OpenOffice settings void openOfficeSettings(); + ///barcode scanner settings + void barcodeSettings(); ///\internal run init scripts void runStartupScript(); diff --git a/src/widgets/barcodeline.cpp b/src/widgets/barcodeline.cpp new file mode 100644 index 0000000..16a50bb --- /dev/null +++ b/src/widgets/barcodeline.cpp @@ -0,0 +1,36 @@ +// +// C++ Implementation: barcode line edit +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2014 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + + +#include "barcodeline.h" +#include "barcode-plugin.h" + +MBarcodeLine::MBarcodeLine(QWidget* parent): MBarcodeLine(QString(),parent) +{ +} + +MBarcodeLine::MBarcodeLine(const QString& cont, QWidget* parent): QLineEdit(cont,parent) +{ + setToolTip(tr("Type a barcode into this line or scan it with a barcode scanner.")); + setPlaceholderText(tr("Type or scan a barcode.")); + connect(MBarcodeHub::instance(),SIGNAL(newBarcode(QString)), this,SLOT(setBarcode(QString))); +} + +void MBarcodeLine::setBarcode(QString bc) +{ + //do we actually have focus? + //TODO: maybe this should be visibility? + if(!hasFocus())return; + //enter barcode and emit ready signal + setText(bc); + emit returnPressed(); +} diff --git a/src/widgets/barcodeline.h b/src/widgets/barcodeline.h new file mode 100644 index 0000000..6da7b37 --- /dev/null +++ b/src/widgets/barcodeline.h @@ -0,0 +1,28 @@ +// +// C++ Interface: barcode line edit +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2014 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_BARCODELINE_H +#define MAGICSMOKE_BARCODELINE_H + +#include + +class MBarcodeLine:public QLineEdit +{ + Q_OBJECT + public: + explicit MBarcodeLine(QWidget* parent = 0); + explicit MBarcodeLine(const QString& , QWidget* parent = 0); + private slots: + void setBarcode(QString); +}; + +#endif diff --git a/src/widgets/widgets.pri b/src/widgets/widgets.pri index f758a46..ac92607 100644 --- a/src/widgets/widgets.pri +++ b/src/widgets/widgets.pri @@ -1,11 +1,13 @@ HEADERS += \ widgets/centbox.h \ widgets/listview.h \ - widgets/treeview.h + widgets/treeview.h \ + widgets/barcodeline.h SOURCES += \ widgets/centbox.cpp \ widgets/listview.cpp \ - widgets/treeview.cpp + widgets/treeview.cpp \ + widgets/barcodeline.cpp INCLUDEPATH += ./widgets