From 42eb413737eb6e911867e1b9c0f5b6cf81c677fd Mon Sep 17 00:00:00 2001 From: alwin Date: Thu, 26 Feb 2004 15:33:31 +0000 Subject: Yeah - zkb fixed and working within OPIE. --- (limited to 'noncore') diff --git a/noncore/applets/zkbapplet/config.in b/noncore/applets/zkbapplet/config.in new file mode 100644 index 0000000..19d6597 --- a/dev/null +++ b/noncore/applets/zkbapplet/config.in @@ -0,0 +1,4 @@ + config ZKBAPPLET + boolean "zkbapplet (switch keyboard layout on the fly)" + default "n" + depends ( LIBQPE || LIBQPE-X11 ) && KEYZCFG diff --git a/noncore/applets/zkbapplet/zkbapplet.control b/noncore/applets/zkbapplet/zkbapplet.control new file mode 100644 index 0000000..973373f --- a/dev/null +++ b/noncore/applets/zkbapplet/zkbapplet.control @@ -0,0 +1,9 @@ +Package: zkbapplet +Files: plugins/applets/libzkbapplet.so* pics/zkb-disabled.png share/zkb/*.xml +Priority: optional +Section: opie/applets +Maintainer: Rajko Albrecht +Architecture: arm +Depends: task-opie-minimal, key-cfg +Description: ZKB Applet +Version: 0.6.0-$EXTRAVERSION diff --git a/noncore/applets/zkbapplet/zkbapplet.cpp b/noncore/applets/zkbapplet/zkbapplet.cpp new file mode 100644 index 0000000..6c71568 --- a/dev/null +++ b/noncore/applets/zkbapplet/zkbapplet.cpp @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include "zkbapplet.h" +#include "zkbwidget.h" + + +ZkbApplet::ZkbApplet() : app(0){ +} + +ZkbApplet::~ZkbApplet() +{ + if (app) delete app; +} + +QWidget* ZkbApplet::applet(QWidget* parent) { + if (app == 0) { + app = new ZkbWidget(parent); + } + + return app; +} + +int ZkbApplet::position() const { + return 8; +} + +QRESULT ZkbApplet::queryInterface(const QUuid& uuid, QUnknownInterface** iface) { + + *iface = 0; + if (uuid == IID_QUnknown) { + *iface = this; + } else if (uuid == IID_TaskbarApplet) { + *iface = this; + } else { + return QS_FALSE; + } + + if (*iface) { + (*iface)->addRef(); + } + + return QS_OK; +} + +Q_EXPORT_INTERFACE() { + Q_CREATE_INSTANCE(ZkbApplet) +} diff --git a/noncore/applets/zkbapplet/zkbapplet.h b/noncore/applets/zkbapplet/zkbapplet.h new file mode 100644 index 0000000..fcf03b5 --- a/dev/null +++ b/noncore/applets/zkbapplet/zkbapplet.h @@ -0,0 +1,23 @@ +#include "qpe/taskbarappletinterface.h" + +#ifndef ZKBAPPLET_H +#define ZKBAPPLET_H + +class ZkbWidget; + +class ZkbApplet : public TaskbarAppletInterface { +public: + ZkbApplet(); + virtual ~ZkbApplet(); + + QRESULT queryInterface(const QUuid&, QUnknownInterface**); + Q_REFCOUNT + + virtual QWidget* applet(QWidget*); + virtual int position() const; + +protected: + ZkbWidget* app; +}; + +#endif diff --git a/noncore/applets/zkbapplet/zkbapplet.pro b/noncore/applets/zkbapplet/zkbapplet.pro new file mode 100644 index 0000000..22615d0 --- a/dev/null +++ b/noncore/applets/zkbapplet/zkbapplet.pro @@ -0,0 +1,22 @@ +TEMPLATE = lib +CONFIG += qt plugin warn_on release +HEADERS = zkbapplet.h\ + zkbwidget.h \ + ../../apps/keyz-cfg/zkbcfg.h \ + ../../apps/keyz-cfg/zkbnames.h \ + ../../apps/keyz-cfg/zkbxml.h \ + ../../apps/keyz-cfg/zkb.h +SOURCES = zkbapplet.cpp \ + zkbwidget.cpp \ + ../../apps/keyz-cfg/zkbcfg.cpp \ + ../../apps/keyz-cfg/zkbnames.cpp \ + ../../apps/keyz-cfg/zkbxml.cpp \ + ../../apps/keyz-cfg/zkb.cpp +TARGET = zkbapplet +DESTDIR = $(OPIEDIR)/plugins/applets +INCLUDEPATH += $(OPIEDIR)/include ../../apps/keyz-cfg +DEPENDPATH += ../$(OPIEDIR)/include +VERSION = 0.6.0 +LIBS += -lqpe + +include ( $(OPIEDIR)/include.pro ) diff --git a/noncore/applets/zkbapplet/zkbwidget.cpp b/noncore/applets/zkbapplet/zkbwidget.cpp new file mode 100644 index 0000000..05a76e7 --- a/dev/null +++ b/noncore/applets/zkbapplet/zkbwidget.cpp @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#include +#include "zkbwidget.h" +#include "zkbcfg.h" + +ZkbWidget::ZkbWidget(QWidget* parent):QLabel(parent),keymap(0), + disabled(Resource::loadPixmap("zkb-disabled")) { + + labels = new QPopupMenu(); + connect(labels, SIGNAL(activated(int)), this, + SLOT(labelChanged(int))); + + loadKeymap(); + + channel = new QCopChannel("QPE/zkb", this); + connect(channel, SIGNAL(received(const QCString&, const QByteArray&)), + this, SLOT(signalReceived(const QCString&, const QByteArray&))); + setFixedWidth ( AppLnk::smallIconSize() ); + setFixedHeight ( AppLnk::smallIconSize() ); +} + +ZkbWidget::~ZkbWidget() { +} + +bool ZkbWidget::loadKeymap() { + ZkbConfig c(QPEApplication::qpeDir()+"/share/zkb"); + QFontMetrics fm(font()); + + if (keymap != 0) { + delete keymap; + keymap = 0; + } + + Keymap* km = new Keymap(); + + if (!c.load("zkb.xml", *km, "")) { + delete km; + setPixmap(disabled); + return false; + } + + connect(km, SIGNAL(stateChanged(const QString&)), + this, SLOT(stateChanged(const QString&))); + + qwsServer->setKeyboardFilter(km); + + Keymap* oldkm = keymap; + keymap = km; + + if (oldkm != 0) { + delete oldkm; + } + + setText(keymap->getCurrentLabel()); + + labels->clear(); + QStringList l = keymap->listLabels(); + labels->insertItem(disabled, 0, 0); + int n = 1; + w = 0; + for(QStringList::Iterator it = l.begin(); it != l.end(); + ++it, n++) { + +// printf("label: %s\n", (const char*) (*it).utf8()); + + labels->insertItem(*it, n, n); + int lw = fm.width(*it); + if (lw > w) { + w = lw; + } + } + + if (w == 0) { + hide(); + } else { + show(); + } + return true; +} + +QSize ZkbWidget::sizeHint() const { + return QSize(AppLnk::smallIconSize(),AppLnk::smallIconSize()); +} + +void ZkbWidget::stateChanged(const QString& s) { +// qDebug("stateChanged: %s\n", (const char*) s.utf8()); + setText(s); +} + +void ZkbWidget::labelChanged(int id) { + if (id == 0) { + keymap->disable(); + setPixmap(disabled); + return; + } + + keymap->enable(); + + QStringList l = keymap->listLabels(); + QString lbl = l[id-1]; + +// printf("labelChanged: %s\n", (const char*) lbl.utf8()); + State* state = keymap->getStateByLabel(lbl); + if (state != 0) { + keymap->setCurrentState(state); + setText(lbl); + } +} + +void ZkbWidget::mouseReleaseEvent(QMouseEvent*) { + QSize sh = labels->sizeHint(); + QPoint p = mapToGlobal(QPoint((width()-sh.width())/2,-sh.height())); + labels->exec(p); +} + +void ZkbWidget::signalReceived(const QCString& msg, const QByteArray& data) { + QDataStream stream(data, IO_ReadOnly); + + if (msg == "enable()") { + keymap->enable(); + } else if (msg == "disable()") { + keymap->disable(); + } else if (msg == "reload()") { + QCopEnvelope("QPE/System", "busy()"); + QTimer::singleShot(0, this, SLOT(reload())); + } else if (msg == "switch(QString)") { + QString lbl; + stream >> lbl; + + if (keymap != 0) { + State* state = keymap->getStateByLabel(lbl); + if (state != 0) { + keymap->setCurrentState(state); + setText(lbl); + } + } + } else if (msg == "debug(QString)") { + QString flag; + stream >> flag; + } +} + +void ZkbWidget::reload() { + loadKeymap(); + QCopEnvelope("QPE/System", "notBusy()"); +} diff --git a/noncore/applets/zkbapplet/zkbwidget.h b/noncore/applets/zkbapplet/zkbwidget.h new file mode 100644 index 0000000..a943563 --- a/dev/null +++ b/noncore/applets/zkbapplet/zkbwidget.h @@ -0,0 +1,38 @@ +#ifndef ZKBWIDGET_H +#define ZKBWIDGET_H + +#include +#include +#include +#include +#include + +#include "zkb.h" + +class ZkbWidget : public QLabel { +Q_OBJECT + +public: + ZkbWidget(QWidget* parent); + ~ZkbWidget(); + + QSize sizeHint() const; + +protected: + QLabel* label; + Keymap* keymap; + QPopupMenu* labels; + QCopChannel* channel; + int w, h; + QPixmap disabled; + + bool loadKeymap(); + void mouseReleaseEvent(QMouseEvent*); + +protected slots: + void stateChanged(const QString&); + void labelChanged(int id); + void signalReceived(const QCString& msg, const QByteArray& data); + void reload(); +}; +#endif diff --git a/noncore/apps/keyz-cfg/cfgdlg.cpp b/noncore/apps/keyz-cfg/cfgdlg.cpp new file mode 100644 index 0000000..863f21e --- a/dev/null +++ b/noncore/apps/keyz-cfg/cfgdlg.cpp @@ -0,0 +1,131 @@ + +#include +#include +#include +#include +#include "cfgdlg.h" + +CfgDlg::CfgDlg(QWidget* parent, CfgFile* cf, QApplication* app):QDialog(parent), cfile(cf), application(app) { + setCaption(tr("keyz configurator")); + + QGridLayout* gl = new QGridLayout(this, 7, 5, 5, 5); + + QLabel* flabel = new QLabel("Available Keymaps", this); + files = new QListBox(this); + QPushButton* addButton = new QPushButton(">>", this); //add->setText("Add"); + connect(addButton, SIGNAL(clicked()), this, SLOT(add())); + QLabel* klabel = new QLabel("Selected Keymaps", this); + keymaps = new QListBox(this); + connect(keymaps, SIGNAL(highlighted(const QString&)), this, SLOT(keymapHighlighted(const QString&))); + QPushButton* delButton = new QPushButton("<<", this); //del->setText("Delete"); + connect(delButton, SIGNAL(clicked()), this, SLOT(del())); + QPushButton* slabelButton = new QPushButton("Set Label", this); //apply->setText("Apply"); + connect(slabelButton, SIGNAL(clicked()), this, SLOT(setLabel())); + QLabel* l = new QLabel("Label", this); + label = new QLineEdit(this); + QLabel* adlabel = new QLabel("Auto Repeat Delay (ms)", this); + QLabel* aplabel = new QLabel("Auto Repeat Period (ms)", this); + ad = new QSpinBox(50, 5000, 5, this); + ap = new QSpinBox(0, 5000, 5, this); + +// QLabel* adms = new QLabel("ms", this); +// QLabel* apms = new QLabel("ms", this); + +// QCheckBox* enable = new QCheckBox("Enable", t); + + gl->setColStretch(0, 1); + gl->setColStretch(1, 1); + gl->setColStretch(3, 1); + gl->setColStretch(4, 1); + gl->setRowStretch(3, 1); + gl->addMultiCellWidget(flabel, 0, 0, 0, 1); + gl->addMultiCellWidget(klabel, 0, 0, 3, 4); + gl->addMultiCellWidget(files, 1, 3, 0, 1); + gl->addMultiCellWidget(keymaps, 1, 3, 3, 4); + gl->addWidget(addButton, 1, 2); + gl->addWidget(delButton, 2, 2); + + gl->addWidget(l, 4, 0); + gl->addWidget(label, 4, 1); + gl->addMultiCellWidget(slabelButton, 4, 4, 3, 4); + + gl->addMultiCellWidget(adlabel, 5, 5, 0, 2); + gl->addMultiCellWidget(ad, 5, 5, 3, 4); +// gl->addWidget(adms, 5, 3); + + gl->addMultiCellWidget(aplabel, 6, 6, 0, 2); + gl->addMultiCellWidget(ap, 6, 6, 3, 4); + +// gl->addWidget(apms, 6, 3); + + QList& e = cfile->getEntries(); + + for(uint i = 0; i < e.count(); i++) { + CfgEntry* entry = e.at(i); + keymaps->insertItem(entry->getFile()); + m.insert(entry->getFile(), entry->getLabel()); + } + + QDir dir(QPEApplication::qpeDir()+"/share/zkb", "*.xml"); + QStringList flist = dir.entryList(); + QStringList::Iterator sit; + for(sit = flist.begin(); sit != flist.end(); ++sit) { + if (*sit != "common.xml" && *sit != "zkb.xml" && m.find(*sit) == m.end()) { + files->insertItem(*sit); + } + } + + ad->setValue(cfile->getAutorepeatDelay()); + ap->setValue(cfile->getAutorepeatPeriod()); + +// gl->addMultiCellWidget(enable, 7, 7, 0, 4); +} + +CfgDlg::~CfgDlg() { +} + +void CfgDlg::add() { + if (!files->currentText().isEmpty()) { + QString t = files->currentText(); + files->removeItem(files->currentItem()); + keymaps->insertItem(t); + cfile->replaceEntry(t, ""); + m.replace(t, ""); + } +} + +void CfgDlg::del() { + if (!keymaps->currentText().isEmpty()) { + QString t = keymaps->currentText(); + keymaps->removeItem(keymaps->currentItem()); + cfile->deleteEntry(t); + files->insertItem(t); + m.remove(files->currentText()); + } +} + +void CfgDlg::setLabel() { + if (!keymaps->currentText().isEmpty()) { + cfile->replaceEntry(keymaps->currentText(), + label->text()); + m.replace(keymaps->currentText(), label->text()); + } +} + +void CfgDlg::keymapHighlighted(const QString&text) { + label->setText(*m.find(text)); +} + + +void CfgDlg::accept() { + cfile->setAutorepeatDelay(ad->value()); + cfile->setAutorepeatPeriod(ap->value()); + + CfgParser p; + p.save(QPEApplication::qpeDir()+"/share/zkb/zkb.xml", *cfile); + QCopEnvelope("QPE/zkb", "reload()"); + + QDialog::accept(); + parentWidget()->close(false); +} + diff --git a/noncore/apps/keyz-cfg/cfgdlg.h b/noncore/apps/keyz-cfg/cfgdlg.h new file mode 100644 index 0000000..16732ee --- a/dev/null +++ b/noncore/apps/keyz-cfg/cfgdlg.h @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cfgfile.h" + +class CfgDlg : public QDialog { +Q_OBJECT + +public: + CfgDlg(QWidget* parent, CfgFile* cfile, QApplication *); + virtual ~CfgDlg(); + +protected: + CfgFile* cfile; + QApplication* application; + + QMap m; + + QListBox* files; + QListBox* keymaps; + QLineEdit* label; + QSpinBox* ap; + QSpinBox* ad; + + virtual void accept(); + +protected slots: + void add(); + void del(); + void setLabel(); + void keymapHighlighted(const QString&); +}; diff --git a/noncore/apps/keyz-cfg/cfgfile.cpp b/noncore/apps/keyz-cfg/cfgfile.cpp new file mode 100644 index 0000000..b0dc968 --- a/dev/null +++ b/noncore/apps/keyz-cfg/cfgfile.cpp @@ -0,0 +1,338 @@ +#include +#include "cfgfile.h" + +// CfgEntry implementation +CfgEntry::CfgEntry() { +} + +CfgEntry::CfgEntry(const QString& f, const QString& l): + file(f), label(l) { +} + +const QString& CfgEntry::getFile() const { + return file; +} + +void CfgEntry::setFile(const QString& f) { + file = f; +} + +const QString& CfgEntry::getLabel() const { + return label; +} + +void CfgEntry::setLabel(const QString& f) { + label = f; +} + +// CfgFile implementation +CfgFile::CfgFile():ardelay(400), arperiod(80) { +} + +CfgFile::~CfgFile() { +} + +QList& CfgFile::getEntries() { + return entries; +} + +bool CfgFile::replaceEntry(const QString& file, const QString& label, int index) { + deleteEntry(file); + + CfgEntry* entry = new CfgEntry(file, label); + if (index >= 0) { + entries.insert(index, entry); + } else { + entries.append(entry); + } + + return true; +} + +bool CfgFile::deleteEntry(const QString& file) { + for(int i = 0; i < (int) entries.count(); i++) { + CfgEntry* entry = entries.at(i); + if (entry->getFile() == file) { + entries.remove(i); + return true; + } + } + return false; +} + +int CfgFile::getAutorepeatDelay() const { + return ardelay; +} + +void CfgFile::setAutorepeatDelay(int n) { + ardelay = n; +} + +int CfgFile::getAutorepeatPeriod() const { + return arperiod; +} + +void CfgFile::setAutorepeatPeriod(int n) { + arperiod = n; +} + +// CfgParser implementation +CfgParser::CfgParser() { +} + +bool CfgParser::load(QString file, CfgFile& cfg) { + QFile f(file); + QXmlInputSource is(f); + QXmlSimpleReader reader; + CfgHandler p(*this); + + reader.setErrorHandler(this); + reader.setContentHandler(&p); + + err = ""; + ardelay = -1; + arperiod = -1; + reader.parse(is); + + if (!err.isEmpty()) { + qDebug(err); + return false; + } + + QMap::Iterator fit, lit; + for(uint i = 0; i < includeList.count(); i++) { + QString file = *includeList.at(i); + fit = includes.find(file); + QString prefix = fit.data(); + QString label = ""; + + qDebug("include: file=" + fit.key() + ", prefix=" + fit.data()); + lit = labels.find(prefix+":*"); + if (lit != labels.end()) { + label = lit.data(); + } + + cfg.replaceEntry(file, label); + } + + if (ardelay != -1) { + cfg.setAutorepeatDelay(ardelay); + } + + if (arperiod != -1) { + cfg.setAutorepeatPeriod(arperiod); + } + + return true; +} + +bool CfgParser::save(QString file, CfgFile& cfg) { + FILE* f = fopen((const char*) file.local8Bit(), "w"); + + fprintf(f, "\n", cfg.getAutorepeatDelay(), + cfg.getAutorepeatPeriod()); + + QList& entries = cfg.getEntries(); + int n; + + for(n=0; n < (int) entries.count(); n++) { + CfgEntry* entry = entries.at(n); + QString l = entry->getLabel(); + if (!l.isEmpty()) { + fprintf(f, "\t"); + fclose(f); + return true; +} + +CfgParser::~CfgParser() { +} + +int CfgParser::getAutorepeatDelay() const { + return ardelay; +} + +void CfgParser::setAutorepeatDelay(int n) { + ardelay = n; +} + +int CfgParser::getAutorepeatPeriod() const { + return arperiod; +} + +void CfgParser::setAutorepeatPeriod(int n) { + arperiod = n; +} + +void CfgParser::addLabel(const QString& name, const QString& state) { + labels.insert(state, name); + labelList.append(&labels.find(state).data()); +} + +void CfgParser::addFile(const QString& file, const QString& prefix) { + includes.insert(file, prefix); + includeList.append(&includes.find(file).key()); +} + +QString CfgParser::errorString() { + return err; +} + +bool CfgParser::warning(const QXmlParseException& e) { + QString tmp; + + tmp.sprintf("%d: warning: %s\n", e.lineNumber(), + (const char*) e.message().utf8()); + + err += tmp; + + return true; +} + +bool CfgParser::error(const QXmlParseException& e) { + QString tmp; + + tmp.sprintf("%d: error: %s\n", e.lineNumber(), + (const char*) e.message().utf8()); + + err += tmp; + + return true; +} + +bool CfgParser::fatalError(const QXmlParseException& e) { + QString tmp; + + tmp.sprintf("%d: fatal error: %s\n", e.lineNumber(), + (const char*) e.message().utf8()); + + err += tmp; + + return false; +} + +// CfgHandler implementation +CfgHandler::CfgHandler(CfgParser& c):cfg(c) { +} + +CfgHandler::~CfgHandler() { +} + +bool CfgHandler::startKeymapElement(int ard, int arp, const QString& author) { + if (author != "keyzcfg") { + bool ret; + ret = QMessageBox::warning(0, "keyz configurator", + "Your zkb.xml doesn't seem created by keyz configurator.\n" + "By using keyz configurator you may loose your current " + "configuration\n Do you want to continue\n\n", + "Yes", "No", 0, 0, 1); + + if (ret != 0) { + err = "cancelled by user"; + return false; + } + } + + if (ard != -1) { + cfg.setAutorepeatDelay(ard); + } + + if (arp != -1) { + cfg.setAutorepeatPeriod(arp); + } + + return true; +} + +bool CfgHandler::startIncludeElement(const QString& file, + const QString& pref) { + + cfg.addFile(file, pref); + return true; +} + +bool CfgHandler::startLabelElement(const QString& label, + const QString& state) { + + cfg.addLabel(label, state); + return true; +} + +bool CfgHandler::startStateElement(const QString&, const QString&, bool) { + + return true; +} + +bool CfgHandler::startMapElement(int, bool) { + return true; +} + +bool CfgHandler::startEventElement(int, int, int, bool, bool) { + return true; +} + +bool CfgHandler::startNextStateElement(const QString&) { + return true; +} + + +bool CfgHandler::endKeymapElement() { + return true; +} + +bool CfgHandler::endIncludeElement() { + return true; +} + +bool CfgHandler::endLabelElement() { + return true; +} + +bool CfgHandler::endStateElement() { + return true; +} + +bool CfgHandler::endMapElement() { + return true; +} + +bool CfgHandler::endEventElement() { + return true; +} + +bool CfgHandler::endNextStateElement() { + return true; +} diff --git a/noncore/apps/keyz-cfg/cfgfile.h b/noncore/apps/keyz-cfg/cfgfile.h new file mode 100644 index 0000000..9759900 --- a/dev/null +++ b/noncore/apps/keyz-cfg/cfgfile.h @@ -0,0 +1,106 @@ +#ifndef CFGFILE_H +#define CFGFILE_H + +#include +#include "zkbxml.h" + +class CfgEntry { +public: + CfgEntry(); + CfgEntry(const QString& file, const QString& label); + + const QString& getFile() const; + void setFile(const QString& f); + const QString& getLabel() const; + void setLabel(const QString& l); + +protected: + QString file; + QString label; +}; + +class CfgFile { +public: + CfgFile(); + ~CfgFile(); + + QList& getEntries(); + bool replaceEntry(const QString& file, const QString& label, + int index = -1); + bool deleteEntry(const QString& file); + + int getAutorepeatDelay() const; + void setAutorepeatDelay(int); + int getAutorepeatPeriod() const; + void setAutorepeatPeriod(int); + +protected: + QList entries; + int ardelay; + int arperiod; +}; + +class CfgParser : public QXmlErrorHandler { +public: + CfgParser(); + virtual ~CfgParser(); + + bool load(QString file, CfgFile& cfg); + bool save(QString file, CfgFile& cfg); + + void addLabel(const QString& name, const QString& state); + void addFile(const QString& file, const QString& prefix); + + int getAutorepeatDelay() const; + void setAutorepeatDelay(int); + int getAutorepeatPeriod() const; + void setAutorepeatPeriod(int); + + virtual bool warning(const QXmlParseException& e); + virtual bool error(const QXmlParseException& e); + virtual bool fatalError(const QXmlParseException& e); + virtual QString errorString(); + + QString getError(); + +protected: + QString err; + QMap labels; + QMap includes; + QList labelList; + QList includeList; + int ardelay; + int arperiod; +}; + +class CfgHandler : public ZkbXmlHandler { +public: + CfgHandler(CfgParser &); + virtual ~CfgHandler(); + +protected: + CfgParser& cfg; + + virtual bool startKeymapElement(int ardelay, int arperiod, + const QString& author); + virtual bool startIncludeElement(const QString& file, + const QString& prfix); + virtual bool startLabelElement(const QString& label, + const QString& state); + virtual bool startStateElement(const QString& name, + const QString& parent, bool dflt); + virtual bool startMapElement(int key, bool pressed); + virtual bool startEventElement(int keycode, int unicode, int modifiers, + bool pressed, bool autorepeat); + virtual bool startNextStateElement(const QString& state); + + virtual bool endKeymapElement(); + virtual bool endIncludeElement(); + virtual bool endLabelElement(); + virtual bool endStateElement(); + virtual bool endMapElement(); + virtual bool endEventElement(); + virtual bool endNextStateElement(); +}; + +#endif diff --git a/noncore/apps/keyz-cfg/config.in b/noncore/apps/keyz-cfg/config.in new file mode 100644 index 0000000..319bc1e --- a/dev/null +++ b/noncore/apps/keyz-cfg/config.in @@ -0,0 +1,4 @@ + config KEYZCFG + boolean "keyz-cfg (configuration tool for keyz applett)" + default "n" + depends ( LIBQPE || LIBQPE-X11 ) diff --git a/noncore/apps/keyz-cfg/keyz-cfg.control b/noncore/apps/keyz-cfg/keyz-cfg.control new file mode 100644 index 0000000..2a74b33 --- a/dev/null +++ b/noncore/apps/keyz-cfg/keyz-cfg.control @@ -0,0 +1,9 @@ +Package: keyz-cfg +Files: bin/keyz-cfg apps/Settings/key-cfg.desktop pics/keyz-cfg.png share/zkb/zkb.xml.sample +Priority: optional +Section: opie/applications +Maintainer: Rajko Albrecht +Architecture: arm +Depends: task-opie-minimal +Description: Keyz configuration program +Version: 0.6.0-$EXTRAVERSION diff --git a/noncore/apps/keyz-cfg/keyz-cfg.postinst b/noncore/apps/keyz-cfg/keyz-cfg.postinst new file mode 100755 index 0000000..c7d1cf4 --- a/dev/null +++ b/noncore/apps/keyz-cfg/keyz-cfg.postinst @@ -0,0 +1,3 @@ +#!/bin/sh + +test -f $OPIEDIR/share/zkb/zkb.xml || cp $OPIEDIR/share/zkb/zkb.xml.sample $OPIEDIR/share/zkb/zkb.xml diff --git a/noncore/apps/keyz-cfg/keyz-cfg.pro b/noncore/apps/keyz-cfg/keyz-cfg.pro new file mode 100644 index 0000000..cbaf718 --- a/dev/null +++ b/noncore/apps/keyz-cfg/keyz-cfg.pro @@ -0,0 +1,24 @@ +TEMPLATE = app +DESTDIR = $(OPIEDIR)/bin +CONFIG = qt warn_on release +HEADERS = zkb.h \ + zkbcfg.h \ + zkbnames.h \ + zkbxml.h \ + cfgdlg.h \ + cfgfile.h + +SOURCES = main.cpp \ + cfgdlg.cpp \ + cfgfile.cpp \ + zkb.cpp \ + zkbcfg.cpp \ + zkbnames.cpp \ + zkbxml.cpp + +INCLUDEPATH += $(OPIEDIR)/include +DEPENDPATH += $(OPIEDIR)/include +LIBS += -lqpe +TARGET = keyz-cfg + +include ( $(OPIEDIR)/include.pro ) diff --git a/noncore/apps/keyz-cfg/main.cpp b/noncore/apps/keyz-cfg/main.cpp new file mode 100644 index 0000000..264db20 --- a/dev/null +++ b/noncore/apps/keyz-cfg/main.cpp @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +#include "cfgfile.h" +#include "cfgdlg.h" + +int main( int argc, char **argv ) { + QPEApplication app(argc, argv); + CfgFile cfile; + CfgParser cp; + cp.load(QPEApplication::qpeDir()+"/share/zkb/zkb.xml", cfile); + + QMainWindow m; + CfgDlg c(&m, &cfile, &app); + app.showMainWidget(&m); + m.hide(); + c.showMaximized(); + + int ret = app.exec(); + + return ret; +} diff --git a/noncore/apps/keyz-cfg/zkb.cpp b/noncore/apps/keyz-cfg/zkb.cpp new file mode 100644 index 0000000..abe1f5f --- a/dev/null +++ b/noncore/apps/keyz-cfg/zkb.cpp @@ -0,0 +1,590 @@ +#include +#include "zkb.h" +#include + +// Implementation of Action class +Action::Action():state(0), keycode(0), unicode(0), flags(0) { +} + +Action::Action(State* s, ushort kc, ushort uni, int f): + state(s), keycode(kc), unicode(uni), flags(f) { +} + +Action::~Action() { +} + +State* Action::getState() const { + return state; +} + +void Action::setState(State* s) { + state = s; + setDefined(true); +} + +bool Action::hasEvent() const { + return flags & Event; +} + +void Action::setEvent(bool e) { + flags = (flags & ~Event) | ((e) ? Event : 0); + + if (e) { + setDefined(true); + } else { + if (state == 0) { + setDefined(false); + } + } +} + +bool Action::isDefined() const { + return flags & Defined; +} + +void Action::setDefined(bool d) { + flags = (flags & ~Defined) | ((d) ? Defined : 0); +} + +int Action::getKeycode() const { + return keycode; +} + +void Action::setKeycode(int c) { + keycode = (ushort) c; + setEvent(true); +} + +int Action::getUnicode() const { + return unicode; +} + +void Action::setUnicode(int u) { + unicode = (ushort) u; + setEvent(true); +} + +int Action::getModifiers() const { + int ret = 0; + if (flags & Shift_Mod) { + ret |= Qt::ShiftButton; + } + + if (flags & Ctrl_Mod) { + ret |= Qt::ControlButton; + } + + if (flags & Alt_Mod) { + ret |= Qt::AltButton; + } + + if (flags & Keypad_Mod) { + ret |= Qt::Keypad; + } + + return ret; +} + +void Action::setModifiers(int m) { + int n = 0; + + if (m & Qt::ShiftButton) { + n |= Shift_Mod; + } + + if (m & Qt::ControlButton) { + n |= Ctrl_Mod; + } + + if (m & Qt::AltButton) { + n |= Alt_Mod; + } + + if (m & Qt::Keypad) { + n |= Keypad_Mod; + } + + flags = flags & ~Mod_Bits | n; + setEvent(true); +} + +bool Action::isPressed() const { + return (flags & Press) != 0; +} + +void Action::setPressed(bool p) { + flags = (flags & ~Press) | ((p) ? Press : 0); + setEvent(true); +} + +bool Action::isAutorepeat() const { + return (flags & Autorepeat) != 0; +} + +void Action::setAutorepeat(bool p) { + flags = (flags & ~Autorepeat) | ((p) ? Autorepeat : 0); + setEvent(true); +} + +// Implementation of State class +const short State::x1[] = { /* from 0x20 to 0x5f */ + 31, 0, 28, 3, 5, 6, 9, 28, /* 0x20 - 0x27 */ + 11, 26, 10, 13, 26, 1, 29, 27, /* 0x28 - 0x2f */ + 15, 16, 22, 4, 17, 19, 24, 20, /* 0x30 - 0x37 */ + 8, 14, 29, 26, 29, 12, 32, 27, /* 0x38 - 0x3f */ + 18, 0, 1, 2, 3, 4, 5, 6, /* 0x40 - 0x47 */ + 7, 8, 9, 10, 11, 12, 13, 14, /* 0x48 - 0x4f */ + 15, 16, 17, 18, 19, 20, 21, 22, /* 0x50 - 0x57 */ + 23, 24, 25, 30, -1, 26, 28, 7, /* 0x58 - 0x5f */ + 31, -1, -1, -1, -1, -1, -1, -1, /* 0x60 - 0x67 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x68 - 0x6f */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x70 - 0x77 */ + -1, -1, -1, 29, 31, 32, 32, 28, /* 0x78 - 0x7f */ +}; + +const short State::x2[] = { /* from 0x1000 to 0x1057*/ + 42, 36, -1, 30, 32, -1, -1, -1, /* 0x1000 - 0x1007 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x1008 - 0x100f */ + -1, -1, 44, 45, 46, 47, -1, -1, /* 0x1010 - 0x1017 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x1018 - 0x101f */ + 33, 35, 34, -1, 36, 27, -1, -1, /* 0x1020 - 0x1027 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x1028 - 0x102f */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x1030 - 0x1037 */ + 37, 38, 40, 39, 41, -1, -1, -1, /* 0x1038 - 0x103f */ + -1, -1, -1, -1, -1, 35, -1, -1, /* 0x1040 - 0x1047 */ + -1, -1, -1, -1, -1, 48, -1, -1, /* 0x1048 - 0x104f */ + 43, 49, 50, -1, -1, -1, -1, -1, /* 0x1050 - 0x1057 */ +}; + +State::State(State* p):parent(p), keys(0) { + keys = new Action[Key_Max * 2 + 1]; +} + +State::State(const State& s) { + parent = s.parent; + keys = new Action[Key_Max * 2 + 1]; + memcpy(keys, s.keys, sizeof(Action) * (Key_Max * 2 + 1)); +} + +State::~State() { + if (keys!=0) { + delete [] keys; + } +} + +Action* State::get(int keycode, bool pressed, bool follow) const { + Action* ret = 0; + int n = translateKeycode(keycode); + + if (n != -1 && keys != 0) { + if (pressed) { + n += Key_Max; + } + ret = &keys[n]; + } + + if (ret==0 || !ret->isDefined()) { + if (follow && parent!=0) { + ret = parent->get(keycode, pressed, follow); + } + } + + return ret; +} + +bool State::set(int keycode, bool pressed, Action& action) { + int n = translateKeycode(keycode); + + if (n==-1 || keys==0) { + return false; + } + + if (pressed) { + n += Key_Max + 1; + } + + keys[n] = action; + return true; +} + +State* State::getParent() const { + return parent; +} + +void State::setParent(State* s) { + parent = s; +} + +int State::translateKeycode(int keycode) const { + if (keycode < 0x20) { + return -1; + } + + if (keycode < 0x80) { + return x1[keycode - 0x20]; + } + + if (keycode < 0x1000) { + return -1; + } + + if (keycode < 0x1057) { + return x2[keycode - 0x1000]; + } + + return -1; +} + +// Implementation of Keymap class +Keymap::Keymap():enabled(true), currentState(0), autoRepeatAction(0), repeater(this) { + repeatDelay=400; + repeatPeriod=80; + connect(&repeater, SIGNAL(timeout()), this, SLOT(autoRepeat())); +} + +Keymap::~Keymap() { + QMap::Iterator it; + for(it = states.begin(); it != states.end(); ++it) { + delete it.data(); + } + states.clear(); +} + +bool Keymap::filter(int unicode, int keycode, int modifiers, + bool isPress, bool autoRepeat) { + + qDebug("filter: >>> unicode=%x, keycode=%x, modifiers=%x, " + "ispressed=%x\n", unicode, keycode, modifiers, isPress); + + if (!enabled) { + return false; + } + + // the second check is workaround to make suspend work if + // the user pressed it right after he did resume. for some + // reason the event sent by qt has autoRepeat true in this + // case + if (autoRepeat && keycode != 4177) { + return true; + } + + (void) unicode; (void) modifiers; + + Action* action = currentState->get(keycode, isPress, true); + if (action==0 || !action->isDefined()) { + return true; + } + + if (action->hasEvent()) { + qDebug("filter:<<< unicode=%x, keycode=%x, modifiers=%x, " + "ispressed=%x\n", action->getUnicode(), + action->getKeycode(), action->getModifiers(), + action->isPressed()); + + QWSServer::sendKeyEvent(action->getUnicode(), + action->getKeycode(), action->getModifiers(), + action->isPressed(), false); + } + + if (action->isAutorepeat()) { + autoRepeatAction = action; + repeater.start(repeatDelay, TRUE); + } else { + autoRepeatAction = 0; + } + + State* nstate = action->getState(); + if (nstate != 0) { + setCurrentState(nstate); + QString lbl = getCurrentLabel(); + if (!lbl.isEmpty()) { + emit stateChanged(lbl); + } + } + + + return true; +} + +void Keymap::enable() { + enabled = true; +} + +void Keymap::disable() { + enabled = false; +} + +QStringList Keymap::listStates() { + QStringList ret; + + QMap::Iterator it; + for(it = states.begin(); it != states.end(); ++it) { + ret.append(it.key()); + } + + return ret; +} + +State* Keymap::getStateByName(const QString& name) { + QMap::Iterator it = states.find(name); + + if (it == states.end()) { + return 0; + } + + return it.data(); +} + +QStringList Keymap::listLabels() { + QStringList ret; + + for(uint i = 0; i < labelList.count(); i++) { + ret.append(*labelList.at(i)); + } + + return ret; +} + +State* Keymap::getStateByLabel(const QString& label) { + QMap::Iterator lit = labels.find(label); + State* state = 0; + + if (lit == labels.end()) { + return 0; + } + + QString name = lit.data(); + + int n = name.find(":*"); + if (n>=0 && n==(int)(name.length()-2)) { + name=name.left(name.length() - 1); + + n = currentStateName.findRev(":"); + if (n >= 0) { + name += currentStateName.mid(n+1); + } + } + +// qDebug("look for: %s\n", (const char*) name.utf8()); + QMap::Iterator sit = states.find(name); + if (sit != states.end()) { + state = sit.data(); + } + + return state; +} + +bool Keymap::addState(const QString& name, State* state) { + if (states.find(name) != states.end()) { + return false; + } + + states.insert(name, state); + lsmapInSync = false; + + if (currentState == 0) { + setCurrentState(state); + } + + return true; +} + +State* Keymap::getCurrentState() const { + return currentState; +} + +QString Keymap::getCurrentLabel() { + return currentLabel; +} + +bool Keymap::setCurrentState(State* state) { + QMap::Iterator it; + for(it = states.begin(); it != states.end(); ++it) { + State* s = it.data(); + if (s == state) { + currentState = s; + currentStateName = it.key(); + + qDebug("state changed: %s\n", (const char*) + currentStateName.utf8()); + + if (!lsmapInSync) { + generateLabelStateMaps(); + } + + QMap::Iterator tit; + tit = stateLabelMap.find(state); + if (tit != stateLabelMap.end()) { + currentLabel = tit.data(); + } else { +// qDebug("no label for: " + currentStateName + "\n"); + currentLabel = ""; + } + + return true; + } + } + + return false; +} + +bool Keymap::removeState(const QString& name, bool force) { + QMap::Iterator it = states.find(name); + + if (it == states.end()) { + return false; + } + + State* state = it.data(); + QList acts = findStateUsage(state); + + if (!acts.isEmpty()) { + if (!force) { + return false; + } else { + for(Action* a = acts.first(); a != 0; a = acts.next()) { + a->setState(0); + } + } + } + + if (state == currentState) { + if (states.begin() != states.end()) { + setCurrentState(states.begin().data()); + } + } + + states.remove(it); + delete state; + + lsmapInSync = false; + + return true; +} + +void Keymap::autoRepeat() { + if (autoRepeatAction != 0) { + qDebug("filter:<<< unicode=%x, keycode=%x, modifiers=%x, " + "ispressed=%x\n", autoRepeatAction->getUnicode(), + autoRepeatAction->getKeycode(), + autoRepeatAction->getModifiers(), + autoRepeatAction->isPressed()); + + QWSServer::sendKeyEvent(autoRepeatAction->getUnicode(), + autoRepeatAction->getKeycode(), + autoRepeatAction->getModifiers(), + autoRepeatAction->isPressed(), true); + } + + repeater.start(repeatPeriod, TRUE); +} + +bool Keymap::addLabel(const QString& label, const QString& state, int index) { + if (labels.find(label) != labels.end()) { + return false; + } + + labels.insert(label, state); + const QString& l = labels.find(label).key(); + if (index == -1) { + labelList.append(l); + } else { + labelList.insert(labelList.at(index), l); + } + + lsmapInSync = false; + + return true; +} + +bool Keymap::removeLabel(const QString& label) { + + if (labels.find(label) == labels.end()) { + return false; + } + + labels.remove(label); + labelList.remove(label); + lsmapInSync = false; + + if (label == currentLabel) { + currentLabel = ""; + } + + return true; +} + +int Keymap::getAutorepeatDelay() const { + return repeatDelay; +} + +void Keymap::setAutorepeatDelay(int n) { + repeatDelay = n; +} + +int Keymap::getAutorepeatPeriod() const { + return repeatPeriod; +} + +void Keymap::setAutorepeatPeriod(int n) { + repeatPeriod = n; +} + +QList Keymap::findStateUsage(State* s) { + QList ret; + + QMap::Iterator it; + for(it = states.begin(); it != states.end(); ++it) { + State* state = it.data(); + + for(int i = 0; i < 0x1100; i++) { + Action* action = state->get(i, false); + if (action!=0 && action->getState()==s) { + ret.append(action); + } + + action = state->get(i, true); + if (action!=0 && action->getState()==s) { + ret.append(action); + } + } + } + + return ret; +} + +void Keymap::generateLabelStateMaps() { + stateLabelMap.clear(); + + QMap::Iterator lit; + for(lit = labels.begin(); lit != labels.end(); ++lit) { + QString label = lit.key(); + QString name = lit.data(); + + bool wc = false; + int n = name.find("*"); + if (n>=0 && n==(int)(name.length()-1)) { + name=name.left(name.length() - 1); + wc = true; + } + + QMap::Iterator sit; + for(sit = states.begin(); sit != states.end(); ++sit) { + QString sname = sit.key(); + State* state = sit.data(); + + if (sname.length() < name.length()) { + continue; + } + + if (sname.left(name.length()) == name) { + if (wc || sname.length()==name.length()) { + stateLabelMap.insert(state, label); + } + + } + } + } + + lsmapInSync = true; +} diff --git a/noncore/apps/keyz-cfg/zkb.h b/noncore/apps/keyz-cfg/zkb.h new file mode 100644 index 0000000..deff869 --- a/dev/null +++ b/noncore/apps/keyz-cfg/zkb.h @@ -0,0 +1,205 @@ +#ifndef ZKB_H +#define ZKB_H + +#include +#include +#include +#include +#include +#include +#include + +class State; + +class Action { +protected: + State* state; + ushort keycode; + ushort unicode; + int flags; + + enum { + Shift_Mod = 1, + Ctrl_Mod = 2, + Alt_Mod = 4, + Keypad_Mod = 8, + Mod_Bits = 15, + Press = 16, + Autorepeat = 32, + Event = 64, + Defined = 128, + }; + + void setDefined(bool); + +public: + Action(); + Action(State*, ushort, ushort, int); + ~Action(); + + State* getState() const; + void setState(State*); + + bool hasEvent() const; + void setEvent(bool); + + bool isDefined() const; + + int getKeycode() const; + void setKeycode(int); + + int getUnicode() const; + void setUnicode(int); + + int getModifiers() const; + void setModifiers(int m); + + bool isPressed() const; + void setPressed(bool); + + bool isAutorepeat() const; + void setAutorepeat(bool); +}; + +class State { +protected: + State* parent; + Action* keys; + + enum { + Key_a=0, + Key_b=1, + Key_c=2, + Key_d=3, + Key_e=4, + Key_f=5, + Key_g=6, + Key_h=7, + Key_i=8, + Key_j=9, + Key_k=10, + Key_l=11, + Key_m=12, + Key_n=13, + Key_o=14, + Key_p=15, + Key_q=16, + Key_r=17, + Key_s=18, + Key_t=19, + Key_u=20, + Key_v=21, + Key_w=22, + Key_x=23, + Key_y=24, + Key_z=25, + Key_Comma=26, + Key_Slash=27, + Key_Quote=28, + Key_Dot=29, + Key_Backspace=30, + Key_Space=31, + Key_Enter=32, + Key_LeftShift=33, + Key_RightShift=34, + Key_Fn=35, + Key_Tab=36, + Key_Calendar=37, + Key_Addressbook=38, + Key_Home=39, + Key_Menu=40, + Key_Mail=41, + Key_Cancel=42, + Key_OK=43, + Key_Left=44, + Key_Up=45, + Key_Right=46, + Key_Down=47, + Key_Middle=48, + Key_Off=49, + Key_Light=50, + + Key_Max=51 + }; + + static const short x1[]; + static const short x2[]; + + int translateKeycode(int keycode) const; + +public: + State(State* parent=0); + State(const State&); + ~State(); + + Action* get(int keycode, bool pressed, bool follow = false) const; + bool set(int keycode, bool pressed, Action& action); + + State* getParent() const; + void setParent(State*); +}; + +class Keymap : public QObject, public QWSServer::KeyboardFilter { +Q_OBJECT + +public: + Keymap(); + virtual ~Keymap(); + + virtual bool filter(int unicode, int keycode, int modifiers, + bool isPress, bool autoRepeat); + + void enable(); + void disable(); + + QStringList listStates(); + State* getStateByName(const QString& name); + + QStringList listLabels(); + State* getStateByLabel(const QString& label); + + bool addState(const QString& name, State* state); + bool removeState(const QString& name, bool force = false); + bool setCurrentState(State*); + State* getCurrentState() const; + QString getCurrentLabel(); + + bool addLabel(const QString& label, const QString& state, + int index=-1); + bool removeLabel(const QString& label); + + int getAutorepeatDelay() const; + void setAutorepeatDelay(int); + + int getAutorepeatPeriod() const; + void setAutorepeatPeriod(int); + +signals: + void stateChanged(const QString& name); + +protected slots: + void autoRepeat(); + +protected: + QMap states; + QMap labels; + QStringList labelList; + + QMap stateLabelMap; + bool lsmapInSync; + + bool enabled; + State* currentState; + QString currentStateName; + QString currentLabel; + Action* autoRepeatAction; + + int repeatDelay; + int repeatPeriod; + QTimer repeater; + + QList findStateUsage(State* s); + void generateLabelStateMaps(); +}; + +#endif diff --git a/noncore/apps/keyz-cfg/zkbcfg.cpp b/noncore/apps/keyz-cfg/zkbcfg.cpp new file mode 100644 index 0000000..0992b9a --- a/dev/null +++ b/noncore/apps/keyz-cfg/zkbcfg.cpp @@ -0,0 +1,228 @@ +#include + +#include "zkbcfg.h" + + +// Implementation of XkbConfig class +ZkbConfig::ZkbConfig(const QString& dir):path(dir) { +} + +ZkbConfig::~ZkbConfig() { +} + +bool ZkbConfig::load(const QString& file, Keymap& keymap, const QString& prefix) { + bool ret; + QFile f(path+"/"+file); + QFileInfo fi(f); + + qDebug("start loading file=%s\n", (const char*) file.utf8()); + if (includedFiles.find(fi.absFilePath()) != includedFiles.end()) { + return false; + } + + includedFiles.insert(fi.absFilePath(), 1); + QXmlInputSource is(f); + QXmlSimpleReader reader; + ZkbHandler h(*this, keymap, prefix); + + reader.setContentHandler(&h); + reader.setErrorHandler(this); + ret = reader.parse(is); + includedFiles.remove(fi.absFilePath()); + + qDebug("end loading file=%s : status=%s\n", (const char*) file.utf8(), + (const char*) err.utf8()); + return ret; +} + +bool ZkbConfig::warning(const QXmlParseException& e) { + QString tmp; + + tmp.sprintf("%d: warning: %s\n", e.lineNumber(), + (const char*) e.message().utf8()); + + err += tmp; + + return true; +} + +bool ZkbConfig::error(const QXmlParseException& e) { + QString tmp; + + tmp.sprintf("%d: error: %s\n", e.lineNumber(), + (const char*) e.message().utf8()); + + err += tmp; + + return true; +} + +bool ZkbConfig::fatalError(const QXmlParseException& e) { + QString tmp; + + tmp.sprintf("%d: fatal error: %s\n", e.lineNumber(), + (const char*) e.message().utf8()); + + err += tmp; + + return false; +} + +QString ZkbConfig::errorString() { + return err; +} + +// Implementation of ZkbHandler +ZkbHandler::ZkbHandler(ZkbConfig& z, Keymap& k, const QString& p):zkc(z), keymap(k), + prefix(p), ardelay(-1), arperiod(-1), currentState(0), currentAction(0) { +} + +ZkbHandler::~ZkbHandler() { +} + +bool ZkbHandler::startKeymapElement(int ard, int arp, const QString&) { + ardelay = ard; + arperiod = arp; + + return true; +} + +bool ZkbHandler::startIncludeElement(const QString& file, + const QString& pref) { + + QString p = prefix; + + if (!pref.isNull()) { + p += pref + ":"; + } + + + bool ret = zkc.load(file, keymap, p); + if (!ret) { + setError("Error including file: " + file); + } + + return ret; +} + +bool ZkbHandler::startLabelElement(const QString& label, + const QString& state) { + + if (!keymap.addLabel(label, prefix + state)) { + err = "label " + label + " already defined"; + return false; + } + + return true; +} + +bool ZkbHandler::startStateElement(const QString& name, + const QString& parentName, bool dflt) { + + currentStateName = prefix + name; + currentState = keymap.getStateByName(currentStateName); + +// qDebug("state name=%s\n", (const char*) currentStateName.utf8()); + + State* parent = 0; + if (!parentName.isEmpty()) { + QString pn = prefix + parentName; + parent = keymap.getStateByName(pn); + if (parent == 0) { + err = currentStateName + + ": undefined parent state: " + pn; + return false; + } + } + + if (currentState == 0) { + currentState = new State(parent); + keymap.addState(currentStateName, currentState); + } else { + if (parent!=0) { + currentState->setParent(parent); + } + } + + if (dflt) { + keymap.setCurrentState(currentState); + } + + return true; +} + +bool ZkbHandler::startMapElement(int keycode, bool pressed) { + currentAction = currentState->get(keycode, pressed); + if (currentAction == 0) { + setError("keycode " + QString::number(keycode) + " not supported"); + return false; + } + + currentAction->setEvent(false); + currentAction->setState(0); + + return true; +} + +bool ZkbHandler::startEventElement(int keycode, int unicode, int modifiers, + bool pressed, bool autorepeat) { + + currentAction->setEvent(true); + currentAction->setKeycode(keycode); + currentAction->setUnicode(unicode); + currentAction->setModifiers(modifiers); + currentAction->setPressed(pressed); + currentAction->setAutorepeat(autorepeat); + + return true; +} + +bool ZkbHandler::startNextStateElement(const QString& state) { + State* s = keymap.getStateByName(prefix + state); + if (s == 0) { + setError("undefine state: " + prefix + state); + return false; + } + + currentAction->setState(s); + return true; +} + + +bool ZkbHandler::endKeymapElement() { + if (ardelay > 0) { + keymap.setAutorepeatDelay(ardelay); + } + + if (arperiod > 0) { + keymap.setAutorepeatPeriod(arperiod); + } + + return true; +} + +bool ZkbHandler::endIncludeElement() { + return true; +} + +bool ZkbHandler::endLabelElement() { + return true; +} + +bool ZkbHandler::endStateElement() { + currentState = 0; + return true; +} + +bool ZkbHandler::endMapElement() { + currentAction = 0; + return true; +} + +bool ZkbHandler::endEventElement() { + return true; +} + +bool ZkbHandler::endNextStateElement() { + return true; +} diff --git a/noncore/apps/keyz-cfg/zkbcfg.h b/noncore/apps/keyz-cfg/zkbcfg.h new file mode 100644 index 0000000..dc1ac07 --- a/dev/null +++ b/noncore/apps/keyz-cfg/zkbcfg.h @@ -0,0 +1,69 @@ +#ifndef ZKBCFG_H +#define ZKBCFG_H + +#include +#include "zkb.h" +#include "zkbxml.h" + +class ZkbConfig : public QXmlErrorHandler { +public: + ZkbConfig(const QString& dir); + virtual ~ZkbConfig(); + + bool load(const QString& file, Keymap& keymap, const QString& prefix); + + virtual bool warning(const QXmlParseException& e); + virtual bool error(const QXmlParseException& e); + virtual bool fatalError(const QXmlParseException& e); + virtual QString errorString(); + +protected: + QString path; + QMap includedFiles; + QString err; +}; + +class ZkbHandler : public ZkbXmlHandler { +public: + ZkbHandler(ZkbConfig& zkc, Keymap& keymap, const QString& prefix); + virtual ~ZkbHandler(); + +protected: + ZkbConfig& zkc; + Keymap& keymap; + QString prefix; + + // stuff for keymap tag + int ardelay; + int arperiod; + + // stuff for state tag + QString currentStateName; + State* currentState; + + // stuff for map tag + Action* currentAction; + + virtual bool startKeymapElement(int ardelay, int arperiod, + const QString& author); + virtual bool startIncludeElement(const QString& file, + const QString& prfix); + virtual bool startLabelElement(const QString& label, + const QString& state); + virtual bool startStateElement(const QString& name, + const QString& parent, bool dflt); + virtual bool startMapElement(int key, bool pressed); + virtual bool startEventElement(int keycode, int unicode, int modifiers, + bool pressed, bool autorepeat); + virtual bool startNextStateElement(const QString& state); + + virtual bool endKeymapElement(); + virtual bool endIncludeElement(); + virtual bool endLabelElement(); + virtual bool endStateElement(); + virtual bool endMapElement(); + virtual bool endEventElement(); + virtual bool endNextStateElement(); +}; + +#endif diff --git a/noncore/apps/keyz-cfg/zkbnames.cpp b/noncore/apps/keyz-cfg/zkbnames.cpp new file mode 100644 index 0000000..fec3a2e --- a/dev/null +++ b/noncore/apps/keyz-cfg/zkbnames.cpp @@ -0,0 +1,450 @@ +#ifdef USE_ZKB_NAMES + +#include +#include + +#include "zkbnames.h" + +QString Null_String((const char*) 0); + +// Implementation of KeyNames +static struct { + int key; + char *name; +} Key_Names[] = { + { 32, "Space" }, + { 39, "Apostrophe" }, + { 44, "Comma" }, + { 46, "Period" }, + { 47, "Slash" }, + { 65, "A" }, + { 66, "B" }, + { 67, "C" }, + { 68, "D" }, + { 69, "E" }, + { 70, "F" }, + { 71, "G" }, + { 72, "H" }, + { 73, "I" }, + { 74, "J" }, + { 75, "K" }, + { 76, "L" }, + { 77, "M" }, + { 78, "N" }, + { 79, "O" }, + { 80, "P" }, + { 81, "Q" }, + { 82, "R" }, + { 83, "S" }, + { 84, "T" }, + { 85, "U" }, + { 86, "V" }, + { 87, "W" }, + { 88, "X" }, + { 89, "Y" }, + { 90, "Z" }, + { 4096, "Cancel" }, + { 4097, "Tab" }, + { 4099, "Backspace" }, + { 4100, "Enter" }, + { 4114, "Left" }, + { 4115, "Up" }, + { 4116, "Right" }, + { 4117, "Down" }, + { 4128, "Left Shift" }, + { 4130, "Right Shift" }, + { 4152, "Calendar" }, + { 4153, "Addressbook" }, + { 4154, "Menu" }, + { 4155, "Home" }, + { 4156, "Mail" }, + { 4165, "Fn" }, + { 4173, "Middle" }, + { 4176, "OK" }, + { 4177, "Off" }, + { 4178, "Light" }, + { 0, 0 } +}; + +static QMap kn_map; +static QMap kn_rmap; + +void init_kn_maps() { + int i = 0; + while (Key_Names[i].name != 0) { + int key = Key_Names[i].key; + QString name(Key_Names[i].name); + + kn_map.insert(name, key); + kn_rmap.insert(key, name); + i++; + } +} + +int KeyNames::find(const QString& key) { + if (kn_map.isEmpty()) { + init_kn_maps(); + } + + QMap::Iterator it = kn_map.find(key); + if (it == kn_map.end()) { + return -1; + } else { + return it.data(); + } +} + +const QString& KeyNames::find(int k) { + if (kn_map.isEmpty()) { + init_kn_maps(); + } + + QMap::Iterator it = kn_rmap.find(k); + if (it == kn_rmap.end()) { + return Null_String; + } else { + return it.data(); + } +} + +// Implementation of ModifierNames +struct { + int value; + char* name; +} Modifier_Names[] = { + { 8, "Shift" }, + { 16, "Control" }, + { 32, "Alt" }, + { 0x4000, "Keypad" }, + { 0, 0 } +}; + +static QMap mn_map; +static QMap mn_rmap; + +void init_mn_maps() { + int i = 0; + while (Modifier_Names[i].name != 0) { + int value = Modifier_Names[i].value; + QString name(Modifier_Names[i].name); + + mn_map.insert(name, value); + mn_rmap.insert(value, name); + i++; + } +} + +int ModifierNames::find(const QString& key) { + if (mn_map.isEmpty()) { + init_mn_maps(); + } + + QMap::Iterator it = mn_map.find(key); + if (it == mn_map.end()) { + return -1; + } else { + return it.data(); + } +} + +const QString& ModifierNames::find(int k) { + if (mn_map.isEmpty()) { + init_mn_maps(); + } + + QMap::Iterator it = mn_rmap.find(k); + if (it == mn_rmap.end()) { + return Null_String; + } else { + return it.data(); + } +} + +// Implementation of KeycodeNames + +struct { + char* name; + int keycode; +} Keycode_Names[] = { + { "Escape", 0x1000 }, + { "Tab", 0x1001 }, + { "Backtab", 0x1002 }, + { "Backspace", 0x1003 }, + { "BackSpace", 0x1003 }, + { "Return", 0x1004 }, + { "Enter", 0x1005 }, + { "Insert", 0x1006 }, + { "Delete", 0x1007 }, + { "Pause", 0x1008 }, + { "Print", 0x1009 }, + { "SysReq", 0x100a }, + { "Home", 0x1010 }, + { "End", 0x1011 }, + { "Left", 0x1012 }, + { "Up", 0x1013 }, + { "Right", 0x1014 }, + { "Down", 0x1015 }, + { "Prior", 0x1016 }, + { "PageUp", 0x1016 }, + { "Next", 0x1017 }, + { "PageDown", 0x1017 }, + { "Shift", 0x1020 }, + { "Control", 0x1021 }, + { "Meta", 0x1022 }, + { "Alt", 0x1023 }, + { "CapsLock", 0x1024 }, + { "NumLock", 0x1025 }, + { "ScrollLock", 0x1026 }, + { "F1", 0x1030 }, + { "F2", 0x1031 }, + { "F3", 0x1032 }, + { "F4", 0x1033 }, + { "F5", 0x1034 }, + { "F6", 0x1035 }, + { "F7", 0x1036 }, + { "F8", 0x1037 }, + { "F9", 0x1038 }, + { "F10", 0x1039 }, + { "F11", 0x103a }, + { "F12", 0x103b }, + { "F13", 0x103c }, + { "F14", 0x103d }, + { "F15", 0x103e }, + { "F16", 0x103f }, + { "F17", 0x1040 }, + { "F18", 0x1041 }, + { "F19", 0x1042 }, + { "F20", 0x1043 }, + { "F21", 0x1044 }, + { "F22", 0x1045 }, + { "F23", 0x1046 }, + { "F24", 0x1047 }, + { "F25", 0x1048 }, + { "F26", 0x1049 }, + { "F27", 0x104a }, + { "F28", 0x104b }, + { "F29", 0x104c }, + { "F30", 0x104d }, + { "F31", 0x104e }, + { "F32", 0x104f }, + { "F33", 0x1050 }, + { "F34", 0x1051 }, + { "F35", 0x1052 }, + { "Super_L", 0x1053 }, + { "Super_R", 0x1054 }, + { "Menu", 0x1055 }, + { "Hyper_L", 0x1056 }, + { "Hyper_R", 0x1057 }, + { "Help", 0x1058 }, + { "Space", 0x20 }, + { "Any", 0x20 }, + { "Exclam", 0x21 }, + { "QuoteDbl", 0x22 }, + { "NumberSign", 0x23 }, + { "Dollar", 0x24 }, + { "Percent", 0x25 }, + { "Ampersand", 0x26 }, + { "Apostrophe", 0x27 }, + { "ParenLeft", 0x28 }, + { "ParenRight", 0x29 }, + { "Asterisk", 0x2a }, + { "Plus", 0x2b }, + { "Comma", 0x2c }, + { "Minus", 0x2d }, + { "Period", 0x2e }, + { "Slash", 0x2f }, + { "0", 0x30 }, + { "1", 0x31 }, + { "2", 0x32 }, + { "3", 0x33 }, + { "4", 0x34 }, + { "5", 0x35 }, + { "6", 0x36 }, + { "7", 0x37 }, + { "8", 0x38 }, + { "9", 0x39 }, + { "Colon", 0x3a }, + { "Semicolon", 0x3b }, + { "Less", 0x3c }, + { "Equal", 0x3d }, + { "Greater", 0x3e }, + { "Question", 0x3f }, + { "At", 0x40 }, + { "A", 0x41 }, + { "B", 0x42 }, + { "C", 0x43 }, + { "D", 0x44 }, + { "E", 0x45 }, + { "F", 0x46 }, + { "G", 0x47 }, + { "H", 0x48 }, + { "I", 0x49 }, + { "J", 0x4a }, + { "K", 0x4b }, + { "L", 0x4c }, + { "M", 0x4d }, + { "N", 0x4e }, + { "O", 0x4f }, + { "P", 0x50 }, + { "Q", 0x51 }, + { "R", 0x52 }, + { "S", 0x53 }, + { "T", 0x54 }, + { "U", 0x55 }, + { "V", 0x56 }, + { "W", 0x57 }, + { "X", 0x58 }, + { "Y", 0x59 }, + { "Z", 0x5a }, + { "BracketLeft", 0x5b }, + { "Backslash", 0x5c }, + { "BracketRight", 0x5d }, + { "AsciiCircum", 0x5e }, + { "Underscore", 0x5f }, + { "QuoteLeft", 0x60 }, + { "BraceLeft", 0x7b }, + { "Bar", 0x7c }, + { "BraceRight", 0x7d }, + { "AsciiTilde", 0x7e }, + { "nobreakspace", 0x0a0 }, + { "exclamdown", 0x0a1 }, + { "cent", 0x0a2 }, + { "sterling", 0x0a3 }, + { "currency", 0x0a4 }, + { "yen", 0x0a5 }, + { "brokenbar", 0x0a6 }, + { "section", 0x0a7 }, + { "diaeresis", 0x0a8 }, + { "copyright", 0x0a9 }, + { "ordfeminine", 0x0aa }, + { "guillemotleft", 0x0ab }, + { "notsign", 0x0ac }, + { "hyphen", 0x0ad }, + { "registered", 0x0ae }, + { "macron", 0x0af }, + { "degree", 0x0b0 }, + { "plusminus", 0x0b1 }, + { "twosuperior", 0x0b2 }, + { "threesuperior", 0x0b3 }, + { "acute", 0x0b4 }, + { "mu", 0x0b5 }, + { "paragraph", 0x0b6 }, + { "periodcentered", 0x0b7 }, + { "cedilla", 0x0b8 }, + { "onesuperior", 0x0b9 }, + { "masculine", 0x0ba }, + { "guillemotright", 0x0bb }, + { "onequarter", 0x0bc }, + { "onehalf", 0x0bd }, + { "threequarters", 0x0be }, + { "questiondown", 0x0bf }, + { "Agrave", 0x0c0 }, + { "Aacute", 0x0c1 }, + { "Acircumflex", 0x0c2 }, + { "Atilde", 0x0c3 }, + { "Adiaeresis", 0x0c4 }, + { "Aring", 0x0c5 }, + { "AE", 0x0c6 }, + { "Ccedilla", 0x0c7 }, + { "Egrave", 0x0c8 }, + { "Eacute", 0x0c9 }, + { "Ecircumflex", 0x0ca }, + { "Ediaeresis", 0x0cb }, + { "Igrave", 0x0cc }, + { "Iacute", 0x0cd }, + { "Icircumflex", 0x0ce }, + { "Idiaeresis", 0x0cf }, + { "ETH", 0x0d0 }, + { "Ntilde", 0x0d1 }, + { "Ograve", 0x0d2 }, + { "Oacute", 0x0d3 }, + { "Ocircumflex", 0x0d4 }, + { "Otilde", 0x0d5 }, + { "Odiaeresis", 0x0d6 }, + { "multiply", 0x0d7 }, + { "Ooblique", 0x0d8 }, + { "Ugrave", 0x0d9 }, + { "Uacute", 0x0da }, + { "Ucircumflex", 0x0db }, + { "Udiaeresis", 0x0dc }, + { "Yacute", 0x0dd }, + { "THORN", 0x0de }, + { "ssharp", 0x0df }, + { "agrave", 0x0e0 }, + { "aacute", 0x0e1 }, + { "acircumflex", 0x0e2 }, + { "atilde", 0x0e3 }, + { "adiaeresis", 0x0e4 }, + { "aring", 0x0e5 }, + { "ae", 0x0e6 }, + { "ccedilla", 0x0e7 }, + { "egrave", 0x0e8 }, + { "eacute", 0x0e9 }, + { "ecircumflex", 0x0ea }, + { "ediaeresis", 0x0eb }, + { "igrave", 0x0ec }, + { "iacute", 0x0ed }, + { "icircumflex", 0x0ee }, + { "idiaeresis", 0x0ef }, + { "eth", 0x0f0 }, + { "ntilde", 0x0f1 }, + { "ograve", 0x0f2 }, + { "oacute", 0x0f3 }, + { "ocircumflex", 0x0f4 }, + { "otilde", 0x0f5 }, + { "odiaeresis", 0x0f6 }, + { "division", 0x0f7 }, + { "oslash", 0x0f8 }, + { "ugrave", 0x0f9 }, + { "uacute", 0x0fa }, + { "ucircumflex", 0x0fb }, + { "udiaeresis", 0x0fc }, + { "yacute", 0x0fd }, + { "thorn", 0x0fe }, + { "ydiaeresis", 0x0ff }, + { "unknown", 0xffff }, + { 0, 0} +}; + +static QMap kcn_map; +static QMap kcn_rmap; + +void init_kcn_maps() { + int i = 0; + while (Keycode_Names[i].name != 0) { + int keycode = Keycode_Names[i].keycode; + QString name(Keycode_Names[i].name); + + kcn_map.insert(name, keycode); + kcn_rmap.insert(keycode, name); + i++; + } +} + +int KeycodeNames::find(const QString& key) { + if (kcn_map.isEmpty()) { + init_kcn_maps(); + } + + QMap::Iterator it = kcn_map.find(key); + if (it == kcn_map.end()) { + return -1; + } else { + return it.data(); + } +} + +const QString& KeycodeNames::find(int k) { + if (kcn_map.isEmpty()) { + init_kcn_maps(); + } + + QMap::Iterator it = kcn_rmap.find(k); + if (it == kcn_rmap.end()) { + return Null_String; + } else { + return it.data(); + } +} + +#endif diff --git a/noncore/apps/keyz-cfg/zkbnames.h b/noncore/apps/keyz-cfg/zkbnames.h new file mode 100644 index 0000000..58462ff --- a/dev/null +++ b/noncore/apps/keyz-cfg/zkbnames.h @@ -0,0 +1,27 @@ +#ifndef ZKBNAMES_H +#define ZKBNAMES_H + +#ifdef USE_ZKB_NAMES + +#include + +class KeyNames { +public: + static int find(const QString& key); + static const QString& find(int); +}; + +class KeycodeNames { +public: + static int find(const QString& key); + static const QString& find(int); +}; + +class ModifierNames { +public: + static int find(const QString& key); + static const QString& find(int); +}; + +#endif +#endif diff --git a/noncore/apps/keyz-cfg/zkbxml.cpp b/noncore/apps/keyz-cfg/zkbxml.cpp new file mode 100644 index 0000000..76472cb --- a/dev/null +++ b/noncore/apps/keyz-cfg/zkbxml.cpp @@ -0,0 +1,587 @@ +#include "zkbxml.h" +#include "zkbnames.h" + +static QString Keymap_Tag("keymap"); +static QString Include_Tag("include"); +static QString Label_Tag("label"); +static QString State_Tag("state"); +static QString Map_Tag("map"); +static QString Event_Tag("event"); +static QString NextState_Tag("next-state"); + +ZkbXmlHandler::ZkbXmlHandler() { +} + +ZkbXmlHandler::~ZkbXmlHandler() { +} + +bool ZkbXmlHandler::startElement(const QString&, const QString&, + const QString& name, const QXmlAttributes& attr) { + + bool ret = false; + + if (name == Keymap_Tag) { + ret = start_keymap(attr); + } else if (name == Include_Tag) { + ret = start_include(attr); + } else if (name == Label_Tag) { + ret = start_label(attr); + } else if (name == State_Tag) { + ret = start_state(attr); + } else if (name == Map_Tag) { + ret = start_map(attr); + } else if (name == Event_Tag) { + ret = start_event(attr); + } else if (name == NextState_Tag) { + ret = start_next_state(attr); + } + + elements.prepend(name); + + return ret; +} + +bool ZkbXmlHandler::endElement(const QString&, const QString&, + const QString& name) { + + bool ret = false; + + elements.remove(elements.begin()); + + if (name == Keymap_Tag) { + ret = end_keymap(); + } else if (name == Include_Tag) { + ret = end_include(); + } else if (name == Label_Tag) { + ret = end_label(); + } else if (name == State_Tag) { + ret = end_state(); + } else if (name == Map_Tag) { + ret = end_map(); + } else if (name == Event_Tag) { + ret = end_event(); + } else if (name == NextState_Tag) { + ret = end_next_state(); + } + + return ret; +} + +QString ZkbXmlHandler::errorString() { + return err; +} + +bool ZkbXmlHandler::startKeymapElement(int ardelay, int arperiod, const QString& author) { + return false; +} + +bool ZkbXmlHandler::startIncludeElement(const QString& file, + const QString& prefix) { + + return false; +} + +bool ZkbXmlHandler::startLabelElement(const QString& label, + const QString& state) { + + return false; +} + +bool ZkbXmlHandler::startStateElement(const QString& name, + const QString& parent, bool dflt) { + + return false; +} + +bool ZkbXmlHandler::startMapElement(int keycode, bool pressed) { + return false; +} + +bool ZkbXmlHandler::startEventElement(int keycode, int unicode, int modifiers, + bool pressed, bool autorepeat) { + + return false; +} + +bool ZkbXmlHandler::startNextStateElement(const QString& state) { + return false; +} + + +bool ZkbXmlHandler::endKeymapElement() { + return false; +} + +bool ZkbXmlHandler::endIncludeElement() { + return false; +} + +bool ZkbXmlHandler::endLabelElement() { + return false; +} + +bool ZkbXmlHandler::endStateElement() { + return false; +} + +bool ZkbXmlHandler::endMapElement() { + return false; +} + +bool ZkbXmlHandler::endEventElement() { + return false; +} + +bool ZkbXmlHandler::endNextStateElement() { + return false; +} + + +bool ZkbXmlHandler::start_keymap(const QXmlAttributes& attr) { + int nattr = 0; + int didx = attr.index("autorepeat-delay"); + int pidx = attr.index("autorepeat-period"); + int aidx = attr.index("author"); + int ard = -1; + int arp = -1; + QString author; + + if (!elements.isEmpty()) { + setError("keymap element should be top-level element"); + return false; + } + + if (didx >= 0) { + QString s = attr.value(didx); + bool ok; + + ard = s.toInt(&ok); + if (!ok) { + setError("Invalid autorepeat-delay value: " + s); + return false; + } + + nattr++; + } + + if (pidx >= 0) { + QString s = attr.value(pidx); + bool ok; + + arp = s.toInt(&ok); + if (!ok) { + setError("Invalid autorepeat-period value: " + s); + return false; + } + + nattr++; + } + + if (aidx >= 0) { + author = attr.value(aidx); + nattr++; + } + + if (attr.length() > nattr) { + setError("Unsupported attributes"); + return false; + } + + return startKeymapElement(ard, arp, author); +} + +bool ZkbXmlHandler::start_include(const QXmlAttributes& attr) { + int nattr = 0; + int fidx = attr.index("file"); + int pidx = attr.index("prefix"); + QString file; + QString prefix((const char*) 0); + + if (elements.first() != Keymap_Tag) { + setError("include element should be used only " + "within keymap element"); + return false; + } + + if (fidx >= 0) { + file = attr.value(fidx); + nattr++; + } else { + setError("Missing file attribute"); + return false; + } + + if (pidx >= 0) { + prefix = attr.value(pidx); + nattr++; + } + + if (attr.length() > nattr) { + setError("Unsupported attributes"); + return false; + } + + return startIncludeElement(file, prefix); +} + +bool ZkbXmlHandler::start_label(const QXmlAttributes& attr) { + int nattr = 0; + int nidx = attr.index("name"); + int sidx = attr.index("state"); + QString name; + QString state; + + if (elements.first() != Keymap_Tag) { + setError("label element should be used only " + "within keymap element"); + return false; + } + + if (nidx >= 0) { + name = attr.value(nidx); + nattr++; + } else { + setError("Missing name attribute"); + return false; + } + + if (sidx >= 0) { + state = attr.value(sidx); + nattr++; + } else { + setError("Missing name attribute"); + return false; + } + + if (attr.length() > nattr) { + setError("Unsupported attributes"); + return false; + } + + return startLabelElement(name, state); +} + +bool ZkbXmlHandler::start_state(const QXmlAttributes& attr) { + int nattr = 0; + int nidx = attr.index("name"); + int pidx = attr.index("parent"); + int didx = attr.index("default"); + QString name; + QString parent((const char*) 0); + bool dflt = false; + + if (elements.first() != Keymap_Tag) { + setError("state element should be used only " + "within keymap element"); + return false; + } + + if (nidx >= 0) { + name = attr.value(nidx); + nattr++; + } else { + setError("Missing name attribute"); + return false; + } + + if (pidx >= 0) { + parent = attr.value(pidx); + nattr++; + } + + if (didx >= 0) { + dflt = str2bool(attr.value(didx)); + if (!err.isEmpty()) { + return false; + } + + nattr++; + } + + if (attr.length() > nattr) { + setError("Unsupported attributes"); + return false; + } + + return startStateElement(name, parent, dflt); +} + +bool ZkbXmlHandler::start_map(const QXmlAttributes& attr) { + int nattr = 0; + int kidx = attr.index("keycode"); + int pidx = attr.index("pressed"); + int key; + bool pressed; + + if (elements.first() != State_Tag) { + setError("map element should be used only " + "within state element"); + return false; + } + + if (kidx >= 0) { + key = str2key(attr.value(kidx)); + if (!err.isEmpty()) { + return false; + } + nattr++; + } else { + setError("Missing keycode attribute"); + return false; + } + + if (pidx >= 0) { + pressed = str2bool(attr.value(pidx)); + if (!err.isEmpty()) { + return false; + } + nattr++; + } else { + setError("Missing pressed attribute"); + return false; + } + + if (attr.length() > nattr) { + setError("Unsupported attributes"); + return false; + } + + return startMapElement(key, pressed); +} + +bool ZkbXmlHandler::start_event(const QXmlAttributes& attr) { + int nattr = 0; + int kidx = attr.index("keycode"); + int pidx = attr.index("pressed"); + int uidx = attr.index("unicode"); + int midx = attr.index("modifiers"); + int aidx = attr.index("autorepeat"); + + int keycode; + int unicode; + int modifiers = 0; + bool pressed; + bool autorepeat = false; + + if (elements.first() != Map_Tag) { + setError("event element should be used only " + "within map element"); + return false; + } + + if (kidx >= 0) { + keycode = str2keycode(attr.value(kidx)); + if (!err.isEmpty()) { + return false; + } + nattr++; + } else { + setError("Missing keycode attribute"); + return false; + } + + if (uidx >= 0) { + unicode = str2unicode(attr.value(uidx)); + if (!err.isEmpty()) { + return false; + } + nattr++; + } else { + setError("Missing unicode attribute"); + return false; + } + + if (midx >= 0) { + modifiers = str2modifier(attr.value(midx)); + if (!err.isEmpty()) { + return false; + } + nattr++; + } + + if (pidx >= 0) { + pressed = str2bool(attr.value(pidx)); + if (!err.isEmpty()) { + return false; + } + nattr++; + } else { + setError("Missing pressed attribute"); + return false; + } + + if (aidx >= 0) { + autorepeat = str2bool(attr.value(aidx)); + if (!err.isEmpty()) { + return false; + } + nattr++; + } + + if (attr.length() > nattr) { + setError("Unsupported attributes"); + return false; + } + + return startEventElement(keycode, unicode, modifiers, pressed, + autorepeat); +} + +bool ZkbXmlHandler::start_next_state(const QXmlAttributes& attr) { + int nattr = 0; + int nidx = attr.index("name"); + QString name; + + if (elements.first() != Map_Tag) { + setError("next-state element should be used only " + "within map element"); + return false; + } + + if (nidx >= 0) { + name = attr.value(nidx); + nattr++; + } else { + setError("Missing name attribute"); + return false; + } + + if (attr.length() > nattr) { + setError("Unsupported attributes"); + return false; + } + + return startNextStateElement(name); +} + +bool ZkbXmlHandler::end_keymap() { + return endKeymapElement(); +} + +bool ZkbXmlHandler::end_include() { + return endIncludeElement(); +} + +bool ZkbXmlHandler::end_label() { + return endLabelElement(); +} + +bool ZkbXmlHandler::end_state() { + return endStateElement(); +} + +bool ZkbXmlHandler::end_map() { + return endMapElement(); +} + +bool ZkbXmlHandler::end_event() { + return endEventElement(); +} + +bool ZkbXmlHandler::end_next_state() { + return endNextStateElement(); +} + +void ZkbXmlHandler::setError(const QString& e) { + err = e; +} + +int ZkbXmlHandler::str2key(const QString& s) { + int ret; + +#ifdef USE_ZKB_NAMES + ret = KeyNames::find(s); + if (ret == -1) { + setError("Invalid value: " + s); + } + +#else + ret = str2uint(s); +#endif + + return ret; +} + +int ZkbXmlHandler::str2modifier(const QString& val) { + int ret; + +#ifdef USE_ZKB_NAMES + int n, i; + ret = 0; + n = 0; + do { + i = val.find('|', n); + if (i < 0) { + i = val.length(); + } + + QString s = val.mid(n, i - n); + int v = ModifierNames::find(s.stripWhiteSpace()); + + if (v == -1) { + setError("Invalid value: " + val); + return -1; + } + + ret |= v; + n = i + 1; + } while (n < val.length()); +#else + ret = str2uint(val); +#endif + + return ret; +} + +bool ZkbXmlHandler::str2bool(const QString& s) { + if (s == "true") { + return true; + } else { + return false; + } +} + +int ZkbXmlHandler::str2unicode(const QString& s) { + return str2uint(s); +} + +int ZkbXmlHandler::str2keycode(const QString& s) { + int ret; + +#ifdef USE_ZKB_NAMES + ret = KeycodeNames::find(s); + if (ret == -1) { + setError("Invalid value: " + s); + } + +#else + ret = str2uint(s); +#endif + + return ret; +} + +int ZkbXmlHandler::str2uint(const QString& s) { + int ret; + bool ok; + QString val = s; + int r; + + if (val.left(2) == "0x") { + val = s.mid(2); + r = 16; + } else if (val.left(1) == "0") { + val = s.mid(1); + r = 8; + } else { + r = 10; + } + + ret = val.toInt(&ok, r); + if (!ok) { + setError("Invalid value: " + s); + ret = -1; + } + + return ret; +} diff --git a/noncore/apps/keyz-cfg/zkbxml.h b/noncore/apps/keyz-cfg/zkbxml.h new file mode 100644 index 0000000..2b15cbb --- a/dev/null +++ b/noncore/apps/keyz-cfg/zkbxml.h @@ -0,0 +1,68 @@ +#ifndef ZKBXML_H +#define ZKBXML_H + +#include + +class ZkbXmlHandler : public QXmlDefaultHandler { +public: + ZkbXmlHandler(); + virtual ~ZkbXmlHandler(); + + virtual bool startElement(const QString&, const QString&, + const QString& name, const QXmlAttributes& attr); + + virtual bool endElement(const QString&, const QString&, + const QString& name); + + virtual QString errorString(); + +protected: + QString err; + QStringList elements; + + virtual bool startKeymapElement(int ardelay, int arperiod, + const QString& author); + virtual bool startIncludeElement(const QString& file, + const QString& prfix); + virtual bool startLabelElement(const QString& label, + const QString& state); + virtual bool startStateElement(const QString& name, + const QString& parent, bool dflt); + virtual bool startMapElement(int key, bool pressed); + virtual bool startEventElement(int keycode, int unicode, int modifiers, + bool pressed, bool autorepeat); + virtual bool startNextStateElement(const QString& state); + + virtual bool endKeymapElement(); + virtual bool endIncludeElement(); + virtual bool endLabelElement(); + virtual bool endStateElement(); + virtual bool endMapElement(); + virtual bool endEventElement(); + virtual bool endNextStateElement(); + + bool start_keymap(const QXmlAttributes&); + bool start_include(const QXmlAttributes&); + bool start_label(const QXmlAttributes&); + bool start_state(const QXmlAttributes&); + bool start_map(const QXmlAttributes&); + bool start_event(const QXmlAttributes&); + bool start_next_state(const QXmlAttributes&); + bool end_keymap(); + bool end_include(); + bool end_label(); + bool end_state(); + bool end_map(); + bool end_event(); + bool end_next_state(); + + void setError(const QString&); + int str2key(const QString&); + int str2modifier(const QString&); + bool str2bool(const QString&); + int str2unicode(const QString&); + int str2keycode(const QString&); + int str2uint(const QString&); +}; + +#endif -- cgit v0.9.0.2