--- /dev/null
+//
+// C++ Implementation: Barcode Plugin for USB
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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 <hidapi.h>
+
+#include <QDebug>
+#include <QSettings>
+#include <QTimer>
+
+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);
+}
+
--- /dev/null
+//
+// C++ Interface: plugin for USB barcode scanners
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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;
+ };
+ QList<Config>mconfig;
+ Config findCfgMatch(int vendor,int product,int iface,QString serial);
+ QList<MHidBarcodeScanner*>mscanners;
+ MHidBarcodeScanner*findScanner(QString path);
+};
+
+#endif
--- /dev/null
+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
--- /dev/null
+//
+// C++ Implementation: Barcode Plugin for USB: Keyboard Stuff
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2013-2014
+//
+// Copyright: See README/COPYING.GPL files that come with this distribution
+//
+//
+
+#include "bcskeyboard.h"
+#include <QFileInfo>
+#include <QCoreApplication>
+#include <QStringList>
+#include <QDebug>
+#include <QDir>
+
+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<MKey> &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"<<filename;
+ return false;
+ }
+ }
+ //load file
+ QFile lf(filename);
+ if(!lf.open(QIODevice::ReadOnly)){
+ qDebug()<<"unable to open keyboard layout"<<filename<<"for USB HID scanners";
+ return false;
+ }
+ return parseLayout(QString::fromUtf8(lf.readAll()));
+}
+
+bool MHidKeyLayout::parseLayout(QString content,QString filename)
+{
+ mfilename.clear();
+ QString ntitle;
+ const QStringList clst=content.split('\n',QString::KeepEmptyParts);
+ for(int i=0;i<clst.size();i++){
+ QString line=clst[i].trimmed();
+ if(line.isEmpty())continue;
+ if(line.startsWith('#'))continue;
+ const QStringList toks=line.split(' ',QString::SkipEmptyParts);
+ if(toks.size()<2){
+ qDebug()<<"Error: incomplete line"<<(i+1)<<"in layout file"<<filename;
+ return false;
+ }
+ if(toks[0]=="title"){
+ ntitle=line.mid(line.indexOf(' ')).trimmed();
+ continue;
+ }
+ if(toks[0]=="include"){
+ if(!loadLayout(toks[1]))return false;
+ else continue;
+ }
+ bool ok;
+ const int kc=toks[0].toInt(&ok,0);
+ if(!ok || kc<0 || kc>255){
+ qDebug()<<"Error: illegal key code"<<toks[0]<<"on line"<<(i+1)<<"in layout file"<<filename;
+ return false;
+ }
+ QList<MKey>keys;
+ for(int i=1;i<toks.size();i++)
+ keys.append(MKey::fromCharName(toks[i]));
+ if(keys.size()==1){
+ keys[0]=keys[0].toLower();
+ keys.append(keys[0].toUpper());
+ }
+ mkeymap.insert(kc,keys);
+ }
+ mfilename=filename;
+ mlname=ntitle;
+ return true;
+}
+
+MKeySequence MHidKeyLayout::toKeys(const MHidKeySequence& hsq) const
+{
+ MKeySequence ret;
+ for(MHidKeyEvent ev:hsq){
+ //get modifiers
+ MKey::Modifiers mod=ev.modifiers();
+ //get key
+ const int key=ev.lastkeycode();
+ //layer?
+ const int layer=mod.testFlag(MKey::AltGr)?2:(mod.testFlag(MKey::Shift)?1:0);
+ //generate key
+ ret.append(MKey(mkeymap.value(key).value(layer),mod));
+ }
+ return ret;
+}
+
+QString MHidKeyLayout::toString(const MHidKeySequence& hsq) const
+{
+ return toKeys(hsq).toString();
+}
+
+QMap< QString, QString > MHidKeyLayout::findLayouts()
+{
+ static QMap<QString,QString>laymap;
+ if(laymap.size()>0)return laymap;
+ //search all files
+ for(QString d:QStringList()<<":/kbdlayouts"<<QCoreApplication::applicationDirPath()+"/kbdlayouts")
+ for(QString fn:QDir(d).entryList(QStringList()<<"*.kbl",QDir::Files)){
+ MHidKeyLayout kl(d+"/"+fn);
+ if(!kl.layoutFileName().isEmpty())
+ laymap.insert(kl.layoutCodeName(),kl.layoutName());
+ }
+ //done
+ return laymap;
+}
+
+MKey::MKey(QChar c, Modifiers m)
+ :mmod(m),mtype(CharKey),mchar(c)
+{
+ //is it space, return, tab?
+ if(c==' ')mtype=Space;else
+ if(c=='\n')mtype=Return;else
+ if(c=='\t')mtype=Tabulator;
+ //sort out shift modifier if this is a normal char
+ else if(m.testFlag(Shift)){
+ mmod^=Shift;
+ mchar=mchar.toUpper();
+ }else{
+ mchar=mchar.toLower();
+ }
+}
+
+MKey::MKey(const MKey& k, Modifiers m)
+ :mmod(k.mmod|m),mtype(k.mtype),mchar(k.mchar)
+{
+ //shift correction
+ if(mtype==CharKey){
+ if(mmod.testFlag(Shift)){
+ mmod^=Shift;
+ mchar=mchar.toUpper();
+ }else{
+ mchar=mchar.toLower();
+ }
+ }
+}
+
+bool MKey::operator==(const MKey& k)
+{
+ //trivial: type and modifier check
+ if(mtype!=k.mtype || mmod!=k.mmod)return false;
+ //char compare?
+ if(mtype==CharKey)return mchar==k.mchar;
+ else return true;
+}
+
+QString MKey::toCharName() const
+{
+ QString ret;
+ //release?
+ if(mtype==AllKeyRelease)return "none";
+ //modifiers
+ if(mmod&Shift)ret+="shift-";
+ if(mmod&Ctrl)ret+="ctrl-";
+ if(mmod&Alt)ret+="alt-";
+ if(mmod&AltGr)ret+="altgr-";
+ //key
+ switch(mtype){
+ case Escape:return ret+"esc";
+ case CapsLock:return ret+"caps";
+ case NumLock:return ret+"num";
+ case Backspace:return ret+"backspace";
+ case Return:return ret+"return";
+ case Tabulator:return ret+"tab";
+ case Space:return ret+"space";
+ case CharKey:return ret+mchar;
+ default:return ret+"none";
+ }
+}
+
+MKey MKey::fromCharName(QString n)
+{
+ //separate modifiers
+ Modifiers mods=None;
+ if(n.contains('-')){
+ QStringList sl=n.split('-',QString::SkipEmptyParts);
+ n=sl.takeLast();
+ for(QString m:sl){
+ m=m.toLower();
+ if(m=="shift")mods|=Shift;
+ else if(m=="ctrl")mods|=Ctrl;
+ else if(m=="alt")mods|=Alt;
+ else if(m=="altgr")mods|=AltGr;
+ else qDebug()<<"Warning: illegal modifier"<<m;
+ }
+ }
+ //normal key?
+ if(n.size()==1)return MKey(n[0],mods);
+ //special key or alias...
+ n=n.toLower();
+ if(n=="minus")return MKey('-',mods);
+ if(n=="plus")return MKey('+',mods);
+ if(n=="tab")return MKey(Tabulator,mods);
+ if(n=="return")return MKey(Return,mods);
+ if(n=="esc")return MKey(Escape,mods);
+ if(n=="caps")return MKey(CapsLock,mods);
+ if(n=="backspace")return MKey(Backspace,mods);
+ if(n=="space")return MKey(Space,mods);
+ if(n=="num")return MKey(NumLock,mods);
+ //unknown sequence or no key
+ if(n=="nokey" || n=="error" || n=="none")return MKey();
+ qDebug()<<"Warning: unknown key type"<<n;
+ return MKey();
+}
+
+bool MKey::isPrintable(bool ign) const
+{
+ //ctrl-* and alt-* cannot be printed
+ if(!ign && (mmod&(Ctrl|Alt)))return false;
+ //exclude some special keys
+ switch(mtype){
+ case CharKey:return mchar.isPrint();
+ case Space:return true;
+ default:return false;
+ }
+}
+
+QChar MKey::toChar(bool ign) const
+{
+ if(!isPrintable(ign))return QChar();
+ if(mtype==Space)return ' ';
+ if(mtype==CharKey)return mchar;
+ //hmm?
+ return QChar();
+}
+
+
+QString MKeySequence::toString() const
+{
+ QString ret;
+ //go through sequence and convert
+ bool altmode=false;
+ int altseq=0;
+ for(MKey key:*this){
+// qDebug()<<"conv"<<key.toCharName();
+ //enable alt mode?
+ if(key.modifiers()==MKey::Alt){
+ altmode=true;
+ const int d=key.toChar(true).digitValue();
+ if(d>=0){
+ altseq*=10;
+ altseq+=d;
+ }
+// qDebug()<<"Alt: "<<d<<altseq<<key.toChar(true);
+ continue;
+ }
+ if(altmode && !key.modifiers().testFlag(MKey::Alt)){
+ altmode=false;
+ if(altseq>0)
+ ret+=QChar::fromLatin1(altseq);
+// qDebug()<<"Alt compl:"<<altseq<<QChar::fromLatin1(altseq);
+ altseq=0;
+ //fall through and process remainder
+ }
+ //printable?
+ if(key.isPrintable())ret+=key.toChar();
+ }
+ //residual alt mode?
+ if(altmode && altseq>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());
+}
--- /dev/null
+//
+// C++ Interface: plugin for USB barcode scanners: Scanner Implementation
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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 <QList>
+#include <QObject>
+#include <QFlag>
+#include <QDateTime>
+#include <QMap>
+
+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<MKey>
+{
+ public:
+ MKeySequence(){}
+ MKeySequence(const QList< MKey >& l):QList< MKey >(l){}
+ MKeySequence(const MKeySequence& other)=default;
+ MKeySequence(MKeySequence&&)=default;
+
+ MKeySequence& operator=(const QList<MKey>&l){QList<MKey>::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<MHidKeyEvent>
+{
+ 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<MKey> &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<QString,QString> findLayouts();
+ private:
+ QString mfilename,mlname;
+ QMap<unsigned char,QList<MKey>>mkeymap;
+};
+
+#endif
--- /dev/null
+//
+// C++ Implementation: Barcode Plugin for USB: Config
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2013-2014
+//
+// Copyright: See README/COPYING.GPL files that come with this distribution
+//
+//
+
+#include "configwidget.h"
+
+#include "barcode-plugin.h"
+#include <QFormLayout>
+#include <QComboBox>
+#include <QPushButton>
+
+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()
+{
+
+}
--- /dev/null
+//
+// C++ Interface: plugin for USB barcode scanners
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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 <QWidget>
+
+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
--- /dev/null
+//
+// C++ Implementation: Barcode Plugin for USB: Scanner
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2013-2014
+//
+// Copyright: See README/COPYING.GPL files that come with this distribution
+//
+//
+
+#include "hidscanner.h"
+#include "configwidget.h"
+
+#include <QDebug>
+#include <QTimer>
+#include <QSettings>
+
+MHidBarcodeScanner::MHidBarcodeScanner(QString path,QString setGrp, QObject* parent)
+ : MBarcodeScanner(parent),mpath(path)
+{
+ qDebug()<<"Trying to open device at"<<path;
+ activate();
+ //read settings
+ QSettings set;
+ set.beginGroup(MUsbBarcodeConfig::settingsGroup);
+ set.beginGroup(setGrp);
+ mtimeout=set.value(MUsbBarcodeConfig::timeoutKey,0).toInt();
+ mterminator=MKey::fromCharName(set.value(MUsbBarcodeConfig::terminatorKey).toString());
+ mname=set.value(MUsbBarcodeConfig::nameKey,mpath).toString();
+ mlayout.loadLayout(set.value(MUsbBarcodeConfig::layoutKey,"qwerty").toString());
+}
+
+MHidBarcodeScanner::~MHidBarcodeScanner()
+{
+ deactivate();
+}
+
+void MHidBarcodeScanner::activate()
+{
+ if(mdev!=nullptr && mrdtmr!=nullptr)return;
+ mdev=hid_open_path(mpath.toLocal8Bit().data());
+ if(!mdev){
+ qDebug()<<"Unable to open device.";
+ deleteLater();
+ return;
+ }
+ hid_set_nonblocking(mdev,1);
+ mrdtmr=new QTimer(this);
+ mrdtmr->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"<<mpath;
+ deactivate();
+ break;
+ }
+ if(rs==0)break;
+ if(rs<3){
+ qDebug()<<"Warning: invalid report from USB device"<<mpath<<"expected >=3 bytes, got"<<rs;
+ }
+ mseq.append(MHidKeyEvent(buf[0],QByteArray((char*)buf+2,rs-2)));
+ }
+ processData();
+}
+
+void MHidBarcodeScanner::processData()
+{
+ if(mseq.isEmpty())return;
+ //is the timeout over?
+ bool force=false;
+ if(mtimeout>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"<<bc;
+ emit newBarcode(bc);
+}
--- /dev/null
+//
+// C++ Interface: plugin for USB barcode scanners: Scanner Implementation
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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 <barcode-plugin.h>
+
+#include <hidapi.h>
+
+#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
--- /dev/null
+#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
--- /dev/null
+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 ,
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+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 / ?
+
--- /dev/null
+<!DOCTYPE RCC>
+<!-- Copyright: (c) Konrad Rosenbaum, 2014
+See COPYING.GPL for details. -->
+<RCC version="1.0">
+ <qresource>
+ <file>kbdlayouts/base.kbl</file>
+ <file>kbdlayouts/qwerty.kbl</file>
+ <file>kbdlayouts/qwertz.kbl</file>
+ <file>kbdlayouts/us.kbl</file>
+ <file>kbdlayouts/de.kbl</file>
+ </qresource>
+</RCC>
+++ /dev/null
-//
-// C++ Implementation: Barcode Plugin Basics
-//
-//
-// Author: Konrad Rosenbaum <konrad@silmor.de>, (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();
-}
+++ /dev/null
-//
-// C++ Interface: plugin base for barcode scanners
-//
-// Description:
-//
-//
-// Author: Konrad Rosenbaum <konrad@silmor.de>, (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
+++ /dev/null
-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
TEMPLATE = subdirs
-SUBDIRS = bcscanner
\ No newline at end of file
+SUBDIRS = bcs-usb
\ No newline at end of file
// Description: Main Program
//
//
-// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2007-2013
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2007-2014
//
// Copyright: See README/COPYING.GPL files that come with this distribution
//
#include "configdialog.h"
#include "debug.h"
+#include "barcode-plugin.h"
#include "hmac.h"
#include "keygen.h"
#include "main.h"
initHelpUrl();
//init updater
initUpdater();
+ //init plugins
+ MBarcodeHub::instance()->initialize();
}
void MApplication::initUpdater()
// Description:
//
//
-// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2007-2011
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2007-2014
//
// Copyright: See README/COPYING.GPL files that come with this distribution
//
// C++ Implementation: Barcode Plugin Basics
//
//
-// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2013
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2013-2014
//
// Copyright: See README/COPYING.GPL files that come with this distribution
//
#include "barcode-plugin.h"
+#include <QBoxLayout>
+#include <QCoreApplication>
+#include <QDebug>
+#include <QDir>
+#include <QPluginLoader>
+#include <QPointer>
+#include <QPushButton>
+#include <QTabWidget>
+
+static QList<QPointer<MBarcodeScanner> >allscanners;
+static QList<MBarcodePlugin* >allplugins;
+
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()
+{
+ QList<MBarcodeScanner*>ret;
+ for(MBarcodeScanner*s:allscanners)
+ if(s)ret<<s;
+ //TODO: prune the allscanners list
+ return ret;
+}
+
+void MBarcodeHub::initialize()
+{
+ //get install dir
+ const QString dir=QCoreApplication::applicationDirPath();
+ //go through all potential barcode plugins (msp-bcs-*.so or ...*.dll)
+ for(const QString file:QDir(dir).entryList(QStringList()<<"msp-bcs-*",QDir::Files)){
+ //attempt to load it
+ qDebug()<<"Attempting to load potential barcode plugin"<<file;
+ QPluginLoader pl(dir+"/"+file);
+ const bool r=pl.load();
+ qDebug()<<" ...."<<file<<(r?"successfully loaded.":"not a valid plugin.");
+ if(r){
+ QObject*oplug=pl.instance();
+ if(!oplug)continue;
+ MBarcodePlugin*plug=qobject_cast< MBarcodePlugin* >(oplug);
+ if(!plug)continue;
+ allplugins<<plug;
+ connect(oplug,SIGNAL(destroyed(QObject*)), this,SLOT(removePlugin(QObject*)));
+ }
+ }
+}
+
+void MBarcodeHub::removePlugin(QObject* obj)
+{
+ if(!obj)return;
+ allplugins.removeAll(qobject_cast< MBarcodePlugin* >(obj));
}
// Description:
//
//
-// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2013
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2013-2014
//
// Copyright: See README/COPYING.GPL files that come with this distribution
//
#include <QtPlugin>
#include <QStringList>
#include <QDialog>
+#include <QList>
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
+ QList<MBarcodeScanner*>allScanners();
+
+ 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"
$$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
#include "misc.h"
#include "msinterface.h"
#include "orderwin.h"
+#include "barcodeline.h"
#include "entrancetab.h"
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);
#include "centbox.h"
#include "sclock.h"
+#include "barcode-plugin.h"
+#include "labeldlg.h"
#include "jsengine.h"
#include <QFormLayout>
#include <QDateTimeEdit>
-#include <labeldlg.h>
-
#include "MTChangeMyPassword"
#include "MTReturnTicketVoucher"
#include "MTDeductVoucher"
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);
c.exec();
}
+void MOverview::barcodeSettings()
+{
+ MBarcodeConfiguration bc(this);
+ bc.exec();
+}
+
void MOverview::aclWindow()
{
MAclWindow::showWindow(this);
void labelSettings();
///OpenOffice settings
void openOfficeSettings();
+ ///barcode scanner settings
+ void barcodeSettings();
///\internal run init scripts
void runStartupScript();
--- /dev/null
+//
+// C++ Implementation: barcode line edit
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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();
+}
--- /dev/null
+//
+// C++ Interface: barcode line edit
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2014
+//
+// Copyright: See README/COPYING.GPL files that come with this distribution
+//
+//
+
+#ifndef MAGICSMOKE_BARCODELINE_H
+#define MAGICSMOKE_BARCODELINE_H
+
+#include <QLineEdit>
+
+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
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