From 71a0c97c7a03e7fc8e8660a10240ea800b020638 Mon Sep 17 00:00:00 2001 From: Konrad Rosenbaum Date: Sun, 10 Jul 2016 00:55:55 +0200 Subject: [PATCH] move more stuff to commonlib and make session manager more powerful --- Makefile | 2 +- commonlib/commonexport.h | 8 + commonlib/commonlib.pri | 10 + commonlib/commonlib.pro | 36 ++ commonlib/configdialog.cpp | 680 ++++++++++++++++++++++++++ commonlib/configdialog.h | 97 ++++ commonlib/crypto/crypto.pri | 9 + commonlib/crypto/hmac.cpp | 102 ++++ commonlib/crypto/hmac.h | 52 ++ commonlib/crypto/keygen.cpp | 235 +++++++++ commonlib/crypto/keygen.h | 68 +++ commonlib/mapplication.cpp | 466 ++++++++++++++++++ commonlib/mapplication.h | 94 ++++ commonlib/misc/barcode-plugin.cpp | 119 +++++ commonlib/misc/barcode-plugin.h | 113 +++++ commonlib/misc/code39.cpp | 111 +++++ commonlib/misc/code39.h | 21 + commonlib/misc/debug.cpp | 63 +++ commonlib/misc/debug.h | 20 + commonlib/misc/domiterator.h | 44 ++ commonlib/misc/dommodel.cpp | 556 ++++++++++++++++++++++ commonlib/misc/dommodel.h | 140 ++++++ commonlib/misc/misc.pri | 16 + commonlib/misc/sclock.cpp | 155 ++++++ commonlib/misc/sclock.h | 40 ++ commonlib/misc/waitcursor.cpp | 38 ++ commonlib/misc/waitcursor.h | 29 ++ commonlib/templates/labeldlg.cpp | 863 ++++++++++++++++++++++++++++++++++ commonlib/templates/labeldlg.h | 230 +++++++++ commonlib/templates/odtrender.cpp | 500 ++++++++++++++++++++ commonlib/templates/odtrender.h | 101 ++++ commonlib/templates/office.cpp | 181 +++++++ commonlib/templates/office.h | 49 ++ commonlib/templates/templates.pri | 13 + commonlib/templates/ticketrender.cpp | 604 ++++++++++++++++++++++++ commonlib/templates/ticketrender.h | 82 ++++ commonlib/widgets/barcodeline.cpp | 41 ++ commonlib/widgets/barcodeline.h | 48 ++ commonlib/widgets/centbox.cpp | 126 +++++ commonlib/widgets/centbox.h | 62 +++ commonlib/widgets/eventview.cpp | 185 ++++++++ commonlib/widgets/eventview.h | 47 ++ commonlib/widgets/listview.cpp | 21 + commonlib/widgets/listview.h | 30 ++ commonlib/widgets/treeview.cpp | 21 + commonlib/widgets/treeview.h | 30 ++ commonlib/widgets/widgets.pri | 15 + mainapp/main.cpp | 4 +- sessman/login.cpp | 14 +- sessman/login.h | 2 +- sessman/sessman.pro | 1 + src/crypto/crypto.pri | 9 - src/crypto/hmac.cpp | 102 ---- src/crypto/hmac.h | 50 -- src/crypto/keygen.cpp | 235 --------- src/crypto/keygen.h | 66 --- src/dialogs/configdialog.cpp | 680 -------------------------- src/dialogs/configdialog.h | 95 ---- src/dialogs/dialogs.pri | 2 - src/dialogs/orderauditdlg.cpp | 2 +- src/libs.pri | 3 + src/main.cpp | 460 +------------------ src/main.h | 80 +--- src/misc/barcode-plugin.cpp | 119 ----- src/misc/barcode-plugin.h | 117 ----- src/misc/code39.cpp | 111 ----- src/misc/code39.h | 19 - src/misc/debug.cpp | 64 --- src/misc/debug.h | 18 - src/misc/domiterator.h | 42 -- src/misc/dommodel.cpp | 556 ---------------------- src/misc/dommodel.h | 138 ------ src/misc/misc.pri | 16 - src/misc/sclock.cpp | 155 ------ src/misc/sclock.h | 39 -- src/misc/waitcursor.cpp | 38 -- src/misc/waitcursor.h | 27 - src/mwin/overview.cpp | 6 +- src/mwin/overview.h | 2 +- src/mwin/tabwin.cpp | 2 +- src/script/jsengine.cpp | 2 +- src/smoke.pri | 5 +- src/smoke.pro | 3 - src/templates/labeldlg.cpp | 863 ---------------------------------- src/templates/labeldlg.h | 228 --------- src/templates/odtrender.cpp | 500 -------------------- src/templates/odtrender.h | 100 ---- src/templates/office.cpp | 181 ------- src/templates/office.h | 47 -- src/templates/templates.pri | 18 +- src/templates/ticketrender.cpp | 604 ------------------------ src/templates/ticketrender.h | 80 ---- src/widgets/barcodeline.cpp | 41 -- src/widgets/barcodeline.h | 46 -- src/widgets/centbox.cpp | 126 ----- src/widgets/centbox.h | 60 --- src/widgets/eventview.cpp | 185 -------- src/widgets/eventview.h | 45 -- src/widgets/listview.cpp | 21 - src/widgets/listview.h | 28 -- src/widgets/treeview.cpp | 21 - src/widgets/treeview.h | 28 -- src/widgets/widgets.pri | 15 - 103 files changed, 6609 insertions(+), 6485 deletions(-) create mode 100644 commonlib/commonexport.h create mode 100644 commonlib/commonlib.pri create mode 100644 commonlib/commonlib.pro create mode 100644 commonlib/configdialog.cpp create mode 100644 commonlib/configdialog.h create mode 100644 commonlib/crypto/crypto.pri create mode 100644 commonlib/crypto/hmac.cpp create mode 100644 commonlib/crypto/hmac.h create mode 100644 commonlib/crypto/keygen.cpp create mode 100644 commonlib/crypto/keygen.h create mode 100644 commonlib/mapplication.cpp create mode 100644 commonlib/mapplication.h create mode 100644 commonlib/misc/barcode-plugin.cpp create mode 100644 commonlib/misc/barcode-plugin.h create mode 100644 commonlib/misc/code39.cpp create mode 100644 commonlib/misc/code39.h create mode 100644 commonlib/misc/debug.cpp create mode 100644 commonlib/misc/debug.h create mode 100644 commonlib/misc/domiterator.h create mode 100644 commonlib/misc/dommodel.cpp create mode 100644 commonlib/misc/dommodel.h create mode 100644 commonlib/misc/misc.pri create mode 100644 commonlib/misc/sclock.cpp create mode 100644 commonlib/misc/sclock.h create mode 100644 commonlib/misc/waitcursor.cpp create mode 100644 commonlib/misc/waitcursor.h create mode 100644 commonlib/templates/labeldlg.cpp create mode 100644 commonlib/templates/labeldlg.h create mode 100644 commonlib/templates/odtrender.cpp create mode 100644 commonlib/templates/odtrender.h create mode 100644 commonlib/templates/office.cpp create mode 100644 commonlib/templates/office.h create mode 100644 commonlib/templates/templates.pri create mode 100644 commonlib/templates/ticketrender.cpp create mode 100644 commonlib/templates/ticketrender.h create mode 100644 commonlib/widgets/barcodeline.cpp create mode 100644 commonlib/widgets/barcodeline.h create mode 100644 commonlib/widgets/centbox.cpp create mode 100644 commonlib/widgets/centbox.h create mode 100644 commonlib/widgets/eventview.cpp create mode 100644 commonlib/widgets/eventview.h create mode 100644 commonlib/widgets/listview.cpp create mode 100644 commonlib/widgets/listview.h create mode 100644 commonlib/widgets/treeview.cpp create mode 100644 commonlib/widgets/treeview.h create mode 100644 commonlib/widgets/widgets.pri delete mode 100644 src/crypto/crypto.pri delete mode 100644 src/crypto/hmac.cpp delete mode 100644 src/crypto/hmac.h delete mode 100644 src/crypto/keygen.cpp delete mode 100644 src/crypto/keygen.h delete mode 100644 src/dialogs/configdialog.cpp delete mode 100644 src/dialogs/configdialog.h delete mode 100644 src/misc/barcode-plugin.cpp delete mode 100644 src/misc/barcode-plugin.h delete mode 100644 src/misc/code39.cpp delete mode 100644 src/misc/code39.h delete mode 100644 src/misc/debug.cpp delete mode 100644 src/misc/debug.h delete mode 100644 src/misc/domiterator.h delete mode 100644 src/misc/dommodel.cpp delete mode 100644 src/misc/dommodel.h delete mode 100644 src/misc/misc.pri delete mode 100644 src/misc/sclock.cpp delete mode 100644 src/misc/sclock.h delete mode 100644 src/misc/waitcursor.cpp delete mode 100644 src/misc/waitcursor.h delete mode 100644 src/templates/labeldlg.cpp delete mode 100644 src/templates/labeldlg.h delete mode 100644 src/templates/odtrender.cpp delete mode 100644 src/templates/odtrender.h delete mode 100644 src/templates/office.cpp delete mode 100644 src/templates/office.h delete mode 100644 src/templates/ticketrender.cpp delete mode 100644 src/templates/ticketrender.h delete mode 100644 src/widgets/barcodeline.cpp delete mode 100644 src/widgets/barcodeline.h delete mode 100644 src/widgets/centbox.cpp delete mode 100644 src/widgets/centbox.h delete mode 100644 src/widgets/eventview.cpp delete mode 100644 src/widgets/eventview.h delete mode 100644 src/widgets/listview.cpp delete mode 100644 src/widgets/listview.h delete mode 100644 src/widgets/treeview.cpp delete mode 100644 src/widgets/treeview.h delete mode 100644 src/widgets/widgets.pri diff --git a/Makefile b/Makefile index 784629c..1168e00 100644 --- a/Makefile +++ b/Makefile @@ -101,7 +101,7 @@ server: wob client: wob taurus tzone wbase cd iface && $(QMAKE) $(QMAKEFLAGS) && $(MAKE) - cd cfglib && $(QMAKE) $(QMAKEFLAGS) && $(MAKE) + cd commonlib && $(QMAKE) $(QMAKEFLAGS) && $(MAKE) cd sesscli && $(QMAKE) $(QMAKEFLAGS) && $(MAKE) cd src && $(QMAKE) $(QMAKEFLAGS) && $(MAKE) cd mainapp && $(QMAKE) $(QMAKEFLAGS) && $(MAKE) diff --git a/commonlib/commonexport.h b/commonlib/commonexport.h new file mode 100644 index 0000000..921f2ca --- /dev/null +++ b/commonlib/commonexport.h @@ -0,0 +1,8 @@ + +#include + +#ifndef MAGICSMOKE_COMMON_LIB_BUILD +#define MAGICSMOKE_COMMON_EXPORT Q_DECL_EXPORT +#else +#define MAGICSMOKE_COMMON_EXPORT Q_DECL_IMPORT +#endif diff --git a/commonlib/commonlib.pri b/commonlib/commonlib.pri new file mode 100644 index 0000000..8b3f2c5 --- /dev/null +++ b/commonlib/commonlib.pri @@ -0,0 +1,10 @@ +#Include PRI for the config library + +LIBS += -lmagicsmoke-common +INCLUDEPATH += $$PWD/../commonlib $$PWD/../commonlib/crypto $$PWD/../commonlib/widgets $$PWD/../commonlib/misc $$PWD/../commonlib/templates +QT += gui widgets + +include($$PWD/../iface/iface.pri) +include($$PWD/../taurus/zip.pri) +include($$PWD/../taurus/elam.pri) +include($$PWD/../taurus/aurora.pri) diff --git a/commonlib/commonlib.pro b/commonlib/commonlib.pro new file mode 100644 index 0000000..b739fe9 --- /dev/null +++ b/commonlib/commonlib.pro @@ -0,0 +1,36 @@ +#Project File for MagicSmoke Config Classes +# (c) Konrad Rosenbaum, 2016 + +#basics +TEMPLATE = lib +VERSION = 0.1 +TARGET = magicsmoke-common + +include(../basics.pri) +include(../iface/iface.pri) +include(../taurus/zip.pri) +include(../taurus/elam.pri) +include(../taurus/aurora.pri) + +#Localization +TRANSLATIONS = \ + smoke-common_de.ts \ + smoke-common_en.ts + +#main source files +HEADERS += configdialog.h mapplication.h +SOURCES += configdialog.cpp mapplication.cpp +INCLUDEPATH += . +DEPENDPATH += $$INCLUDEPATH + +include(crypto/crypto.pri) +include(widgets/widgets.pri) +include(misc/misc.pri) +include(templates/templates.pri) + + +#make sure exports are ok +DEFINES += MAGICSMOKE_COMMON_LIB_BUILD=1 + +#make sure the correct Qt DLLs are used +QT += gui widgets network printsupport diff --git a/commonlib/configdialog.cpp b/commonlib/configdialog.cpp new file mode 100644 index 0000000..d4aab14 --- /dev/null +++ b/commonlib/configdialog.cpp @@ -0,0 +1,680 @@ +// +// C++ Implementation: config dialog +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "keygen.h" +#include "mapplication.h" +#include "configdialog.h" +#include "office.h" +#include "listview.h" +#include "sslexception.h" +#include "misc.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MConfigDialog::MConfigDialog() +{ + setWindowTitle(tr("Magic Smoke Configuration")); + + oldrow=-1; + sslexcept=0; + //main layout + QHBoxLayout*hl; + QVBoxLayout*vl; + setLayout(hl=new QHBoxLayout); + //create Menu Bar + QMenuBar*mb; + hl->setMenuBar(mb=new QMenuBar); + QMenu*m=mb->addMenu(tr("&Profile")); + m->addAction(tr("&New Profile..."),this,SLOT(newProfile())); + m->addAction(tr("&Delete Profile"),this,SLOT(deleteProfile())); + m->addAction(tr("&Rename Profile"),this,SLOT(renameProfile())); + m->addAction(tr("C&lone Profile"),this,SLOT(cloneProfile())); + m->addAction(tr("&Make Default Profile"),this,SLOT(defaultProfile())); + m->addSeparator(); + m->addAction(tr("&Export Host Key..."),this,SLOT(exportKey())); + m->addAction(tr("&Import Host Key..."),this,SLOT(importKey())); + m->addAction(tr("&Generate Host Key..."),this,SLOT(generateKey())); + m->addSeparator(); + m->addAction(tr("&Close Window"),this,SLOT(close())); + m=mb->addMenu(tr("&Settings")); + m->addAction(tr("&Language..."),this,SLOT(changeLang())); + m->addAction(tr("&OpenOffice.org Settings..."),this,SLOT(openOfficeCfg())); + m->addAction(tr("Set &Default Label Font..."),this,SLOT(setDefaultFont())); + m->addAction(tr("Set &Application Style..."),this,SLOT(setAppStyle())); + mb->addMenu(MApplication::helpMenu()); + + //create list view + hl->addWidget(profiles=new MListView); + profilemodel=new QStandardItemModel(this); + profiles->setModel(profilemodel); + profiles->setEditTriggers(QListView::NoEditTriggers); + connect(profiles,SIGNAL(clicked(const QModelIndex&)),this,SLOT(loadProfile())); + connect(profiles,SIGNAL(activated(const QModelIndex&)),this,SLOT(loadProfile())); + //create tabs + QTabWidget*tab; + QWidget*w; + hl->addWidget(tab=new QTabWidget,10); + tab->addTab(w=new QWidget,tr("Connection")); + QGridLayout*gl; + w->setLayout(gl=new QGridLayout); + QLabel*lab; + int lctr=0; + gl->addWidget(lab=new QLabel(tr("Server URL:")),++lctr,0); + lab->setAlignment(Qt::AlignRight); + gl->addLayout(hl=new QHBoxLayout,lctr,1); + hl->addWidget(new QLabel("https://"),0); + hl->addWidget(serverurl=new QLineEdit,1); + gl->addWidget(useproxy=new QCheckBox(tr("Proxy:")),++lctr,0); + gl->addLayout(hl=new QHBoxLayout,lctr,1); + hl->addWidget(proxyname=new QLineEdit,1); + hl->addWidget(new QLabel(":"),0); + hl->addWidget(proxyport=new QSpinBox,0); + proxyport->setRange(1,65535); + connect(useproxy,SIGNAL(toggled(bool)),proxyname,SLOT(setEnabled(bool))); + connect(useproxy,SIGNAL(toggled(bool)),proxyport,SLOT(setEnabled(bool))); + gl->addWidget(lab=new QLabel(tr("Proxy Username:")),++lctr,0); + lab->setAlignment(Qt::AlignRight); + gl->addWidget(proxyuser=new QLineEdit,lctr,1); + gl->addWidget(lab=new QLabel(tr("Proxy Password:")),++lctr,0); + lab->setAlignment(Qt::AlignRight); + gl->addWidget(proxypass=new QLineEdit,lctr,1); + proxypass->setEchoMode(QLineEdit::Password); + connect(useproxy,SIGNAL(toggled(bool)),proxyuser,SLOT(setEnabled(bool))); + connect(useproxy,SIGNAL(toggled(bool)),proxypass,SLOT(setEnabled(bool))); + gl->setRowStretch(++lctr,10); + + tab->addTab(w=new QWidget,tr("Authentication")); + w->setLayout(gl=new QGridLayout); + lctr=0; + gl->addWidget(lab=new QLabel(tr("Hostname:")),++lctr,0); + lab->setAlignment(Qt::AlignRight); + gl->addWidget(hostname=new QLineEdit,lctr,1); + gl->addWidget(lab=new QLabel(tr("Hostkey:")),++lctr,0); + lab->setAlignment(Qt::AlignRight); + gl->addWidget(hostkey=new QLineEdit,lctr,1); + gl->addWidget(lab=new QLabel(tr("Default Username:")),++lctr,0); + lab->setAlignment(Qt::AlignRight); + gl->addWidget(username=new QLineEdit,lctr,1); + gl->addWidget(lab=new QLabel(tr("Hint for Username:")),++lctr,0); + lab->setAlignment(Qt::AlignRight); + gl->addWidget(userhint=new QLineEdit,lctr,1); + gl->setRowStretch(++lctr,10); + gl->addLayout(hl=new QHBoxLayout,++lctr,0,1,2); + + tab->addTab(w=new QWidget,tr("SSL Exceptions")); + w->setLayout(vl=new QVBoxLayout); + vl->addWidget(new QLabel(tr("List of non-fatal SSL exceptions:")),0); + vl->addWidget(ssltable=new QTableView,10); + ssltable->setModel(sslmodel=new QStandardItemModel(this)); + ssltable->setEditTriggers(QListView::NoEditTriggers); + vl->addSpacing(10); + vl->addLayout(hl=new QHBoxLayout,0); + hl->addStretch(10); + QPushButton*pb; + hl->addWidget(pb=new QPushButton(tr("Clear"))); + connect(pb,SIGNAL(clicked()),this,SLOT(clearSslExceptions())); + hl->addWidget(pb=new QPushButton(tr("Probe Server"))); + connect(pb,SIGNAL(clicked()),this,SLOT(serverProbe())); + + tab->addTab(w=new QWidget,tr("Scripting")); + w->setLayout(gl=new QGridLayout); + gl->setColumnStretch(4,1); + lctr=0; + gl->addWidget(lab=new QLabel(tr("You can set scripting preferences here. You have the following options:\nAllow: if active scripts from this source are allowed to run.\nPriority: locations with the lowest value are searched first, when a script it found the other locations are ignored.")),lctr,0,1,5); + lab->setWordWrap(true); + gl->addWidget(lab=new QLabel(tr("Server side scripts:")),++lctr,0); + lab->setAlignment(Qt::AlignRight); + gl->addWidget(asrscript=new QCheckBox(tr("allow")),lctr,1); + gl->addWidget(new QLabel(tr("Prio:")),lctr,2); + gl->addWidget(psrscript=new QSpinBox,lctr,3); + psrscript->setRange(0,100); + gl->addWidget(lab=new QLabel(tr("Built in scripts:")),++lctr,0); + lab->setAlignment(Qt::AlignRight); + gl->addWidget(abiscript=new QCheckBox(tr("allow")),lctr,1); + gl->addWidget(new QLabel(tr("Prio:")),lctr,2); + gl->addWidget(pbiscript=new QSpinBox,lctr,3); + pbiscript->setRange(0,100); + gl->addWidget(lab=new QLabel(tr("User local scripts:")),++lctr,0); + lab->setAlignment(Qt::AlignRight); + gl->addWidget(ausscript=new QCheckBox(tr("allow")),lctr,1); + gl->addWidget(new QLabel(tr("Prio:")),lctr,2); + gl->addWidget(pusscript=new QSpinBox,lctr,3); + pusscript->setRange(0,100); + gl->addWidget(lab=new QLabel(tr("User script path:")),++lctr,0); + lab->setAlignment(Qt::AlignRight); + gl->addWidget(usrscript=new QLineEdit,lctr,1,1,4); + gl->setRowStretch(++lctr,1); + + setSizeGripEnabled(true); + + initProfiles(); + loadProfile(); +} + +MConfigDialog::~MConfigDialog() +{ + saveProfile(); +} + +void MConfigDialog::initProfiles(QString selIdx) +{ + oldrow=-1; + QSettings set; + int defpro=set.value("defaultprofile",0).toInt(); + set.beginGroup("profiles"); + QStringList prf=set.childGroups(); + profilemodel->clear(); + if(profilemodel->columnCount()<1) + profilemodel->insertColumn(0); + profilemodel->insertRows(0,prf.size()); + int newrow=0; + for(int i=0;iindex(i,0); + profilemodel->setData(idx,set.value(prf[i]+"/name").toString()); + profilemodel->setData(idx,prf[i],Qt::UserRole); + if(i==defpro){ + QFont f=profiles->font(); + f.setBold(true); + profilemodel->setData(idx,f,Qt::FontRole); + } + if(prf[i]==selIdx)newrow=i; + } + profiles->setCurrentIndex(profilemodel->index(newrow,0)); +} + +void MConfigDialog::loadProfile() +{ + //save old + saveProfile(); + if(sslexcept)delete sslexcept; + sslexcept=0; + //get new + QModelIndex idx=profiles->currentIndex(); + if(!idx.isValid())return; + oldrow=idx.row(); + QString key=profilemodel->data(idx,Qt::UserRole).toString(); + const QString&dataDir=MApplication::dataDir(); + QSettings set; + set.beginGroup("profiles/"+key); + hostname->setText(set.value("hostname").toString()); + hostkey->setText(set.value("hostkey").toString()); + serverurl->setText(set.value("serverurl","my.host.com/path/machine.php").toString()); + useproxy->setChecked(set.value("useproxy",false).toBool()); + proxyname->setText(set.value("proxyname","proxy").toString()); + proxyport->setValue(set.value("proxyport",74).toInt()); + proxyuser->setText(set.value("proxyuser").toString()); + proxypass->setText(set.value("proxypass").toString()); + proxyname->setEnabled(useproxy->isChecked()); + proxyport->setEnabled(useproxy->isChecked()); + proxyuser->setEnabled(useproxy->isChecked()); + proxypass->setEnabled(useproxy->isChecked()); + username->setText(set.value("username").toString()); + userhint->setText(set.value("usernamehint").toString()); + sslexcept=new MSslExceptions(dataDir+"/profile."+key+"/sslexceptions.xml"); + sslFillModel(); + abiscript->setChecked(set.value("script/allowbuiltin",true).toBool()); + ausscript->setChecked(set.value("script/allowuser",false).toBool()); + asrscript->setChecked(set.value("script/allowserver",false).toBool()); + pbiscript->setValue(set.value("script/priobuiltin",10).toInt()); + pusscript->setValue(set.value("script/priouser",0).toInt()); + psrscript->setValue(set.value("script/prioserver",20).toInt()); + usrscript->setText(set.value("script/userpath",dataDir+"/userscripts").toString()); +} + +void MConfigDialog::saveProfile() +{ + if(oldrow<0 || oldrow>=profilemodel->rowCount())return; + QString key=profilemodel->data(profilemodel->index(oldrow,0),Qt::UserRole).toString(); + QSettings set; + set.beginGroup("profiles/"+key); + set.setValue("hostname",hostname->text()); + set.setValue("hostkey",hostkey->text()); + set.setValue("serverurl",serverurl->text()); + set.setValue("useproxy",useproxy->isChecked()); + set.setValue("proxyname",proxyname->text()); + set.setValue("proxyport",proxyport->value()); + set.setValue("proxyuser",proxyuser->text()); + set.setValue("proxypass",proxypass->text()); + set.setValue("username",username->text()); + set.setValue("usernamehint",userhint->text()); + QDir(MApplication::dataDir()).mkdir("profile."+key); + if(sslexcept)sslexcept->savesslexcept(); + set.setValue("script/allowbuiltin",abiscript->isChecked()); + set.setValue("script/allowuser",ausscript->isChecked()); + set.setValue("script/allowserver",asrscript->isChecked()); + set.setValue("script/priobuiltin",pbiscript->value()); + set.setValue("script/priouser",pusscript->value()); + set.setValue("script/prioserver",psrscript->value()); + set.setValue("script/userpath",usrscript->text()); +} + +void MConfigDialog::newProfile() +{ + saveProfile(); + //scan for existing ones... + QSettings set; + set.beginGroup("profiles"); + QStringList prf=set.childGroups(); + QStringList prn; + for(int i=0;icurrentIndex(); + if(!idx.isValid())return; + QString key=profilemodel->data(idx,Qt::UserRole).toString(); + QSettings set; + set.beginGroup("profiles"); + set.remove(key); + set.sync(); + oldrow=-1; + initProfiles(); + loadProfile(); +} + +void MConfigDialog::renameProfile() +{ + //get old name + QModelIndex idx=profiles->currentIndex(); + if(!idx.isValid())return; + QString key=profilemodel->data(idx,Qt::UserRole).toString(); + QString pname=profilemodel->data(idx).toString(); + //query + bool ok; + QString npname=QInputDialog::getText(this,tr("Rename Profile"),tr("Please enter a profile name. It must be non-empty and must not be used yet:"),QLineEdit::Normal,pname,&ok); + if(!ok)return; + //check + if(npname==pname)return; + for(int i=0;irowCount();i++){ + QString pn=profilemodel->data(profilemodel->index(i,0)).toString(); + if(pn==npname){ + QMessageBox::warning(this,tr("Warning"),tr("This profile name is already in use.")); + return; + } + } + //set + QSettings().setValue("profiles/"+key+"/name",npname); + profilemodel->setData(idx,npname); +} + +void MConfigDialog::cloneProfile() +{ + saveProfile(); + //get current + QModelIndex idx=profiles->currentIndex(); + if(!idx.isValid())return; + QString key=profilemodel->data(idx,Qt::UserRole).toString(); + //scan for existing ones... + QSettings set; + set.beginGroup("profiles"); + QStringList prf=set.childGroups(); + QStringList prn; + for(int i=0;icurrentIndex(); + if(!idx.isValid())return; + QString key=profilemodel->data(idx,Qt::UserRole).toString(); + QSettings().setValue("defaultprofile",key); + initProfiles(key); + loadProfile(); +} + + +void MConfigDialog::changeLang() +{ + MApplication::choseLanguage(); +} + +void MConfigDialog::exportKey() +{ + QSettings st; + QModelIndex idx=profiles->currentIndex(); + if(!idx.isValid())return; + QString pkey=profilemodel->data(idx,Qt::UserRole).toString(); + st.beginGroup("profiles/"+pkey); + QString host=hostname->text().trimmed(); + QString key=hostkey->text().trimmed(); + saveKey(host,key); +} + +void MConfigDialog::generateKey() +{ + //ask nicely + if(hostkey->text()!="") + if(QMessageBox::question(this,tr("Generate Hostkey"), tr("Do you really want to generate a new host key for this profile? This may disable all accounts from this host."), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) + return; + //actually create new key + QString name; + MKeyGen mkg(this); + QString k=mkg.getKey(); + if(k=="") + if(mkg.exec()!=QDialog::Accepted) + return; + hostkey->setText(mkg.getKey()); +} + +void MConfigDialog::saveKey(QString host,QString key) +{ + QStringList fn; + QFileDialog fdlg(this,tr("Export Key to File"),QString(),"Magic Smoke Host Key (*.mshk)"); + fdlg.setDefaultSuffix("mshk"); + fdlg.setAcceptMode(QFileDialog::AcceptSave); + fdlg.setFileMode(QFileDialog::AnyFile); + fdlg.setDirectory(currentDir()); + if(!fdlg.exec())return; + fn=fdlg.selectedFiles(); + if(fn.size()!=1)return; + setCurrentDir(fn[0]); + QFile fd(fn[0]); + if(!fd.open(QIODevice::WriteOnly|QIODevice::Truncate)){ + QMessageBox::warning(this,tr("Warning"),tr("Unable to open file %1 for writing: %2").arg(fn[0]).arg(fd.errorString())); + return; + } + QString chk=QCryptographicHash::hash(key.toLatin1(),QCryptographicHash::Md5).toHex(); + QString out="MagicSmokeHostKey\n"+host+"\n"+key+"\n"+chk; + fd.write(out.toLatin1()); + fd.close(); +} + +void MConfigDialog::importKey() +{ + QModelIndex idx=profiles->currentIndex(); + if(!idx.isValid())return; + QString profkey=profilemodel->data(idx,Qt::UserRole).toString(); + + if(QMessageBox::warning(this,tr("Warning"),tr("Importing a key overwrites the host key that is currently used by this profile. This may disable your accounts. Do you still want to continue?"),QMessageBox::Yes|QMessageBox::Abort,QMessageBox::Abort)!=QMessageBox::Yes) + return; + QStringList fn; + QFileDialog fdlg(this,tr("Import Key from File"),QString(),"Magic Smoke Host Key (*.mshk)"); + fdlg.setDefaultSuffix("mshk"); + fdlg.setAcceptMode(QFileDialog::AcceptOpen); + fdlg.setFileMode(QFileDialog::ExistingFile); + fdlg.setDirectory(currentDir()); + if(!fdlg.exec())return; + fn=fdlg.selectedFiles(); + if(fn.size()!=1)return; + setCurrentDir(fn[0]); + QFile fd(fn[0]); + if(!fd.open(QIODevice::ReadOnly)){ + QMessageBox::warning(this,tr("Warning"),tr("Unable to open file %1 for reading: %2").arg(fn[0]).arg(fd.errorString())); + return; + } + //read content (max: 10k to limit potential damage) + QStringList fc=QString::fromLatin1(fd.read(10240)).split("\n",QString::SkipEmptyParts); + fd.close(); + //check content + if(fc.size()<3){ + QMessageBox::warning(this,tr("Warning"),tr("This is not a host key file.")); + return; + } + if(fc[0].trimmed()!="MagicSmokeHostKey"){ + QMessageBox::warning(this,tr("Warning"),tr("This is not a host key file.")); + return; + } + QString hname=fc[1].trimmed(); + if(!QRegExp("[A-Za-z][A-Za-z0-9_]*").exactMatch(hname)){ + QMessageBox::warning(this,tr("Warning"),tr("This host key file does not contain a valid host name.")); + return; + } + QString key=fc[2].trimmed(); + if(!QRegExp("[0-9a-fA-F]+").exactMatch(key) || key.size()<40){ + QMessageBox::warning(this,tr("Warning"),tr("This host key file does not contain a valid key.")); + return; + } + QString chk=QCryptographicHash::hash(key.toLatin1(),QCryptographicHash::Md5).toHex(); + if(chk!=fc[3].trimmed()){ + QMessageBox::warning(this,tr("Warning"),tr("The key check sum did not match. Please get a clean copy of the host key file.")); + return; + } + //save + hostname->setText(hname); + hostkey->setText(key); + QSettings set; + set.beginGroup("profiles/"+profkey); + set.setValue("hostkey",key); + set.setValue("hostname",hname); +} + +void MConfigDialog::openOfficeCfg() +{ + MOfficeConfig c(this); + c.exec(); +} + +void MConfigDialog::setDefaultFont() +{ + QStringList fonts=QFontDatabase().families(); + QString df=QInputDialog::getItem(this,tr("Chose Default Font"),tr("Please chose a default font:"),fonts,fonts.indexOf(QSettings().value("defaultfont","").toString()),false); + if(df.isEmpty())return; + QSettings().setValue("defaultfont",df); +} + +void MConfigDialog::setAppStyle() +{ + MAppStyleDialog d(this); + d.exec(); +} + +void MConfigDialog::serverProbe() +{ + //sanity check + if(!sslexcept)return; + sslexcept->clearRecorded(); + //set up mini-environment + QEventLoop loop; + QNetworkAccessManager man; + connect(&man,SIGNAL(finished(QNetworkReply*)),&loop,SLOT(quit())); + QTimer::singleShot(30000,&loop,SLOT(quit())); + connect(&man,SIGNAL(sslErrors(QNetworkReply*,const QList&)), this,SLOT(sslErrors(QNetworkReply*,QList))); + if(useproxy->isChecked()) + man.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy,proxyname->text(),proxyport->value(),proxyuser->text(),proxypass->text())); + //query server + QNetworkRequest rq(QUrl("https://"+serverurl->text())); + QNetworkReply *rp=man.get(rq); + //wait for result + setEnabled(false); + loop.exec(); + setEnabled(true); + //probe result + if(rp->error()==QNetworkReply::NoError){ + QMessageBox::information(this,tr("Server Probe"),tr("The request finished without errors.")); + }else{ + QMessageBox::warning(this,tr("Server Probe"),tr("The request finished with an error: %1").arg(rp->errorString())); + } + delete rp; + //save + sslexcept->savesslexcept(); +} + +void MConfigDialog::sslErrors(QNetworkReply*rp,QListerrs) +{ + if(!sslexcept)return; + //check/record/clear + if(sslexcept->checksslexcept(errs)){ + rp->ignoreSslErrors(); + return; + } + //convert to string + QString err=tr("SSL Errors encountered:\n"); + for(int i=0;i= 0x50000 + .value(0) +#endif + ) + .arg(QString::fromLatin1(c.digest(QCryptographicHash::Sha1).toHex())) + .arg(errs[i].errorString()); + } + err+=tr("Accept connection anyway?"); + if(QMessageBox::warning(this,tr("SSL Warning"),err,QMessageBox::Yes|QMessageBox::No) == QMessageBox::Yes){ + rp->ignoreSslErrors(); + sslexcept->acceptRecorded(); + } + sslFillModel(); +} + +void MConfigDialog::clearSslExceptions() +{ + if(sslexcept)sslexcept->clear(); + sslmodel->clear(); +} + +void MConfigDialog::sslFillModel() +{ + sslmodel->clear(); + if(!sslexcept)return; + sslmodel->insertColumns(0,3); + sslmodel->setHorizontalHeaderLabels(QStringList()< >lst=sslexcept->nonFatalExceptions(); + sslmodel->insertRows(0,lst.size()); + for(int i=0;isetData(sslmodel->index(i,0),lst[i].first.subjectInfo(QSslCertificate::CommonName)); + sslmodel->setData(sslmodel->index(i,1),QString::fromLatin1(lst[i].first.digest(QCryptographicHash::Sha1).toHex())); + sslmodel->setData(sslmodel->index(i,2),QSslError((QSslError::SslError)lst[i].second).errorString()); + } +} + +MAppStyleDialog::MAppStyleDialog(QWidget*par) + :QDialog(par) +{ + setWindowTitle(tr("Application Style")); + QGridLayout *gl; + setLayout(gl=new QGridLayout); + gl->addWidget(new QLabel(tr("GUI Style:")),0,0); + gl->addWidget(style=new QComboBox,0,1,1,2); + style->addItem(tr("System Default")); + style->setEditable(false); + QStringList k=QStyleFactory::keys(); + QString cs=QSettings().value("appstyle").toString(); + style->addItems(k); + if(k.contains(cs)) + style->setCurrentIndex(k.indexOf(cs)+1); + + gl->addWidget(new QLabel(tr("Stylesheet:")),1,0); + gl->addWidget(css=new QLineEdit,1,1); + css->setText(QSettings().value("appstylesheet").toString()); + QPushButton*p; + gl->addWidget(p=new QPushButton("..."),1,2); + connect(p,SIGNAL(clicked()),this,SLOT(selectCSS())); + + gl->setRowMinimumHeight(2,15); + QHBoxLayout*hl; + gl->addLayout(hl=new QHBoxLayout,3,0,1,3); + hl->addStretch(10); + hl->addWidget(p=new QPushButton(tr("Ok"))); + connect(p,SIGNAL(clicked()),this,SLOT(accept()),Qt::QueuedConnection); + connect(p,SIGNAL(clicked()),this,SLOT(save())); + hl->addWidget(p=new QPushButton(tr("Cancel"))); + connect(p,SIGNAL(clicked()),this,SLOT(reject())); +} + +void MAppStyleDialog::selectCSS() +{ + QString s=QFileDialog::getOpenFileName(this,tr("Select Stylesheet"),currentDir()); + if(s!=""){ + css->setText(s); + setCurrentDir(s); + } +} + +void MAppStyleDialog::save() +{ + if(style->currentIndex()==0) + QSettings().remove("appstyle"); + else + QSettings().setValue("appstyle",style->currentText()); + QSettings().setValue("appstylesheet",css->text()); +} + diff --git a/commonlib/configdialog.h b/commonlib/configdialog.h new file mode 100644 index 0000000..5a75635 --- /dev/null +++ b/commonlib/configdialog.h @@ -0,0 +1,97 @@ +// +// C++ Interface: mainwindow +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_CONFIGDIALOG_H +#define MAGICSMOKE_CONFIGDIALOG_H + +#include +#include +#include + +class QCheckBox; +class QLineEdit; +class QListView; +class QNetworkReply; +class QSpinBox; +class QStandardItemModel; +class QTableView; + +class MSslExceptions; + +#include "commonexport.h" + +/**login and profile configuration window*/ +class MAGICSMOKE_COMMON_EXPORT MConfigDialog:public QDialog +{ + Q_OBJECT + public: + MConfigDialog(); + ~MConfigDialog(); + + private: + QCheckBox*useproxy,*abiscript,*ausscript,*asrscript; + QLineEdit*hostname,*hostkey,*serverurl,*proxyname,*username, + *userhint,*proxyuser,*proxypass,*usrscript; + QSpinBox*proxyport,*pbiscript,*pusscript,*psrscript; + QListView*profiles; + QStandardItemModel*profilemodel,*sslmodel; + QTableView*ssltable; + + MSslExceptions*sslexcept; + + int oldrow; + + //helper for exportKey and generateKey + void saveKey(QString hostname,QString hostkey); + + private slots: + //handling of login/profile screen + void initProfiles(QString idx=QString()); + void loadProfile(); + void saveProfile(); + void newProfile(); + void deleteProfile(); + void renameProfile(); + void cloneProfile(); + void defaultProfile(); + //settings + void changeLang(); + void exportKey(); + void importKey(); + void generateKey(); + void openOfficeCfg(); + void setDefaultFont(); + void setAppStyle(); + //ssl server probe + void serverProbe(); + void sslErrors(QNetworkReply*,QList); + void clearSslExceptions(); + void sslFillModel(); +}; + +class QComboBox; +class QLineEdit; + +class MAGICSMOKE_COMMON_EXPORT MAppStyleDialog:public QDialog +{ + Q_OBJECT + public: + MAppStyleDialog(QWidget*); + private slots: + void selectCSS(); + void save(); + private: + QComboBox*style; + QLineEdit*css; +}; + +#endif diff --git a/commonlib/crypto/crypto.pri b/commonlib/crypto/crypto.pri new file mode 100644 index 0000000..2958656 --- /dev/null +++ b/commonlib/crypto/crypto.pri @@ -0,0 +1,9 @@ +HEADERS += \ + crypto/keygen.h \ + crypto/hmac.h + +SOURCES += \ + crypto/keygen.cpp \ + crypto/hmac.cpp + +INCLUDEPATH += ./crypto \ No newline at end of file diff --git a/commonlib/crypto/hmac.cpp b/commonlib/crypto/hmac.cpp new file mode 100644 index 0000000..972b29a --- /dev/null +++ b/commonlib/crypto/hmac.cpp @@ -0,0 +1,102 @@ +// +// C++ Implementation: hmac +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "hmac.h" +#include + +SMHmac::SMHmac(QCryptographicHash::Algorithm algo,const QByteArray&key) + :subhashin(algo),subhashout(algo),state(Collecting) +{ + //calculate key schedules + QByteArray k2=key; + int hlen=blockWidth(algo); + if(k2.size()>hlen){ + //hash the key if it is too long + k2=QCryptographicHash::hash(k2,algo); + }else + if(k2.size(), (C) 2007-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef SMOKE_HMAC_H +#define SMOKE_HMAC_H + +#include + +#include "commonexport.h" + +/**Calculate a cryptographic HMAC (used by authentication algorithm)*/ +class MAGICSMOKE_COMMON_EXPORT SMHmac +{ + public: + /**constructs an object that calculates HMACs*/ + SMHmac(QCryptographicHash::Algorithm algo,const QByteArray&key); + /**adds length bytes of data to the hash-stream*/ + void addData(const char * data, int length ); + /**adds data to the hash-stream*/ + void addData(const QByteArray & data ); + /**reset the hash to the state immediately after construction*/ + void reset(); + /**finalize the hash and return the result*/ + QByteArray result(); + + /**returns the length of the results of given algorithm in bytes; this should have been implemented by QCryptographicHash! performs a test calculation if the algo is unknown*/ + static int resultWidth(QCryptographicHash::Algorithm); + /**returns the length of the blocks used internally in the given algorithm in bytes; this should have been implemented by QCryptographicHash! returns -1 if in doubt*/ + static int blockWidth(QCryptographicHash::Algorithm); + /**complete HMAC calculation in a can*/ + static QByteArray hmac(const QByteArray&data,const QByteArray&key,QCryptographicHash::Algorithm method); + private: + //the two key schedules + QByteArray keyA,keyB; + //remember where we are + enum State {Collecting,Finished}; + mutable State state; + //inner hash function + QCryptographicHash subhashin,subhashout; +}; + + +#endif diff --git a/commonlib/crypto/keygen.cpp b/commonlib/crypto/keygen.cpp new file mode 100644 index 0000000..408974b --- /dev/null +++ b/commonlib/crypto/keygen.cpp @@ -0,0 +1,235 @@ +// +// C++ Implementation: keygen +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "keygen.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hmac.h" + +//enable linux to read /dev/random +#ifdef __linux__ +#include +#include +#endif + +//amount of random bits needed: +#define RANDNEED 160 + +static QPointerefilter; + +MKeyGen::MKeyGen(QWidget*parentw) + :QDialog(parentw) +{ + setWindowTitle(tr("Magic Smoke Key Generator")); + + //pre-init random buffer + randstat=-1; + connect(efilter,SIGNAL(moreBits()),this,SLOT(updateProps())); + //make sure all mouse events arrive + setMouseTracking(true); + QVBoxLayout*vl; + setLayout(vl=new QVBoxLayout); + QLabel*lab; + //main explanation + vl->addWidget(lab=new QLabel(tr("

Key Generation

\nI am currently collecting random bits in order to generate a host key for this installation. Please use mouse and keyboard to generate more random. Alternatively you can load a key from an external medium.

\nAt least %1 Bits of random are required.").arg(RANDNEED)),0); + lab->setWordWrap(true); + lab->setMouseTracking(true); + //buffer display + int e=efilter->entropy(); + vl->addWidget(randlab=new QLabel(tr("Current random buffer: %n Bits","",e)),0); + randlab->setMouseTracking(true); + randlab->setFrameShape(QFrame::Box); + randlab->setAutoFillBackground(true); + + vl->addStretch(1); + + //buttons + QHBoxLayout*hl; + vl->addLayout(hl=new QHBoxLayout,0); + hl->addStretch(1); + hl->addWidget(okbtn=new QPushButton(tr("&OK")),0); + connect(okbtn,SIGNAL(clicked()),this,SLOT(accept())); + hl->addWidget(ccbtn=new QPushButton(tr("&Cancel")),0); + connect(ccbtn,SIGNAL(clicked()),this,SLOT(reject())); + + //make sure widgets look right + updateProps(); + + //make window really big + showMaximized(); +} + +MKeyGen::~MKeyGen() +{ +} + +void MKeyGen::updateProps() +{ + int e=efilter->entropy(); + randlab->setText(tr("Current random buffer: %n Bits","",e)); + if(efilter->entropy()palette(); + pal.setColor(QPalette::Window,QColor("#ff8080")); + randlab->setPalette(pal); + //set button + okbtn->setEnabled(false); + }else{ + //check whether we need to set it + if(randstat==1)return; + randstat=1; + //set label color + QPalette pal=randlab->palette(); + pal.setColor(QPalette::Window,QColor("#80ff80")); + randlab->setPalette(pal); + //set button + okbtn->setEnabled(true); + } +} + +QString MKeyGen::getKey(int len) +{ + if(efilter->entropy()getRandom(len).toHex(); +} + + +EFilter::EFilter() +{ + efilter=this; + randctr=0; + //preload seed + QSettings set; + randbuf.append(set.value("randomseed").toByteArray()); + randent=randbuf.size(); + if(randent>=RANDNEED)set.setValue("randomseed",getRandom(RANDNEED)); + //if Linux: try to pre-load some random +#ifdef __linux__ + int fd=::open("/dev/random",O_RDONLY|O_NONBLOCK); + if(fd>=0){ + char buf[RANDNEED/8]; + int rd=::read(fd,buf,sizeof(buf)); + if(rd>0){ + randbuf.append(QByteArray(buf,rd)); + randent+=rd*8; + } + ::close(fd); + } +#endif +} + +EFilter::~EFilter() +{ + QSettings set; + set.setValue("randomseed",getRandom(RANDNEED)); +} + +EFilter* EFilter::instance() +{ + return efilter; +} + +QByteArray EFilter::getRandom(int bytes) +{ + QByteArray ret; + while(ret.size()type()){ + case QEvent::KeyPress:case QEvent::KeyRelease: + { + QKeyEvent*ke=(QKeyEvent*)e; + addBit(ke->key()+(int)ke->modifiers()); + break; + } + case QEvent::MouseButtonPress:case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + { + QMouseEvent*me=(QMouseEvent*)e; + addBit((int)me->buttons()+me->x()+me->y()); + break; + } + default: + //ignore + break; + } + return false; +} + +void EFilter::addBit(int b) +{ + //add bit to buffer + randbuf.append((b>>24)&0xff); + randbuf.append((b>>16)&0xff); + randbuf.append((b>>8)&0xff); + randbuf.append(b&0xff); + randent++; + //add time info as another bit + QTime ct=QTime::currentTime(); + if(ct.msec()!=0){ //don't use it if platform has no msecs + int t=ct.msec()+ct.second()+ct.minute(); + randbuf.append((t>>24)&0xff); + randbuf.append((t>>16)&0xff); + randbuf.append((t>>8)&0xff); + randbuf.append(t&0xff); + randent++; + } + //pack buffer if necessary (>10kB) + if(randbuf.size()>=10240){ + randbuf=getRandom(80); + if(randent>320)randent=320; + } + //update display + emit moreBits(); +} + +QByteArray getRandom(int num) +{ + if(efilter.isNull())return QByteArray(); + return efilter->getRandom(num); +} + +int getEntropy() +{ + if(efilter.isNull())return 0; + return efilter->entropy(); +} diff --git a/commonlib/crypto/keygen.h b/commonlib/crypto/keygen.h new file mode 100644 index 0000000..92df7eb --- /dev/null +++ b/commonlib/crypto/keygen.h @@ -0,0 +1,68 @@ +// +// C++ Interface: keygen +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_KEYGEN_H +#define MAGICSMOKE_KEYGEN_H + +#include +#include + +class QLabel; +class QPushButton; + +#include "commonexport.h" + +class MAGICSMOKE_COMMON_EXPORT MKeyGen:public QDialog +{ + Q_OBJECT + public: + MKeyGen(QWidget*parent=0); + ~MKeyGen(); + + QString getKey(int len=40); + + private: + QLabel*randlab; + int randstat; + + QPushButton *okbtn,*ccbtn; + + private slots: + void updateProps(); +}; + +class MAGICSMOKE_COMMON_EXPORT EFilter:public QObject +{ + Q_OBJECT + public: + EFilter(); + ~EFilter(); + + static EFilter*instance(); + + int entropy(); + QByteArray getRandom(int); + signals: + void moreBits(); + protected: + bool eventFilter(QObject*,QEvent*); + private: + QByteArray randbuf,randlast; + int randent,randctr; + void addBit(int); +}; + +//shortcut: +MAGICSMOKE_COMMON_EXPORT QByteArray getRandom(int); +MAGICSMOKE_COMMON_EXPORT int getEntropy(); + +#endif diff --git a/commonlib/mapplication.cpp b/commonlib/mapplication.cpp new file mode 100644 index 0000000..e82efc5 --- /dev/null +++ b/commonlib/mapplication.cpp @@ -0,0 +1,466 @@ +// +// C++ Implementation: main +// +// Description: Main Program +// +// +// Author: Konrad Rosenbaum , (C) 2007-2016 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "configdialog.h" +#include "debug.h" +#include "barcode-plugin.h" +#include "hmac.h" +#include "keygen.h" +#include "mapplication.h" +// #include "login.h" +#include "msinterface.h" +#include +#include "misc.h" +#include +#include "boxwrapper.h" + +QString MApplication::choseLanguage(bool warn) +{ + QString lang=QSettings().value("lang","--").toString(); + if(lang=="--"){ + lang=QLocale::system().name(); + } + int cur=0; + QStringList langs; + langs<<"C - default"; + QStringList files=QDir(QApplication::applicationDirPath()).entryList(QStringList()<<"smoke_*.qm", QDir::Files, QDir::Name); + for(int i=0;isetMinimumDuration(0); + pd->show(); + } + ~MProgressWrapperGui() + { + if(pd)pd->deleteLater(); + pd=0; + } + virtual void setLabelText(QString l) + { + pd->setLabelText(l); + } + virtual void setCancelButtonText(QString t) + { + pd->setCancelButtonText(t); + } + virtual void cancel() + { + pd->cancel(); + } + virtual void setRange(int mi,int ma) + { + pd->setRange(mi,ma); + } + virtual void setValue(int v) + { + pd->setValue(v); + } +}; + +#ifndef HOMEPAGE_BASEURL +#define HOMEPAGE_BASEURL "http://smoke.silmor.de" +#endif + +void MApplication::aboutMS() +{ + QMessageBox mb; + mb.setIconPixmap(QPixmap(":/icon.png")); + mb.setWindowTitle(tr("About MagicSmoke")); + MSInterface*ifc=MSInterface::instance(); + mb.setText(tr( "

MagicSmoke v. %1

" + "© Konrad Rosenbaum, 2007-2013
" + "© Peter Keller, 2007-2008
" + "protected under the GNU GPL v.3 or at your option any newer

" + "See also the MagicSmoke Homepage.

" + "This version was compiled from repository '%3' revision '%4'.

" + "The current application data base path is '%5'.") + .arg(MSInterface::staticVersionInfo(WOb::VersionHR)) //%1 + .arg(HOMEPAGE_BASEURL) //%2 + .arg(MSInterface::staticVersionInfo(WOb::VersionRootURL)) //%3 + .arg(MSInterface::staticVersionInfo(WOb::VersionNumber)) //%4 + .arg(ifc?ifc->dataDir(): dataDir()) + ); + mb.setStandardButtons(QMessageBox::Ok); + mb.exec(); +} + +void MApplication::versionDlg() +{ + QMessageBox mb; + mb.setIconPixmap(QPixmap(":/icon.png")); + mb.setWindowTitle(tr("MagicSmoke Version Information")); + TimeZoneLib::TZFile tzf=TimeStamp::defaultZoneFile(); + auto unknown=[](const QString&s)->QString{if(s.isEmpty())return "(unknown)";else return "'"+s+"'";}; + mb.setText(tr( "

MagicSmoke Version %3

" + "" + "" + "" + "" + "" + "" + "
Repository:%1
Revision:%2
Modification State:%4
Commit Time:%5
Committer:%6

\n" + "

Libraries

\n" + "" + "" + "" + "" + "" + "" + "
WOC:%7
%8
PACK Library:%9
%10
Qt:%11
ELAM:%12
Time Zone Default:%13 in directory %14
version %15
Time Zone Built-In:%16 (library: %17)
" + ) + .arg(htmlize(MSInterface::staticVersionInfo(WOb::VersionRootURL))) // %1 + .arg(htmlize(MSInterface::staticVersionInfo(WOb::VersionNumber))) //%2 + .arg(htmlize(MSInterface::staticVersionInfo(WOb::VersionHR))) //%3 + .arg(MSInterface::staticVersionInfo(WOb::VersionLocallyModified)) //%4 + .arg(htmlize(MSInterface::staticVersionInfo(WOb::VersionTime))) //%5 + .arg(htmlize(MSInterface::staticVersionInfo(WOb::VersionAuthor))) //&6 + .arg(htmlize(MSInterface::staticWocVersionInfo(WOb::VersionRootURL))) //%7 + .arg(htmlize(MSInterface::staticWocVersionInfo(WOb::VersionNumber))) + .arg(htmlize(WInterface::staticLibraryVersionInfo(WOb::VersionRootURL))) //%9 + .arg(htmlize(WInterface::staticLibraryVersionInfo(WOb::VersionNumber))) + .arg(htmlize(QT_VERSION_STR)) //%11 + .arg(htmlize(ELAM::versionInfo())) //%12 + .arg(unknown(tzf.name())) //%13 + .arg(unknown(tzf.dirName())) + .arg(unknown(tzf.version())) + .arg(TimeZoneLib::TZFile::builtinVersion()) //%16 + .arg(TimeZoneLib::TZFile::libraryVersion()) //%17 + ); + mb.setStandardButtons(QMessageBox::Ok); + mb.exec(); +} + + +struct HelpUrl { + enum Type {None, Item, Separator} type=None; + QString label,url; + HelpUrl(Type t,QString l,QString u=QString()):type(t),label(l),url(u){} +}; +static QList helpUrl; + +static void loadHelpUrlFile(const QString&fname) +{ + QFile fd(fname); + QList urls; + //try to open + if(fd.open(QIODevice::ReadOnly)){ + //read config + QDomDocument doc; + doc.setContent(&fd); + QDomNodeList nl=doc.documentElement().childNodes(); + for(int i=0;i0 && urls.size()>0)helpUrl.append(HelpUrl(HelpUrl::Separator,"")); + helpUrl.append(urls); +} + +void MApplication::initHelpUrl() +{ + //check file exists, if not initialize it + loadHelpUrlFile(dataDir()+"/helpMenu.xml"); + loadHelpUrlFile(applicationDirPath()+"/helpMenu.xml"); + //fallback + if(helpUrl.size()<1) + helpUrl<addSeparator()->setText(helpUrl[i].label); + }else{ + QAction*a=m->addAction(helpUrl[i].label,map,SLOT(map())); + map->setMapping(a,i); + } + } + m->addSeparator(); + m->addAction("About &MagicSmoke",qApp,SLOT(aboutMS())); + m->addAction("About &Qt",qApp,SLOT(aboutQt())); + m->addAction("&Version Info",qApp,SLOT(versionDlg())); + return m; +} + +static inline QUrl convHelpUrl(QUrl s) +{ + if(s.scheme()=="default"){ + static const QString ad=QApplication::applicationDirPath()+"/doc/"; + if(QFile(ad+"index.html").exists()) + return QUrl::fromLocalFile(ad+s.path()); + else + //TODO: allow different versions? + return HOMEPAGE_BASEURL "/doc/" + s.path(); + } + else return s; +} + + + +void MApplication::help() +{ + qDebug()<<"Opening default help..."; + QDesktopServices::openUrl(convHelpUrl(QUrl("default:/index.html"))); +} + +void MApplication::help(int idx) +{ + if(idx<0 || idx>=helpUrl.size()){ + help(); + return; + } + QUrl u=convHelpUrl(helpUrl[idx].url); + qDebug()<<"Opening help:"<MProgressWrapper*{ + return new MProgressWrapperGui(label,button); + }); + + //check parameters +// qDebug()<<"arguments"<load(prog+"_"+lang,lpath[i]); + QString msg=QString("...loading %1_%2 from %3 ...%4") + .arg(prog).arg(lang) + .arg(lpath[i]) + .arg(ok?"ok":"failed"); + qDebug("%s",msg.toLatin1().data()); + if(ok)return; + } +} + +void MApplication::initLanguage() +{ + //try to find appropriate locale + QString lang=QSettings().value("lang","--").toString(); + if(lang=="--"){ + lang=choseLanguage(false); + } + qDebug("Loading language %s",lang.toLatin1().data()); + //load Qt translation + loadTranslation(qttrans=new QTranslator(this),lang,"qt"); + installTranslator(qttrans); + //load magicSmoke translation + loadTranslation(mstrans=new QTranslator(this),lang,"smoke"); + installTranslator(mstrans); + //load Pack translation + QTranslator*xtrans; + loadTranslation(xtrans=new QTranslator(this),lang,"qwbase"); + installTranslator(xtrans); + //detect and load remaining modules + QStringList files=QDir(applicationDirPath()).entryList(QStringList()<<"smoke-*.qm",QDir::Files|QDir::Readable,QDir::Name); + QStringList loaded, modules; + // --> stage 1: find modules + for(auto file:files){ + QString m=file.split('_').value(0); + if(!m.isEmpty() && !modules.contains(m)) + modules.append(m); + } + // --> stage 2: go through modules and load + for(auto mod:modules){ + loadTranslation(xtrans=new QTranslator(this),lang,mod); + installTranslator(xtrans); + } + //defaults + if(lang!="--"&&lang!=""){ + QLocale::setDefault(lang); +#ifndef Q_OS_WIN + setenv("LANG",lang.toLatin1().data(),1); + }else{ + setenv("LANG","C",1); +#endif + } +} + +void MApplication::initialize() +{ + //load the correct style + setMyStyle(); + //initialize log file + initDebug(dataDir()); + //init localization and profiles + initLanguage(); + initProfile(); + //init help menu layout + initHelpUrl(); + //init updater + initUpdater(); + //init plugins + MBarcodeHub::instance()->initialize(); +} + +void MApplication::initUpdater() +{ + updater=new Aurora(applicationDirPath()+"/magicsmoke.xml",this); + connect(updater,SIGNAL(newVersionAvailable(QString)),this,SLOT(updateReadyDownload(QString))); + connect(updater,SIGNAL(readyForInstallation()),this,SLOT(updaterReadyInstall())); + connect(updater,SIGNAL(installationFinished()),this,SLOT(updaterCompleted())); + connect(updater,SIGNAL(downloadFailed()),this,SLOT(updaterFailed())); + connect(updater,SIGNAL(installationFailed()),this,SLOT(updaterFailed())); + //we ignore all errors that happen prior to successful verification, since they + //would create too much noise +} + +void MApplication::updateReadyDownload(const QString& v) +{ + qDebug()<<"Asking for Download permission"; + QMessageBox::StandardButton r=QMessageBox::question(0,tr("New Update"),tr("A new version of MagicSmoke is available. Do you want to download the new version %1?").arg(v),QMessageBox::Yes|QMessageBox::No,QMessageBox::Yes); + if(r==QMessageBox::Yes) + updater->startDownload(); +} + +void MApplication::updaterReadyInstall() +{ + QMessageBox::Button r=QMessageBox::question(0,tr("New Update"),tr("A new version of MagicSmoke is ready for installation. Do you want to install?"),QMessageBox::Yes|QMessageBox::No,QMessageBox::Yes); + if(r==QMessageBox::Yes) + updater->startInstallation(); +} + +void MApplication::updaterCompleted() +{ + QMessageBox::information(0,tr("Update Complete"),tr("A new version of MagicSmoke has been installed. It will be used the next time you start MagicSmoke.")); +} + +void MApplication::updaterFailed() +{ + QMessageBox::warning(0,tr("Update Failed"),tr("An update of MagicSmoke failed.")); +} + +QString MApplication::dataDir() +{ + return MSInterface::appDataDir(); +} + +void MApplication::initProfile() +{ + //check/generate profile + if(!QSettings().childGroups().contains("profiles")){ + QMessageBox::warning(0,translate("initprofile","Initial Profile Warning"), translate("initprofile","You need a profile to work with Magic Smoke. Please create one now.")); + MConfigDialog().exec(); + } +} diff --git a/commonlib/mapplication.h b/commonlib/mapplication.h new file mode 100644 index 0000000..eb17647 --- /dev/null +++ b/commonlib/mapplication.h @@ -0,0 +1,94 @@ +// +// C++ Interface: main +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007-2014 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_MAPP_H +#define MAGICSMOKE_MAPP_H + +#include +#include + +#include "commonexport.h" + +class QMenu; +class EFilter; +namespace AuroraUpdater{class Aurora;}; +///Main application object of MagicSmoke +class MAGICSMOKE_COMMON_EXPORT MApplication:public QApplication +{ + Q_OBJECT + public: + ///create MagicSmoke application + MApplication(int&ac,char**av); + + ///return the standard help menu + static QMenu*helpMenu(); + + ///shortcut: the main function + static int realmain(int,char**); + /**contains the directory that is used for external data storage*/ + static QString dataDir(); + /**show a dialog to change the language*/ + static QString choseLanguage(bool warn=true); + + ///override the data directory + ///- call it before any of the init functions + ///- never call this while a session is active! + static void setDataDir(QString); + ///override the configuration directory + ///- call this before initialize + ///- on Windows and MacOS, this also switches the settings mode to ini-files + static void setConfigDir(QString); + public slots: + ///complete initialization: style, language, data dir + void initialize(); + ///set the configured application style + void setMyStyle(); + ///initialize the localization + void initLanguage(); + ///initialize the profiles + void initProfile(); + + ///show about dialog + void aboutMS(); + ///show version info + void versionDlg(); + ///start a browser with the help page + void help(); + private slots: + ///jump to a specific help page + void help(int); + + ///initialize the help menu from config files + void initHelpUrl(); + + ///initialize the updater + void initUpdater(); + + ///updater is ready for download + void updateReadyDownload(const QString&); + ///updater is ready for install + void updaterReadyInstall(); + ///update complete + void updaterCompleted(); + ///something failed for the updater + void updaterFailed(); + + private: + EFilter *ef=nullptr; + QTranslator*qttrans=nullptr,*mstrans=nullptr; + AuroraUpdater::Aurora*updater=nullptr; +}; + +///return the instance of the MApplication +#define mApp (qobject_cast(qApp)) + +#endif diff --git a/commonlib/misc/barcode-plugin.cpp b/commonlib/misc/barcode-plugin.cpp new file mode 100644 index 0000000..2542a43 --- /dev/null +++ b/commonlib/misc/barcode-plugin.cpp @@ -0,0 +1,119 @@ +// +// C++ Implementation: Barcode Plugin Basics +// +// +// Author: Konrad Rosenbaum , (C) 2013-2014 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "barcode-plugin.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +static QList >allscanners; +static QListallplugins; + +MBarcodeConfiguration::MBarcodeConfiguration(QWidget* parent): QDialog(parent) +{ + setWindowTitle(tr("Configure Barcode Plugins")); + + QVBoxLayout*vl; + QHBoxLayout*hl; + QPushButton*p; + setLayout(vl=new QVBoxLayout); + vl->addWidget(mtab=new QTabWidget,1); + vl->addLayout(hl=new QHBoxLayout); + hl->addStretch(1); + hl->addWidget(p=new QPushButton(tr("&Save"))); + connect(p,SIGNAL(clicked(bool)),this,SLOT(accept())); + hl->addWidget(p=new QPushButton(tr("&Cancel"))); + connect(p,SIGNAL(clicked(bool)),this,SLOT(reject())); + + setSizeGripEnabled(true); + + for(MBarcodePlugin*plug:allplugins) + if(plug)plug->configure(this); +} + +void MBarcodeConfiguration::addTab(QWidget* w, QString t) +{ + mtab->addTab(w,t); +} + + + +MBarcodeHub* MBarcodeHub::instance() +{ + static MBarcodeHub hub; + return &hub; +} + +MBarcodeHub::MBarcodeHub(): QObject() +{ + qDebug()<<"instantiating barcode hub"; +} + +MBarcodeHub::~MBarcodeHub() +{ + qDebug()<<"deleting barcode hub"; +} + +MBarcodeScanner::MBarcodeScanner(QObject* parent): QObject(parent) +{ +} + +void MBarcodePlugin::registerScanner(MBarcodeScanner* scanner) +{ + if(!scanner)return; + allscanners.append(scanner); + QObject::connect(scanner,SIGNAL(newBarcode(QString)), MBarcodeHub::instance(),SIGNAL(newBarcode(QString))); +} + +MBarcodePlugin::~MBarcodePlugin() +{} + +QList< MBarcodeScanner* > MBarcodeHub::allScanners() +{ + QListret; + for(MBarcodeScanner*s:allscanners) + if(s)ret<(oplug); + if(!plug)continue; + allplugins<(obj)); +} diff --git a/commonlib/misc/barcode-plugin.h b/commonlib/misc/barcode-plugin.h new file mode 100644 index 0000000..ee6034f --- /dev/null +++ b/commonlib/misc/barcode-plugin.h @@ -0,0 +1,113 @@ +// +// C++ Interface: plugin base for barcode scanners +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2013-2014 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_BARCODE_PLUGIN_H +#define MAGICSMOKE_BARCODE_PLUGIN_H + +#include "commonexport.h" + +#include +#include +#include +#include + +class QTabWidget; + +///Scanner Configuration Dialog +class MAGICSMOKE_COMMON_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_COMMON_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_COMMON_EXPORT MBarcodePlugin +{ + public: + virtual ~MBarcodePlugin(); + + ///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_COMMON_EXPORT MBarcodeHub:public QObject +{ + Q_OBJECT + public: + ///returns the hub object + static MBarcodeHub*instance(); + + ///initializes plugins (unless already initialized) + void initialize(); + + ///returns all currently active scanners + QListallScanners(); + + signals: + ///this is emitted whenever any of the barcode scanners find a new barcode + void newBarcode(QString); + + private slots: + ///automatically called by when a plugin destructs + void removePlugin(QObject*); + private: + MBarcodeHub(); + virtual ~MBarcodeHub(); +}; + +#define MBarcodePlugin_IID "de.silmor.MagicSmoke.BarcodePlugin/1.0" + +Q_DECLARE_INTERFACE(MBarcodePlugin, MBarcodePlugin_IID); + + +#endif diff --git a/commonlib/misc/code39.cpp b/commonlib/misc/code39.cpp new file mode 100644 index 0000000..d559742 --- /dev/null +++ b/commonlib/misc/code39.cpp @@ -0,0 +1,111 @@ +// +// C++ Implementation: code39 +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "code39.h" + +#include +#include + +//order of characters for checksum calculation and list of allowed chars +static const QString c39mod="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"; + +//init pixel map +static QMap initmap() +{ + QMapmap; + // 0=black 1=white pixel + map.insert('*',"0111010001000101"); + map.insert('-',"0111010100010001"); + map.insert('$',"0111011101110101"); + map.insert('%',"0101110111011101"); + map.insert(' ',"0111000101000101"); + map.insert('.',"0001110101000101"); + map.insert('/',"0111011101011101"); + map.insert('+',"0111010111011101"); + map.insert('0',"0101110001000101"); + map.insert('1',"0001011101010001"); + map.insert('2',"0100011101010001"); + map.insert('3',"0001000111010101"); + map.insert('4',"0101110001010001"); + map.insert('5',"0001011100010101"); + map.insert('6',"0100011100010101"); + map.insert('7',"0101110100010001"); + map.insert('8',"0001011101000101"); + map.insert('9',"0100011101000101"); + map.insert('A',"0001010111010001"); + map.insert('B',"0100010111010001"); + map.insert('C',"0001000101110101"); + map.insert('D',"0101000111010001"); + map.insert('E',"0001010001110101"); + map.insert('F',"0100010001110101"); + map.insert('G',"0101011100010001"); + map.insert('H',"0001010111000101"); + map.insert('I',"0100010111000101"); + map.insert('J',"0101000111000101"); + map.insert('K',"0001010101110001"); + map.insert('L',"0100010101110001"); + map.insert('M',"0001000101011101"); + map.insert('N',"0101000101110001"); + map.insert('O',"0001010001011101"); + map.insert('P',"0100010001011101"); + map.insert('Q',"0101010001110001"); + map.insert('R',"0001010100011101"); + map.insert('S',"0100010100011101"); + map.insert('T',"0101000100011101"); + map.insert('U',"0001110101010001"); + map.insert('V',"0111000101010001"); + map.insert('W',"0001110001010101"); + map.insert('X',"0111010001010001"); + map.insert('Y',"0001110100010101"); + map.insert('Z',"0111000100010101"); + return map; +} +//map characters on pixel codes +static const QMapc39map=initmap(); + +//calculate checksum +static char code39mod(QString str) +{ + int sum=0; + for(int i=0;i %c",str.toLatin1().data(),code39mod(str)); + //define xpm + const char *xpm[4]; + QByteArray xpmsz=QString().sprintf("%i 1 2 1",rstr.size()).toLatin1(); + xpm[0]=xpmsz.data(); + xpm[1]="0\tg #000000"; + xpm[2]="1\tg #FFFFFF"; + QByteArray xpmc=rstr.toLatin1(); + xpm[3]=xpmc.data(); + //create pixmap + return QImage(xpm); +} diff --git a/commonlib/misc/code39.h b/commonlib/misc/code39.h new file mode 100644 index 0000000..8a4a6d7 --- /dev/null +++ b/commonlib/misc/code39.h @@ -0,0 +1,21 @@ +// +// C++ Interface: code39 +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include +#include + +#include "commonexport.h" + +/**Takes a string and converts it into a code-39 bar code. +Code-39 allows letters (case-insensitive), digits, spaces and the special chars "-.$/+%". +The bar code pixmap will be 1 pixel high and 16 pixels wide for each character (plus start/stop character and checksum character) - it needs to be scaled up to fit the intended size.*/ +MAGICSMOKE_COMMON_EXPORT QImage code39(QString); diff --git a/commonlib/misc/debug.cpp b/commonlib/misc/debug.cpp new file mode 100644 index 0000000..986074f --- /dev/null +++ b/commonlib/misc/debug.cpp @@ -0,0 +1,63 @@ +// +// C++ Implementation: debug +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2008-2012 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "debug.h" +// #include "main.h" + +#include +#include +#include +#include +#include + +static QFile*mylogFile=0; + +static void mymsghandler(QtMsgType,const QMessageLogContext&, const QString&msg) +{ + if(mylogFile){ + mylogFile->write(msg.toLatin1()); + mylogFile->write("\n",1); + mylogFile->flush(); + } +#ifdef Q_OS_UNIX + fprintf(stderr,"%s\n",msg.toLatin1().data()); +#endif +} + +void initDebug(const QString&dataDir) +{ + if(QCoreApplication::instance()->arguments().contains("-nolog")){ + qDebug()<<"-nolog argument was given, will not create a log file"; + } + //create new log file + QDir(dataDir).mkpath("debuglog"); + mylogFile=new QFile(dataDir+"/debuglog/log-"+QDateTime::currentDateTime().toString("yyyy-MM-dd_hh.mm.ss.zzz")+".txt"); + //...open it + if(mylogFile->open(QIODevice::WriteOnly|QIODevice::Append|QIODevice::Text)){ + //install as default log + qDebug("Installing debuglog in %s",mylogFile->fileName().toLatin1().data()); + qInstallMessageHandler(mymsghandler); + }else{ + //hmm, failed to open, well hope that stderr is working... + delete mylogFile; + mylogFile=0; + qDebug("Failed to install debuglog."); + } + //delete old logs (older than 30 days) + QStringList fll=QDir(dataDir+"/debuglog").entryList(QDir::Files); + QDateTime old=QDateTime::currentDateTime().addDays(-30); + for(int i=0;i, (C) 2008-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_DEBUG_H +#define MAGICSMOKE_DEBUG_H + +#include "commonexport.h" + +MAGICSMOKE_COMMON_EXPORT void initDebug(const QString&dataDir); + +#endif diff --git a/commonlib/misc/domiterator.h b/commonlib/misc/domiterator.h new file mode 100644 index 0000000..15759e7 --- /dev/null +++ b/commonlib/misc/domiterator.h @@ -0,0 +1,44 @@ +// +// C++ Implementation: DOM node iterator for range based for loops +// +// +// Author: Konrad Rosenbaum , (C) 2013-2014 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// originally introduced at http://silmor.de/qtstuff.domfor.php + +#ifndef SMOKE_DOM_ITERATOR_H +#define SMOKE_DOM_ITERATOR_H + +#include "commonexport.h" + +class MAGICSMOKE_COMMON_EXPORT QDomNodeIterator +{ + int pos; + const QDomNodeList&container; +public: + //constructors and assignments + QDomNodeIterator(const QDomNodeList&l,int p):pos(p),container(l){} + QDomNodeIterator(const QDomNodeIterator&)=default; + QDomNodeIterator(QDomNodeIterator&&)=default; + QDomNodeIterator& operator=(const QDomNodeIterator&)=default; + QDomNodeIterator& operator=(QDomNodeIterator&&)=default; + + //increment + QDomNodeIterator& operator++(){pos++;return *this;} + + //comparison + bool operator==(const QDomNodeIterator&o){return pos==o.pos && container==o.container;} + bool operator!=(const QDomNodeIterator&o){return pos!=o.pos || container!=o.container;} + + //indirection + QDomNode operator*(){return container.at(pos);} +}; + +//begin and end +inline QDomNodeIterator begin(const QDomNodeList&l){return QDomNodeIterator(l,0);} +inline QDomNodeIterator end(const QDomNodeList&l){return QDomNodeIterator(l,l.size());} + + +#endif diff --git a/commonlib/misc/dommodel.cpp b/commonlib/misc/dommodel.cpp new file mode 100644 index 0000000..62f61ad --- /dev/null +++ b/commonlib/misc/dommodel.cpp @@ -0,0 +1,556 @@ +// +// C++ Implementation: DOM model +// +// +// Author: Konrad Rosenbaum , (C) 2012-2014 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "dommodel.h" + +#include +#include +#include +#include + +#include + +//switch this to en-/dis-able debug messages +static inline +// QDebug mDebug(){return QDebug(QtDebugMsg);} +QNoDebug mDebug(){return QNoDebug();} + +#include + +class DPTR_CLASS_NAME(MDomItemModel) +{ + public: + //nextid: counter for internal DOM node ids + //docid: id of the document node + int nextidx,docidx; + //cache structure that holds one node each + struct DomCache{ + QDomNode node; + QListchildren; + int parent; + DomCache():parent(-1){} + DomCache(const DomCache&)=default; + DomCache(const QDomNode&node_,int parent_=-1) + :node(node_),parent(parent_){} + }; + //cache of all DOM nodes, index is the internal ID + QMapdomCache; + //set of node types that are shown + QSetshowType; + //functors for generation of the display + QMap contentFromNode; + //config for element display + int elemAttrLen,elemTextLen; + bool showtypeLabel; + //header data + QMap,QVariant>horizHeader,vertHeader; + + Private(); + + int buildCache(const QDomNode&,int p=-1); + void removeNode(int nodeid,bool insideRecursion=false); +}; + +DEFINE_DPTR(MDomItemModel); + +MDomItemModel::MDomItemModel(QObject* parent) + : QAbstractItemModel(parent) +{ +} + +MDomItemModel::Private::Private() + :nextidx(1),docidx(-1) +{ + showType<domCache.clear(); + d->docidx=d->buildCache(doc); + mDebug()<<"DOM model setting new document - found"<domCache.size()<<"DOM nodes, root node is"<docidx; + endResetModel(); +} + +int MDomItemModel::Private::buildCache(const QDomNode& node,int parent) +{ + if(node.isNull())return -1; + //create this node + int idx=nextidx++; + DomCache dc(node,parent); + //recursively add children + QDomNodeList nl=node.childNodes(); + mDebug()<<"node"<& nt) +{ + if(nt==d->showType)return; + beginResetModel(); + d->showType=nt; + if(!d->showType.contains(QDomNode::ElementNode)) + d->showType.insert(QDomNode::ElementNode); + mDebug()<<"DOM Model - showing these types"<showType; + endResetModel(); +} + +void MDomItemModel::addShowNodeType(QDomNode::NodeType nt) +{ + if(d->showType.contains(nt))return; + beginResetModel(); + d->showType.insert(nt); + mDebug()<<"DOM Model - showing these types"<showType; + endResetModel(); +} + +void MDomItemModel::addShowNodeTypes(const QSet< QDomNode::NodeType >& nt) +{ + if(nt.isEmpty())return; + beginResetModel(); + foreach(QDomNode::NodeType n,nt) + if(!d->showType.contains(n)) + d->showType.insert(n); + mDebug()<<"DOM Model - showing these types"<showType; + endResetModel(); +} + +void MDomItemModel::showAllNodeTypes() +{ + showNodeTypes(QSet() + < MDomItemModel::shownNodeTypes()const +{ + return d->showType; +} + +void MDomItemModel::showElementProperties(int ma,int mt) +{ + //ignore if there is no change + if(d->elemAttrLen == ma && d->elemTextLen == mt)return; + //send a model reset if this has an actual effect, ie. if we do the rendering + bool b=!d->contentFromNode.contains(Qt::DisplayRole); + if(b)beginResetModel(); + //change params + d->elemAttrLen=ma; + d->elemTextLen=mt; + //tell the view + if(b)endResetModel(); +} + +void MDomItemModel::showTypeLabel(bool show) +{ + //ignore if there is no change + if(d->showtypeLabel == show)return; + //send a model reset if this has an actual effect, ie. if we do the rendering + bool b=!d->contentFromNode.contains(Qt::DisplayRole); + if(b)beginResetModel(); + //change params + d->showtypeLabel=show; + //tell the view + if(b)endResetModel(); +} + +QDomNode MDomItemModel::node(const QModelIndex& index) const +{ + if(!index.isValid()){ + if(!d->domCache.contains(d->docidx)) return QDomNode(); + else return d->domCache[d->docidx].node; + } + if(!d->domCache.contains(index.internalId()))return QDomNode(); + QDomNode node=d->domCache[index.internalId()].node; + qDebug()<<"returning node"<domCache.contains(nid))return; + int pid=d->domCache[nid].parent; + if(pid<=0 || !d->domCache.contains(pid))return; + //invalidate children + int csize=d->domCache[nid].children.size()-1; + if(csize<0)csize=0; + beginRemoveRows(index,0,csize); + for(int n:d->domCache[nid].children)d->removeNode(n); + d->domCache[nid].children.clear(); + endRemoveRows(); + //replace the node in DOM + qDebug()<<"replacing node"<domCache[nid].node.nodeValue()<<"new"<domCache[pid].node.replaceChild(nnode,d->domCache[nid].node); + d->domCache[nid].node=nnode; + qDebug()<<" new nodes type is"<domCache[nid].children.append(d->buildCache(nl.at(i),nid)); + endInsertRows(); + //tell the view we are finished + dataChanged(index,index); +} + +void MDomItemModel::insertNodes(const QDomNodeList& newnodes, const QModelIndex& parent, int row) +{ + QListnnl; + for(int i=0;i()<& newnodes, const QModelIndex& parent, int row) +{ + if(newnodes.size()<1)return; + //check parent validity + if(!parent.isValid())return; + int pid=parent.internalId(); + if(!d->domCache.contains(pid))return; + //only add to tags (TODO: there are a few other node types that can have children) + if(!d->domCache[pid].node.isElement())return; + //get the parent and a clone of the new node + QDomElement pn=d->domCache[pid].node.toElement(); + const int rcnt=rowCount(parent); + //handle appending + if(row<0 || row>=rcnt){ + const int rmax=rcnt+newnodes.size()-1; + beginInsertRows(parent,rcnt,rmax); + for(QDomNode nd:newnodes){ + QDomNode nn=nd.cloneNode(); + pn.appendChild(nn); + d->domCache[pid].children.append(d->buildCache(nn,pid)); + } + endInsertRows(); + return; + } + //handle inserting + //get current occupant of this row + QDomNode sibl=node(index(row,0,parent)); + const int rmax=row+newnodes.size()-1; + beginInsertRows(parent,row,rmax); + //insert + for(QDomNode nd:newnodes){ + QDomNode nn=nd.cloneNode(); + qDebug()<<"Attempting insert with"<domCache[pid].children.insert(row,d->buildCache(nn,pid)); + } + endInsertRows(); +} + +int MDomItemModel::columnCount(const QModelIndex&) const +{ + return 1; +} + +QDomDocument MDomItemModel::domDocument() const +{ + if(d->docidx>=0 && d->domCache.contains(d->docidx)) + return d->domCache[d->docidx].node.cloneNode().toDocument(); + else + return QDomDocument(); +} + +QVariant MDomItemModel::data(const QModelIndex& index, int role) const +{ + if(role==DomNodeRole)return QVariant::fromValue(node(index)); + //root index + QDomNode node; + if(!index.isValid()){ + if(d->domCache.contains(d->docidx)) + node=d->domCache[d->docidx].node; + }else{ + if(d->domCache.contains(index.internalId())) + node=d->domCache[index.internalId()].node; + } + //check node + if(node.isNull())return QVariant(); + //try to find callback + if(d->contentFromNode.contains(role))return d->contentFromNode[role](node); + //no callback: display role + if(role==Qt::DisplayRole)return displayFromNode(node); + //fall back + return QVariant(); +} + +QVariant MDomItemModel::displayFromNode(const QDomNode& node) const +{ + if(node.isNull())return "NULL node"; + switch(node.nodeType()){ + case QDomNode::ElementNode:{ + QString r; + if(d->showtypeLabel)r+="tag "; + r+="<"+node.nodeName(); + QString a,t; + //append attribs + if(d->elemAttrLen>=0 && node.hasAttributes()){ + auto attrs=node.attributes(); + QString a; + for(int i=0;id->elemAttrLen){ + a.truncate(d->elemAttrLen); + a+="..."; + } + r+=" "+a.trimmed(); + } + r+=">"; + //append text + if(d->elemTextLen>0){ + QString t; + QDomNodeList nl=node.childNodes(); + for(int i=0;i0)t+=" "; + t+=QString(nd.nodeValue()).replace('\n',' '); + } + } + if(t.size()>d->elemTextLen){ + t.truncate(d->elemTextLen); + t+="..."; + } + r+=t.trimmed(); + } + return r; + } + case QDomNode::AttributeNode: + return (d->showtypeLabel?"attribute ":"")+node.nodeName()+"="+node.nodeValue(); + case QDomNode::TextNode: + case QDomNode::CDATASectionNode: + return QString(d->showtypeLabel?"text ":"")+"\""+QString(node.nodeValue()).replace('\n',' ')+"\""; + case QDomNode::CommentNode: + return QString(d->showtypeLabel?"comment ":"")+""; + default: + return (d->showtypeLabel?("node ("+QString::number(node.nodeType())+"): "):QString())+node.nodeName()+" - \""+node.nodeValue()+"\""; + } +} + +int MDomItemModel::rowCount(const QModelIndex& parent) const +{ + int pid=-1; + if(!parent.isValid())pid=d->docidx; + else pid=parent.internalId(); + if(!d->domCache.contains(pid)){ + mDebug()<<"DOM Model - index"<domCache[pid].children) + if(d->domCache.contains(cid) && d->showType.contains(d->domCache[cid].node.nodeType())) + ret++; + mDebug()<<"DOM Model - index"<domCache[pid].children.size()<<"items"; + return ret; +} + +QModelIndex MDomItemModel::index(int row, int column, const QModelIndex& parent) const +{ + //only col 0 is valid for now + if(column!=0){ + mDebug()<<"DOM Model - index for wrong column requested"<docidx; + else pid=parent.internalId(); + if(pid<=0 || !d->domCache.contains(pid)){ + mDebug()<<"DOM Model - index for invalid node requested"<=d->domCache[pid].children.size()){ + mDebug()<<"DOM Model - index of empty parent requested, parent:"<domCache[pid].children){ + if(!d->showType.contains(d->domCache[cid].node.nodeType())) + continue; + if(row==rc++){ + mDebug()<<"DOM Model - creating index"<domCache.contains(index.internalId())){ + mDebug()<<"DOM Model - requesting parent of"<domCache[index.internalId()].parent; + if(pid<=0 || !d->domCache.contains(pid)){ + mDebug()<<"DOM Model - requesting parent of"<domCache[pid].parent; + //is grand-parent invalid? (parent must be the root node) + if(gpid<=0 || !d->domCache.contains(gpid)){ + mDebug()<<"DOM Model - requesting parent of"<domCache[gpid].children){ + if(nid==pid)break; + if(d->showType.contains(d->domCache[nid].node.nodeType()))row++; + } + mDebug()<<"DOM Model - requesting parent of"<domCache.contains(nid))return; + //find parent index and warn the view + QModelIndex pidx=parent(index); + if(pidx.isValid())beginRemoveRows(pidx,index.row(),index.row()); + else beginResetModel(); + //remove the node + d->removeNode(nid); + //tell the view we are done + if(pidx.isValid())endRemoveRows(); + else endResetModel(); +} + +void MDomItemModel::Private::removeNode(int nid,bool inrecurs) +{ + //sanity check + if(!domCache.contains(nid))return; + //remove main node from model + if(!inrecurs){ + int pid=domCache[nid].parent; + if(domCache.contains(pid)){ + domCache[pid].node.removeChild(domCache[nid].node); + domCache[pid].children.removeAll(nid); + } + } + //remove children + foreach(int cid,domCache[nid].children) + removeNode(cid,true); + //remove self + domCache.remove(nid); +} + + +bool MDomItemModel::removeRows(int row, int count, const QModelIndex& parent) +{ + //sanity check + if(row<0 || count<=0)return false; + //find the parent + int pid=-1; + if(parent.isValid())pid=parent.internalId(); + else pid=d->docidx; + if(!d->domCache.contains(pid)) + return false; + //check the parent has those children + if(rowCount(parent)<(row+count)) + return false; + //warn the view + beginRemoveRows(parent,row,row+count-1); + //find the children's IDs + QListcids; + int cnt=0; + foreach(int cid,d->domCache[pid].children){ + if(cnt>=(row+count))break; + if(!d->showType.contains(d->domCache[cid].node.nodeType())) + continue; + if(cnt++>=row)cids<removeNode(cid); + //update view + endRemoveRows(); + return true; +} + +void MDomItemModel::setContentFromNodeCall(int role,MDomModelFunctor f) +{ + if(role==DomNodeRole)return; + beginResetModel(); + if(f) + d->contentFromNode.insert(role,f); + else + d->contentFromNode.remove(role); + endResetModel(); +} + +QVariant MDomItemModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if(orientation==Qt::Horizontal) + return d->horizHeader.value(QPair(section,role)); + else + return d->vertHeader.value(QPair(section,role)); +} + +bool MDomItemModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant& value, int role) +{ + if(orientation==Qt::Horizontal) + d->horizHeader.insert(QPair(section,role),value); + else + d->vertHeader.insert(QPair(section,role),value); + return true; +} diff --git a/commonlib/misc/dommodel.h b/commonlib/misc/dommodel.h new file mode 100644 index 0000000..6b37a03 --- /dev/null +++ b/commonlib/misc/dommodel.h @@ -0,0 +1,140 @@ +// +// C++ Interface: odtrender +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2008-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_DOMMODEL_H +#define MAGICSMOKE_DOMMODEL_H + +#include +#include +#include + +#include + +#include "commonexport.h" + +class QDomNode; +class QDomDocument; + +/** \brief Special functor that can be used to customize MDomItemModel. +Any static function or lambda that takes a QDomNode as argument and returns a QVariant can be used to specialize MDomItemModel. The type of data returned through the QVariant depends on the role the function is supposed to serve. Only one function/lambda can be registered for each role in any given model instance.*/ +typedef std::function MDomModelFunctor; + +/** \brief This is a specialized model type that shows and allows to manipulate a DOM tree. +The model holds a copy of the DOM tree, so the original is not changed even if the model changes. +You can retrieve a current copy of the model's DOM tree by calling domDocument(). +This model can not carry application specific user data. It is only editable through its specialized node methods.*/ +class MAGICSMOKE_COMMON_EXPORT MDomItemModel:public QAbstractItemModel +{ + Q_OBJECT + DECLARE_DPTR(d); + public: + ///instantiate an empty DOM model + MDomItemModel(QObject* parent = 0); + ///instantiate a DOM model with an initial DOM tree + ///\param xml the model will be fed with a copy of this DOM tree + MDomItemModel(const QDomDocument&xml, QObject* parent = 0); + + /**returns a copy of the DOM tree represented by this model, + you can safely manipulate this copy without influencing the model. If you want + to change the model's content use the node methods provided here.*/ + virtual QDomDocument domDocument()const; + + ///alias for Qt::UserRole that is used to retrieve the DOM node of an index. + static const int DomNodeRole=Qt::UserRole; + + ///always returns 1 - the DOM tree has only one column corresponding to the node + virtual int columnCount(const QModelIndex&parent=QModelIndex())const; + ///returns data corresponding to the node represented by index; + ///this method can be customized through setContentFromNodeCall(...) + virtual QVariant data(const QModelIndex&index, int role=Qt::DisplayRole)const; + + ///returns an index corresponding to the row, column, and parent node + /// \param row the row beneith the parent node - the row number depends on which node types are shown, only visible node types are counted + /// \param column must be 0, otherwise an invalid index is returned + /// \param parent an invalid node for the root node (QDomDocument) or any valid index returned through index(...) + virtual QModelIndex index(int row, int column, const QModelIndex&parent=QModelIndex())const; + ///returns the parent index of a node - if it has a parent + virtual QModelIndex parent(const QModelIndex&index)const; + ///returns the amount of visible nodes beneith parent + virtual int rowCount(const QModelIndex&parent=QModelIndex())const; + + ///returns a set of node types that are configured to be visible in this model + virtual QSet shownNodeTypes()const; + + ///returns the QDomNode corresponding to index, for the invalid index the QDomDocument is returned + virtual QDomNode node(const QModelIndex&index)const; + + ///sets header data - it is currently possible to set any header for any role, although only few are actually shown in views + bool setHeaderData(int section, Qt::Orientation orientation, const QVariant & value, int role = Qt::EditRole); + ///returns the header data for a specific header position and role + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole)const; + + public slots: + /** sets the document represented by this model; + the model makes a deep copy of the document, so that the original stays intact even if the model changes. Use domDocument() to retrieve a fresh copy of the models version of the document.*/ + virtual void setDomDocument(const QDomDocument&); + + ///changes the settings of what kinds of nodes are shown in the model, + ///element nodes cannot be switched off, + ///all model indexes become invalid after a call to this method + void showNodeTypes(const QSet&); + ///changes the settings of what kinds of nodes are shown in the model, + ///all model indexes become invalid after a call to this method + void addShowNodeType(QDomNode::NodeType); + ///changes the settings of what kinds of nodes are shown in the model, + ///all model indexes become invalid after a call to this method + void addShowNodeTypes(const QSet&); + ///changes the settings of what kinds of nodes are shown in the model, + ///all model indexes become invalid after a call to this method + void showAllNodeTypes(); + + /**changes the way element nodes are displayed, + this method has no effect if you customize Qt::DisplayRole through setContentFromNodeCall(...) + \param maxattr the amount of characters shown for attributes, if this is 0 the model will just show "..." if the element has attributes, if this is <0 the model will ignore attributes + \param maxtext the amount of characters shown for character data (QDomText and QDomCDATASection), if this is 0 the model will just show "..." if the element has text, if this is <0 the model will ignore any text + */ + void showElementProperties(int maxattr,int maxtext); + + ///if true the default display routine will show a node type label + void showTypeLabel(bool show=true); + + ///replaces the node at the index, you cannot replace the entire document with this function - use setDomDocument for this + virtual void setNode(const QModelIndex&index,const QDomNode&); + ///insert a node into the parent at given position (if no position is given: append) + virtual void insertNode(const QDomNode&newnode,const QModelIndex&parent,int row=-1); + ///insert a list of nodes into the parent at given position (if no position is given: append) + virtual void insertNodes(const QDomNodeList&newnodes,const QModelIndex&parent,int row=-1); + ///insert a list of nodes into the parent at given position (if no position is given: append) + virtual void insertNodes(const QList&newnodes,const QModelIndex&parent,int row=-1); + ///removes the nodes at the given position and their child nodes + virtual bool removeRows(int row, int count, const QModelIndex&parent=QModelIndex()); + ///removes the node at the given position and its child nodes + virtual void removeNode(const QModelIndex&); + + /**Customize the way the model returns data to the view, per default the model only has code to generate a text representation for Qt::DisplayRole. You can override any role, including Qt::DisplayRole, except for DomNodeRole. The callback takes a const reference to QDomNode as argument and should convert it to a QVariant appropriate for the role. + \param role the role to be customized + \param callback a static function, functor or lambda that takes a node as argument and returns a variant as result, use nullptr to delete a customization + */ + void setContentFromNodeCall(int role,MDomModelFunctor callback); + + ///resets the model to an invalid/empty QDomDocument + virtual void clear(){setDomDocument(QDomDocument());} + + private: + ///default implementation for Display-Role + QVariant displayFromNode(const QDomNode&)const; +}; + +Q_DECLARE_METATYPE(QDomNode); +Q_DECLARE_METATYPE(MDomModelFunctor); + +#endif diff --git a/commonlib/misc/misc.pri b/commonlib/misc/misc.pri new file mode 100644 index 0000000..565a3d5 --- /dev/null +++ b/commonlib/misc/misc.pri @@ -0,0 +1,16 @@ +HEADERS += \ + $$PWD/debug.h \ + $$PWD/waitcursor.h \ + $$PWD/sclock.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/barcode-plugin.cpp + +INCLUDEPATH += $$PWD diff --git a/commonlib/misc/sclock.cpp b/commonlib/misc/sclock.cpp new file mode 100644 index 0000000..3284d12 --- /dev/null +++ b/commonlib/misc/sclock.cpp @@ -0,0 +1,155 @@ +// +// C++ Implementation: overview +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "sclock.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "misc.h" + +MServerClock::MServerClock() +{ + QTimer *tm=new QTimer(this); + tm->setSingleShot(false); + tm->start(1000); + connect(tm,SIGNAL(timeout()),this,SLOT(updateClock())); + + connect(this,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(contextMenu(QPoint))); + setContextMenuPolicy(Qt::CustomContextMenu); + setFrameStyle(QFrame::Panel|QFrame::Sunken); + + contextmenu=new QMenu(this); + contextmenu->addAction(tr("Show Format Info"),this,SLOT(showInfo())); + contextmenu->addSeparator(); + QActionGroup*ag=new QActionGroup(this); + QAction*ac=ag->addAction(tr("Show Full Time")); + ac->setCheckable(true);ac->setChecked(true); + ac->setData(tr("%W, %D %N %Y %a:%I %p %t","full time format")); + contextmenu->addAction(ac);showfull=ac; + ac=ag->addAction(tr("Show Date Only"));ac->setCheckable(true); + ac->setData(tr("%w, %M/%D/%Y","date only format")); + contextmenu->addAction(ac);showdate=ac; + ac=ag->addAction(tr("Show Time Only"));ac->setCheckable(true); + ac->setData(tr("%a:%I %p %t","time only format")); + contextmenu->addAction(ac);showtime=ac; + ac=ag->addAction(tr("Show Short Date/Time"));ac->setCheckable(true); + ac->setData(tr("%w %Y-%M-%D %h:%I %t","ISO like short time format")); + contextmenu->addAction(ac);showiso=ac; + connect(ag,SIGNAL(triggered(QAction*)),this,SLOT(updateClock())); + + updateClock(); +} + +void MServerClock::updateClock() +{ + //get time and format + TimeStamp ts=TimeStamp::now(); + QString fm=showfull->data().toString(); + if(showdate->isChecked())fm=showdate->data().toString(); + if(showtime->isChecked())fm=showtime->data().toString(); + if(showiso->isChecked())fm=showiso->data().toString(); + //set it + setText(MLocalFormat().formatDateTime(ts,fm)); + //make sure tool tip is up to date + int off=ts.offsetFromUTC()/60; + QString tz=tr("Server Time Zone: %1\nOffset from UTC: %2 minutes %3") + .arg(MLocalFormat().timeZone()) + .arg(off<0?-off:off) + .arg(off>=0?tr("east","positive time zone offset"):tr("west","negative time zone offset")); + if(toolTip()!=tz)setToolTip(tz); +} + +void MServerClock::mouseDoubleClickEvent(QMouseEvent* event) +{ + QWidget::mouseDoubleClickEvent(event); + if(event->button()!=Qt::LeftButton)return; + showInfo(); +} + +static inline QString list2str(const QStringList&l) +{ + QString ret,r; + for(int i=0;i=30){ + ret+=r+"\n"; + r=""; + } + } + ret+=r; + return ret.trimmed(); +} + +void MServerClock::showInfo() +{ + QDialog d(this); + d.setWindowTitle(tr("Server Format Info")); + QVBoxLayout*vl; + QFormLayout*fl; + QHBoxLayout*hl; + d.setLayout(vl=new QVBoxLayout); + vl->addLayout(fl=new QFormLayout,10); + fl->setLabelAlignment(Qt::AlignRight|Qt::AlignTop); + MLocalFormat lf; + fl->addRow(new QLabel(tr("Number Format:"))); + fl->addRow(tr("Decimal Dot:"),new QLabel(lf.decimalDot())); + fl->addRow(tr("Separator:"),new QLabel(tr("'%1' every %2 digits").arg(lf.thousandSeparator()).arg(lf.thousandDigits()))); + + fl->addRow(new QLabel); + fl->addRow(new QLabel(tr("Currency Settings:"))); + fl->addRow(tr("Currency Symbol:"),new QLabel(lf.currency())); + fl->addRow(tr("Division Digits:"),new QLabel(QString::number(lf.moneyDecimals()))); + fl->addRow(tr("Negative Sign:"),new QLabel(lf.moneyNegativeSign())); + fl->addRow(tr("Positive Sign:"),new QLabel(lf.moneyPositiveSign())); + fl->addRow(tr("Example:"),new QLabel(lf.formatMoney(-1234567890))); + + fl->addRow(new QLabel); + fl->addRow(new QLabel(tr("Date and Time Settings:"))); + fl->addRow(tr("Day of the Week:"),new QLabel(list2str(lf.weekDayNames()))); + fl->addRow(tr("Day of the Week Abbreviated:"),new QLabel(list2str(lf.shortWeekDayNames()))); + fl->addRow(tr("Month Names:"),new QLabel(list2str(lf.monthNames()))); + fl->addRow(tr("Month Names Abbreviated:"),new QLabel(list2str(lf.shortMonthNames()))); + fl->addRow(tr("Date Format:"),new QLabel(lf.dateFormat())); + fl->addRow(tr("Time Format:"),new QLabel(lf.timeFormat())); + fl->addRow(tr("Date and Time Format:"),new QLabel(lf.dateTimeFormat())); + MLocalFormat lfs;lfs.setTimeZone(TimeStamp::systemLocalZone()); + TimeStamp now=TimeStamp::now(); + fl->addRow(tr("System Time Zone:"),new QLabel(lfs.timeZone())); + fl->addRow(tr("Current Local Time:"),new QLabel(lfs.formatDateTime(now))); + fl->addRow(tr("Theater/Server Time Zone:"),new QLabel(lf.timeZone())); + fl->addRow(tr("Current Theater/Server Time:"),new QLabel(lf.formatDateTime(now))); + + vl->addLayout(hl=new QHBoxLayout,0); + hl->addStretch(10); + QPushButton*p; + hl->addWidget(p=new QPushButton(tr("Close"))); + p->setDefault(true); + connect(p,SIGNAL(clicked()),&d,SLOT(close())); + + d.exec(); +} + +void MServerClock::contextMenu(const QPoint& p) +{ + contextmenu->popup(mapToGlobal(p)); +} diff --git a/commonlib/misc/sclock.h b/commonlib/misc/sclock.h new file mode 100644 index 0000000..6e80b8a --- /dev/null +++ b/commonlib/misc/sclock.h @@ -0,0 +1,40 @@ +// +// C++ Interface: overview +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_SCLOCK_H +#define MAGICSMOKE_SCLOCK_H + +#include + +#include "commonexport.h" + +class QMenu; +class QAction; + + +class MAGICSMOKE_COMMON_EXPORT MServerClock:public QLabel +{ + Q_OBJECT + public: + MServerClock(); + private slots: + void updateClock(); + void contextMenu(const QPoint&); + void showInfo(); + protected: + virtual void mouseDoubleClickEvent ( QMouseEvent * event ); + private: + QMenu*contextmenu; + QAction*showfull,*showtime,*showdate,*showiso; +}; + +#endif diff --git a/commonlib/misc/waitcursor.cpp b/commonlib/misc/waitcursor.cpp new file mode 100644 index 0000000..21410ce --- /dev/null +++ b/commonlib/misc/waitcursor.cpp @@ -0,0 +1,38 @@ +// +// C++ Implementation: waitcursor +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009-2013 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "waitcursor.h" +#include + +#include +#include + +WaitCursor::WaitCursor() +{ + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); +} + +WaitCursor::~WaitCursor() +{ + QApplication::restoreOverrideCursor(); +} + +static int transactionCursor() +{ + MTransaction::setStartStopActions( + []{QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));}, + []{QApplication::restoreOverrideCursor();} + ); + return 0; +} + +static int tcdummy=transactionCursor(); \ No newline at end of file diff --git a/commonlib/misc/waitcursor.h b/commonlib/misc/waitcursor.h new file mode 100644 index 0000000..29aecdb --- /dev/null +++ b/commonlib/misc/waitcursor.h @@ -0,0 +1,29 @@ +// +// C++ Interface: waitcursor +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_WAITCURSOR_H +#define MAGICSMOKE_WAITCURSOR_H + +#include "commonexport.h" + +/**simple class to show a busy-cursor while an instance of it exists*/ +class MAGICSMOKE_COMMON_EXPORT WaitCursor +{ + public: + /**displays a wait cursor (Qt::WaitCursor)*/ + WaitCursor(); + /**restores the last normal cursor*/ + ~WaitCursor(); +}; + + +#endif diff --git a/commonlib/templates/labeldlg.cpp b/commonlib/templates/labeldlg.cpp new file mode 100644 index 0000000..324acef --- /dev/null +++ b/commonlib/templates/labeldlg.cpp @@ -0,0 +1,863 @@ +// +// C++ Implementation: labeldlg +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2008-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "labeldlg.h" + +#include "msinterface.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// #include +#include +#include +#include +#include +#include +#include +#include + +#define ROWS 20 +#define COLS 20 + +MLabelDialog::MLabelDialog(QWidget*par,QPrinter* pn,int nl,QSizeF ls) + :QDialog(par) +{ + printer=pn; + numlabels=nl; + labelsize=ls; + maxrows=ROWS; + maxcols=COLS; + + setWindowTitle(tr("Label Printing Setup")); + + //get settings + QSettings set; + set.beginGroup("printer/"+printer->printerName()); + double ox=set.value("offsetx",0.0).toDouble(); + double oy=set.value("offsety",0.0).toDouble(); + double lsx=set.value("sizex",0.0).toDouble(); + double lsy=set.value("sizey",0.0).toDouble(); + QString mtrc=set.value("metric",tr("mm","defaultmetric: mm, in, cm")).toString(); + if(lsx==0.0 || lsy==0.0){ + //convert ticket template size + double dx=printer->logicalDpiX(); + double dy=printer->logicalDpiY(); + if(mtrc=="in"){ + lsx=ls.width()/dx; + lsy=ls.height()/dy; + }else + if(mtrc=="cm"){ + lsx=ls.width()/dx*2.54; + lsy=ls.height()/dy*2.54; + }else{//mm + lsx=ls.width()/dx*25.4; + lsy=ls.height()/dy*25.4; + } + } + + //display + + QVBoxLayout*vl; + QGridLayout*gl; + setLayout(vl=new QVBoxLayout); + vl->addLayout(gl=new QGridLayout,0); + + int ln=0; + gl->addWidget(new QLabel(tr("Label offset:")),ln,0); + gl->addWidget(offx=new QLineEdit(QString::number(ox)),ln,1); + offx->setValidator(new QDoubleValidator(0.0,1000.0,2,this)); + gl->addWidget(new QLabel("x"),ln,2); + gl->addWidget(offy=new QLineEdit(QString::number(oy)),ln,3); + offy->setValidator(new QDoubleValidator(0.0,1000.0,2,this)); + gl->addWidget(new QLabel(tr("Label size:")),++ln,0); + gl->addWidget(sizex=new QLineEdit(QString::number(lsx)),ln,1); + sizex->setValidator(new QDoubleValidator(0.0,1000.0,2,this)); + gl->addWidget(new QLabel("x"),ln,2); + gl->addWidget(sizey=new QLineEdit(QString::number(lsy)),ln,3); + sizey->setValidator(new QDoubleValidator(0.0,1000.0,2,this)); + gl->addWidget(new QLabel(tr("Unit:")),++ln,0); + gl->addWidget(metric=new QComboBox,ln,1,1,3); + metric->addItem(tr("Millimeter"),"mm"); + metric->addItem(tr("Centimeter"),"cm"); + metric->addItem(tr("Inch"),"in"); + gl->addWidget(warning=new QLabel(""),++ln,0,1,4); + QPalette pal=warning->palette(); + pal.setColor(QPalette::WindowText,Qt::red); + warning->setPalette(pal); + gl->setColumnStretch(++ln,10); + + vl->addSpacing(10); + vl->addWidget(new QLabel(tr("Page usage:")),0); + vl->addWidget(page=new QComboBox,0); + for(int i=0;iaddItem(tr("Page %1").arg(i+1),i); + oldpage=0; + + QScrollArea *sa; + QWidget*w=new QWidget; + vl->addWidget(sa=new QScrollArea,10); + w->setLayout(gl=new QGridLayout); + QToolButton*t; + gl->addWidget(t=new QToolButton,0,0); + t->setIcon(QIcon(":/arrowdiag.png")); + connect(t,SIGNAL(clicked()),this,SLOT(toggleAll())); + QSignalMapper *cmap=new QSignalMapper(this); + connect(cmap,SIGNAL(mapped(int)),this,SLOT(toggleColumn(int))); + for(int i=1;i<=COLS;i++){ + gl->addWidget(t=new QToolButton,0,i); + t->setIcon(QIcon(":/arrowdown.png")); + connect(t,SIGNAL(clicked()),cmap,SLOT(map())); + cmap->setMapping(t,i-1); + } + QSignalMapper *rmap=new QSignalMapper(this); + connect(rmap,SIGNAL(mapped(int)),this,SLOT(toggleRow(int))); + for(int i=1;i<=ROWS;i++){ + gl->addWidget(t=new QToolButton,i,0); + t->setIcon(QIcon(":/arrowright.png")); + connect(t,SIGNAL(clicked()),rmap,SLOT(map())); + rmap->setMapping(t,i-1); + for(int j=1;j<=COLS;j++){ + QCheckBox*b; + gl->addWidget(b=new QCheckBox,i,j); + checks.append(b); + connect(b,SIGNAL(clicked()),this,SLOT(savePage())); + } + } + sa->setWidget(w); + connect(page,SIGNAL(currentIndexChanged(int)),this,SLOT(updatePage())); + connect(sizex,SIGNAL(textChanged(const QString&)),this,SLOT(updatePage())); + connect(sizey,SIGNAL(textChanged(const QString&)),this,SLOT(updatePage())); + connect(metric,SIGNAL(currentIndexChanged(int)),this,SLOT(updatePage())); + + vl->addSpacing(15); + QHBoxLayout*hl; + vl->addLayout(hl=new QHBoxLayout); + hl->addStretch(10); + QPushButton*p; + hl->addWidget(p=new QPushButton(tr("Ok")),0); + connect(p,SIGNAL(clicked()),this,SLOT(accept())); + connect(p,SIGNAL(clicked()),this,SLOT(saveSettings())); + p->setDefault(true); + hl->addWidget(p=new QPushButton(tr("Cancel")),0); + connect(p,SIGNAL(clicked()),this,SLOT(reject())); + + //initialize + QListtpl; + for(int i=0;i<(ROWS*COLS);i++)tpl.append(true); + for(int i=0;i>(QDataStream &in, MLabelConfig &myObj) +{ + char *t; + uint l; + in.readBytes(t,l); + if(t && l>0) + myObj.m_type=(MLabelConfig::LabelType)(*t); + if(t)delete t; + return in; +} + +void MLabelConfig::initMeta() +{ + static int mt=-1; + if(mt>=0)return; + mt=qRegisterMetaType(); + qRegisterMetaTypeStreamOperators(); +} + +MLabelDialog::~MLabelDialog(){} + +int MLabelDialog::findLabel(int n,int&row,int&col)const +{ + //search allowed labels + int ctr=-1; + for(int p=0;p=0;r--) + for(int c=0;ctext().toDouble(); + double py=offy->text().toDouble(); + //add rows/cols + px+=col*sizex->text().toDouble(); + py+=row*sizey->text().toDouble(); + //correct to DPI + QString mtrc=metric->itemData(metric->currentIndex()).toString(); + if(mtrc=="in"){ + px*=printer->logicalDpiX(); + py*=printer->logicalDpiY(); + }else + if(mtrc=="cm"){ + px*=printer->logicalDpiX()/2.54; + py*=printer->logicalDpiY()/2.54; + }else{ + px*=printer->logicalDpiX()/25.4; + py*=printer->logicalDpiY()/25.4; + } + //return + return QPointF(px,py); +} + +bool MLabelDialog::labelNeedsPageTurn(int n)const +{ + //find it + int pg,row=0,col=0; + pg=findLabel(n,row,col); + //page 0 needs no turn + if(pg<=0)return false; + //scan that page (all rows below label) + for(int r=maxrows-1;r>row;r--) + for(int c=0;csetChecked(checked[oldpage][i]); + } +} + +void MLabelDialog::toggleColumn(int c) +{ + for(int r=0;rsetChecked(checked[oldpage][i]); + } +} + +void MLabelDialog::toggleAll() +{ + for(int i=0;i<(ROWS*COLS);i++){ + checked[oldpage][i]^=true; + checks[i]->setChecked(checked[oldpage][i]); + } +} + +void MLabelDialog::savePage() +{ + for(int i=0;i<(ROWS*COLS);i++) + checked[oldpage][i]=checks[i]->isChecked(); +} + +void MLabelDialog::updatePage() +{ + //find how many rows/cols fit on the page + double lx=sizex->text().toDouble(); + double ly=sizey->text().toDouble(); + QRect pr=printer->pageRect(); + QString mtrc=metric->itemData(metric->currentIndex()).toString(); + if(mtrc=="in"){ + lx*=printer->logicalDpiX(); + ly*=printer->logicalDpiY(); + }else + if(mtrc=="cm"){ + lx*=printer->logicalDpiX()/2.54; + ly*=printer->logicalDpiY()/2.54; + }else{ + lx*=printer->logicalDpiX()/25.4; + ly*=printer->logicalDpiY()/25.4; + } + + bool dowarn=false; + if(ly>0.0){ + maxrows=pr.height()/ly; + if(maxrows>ROWS)maxrows=ROWS; + if(maxrows<1){ + maxrows=1; + dowarn=true; + } + }else maxrows=ROWS; + if(lx>0.0){ + maxcols=pr.width()/lx; + if(maxcols>COLS)maxcols=COLS; + if(maxcols<1){ + maxcols=1; + dowarn=true; + } + }else maxcols=COLS; + //update + oldpage=page->itemData(page->currentIndex()).toInt(); + for(int r=0;rsetChecked(b && checked[oldpage][i]); + checks[i]->setEnabled(b); + } + if(dowarn) + warning->setText(tr("Warning: the label may not fit on the page!")); + else + warning->setText(""); +} + +void MLabelDialog::saveSettings() +{ + QSettings set; + set.beginGroup("printer/"+printer->printerName()); + set.setValue("offsetx",offx->text().toDouble()); + set.setValue("offsety",offy->text().toDouble()); + set.setValue("sizex",sizex->text().toDouble()); + set.setValue("sizey",sizey->text().toDouble()); + set.setValue("metric",metric->itemData(metric->currentIndex()).toString()); +} + + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +void MLabelConfig::configDialog(QWidget* parent) +{ + QDialog d(parent); + MLabelConfig ticket(MLabelConfig::Ticket),voucher(MLabelConfig::Voucher); + d.setWindowTitle(tr("Label Configuration")); + QFormLayout*fl; + d.setLayout(fl=new QFormLayout); + fl->addRow(new QLabel(tr("Ticket Labels:"))); + //each one: ask printer mode, ask label-page mode, printer/settings + QComboBox*t_prnmode,*t_pagmode,*t_prnbufmode; + fl->addRow(tr("Print Dialog:"),t_prnmode=new QComboBox); + t_prnmode->addItem(tr("Always ask for printer"),PrintAskAlways); + t_prnmode->addItem(tr("Ask if unknown or not present"),PrintAskIfUnknown); + t_prnmode->addItem(tr("Never ask for printer"),PrintAskNever); + t_prnmode->setCurrentIndex(ticket.printAskMode()); + fl->addRow(tr("Page Dialog:"),t_pagmode=new QComboBox); + t_pagmode->addItem(tr("Always ask for page layout"),PageAskAlways); + t_pagmode->addItem(tr("Ask if more than one label per page"),PageAskIfNeeded); + t_pagmode->addItem(tr("Never ask for page layout"),PageAskNever); + t_pagmode->setCurrentIndex(ticket.pageAskMode()); + QHBoxLayout*hl; + QLabel*t_prn;QMapt_prnset; + QToolButton*p; + QPrinter t_printer; + ticket.configurePrinter(t_printer); + fl->addRow(tr("Printer:"),hl=new QHBoxLayout); + hl->addWidget(t_prn=new QLabel(ticket.printerName()),1); + hl->addWidget(p=new QToolButton); + p->setText("..."); + auto settprn=[&]{ + MLabelPrintDialog pd(&t_printer,&d); + pd.setWindowTitle(tr("Chose Printer for Tickets")); + pd.setButtonLabel(tr("Set Printer")); +// pd.setOptions(QAbstractPrintDialog::PrintShowPageSize); + if(pd.exec()!=QDialog::Accepted)return; + t_prn->setText(t_printer.printerName()); + }; + d.connect(p,&QToolButton::clicked,settprn); + fl->addRow(tr("Print Mode:"),t_prnbufmode=new QComboBox); + t_prnbufmode->addItem(tr("Direct Print")); + t_prnbufmode->addItem(tr("Use Buffer Pixmap")); + t_prnbufmode->setCurrentIndex((int)ticket.printMode()); + QFrame*frm; + fl->addRow(frm=new QFrame); + frm->setFrameStyle(QFrame::HLine|QFrame::Sunken); + //Vouchers... + fl->addRow(new QLabel(tr("Voucher Labels:"))); + //each one: ask printer mode, ask label-page mode, printer/settings + QComboBox*v_prnmode,*v_pagmode,*v_prnbufmode; + fl->addRow(tr("Print Dialog:"),v_prnmode=new QComboBox); + v_prnmode->addItem(tr("Always ask for printer"),PrintAskAlways); + v_prnmode->addItem(tr("Ask if unknown or not present"),PrintAskIfUnknown); + v_prnmode->addItem(tr("Never ask for printer"),PrintAskNever); + v_prnmode->setCurrentIndex(voucher.printAskMode()); + fl->addRow(tr("Page Dialog:"),v_pagmode=new QComboBox); + v_pagmode->addItem(tr("Always ask for page layout"),PageAskAlways); + v_pagmode->addItem(tr("Ask if more than one label per page"),PageAskIfNeeded); + v_pagmode->addItem(tr("Never ask for page layout"),PageAskNever); + v_pagmode->setCurrentIndex(voucher.pageAskMode()); + QLabel*v_prn;QMapv_prnset; + QPrinter v_printer; + voucher.configurePrinter(v_printer); + fl->addRow(tr("Printer:"),hl=new QHBoxLayout); + hl->addWidget(v_prn=new QLabel(voucher.printerName()),1); + hl->addWidget(p=new QToolButton); + p->setText("..."); + auto setvprn=[&]{ + MLabelPrintDialog pd(&v_printer,&d); + pd.setWindowTitle(tr("Chose Printer for Vouchers")); + pd.setButtonLabel(tr("Set Printer")); +// pd.setOptions(QAbstractPrintDialog::PrintShowPageSize); + if(pd.exec()!=QDialog::Accepted)return; + v_prn->setText(v_printer.printerName()); + }; + d.connect(p,&QToolButton::clicked,setvprn); + fl->addRow(tr("Print Mode:"),v_prnbufmode=new QComboBox); + v_prnbufmode->addItem(tr("Direct Print")); + v_prnbufmode->addItem(tr("Use Buffer Pixmap")); + v_prnbufmode->setCurrentIndex((int)voucher.printMode()); + //button... + fl->addRow(new QLabel(" ")); + fl->addRow(hl=new QHBoxLayout); + hl->addStretch(1); + QPushButton*b; + hl->addWidget(b=new QPushButton(tr("Ok"))); + d.connect(b,SIGNAL(clicked()),&d,SLOT(accept())); + hl->addWidget(b=new QPushButton(tr("Cancel"))); + d.connect(b,SIGNAL(clicked()),&d,SLOT(reject())); + //show dialog + if(d.exec()!=QDialog::Accepted)return; + //save settings + ticket.storePrinter(t_printer); + ticket.storeAskModes( + (MLabelConfig::PrintAskMode)t_prnmode->currentIndex(), + (MLabelConfig::PageAskMode)t_pagmode->currentIndex() + ); + ticket.storePrintMode((MLabelConfig::PrintMode)t_prnbufmode->currentIndex()); + voucher.storePrinter(v_printer); + voucher.storeAskModes( + (MLabelConfig::PrintAskMode)v_prnmode->currentIndex(), + (MLabelConfig::PageAskMode)v_pagmode->currentIndex() + ); + voucher.storePrintMode((MLabelConfig::PrintMode)v_prnbufmode->currentIndex()); +} + +QString MLabelConfig::tr(const char* s, const char* c) +{ + return QCoreApplication::translate("MLabelConfig",s,c); +} + +QString MLabelConfig::printerName() const +{ + QString key=m_type==Ticket?"ticket":"voucher"; + QSettings set; + set.beginGroup(req->settingsGroup()+"/"+key); + if(!set.contains("name"))return QString(); + return set.value("name").toString(); +} + +bool MLabelConfig::selectPrinter(QPrinter& printer, bool force) +{ + bool gotit=configurePrinter(printer); + if(!force) + switch(printAskMode()){ + case PrintAskAlways:force=true;break; + case PrintAskIfUnknown:if(!gotit)force=true;break; + case PrintAskNever:/*do not override the force*/ break; + } + if(force){ + MLabelPrintDialog pd(&printer); + return pd.exec()==QDialog::Accepted; + }else + return gotit; +} + +QString MLabelConfig::cgroup() const +{ + const QString key=m_type==Ticket?"ticket":"voucher"; + return req->settingsGroup()+"/"+key; +} + +static inline void dumpPrn(QPrinter&p,QString s) +{ + qDebug()<<"printer"< paperTypes; + +void MLabelPrintDialog::initPaper() +{ + if(paperTypes.size())return; + paperTypes=QList() + << Paper_s(tr("Custom Size","paper type"),QPrinter::Custom,0,0) + << Paper_s(tr("A0","paper type"),QPrinter::A0,841,1189) + << Paper_s(tr("A1","paper type"),QPrinter::A1,594,841) + << Paper_s(tr("A2","paper type"),QPrinter::A2,420,594) + << Paper_s(tr("A3","paper type"),QPrinter::A3,297,420) + << Paper_s(tr("A4","paper type"),QPrinter::A4,210,297) + << Paper_s(tr("A5","paper type"),QPrinter::A5,148,210) + << Paper_s(tr("A6","paper type"),QPrinter::A6,105,148) + << Paper_s(tr("A7","paper type"),QPrinter::A7,74,105) + << Paper_s(tr("A8","paper type"),QPrinter::A8,52,74) + << Paper_s(tr("A9","paper type"),QPrinter::A9,37,52) + << Paper_s(tr("B0","paper type"),QPrinter::B0,1000,1414) + << Paper_s(tr("B1","paper type"),QPrinter::B1,707,1000) + << Paper_s(tr("B2","paper type"),QPrinter::B2,500,707) + << Paper_s(tr("B3","paper type"),QPrinter::B3,353,500) + << Paper_s(tr("B4","paper type"),QPrinter::B4,250,353) + << Paper_s(tr("B5","paper type"),QPrinter::B5,176,250) + << Paper_s(tr("B6","paper type"),QPrinter::B6,125,176) + << Paper_s(tr("B7","paper type"),QPrinter::B7,88,125) + << Paper_s(tr("B8","paper type"),QPrinter::B8,62,88) + << Paper_s(tr("B9","paper type"),QPrinter::B9,33,62) + << Paper_s(tr("B10","paper type"),QPrinter::B10,31,44) + << Paper_s(tr("C5E","paper type"),QPrinter::C5E,163,229) + << Paper_s(tr("U.S. Common 10 Envelope","paper type"),QPrinter::Comm10E,105,241) + << Paper_s(tr("DLE","paper type"),QPrinter::DLE,110,220) + << Paper_s(tr("Executive","paper type"),QPrinter::Executive,190.5,254) + << Paper_s(tr("Folio","paper type"),QPrinter::Folio,210,330) + << Paper_s(tr("Ledger","paper type"),QPrinter::Ledger,431.8,279.4) + << Paper_s(tr("Legal","paper type"),QPrinter::Legal,215.9,355.6) + << Paper_s(tr("Letter","paper type"),QPrinter::Letter,215.9,279.4) + << Paper_s(tr("Tabloid","paper type"),QPrinter::Tabloid,279.4,431.8) + ; +} + + + +MLabelPrintDialog::MLabelPrintDialog(QPrinter* prn, QWidget* parent, Qt::WindowFlags f) + : QDialog(parent, f) + , mprinter(prn) +{ + setWindowTitle(tr("Chose Printer")); + QFormLayout*fl; + setLayout(fl=new QFormLayout); + fl->addRow(tr("Printer:"),mprnselect=new QComboBox); + int cur=-1,def=-1; + for(const QPrinterInfo&info:QPrinterInfo::availablePrinters()){ + if(info.printerName()==prn->printerName())cur=mprnselect->count(); + if(info.isDefault())def=mprnselect->count(); + mprnselect->addItem(info.printerName()); + } + if(cur>=0)mprnselect->setCurrentIndex(cur); + else if(def>=0)mprnselect->setCurrentIndex(def); + connect(mprnselect,SIGNAL(currentIndexChanged(int)), this,SLOT(printerChanged(int))); + fl->addRow(tr("Make & Model:"),mmakemodel=new QLabel); + fl->addRow(tr("Location:"),mlocation=new QLabel); + fl->addRow(tr("Description:"),mdescript=new QLabel); + fl->addRow(tr("Unit of Measure:"),munit=new QComboBox); + munit->addItem(tr("Millimeter"),1.); + munit->addItem(tr("Centimeter"),10.); + munit->addItem(tr("Inch"),25.4); + connect(munit,SIGNAL(currentIndexChanged(int)),this,SLOT(unitChanged(int))); + fl->addRow(tr("Paper Type:"),mpaper=new QComboBox); + initPaper(); + cur=0; + for(const auto&paper:paperTypes){ + if(mprinter->paperSize()==paper.ptype)cur=mpaper->count(); + mpaper->addItem(paper.pname,paper.ptype); + } + mpaper->setCurrentIndex(cur); + connect(mpaper,SIGNAL(currentIndexChanged(int)), this,SLOT(paperChanged(int))); + QHBoxLayout*hl; + fl->addRow(tr("Paper Size:"),hl=new QHBoxLayout); + hl->addWidget(msizex=new QDoubleSpinBox,1); + msizex->setRange(0,10000); + hl->addWidget(new QLabel(tr("wide x","paper size: width"))); + hl->addWidget(msizey=new QDoubleSpinBox); + msizey->setRange(0,10000); + hl->addWidget(new QLabel(tr("high","paper size: height"))); + QGridLayout*gl; + fl->addRow(tr("Margins:"),gl=new QGridLayout); + qreal ml,mr,mt,mb; + mprinter->getPageMargins(&ml,&mt,&mr,&mb,QPrinter::Millimeter); + gl->addWidget(mmargtop=new QDoubleSpinBox,0,1); + mmargtop->setValue(mt/moldunit); + gl->addWidget(mmargleft=new QDoubleSpinBox,1,0); + mmargleft->setValue(ml/moldunit); + gl->addWidget(mmargright=new QDoubleSpinBox,1,2); + mmargright->setValue(mr/moldunit); + gl->addWidget(mmargbottom=new QDoubleSpinBox,2,1); + mmargbottom->setValue(mb/moldunit); + fl->addRow(tr("Resolution:"),mresolution=new QComboBox); + fl->addRow(new QLabel(" ")); + fl->addRow(hl=new QHBoxLayout); + hl->addStretch(1); + hl->addWidget(mokbtn=new QPushButton(tr("Print"))); + connect(mokbtn,SIGNAL(clicked(bool)),this,SLOT(okBtnPressed())); + QPushButton *cc; + hl->addWidget(cc=new QPushButton(tr("Cancel"))); + connect(cc,SIGNAL(clicked(bool)),this,SLOT(reject())); + + //make sure it is selected + printerChanged(mprnselect->currentIndex()); + + //reset selected paper type and size from printer + paperChanged(mpaper->currentIndex()); + //reset margins from printer +} + +void MLabelPrintDialog::setButtonLabel(const QString& l) +{ + mokbtn->setText(l); +} + +// QString MLabelPrintDialog::paperSourceStr(int p) +// { +// switch(p){ +// case QPrinter::Auto:return tr("Automatic","paper source"); +// case QPrinter::Cassette:return tr("Cassette","paper source"); +// case QPrinter::Envelope:return tr("Envelope","paper source"); +// case QPrinter::EnvelopeManual:return tr("Manual Envelope","paper source"); +// case QPrinter::FormSource:return tr("Forms","paper source"); +// case QPrinter::LargeCapacity:return tr("Large Capacity","paper source"); +// case QPrinter::LargeFormat:return tr("Large Format","paper source"); +// case QPrinter::Lower:return tr("Lower Tray","paper source"); +// case QPrinter::MaxPageSource:return tr("Maximum Page Source","paper source"); +// case QPrinter::Middle:return tr("Middle Tray","paper source"); +// case QPrinter::Manual:return tr("Manual Feed","paper source"); +// case QPrinter::OnlyOne:return tr("Only One Source","paper source"); +// case QPrinter::Tractor:return tr("Tractor","paper source"); +// case QPrinter::SmallFormat:return tr("Small Format","paper source"); +// default:return tr("Unknown","paper source"); +// } +// } + +void MLabelPrintDialog::printerChanged(int idx) +{ + //get printer + const QString &pname=mprnselect->itemText(idx); + if(pname.isEmpty())return; + //set location and description + const QPrinterInfo info=QPrinterInfo::printerInfo(pname); + if(info.isNull())return; + mmakemodel->setText(info.makeAndModel()); + mlocation->setText(info.location()); + mdescript->setText(info.description()); + //set resolution + QPrinter prn(info); + mresolution->clear(); + const int cur=mresolution->itemData(mresolution->currentIndex()).toInt(); + int curidx=-1; + const int def=prn.resolution(); + int defidx=-1; + for(auto r:prn.supportedResolutions()){ + if(r==cur)curidx=mresolution->count(); + if(r==def)defidx=mresolution->count(); + mresolution->addItem(QString("%1 dpi").arg(r),r); + } + if(curidx>=0)defidx=curidx; + if(defidx>=0)mresolution->setCurrentIndex(defidx); +} + +void MLabelPrintDialog::paperChanged(int idx) +{ + const int ptype=mpaper->itemData(idx).toInt(); + for(const auto&paper:paperTypes){ + if(paper==ptype){ + //set paper size + if(ptype == QPrinter::Custom){ + msizex->setValue(mprinter->pageSizeMM().width()/moldunit); + msizey->setValue(mprinter->pageSizeMM().height()/moldunit); + }else{ + msizex->setValue(paper.psize.width()/moldunit); + msizey->setValue(paper.psize.height()/moldunit); + } + break; + } + } + msizex->setEnabled(ptype==QPrinter::Custom); + msizey->setEnabled(ptype==QPrinter::Custom); +} + +void MLabelPrintDialog::unitChanged(int idx) +{ + const double fac=munit->itemData(idx).toDouble(); + //recalculate everything + msizex->setValue(msizex->value()*moldunit/fac); + msizey->setValue(msizey->value()*moldunit/fac); + mmargbottom->setValue(mmargbottom->value()*moldunit/fac); + mmargleft->setValue(mmargleft->value()*moldunit/fac); + mmargright->setValue(mmargright->value()*moldunit/fac); + mmargtop->setValue(mmargtop->value()*moldunit/fac); + //remember + moldunit=fac; +} + +void MLabelPrintDialog::okBtnPressed() +{ + //save data to printer + mprinter->setPrinterName(mprnselect->itemText(mprnselect->currentIndex())); + mprinter->setPaperSize(QPrinter::PaperSize(mpaper->itemData(mpaper->currentIndex()).toInt())); + mprinter->setPageSizeMM(QSizeF(msizex->value()*moldunit,msizey->value()*moldunit)); + mprinter->setPageMargins(mmargleft->value()*moldunit, mmargtop->value()*moldunit, mmargright->value()*moldunit, mmargbottom->value()*moldunit, QPrinter::Millimeter); + mprinter->setResolution(mresolution->itemData(mresolution->currentIndex()).toInt()); + + //close the dialog + accept(); +} diff --git a/commonlib/templates/labeldlg.h b/commonlib/templates/labeldlg.h new file mode 100644 index 0000000..e3c18f5 --- /dev/null +++ b/commonlib/templates/labeldlg.h @@ -0,0 +1,230 @@ +// +// C++ Interface: labeldlg +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2008-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_LABELDLG_H +#define MAGICSMOKE_LABELDLG_H + +#include "commonexport.h" + +#include +#include +#include + +class QDoubleSpinBox; +class QPaintDevice; +class QCheckBox; +class QComboBox; +class QLineEdit; +class QPrinter; +class QLabel; + +///access to the label specific configuration +class MAGICSMOKE_COMMON_EXPORT MLabelConfig +{ + public: + ///shows the configuration dialog + static void configDialog(QWidget*parent=0); + + ///the type of label whose configuration is being queried + enum LabelType { + ///invalid config object + Invalid=0, + ///ticket label + Ticket=1, + ///voucher label + Voucher=2 + }; + ///instantiate an empty configuration object + MLabelConfig(){initMeta();} + ///instantiates a configuration object for the given label type + MLabelConfig(LabelType lt):m_type(lt){initMeta();} + ///copies the config object + MLabelConfig(const MLabelConfig&lc):m_type(lc.m_type){initMeta();} + ///copies the config object + MLabelConfig& operator=(const MLabelConfig&lc){m_type=lc.m_type;return *this;} + + ///returns the type represented by this config object + LabelType labelType()const{return m_type;} + + ///returns the configured printer name (even if not available on the local system) + QString printerName()const; + + ///configures the QPrinter object to the printer set for this label type; + ///use selectPrinter if you want to fall back to a selection dialog + /// \returns true if the printer was successfully configured + bool configurePrinter(QPrinter&)const; + + ///configures the printer for this particular label type; + ///whether the dialog is shown depends on settings and printer availability; + ///if the dialog is shown the function remembers the new printer settings + /// \param printer pointer to the QPrinter object to be configured + /// \param force if true: force showing the printer dialog + /// \returns true if the selection was successful + bool selectPrinter(QPrinter&printer,bool force=false); + + ///whether to ask for a printer when printing labels + enum PrintAskMode{ + //do not change the order of these entries! + //their numerical value is used as index in configDialog() + ///always ask for a printer + PrintAskAlways=0, + ///only ask if the currently set printer is not known/connected + PrintAskIfUnknown=1, + ///never ask for a printer, just fail if the printer is unavailable + PrintAskNever=2 + }; + ///whether to ask for the page layout when printing labels + enum PageAskMode{ + //do not change the order of these entries! + //their numerical value is used as index in configDialog() + ///always ask + PageAskAlways=0, + ///only ask if there are more than 1 labels on the page + PageAskIfNeeded=1, + ///never ask, just assume the whole page is available + PageAskNever=2, + }; + + ///returns the policy for asking for a printer + PrintAskMode printAskMode()const; + + ///returns the policy for asking for page layout + PageAskMode pageAskMode()const; + + ///how to send data to the printer + enum PrintMode{ + //do not change the order of these entries! + //their numerical value is used as index in configDialog() + ///print directly through the printer driver + PrintDirect=0, + ///use a buffer pixmap to render fonts/graphics in memory first + PrintPixmap=1 + }; + + ///returns how to send data to the printer + PrintMode printMode()const; + + private: + LabelType m_type; + static QString tr(const char*,const char*c=0); + + /// \internal helper to store printer settings for next time + void storePrinter(QPrinter&); + /// \internal helper to store ask modes + void storeAskModes(PrintAskMode,PageAskMode); + /// \internal helper to store print mode + void storePrintMode(PrintMode); + /// \internal return the config group + QString cgroup()const; + + /// \internal initialize meta type info + void initMeta(); + + friend QDataStream&operator<<(QDataStream&,const MLabelConfig&); + friend QDataStream&operator>>(QDataStream&,MLabelConfig&); +}; +MAGICSMOKE_COMMON_EXPORT QDataStream &operator<<(QDataStream &out, const MLabelConfig &myObj); +MAGICSMOKE_COMMON_EXPORT QDataStream &operator>>(QDataStream &in, MLabelConfig &myObj); + +Q_DECLARE_METATYPE(MLabelConfig); + +///dialog that allows to select which labels on a sheet of paper are used +class MAGICSMOKE_COMMON_EXPORT MLabelDialog:public QDialog +{ + Q_OBJECT + public: + /**creates a label dialog*/ + MLabelDialog(QWidget*parent,QPrinter*printer,int numlabels,QSizeF labelsize); + /**deletes the label dialog and stores its current settings*/ + ~MLabelDialog(); + + /**returns the offset of label number n; relative to the coordinate system of the given paint device; starts at the bottom left of the page*/ + QPointF labelOffset(int n)const; + /**returns whether this label is on a new page*/ + bool labelNeedsPageTurn(int n)const; + ///returns whether there is only one label per page + bool oneLabelPerPage()const; + + ///configures the printer for this particular label type + ///whether the dialog is shown depends on settings and printer availability + /// \param type type of label + /// \param printer pointer to the QPrinter object to be configured + /// \param force if true: force showing the printer dialog + /// \returns true if the selection was successful + static inline bool selectPrinter(MLabelConfig::LabelType type, QPrinter&printer, bool force=false) + {return MLabelConfig(type).selectPrinter(printer,force);} + + public slots: + ///shows the dialog if necessary - this depends on the local configuration for + ///this label type + ///if not shown it returns true (presuming the user would have wanted to print) + ///if shown it returns true if the user clicked "Ok" and false otherwise + bool conditionalExec(MLabelConfig::LabelType); + + private slots: + /**internal: toggle Row button clicked*/ + void toggleRow(int); + /**internal: toggle Column button clicked*/ + void toggleColumn(int); + /**internal: toggle all button clicked*/ + void toggleAll(); + + /**internal: display correct page*/ + void updatePage(); + /**helper: save current/old page*/ + void savePage(); + /**internal: save settings for next time*/ + void saveSettings(); + + private: + QLineEdit *offx,*offy,*sizex,*sizey; + QLabel *warning; + QSizeF labelsize; + QComboBox *metric,*page; + QListchecks; + QList >checked; + QPrinter* printer; + int numlabels,oldpage,maxrows,maxcols; + + /**internal helper: find coordinates of label n; returns page id; returns -1 on failure*/ + int findLabel(int n,int&row,int&col)const; +}; + + +///Dialog that allows to configure details on how to print a label. +class MAGICSMOKE_COMMON_EXPORT MLabelPrintDialog:public QDialog +{ + Q_OBJECT + public: + explicit MLabelPrintDialog(QPrinter*,QWidget* parent = 0, Qt::WindowFlags f = 0); + public slots: + void setButtonLabel(const QString&); + private slots: + void printerChanged(int); + void paperChanged(int); + void unitChanged(int); + + void okBtnPressed(); + private: + QPrinter*mprinter; + QComboBox*mprnselect,*mresolution,*mpaper,*munit; + QDoubleSpinBox*mmargleft,*mmargright,*mmargtop,*mmargbottom; + QDoubleSpinBox*msizex,*msizey; + QLabel*mdescript,*mlocation,*mmakemodel; + QPushButton*mokbtn; + double moldunit=1.; + + //internal: initialize paper types + void initPaper(); +}; + +#endif diff --git a/commonlib/templates/odtrender.cpp b/commonlib/templates/odtrender.cpp new file mode 100644 index 0000000..18e8ba8 --- /dev/null +++ b/commonlib/templates/odtrender.cpp @@ -0,0 +1,500 @@ +// +// C++ Implementation: odtrender +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2008-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "misc.h" +#include "odtrender.h" +#include "office.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "formula.h" +using namespace ELAM; + +class MOdfEngine:public MElamEngine +{ + MOdtRenderer*parent; + public: + MOdfEngine(MOdtRenderer* pa):parent(pa) + { + CharacterClassSettings cs=characterClasses(); + cs.setAssignmentChars(0,'='); + cs.setOperatorClass(cs.operatorClass().remove(':')); + QPairnc=cs.nameClass(); + nc.second+=':'; + cs.setNameClass(nc); + } + bool hasConstant(QString v)const + { + if(parent->getVariable(v).isValid()) + return true; + else + return MElamEngine::hasConstant(v); + } + QVariant getConstant(QString v)const + { + QVariant vv=parent->getVariable(v); + if(vv.isValid()) + return vv; + else + return MElamEngine::getConstant(v); + } +}; + +class MOdtRendererPrivate +{ + protected: + friend class MOdtRenderer; + + //methods that the parent uses + MOdtRendererPrivate(QString file,MOdtRenderer*p); + ~MOdtRendererPrivate(); + + bool renderToFile(QFile&); + + //data the parent uses + QString extension; + MOdtRenderer::FileFormat fileformat; + + private: + //methods that the parent does not call + + ///overall rendering: copies the templates content, calls render() + void render(QIODevice*); + + ///content.xml rendering + QList render(QDomNode node); + + ///scan string and replace variable values + QString renderString(QString); + + ///gets a scalar variable + QString getVariable(QString varname); + + //data the parent does not access + //parent + MOdtRenderer*parent; + //the template file + Unzip temp; + QFile tfile; + //xml representation of the content.xml file in the template + QDomDocument cdoc; + + //local variables and calculation engine + Engine *calc; +}; + +MOdtRenderer::MOdtRenderer(MTemplate file) +{ + d=new MOdtRendererPrivate(file.cacheFileName(),this); + d->extension=file.targetExtension(); + d->calc=new MOdfEngine(this); +} + +const QString OdfTemplateNS("http://smoke.silmor.de/odftemplate/namespace"); +const QString OdfTemplatePrefix("msmoketpl"); +MOdtRendererPrivate::MOdtRendererPrivate(QString file,MOdtRenderer*p) + :fileformat(MOdtRenderer::FileFormat::None),tfile(file) +{ + parent=p; + //open ZIP + if(tfile.open(QIODevice::ReadOnly))temp.open(&tfile); + else { + qDebug()<<"Error opening ODF template file"<calc!=nullptr)delete d->calc; + d->calc=nullptr; + delete d; + d=nullptr; +} +MOdtRendererPrivate::~MOdtRendererPrivate() +{ + temp.close(); + tfile.close(); +} + +MOdtRenderer::FileFormat MOdtRenderer::fileFormat()const +{ + return d->fileformat; +} + +void MOdtRenderer::renderToFile(QString file) +{ + QFile f(file); + if(f.open(QIODevice::ReadWrite)){ + renderToFile(f); + f.close(); + } +} + +void MOdtRenderer::renderToFile(QFile &file) +{ + if(d->renderToFile(file)) + if(QSettings().value("doOpenODFs",false).toBool()) + openOfficeFile(file.fileName()); +} +bool MOdtRendererPrivate::renderToFile(QFile &file) +{ + if(!file.isWritable()) + if(!file.open(QIODevice::ReadWrite))return false; + file.seek(0); + file.resize(0); + render(&file); + return true; +} + +void MOdtRenderer::renderToPrinter() +{ + //generate temporary file + QTemporaryFile tfile; + tfile.setAutoRemove(false);//we don't want it to be auto-deleted on close() + tfile.setFileTemplate(QDir::tempPath()+"/msmoke_XXXXXX."+d->extension); + tfile.open(); + QString tname=tfile.fileName(); + //render + d->renderToFile(tfile); + tfile.close(); + //call ooffice and print + printOfficeFile(tname); + //remove temporary file + QFile(tname).remove(); +} + +void MOdtRendererPrivate::render(QIODevice*out) +{ + //sanity check + if(!temp.isOpen()){ + qDebug()<<"ODF Renderer: I don't have a valid template, cannot render."; + return; + } + if(!out->isWritable()){ + qDebug()<<"ODF Renderer Ooops: output device not writeable when trying to render."; + return; + } + //rewind input + if(!temp.firstFile())return; + //create output + Zip ozip; + ozip.open(out); + //copy contents + do{ + ZipFileInfo info= temp.currentFile(); + if(info.fileName()=="content.xml"){ + //render + QByteArray cont=render(cdoc.cloneNode()).value(0).toDocument().toByteArray(); + //write + QBuffer buffer; + buffer.setData(cont); + buffer.open(QBuffer::ReadWrite); + buffer.seek(0); + ozip.storeFile(info.fileName(),buffer,info.createTime()); + }else{ + //copy unchanged + temp.copyCurrentFile(ozip); + } + }while(temp.nextFile()); + ozip.close(); +} + +static inline QList n2q(const QDomNodeList&nl){ + QListret; + for(int i=0;i MOdtRendererPrivate::render(QDomNode node) +{ + //trivial cases + if(node.isComment()||node.isDocumentType()||node.isNotation()||node.isProcessingInstruction()){ + qDebug()<<"trivial type"<<(int)node.nodeType()<()<()<ret; + if(tnl.value(1)=="if"){ +// qDebug()<<"????????it's a bit iffy"<evaluate(el.attribute("select")); + if(!res.canConvert()){ + qDebug()<<"!!!!!!!! ODF Engine error: if has been called with instructions that do not convert to bool"< tag found, ignoring it."; + }else if(tnl.value(1)=="calculate"){ +// qDebug()<<"????????calculatin'"<evaluate(form); + qDebug()<<"!!!!!!!! ODF Engine Calculation"<getLoopIterations(lvn); + qDebug()<<"!!!!!!!! entering loop"<setLoopIteration(lvn,i); + foreach(QDomNode nd,n2q(nl)) + if(nd.isElement()) + ret<()<ret; + if(node.isText()) + ret<()<0) + ret+=calc->evaluate(vname).toString(); + else + ret+="@"; + //reset mode + isvar=false; + vname=""; + }else + //continuation of var + vname+=c; + }else{//not inside variable name + //is this the start of a var? + if(c=='@'){ + isvar=true; + vname=""; + }else{ + ret+=c; + } + } + } + //anything left over? + if(isvar){ + //reset + ret+="@"+vname; + } + //return transformed line + return ret; +} + +QByteArray MOdtRenderer::convertV1toV2(const QByteArray& old) +{ + QByteArray nba; + QListolst=old.split('\n'); + bool hstarted=false; + foreach(QByteArray line,olst){ + //is this the start of the file? + if(!hstarted){ + QByteArray st=line.trimmed().left(2); + //find the first real tag and insert the new start tag there + if(st!="\n"; + hstarted=true; + } + //add the line just scanned... + nba+=line; + nba+='\n'; + continue; + } + //is this a special line? + QByteArray lnt=line.trimmed(); + if(lnt.size()>1 && lnt.at(0)=='#'){ + //extract command + int cnt=lnt.indexOf(':'); + QByteArray parm; + if(cnt>0){ + parm=lnt.mid(cnt+1); + lnt=lnt.left(cnt); +// qDebug()<<"found command"<"; + }else if(lnt=="#ELSE") + nba+=""; + else if(lnt=="#ENDIF") + nba+=""; + else if(lnt=="#SETNEWLINE"){ + nba+=""; + }else if(lnt=="#CALC"){ + nba+=""; + }else if(lnt=="#LOOP"){ + nba+=""; + }else if(lnt=="#ENDLOOP"){ + nba+=""; + }else{ + nba+=""; + } + }else //no, not special: just store it + nba+=line; + //add a newline anyway + nba+='\n'; + } + //close the template + nba+=""; +// qDebug()<<"conversion test"<, (C) 2008-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_ODTRENDER_H +#define MAGICSMOKE_ODTRENDER_H + +#include +#include + +#include "templates.h" +#include "commonexport.h" + +class MOdtRendererPrivate; +class QFile; + +MAGICSMOKE_COMMON_EXPORT extern const QString OdfTemplateNS; +MAGICSMOKE_COMMON_EXPORT extern const QString OdfTemplatePrefix; + +/**abstract base class for all ODT rendering classes*/ +class MAGICSMOKE_COMMON_EXPORT MOdtRenderer +{ + public: + /**instantiates a renderer loaded from template file*/ + MOdtRenderer(MTemplate file); + /**deletes the renderer*/ + virtual ~MOdtRenderer(); + + /**starts the internal rendering routine and outputs to file*/ + virtual void renderToFile(QString file); + + /**starts the internal rendering routine and outputs to file*/ + virtual void renderToFile(QFile& file); + + /**starts the internal rendering routine and outputs to printer (calls OpenOffice to print)*/ + virtual void renderToPrinter(); + + ///helper routine: converts a V1 template to V2 + ///you have to make sure to not do a double conversion on an already converted document + static QByteArray convertV1toV2(const QByteArray&); + + ///format of the file represented by this renderer + enum class FileFormat{ + ///no file loaded or loading was not successful + None, + ///file was a valid v2 format + Version2, + ///file was probably v1 or plain ODF, it has been converted + ConvertedV1, + }; + ///returns the format of the file + FileFormat fileFormat()const; + + protected: + friend class MOdtRendererPrivate; + friend class MOdfEngine; + /**implement this to return the value of a variable during rendering; should return empty string if the variable does not exist*/ + virtual QVariant getVariable(QString varname)=0; + + /**implement this to return the amount of iterations for a defined loop; should return 0 if the loop does not exist*/ + virtual int getLoopIterations(QString loopname)=0; + + /**implement this to populate the variables used in a specific iteration of the loop*/ + virtual void setLoopIteration(QString loopname, int interation)=0; + private: + MOdtRendererPrivate*d; +}; + +/**generic class that implements MOdtRenderer by calling signals; the signals must be connected using a direct or blocking connection; if any of them is not used it will behave as if the variable/loop did not exist*/ +class MAGICSMOKE_COMMON_EXPORT MOdtSignalRenderer:public QObject,public MOdtRenderer +{ + Q_OBJECT + public: + /**instantiates a renderer loaded from template file*/ + MOdtSignalRenderer(MTemplate file); + /**deletes the renderer*/ + ~MOdtSignalRenderer(); + + signals: + /**connect this to return the value of a variable during rendering; should return empty string if the variable does not exist*/ + void getVariable(QString varname,QVariant&value); + + /**connect this to return the amount of iterations for a defined loop; should return 0 if the loop does not exist*/ + void getLoopIterations(QString loopname,int&iterations); + + void setLoopIteration(QString loopname, int interation); + + protected: + QVariant getVariable(QString varname); + int getLoopIterations(QString loopname); +}; + +#endif diff --git a/commonlib/templates/office.cpp b/commonlib/templates/office.cpp new file mode 100644 index 0000000..398b855 --- /dev/null +++ b/commonlib/templates/office.cpp @@ -0,0 +1,181 @@ +// +// C++ Implementation: office +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2008-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "office.h" +#include "misc.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static QString getofficepath() +{ + return QSettings().value("officePath","soffice").toString(); +} + +void openOfficeFile(QString fname) +{ + //calculate parameters + QStringList r; + if(QSettings().value("officeViewOnly",false).toBool())r<<"-view"; + r<addWidget(new QLabel(QCoreApplication::translate("office","Please chose a printer:")),0); + QComboBox*printer; + vl->addWidget(printer=new QComboBox,0); + printer->setEditable(false); + printer->addItem(QCoreApplication::translate("office","(Default Printer)")); + QListaprn=QPrinterInfo::availablePrinters(); + int cprn=0; + for(int i=0;iaddItem(s); + if(s==prn)cprn=i+1; + } + printer->setCurrentIndex(cprn); +// qDebug()<<"printer selection"<addSpacing(10); + vl->addStretch(1); + QHBoxLayout*hl; + vl->addLayout(hl=new QHBoxLayout,0); + hl->addStretch(10); + QPushButton*p; + hl->addWidget(p=new QPushButton(QCoreApplication::translate("office","Ok"))); + QObject::connect(p,SIGNAL(clicked()),&d,SLOT(accept())); + d.exec(); + if(printer->currentIndex()==0)prn=""; + else prn=printer->currentText(); +} + +void printOfficeFile(QString fname) +{ + //calculate parameters + QStringList r; + QString p=QSettings().value("officePrinter","").toString(); + if(QSettings().value("officePrinterConfirm",false).toBool())confirmPrinter(p); + if(p=="")r<<"-p"; + else r<<"-pt"<addWidget(gb=new QGroupBox(tr("OpenOffice.org"))); + gb->setLayout(hl=new QHBoxLayout); + hl->addWidget(new QLabel(tr("Path to Executable:"))); + hl->addWidget(oopath=new QLineEdit(set.value("officePath","soffice").toString()),1); + hl->addWidget(p=new QPushButton(tr("...","select OpenOffice path button"))); + connect(p,SIGNAL(clicked()),this,SLOT(selectpath())); + + vl->addWidget(gb=new QGroupBox(tr("Printing ODF"))); + gb->setLayout(vl2=new QVBoxLayout); + vl2->addLayout(hl=new QHBoxLayout); + hl->addWidget(new QLabel(tr("Printer:"))); + hl->addWidget(printer=new QComboBox,1); + printer->setEditable(false); + printer->addItem(tr("(Default Printer)")); + QListaprn=QPrinterInfo::availablePrinters(); + int cprn=0; + QString cp=set.value("officePrinter","").toString(); + for(int i=0;iaddItem(s); + if(cp==s)cprn=i+1; + } + printer->setCurrentIndex(cprn); + vl2->addWidget(askprint=new QCheckBox(tr("Always confirm printer when printing ODF"))); + askprint->setChecked(set.value("officePrinterConfirm",false).toBool()); + vl2->addWidget(saveprint=new QCheckBox(tr("Save printed files"))); + saveprint->setChecked(set.value("officePrinterSave",false).toBool()); + + vl->addWidget(gb=new QGroupBox(tr("Opening ODF"))); + gb->setLayout(vl2=new QVBoxLayout); + vl2->addWidget(viewonly=new QCheckBox(tr("Always open as Read-Only"))); + viewonly->setChecked(set.value("officeViewOnly",false).toBool()); + vl2->addWidget(doopen=new QCheckBox(tr("Automatically open all newly created files"))); + doopen->setChecked(set.value("doOpenODFs",false).toBool()); + + vl->addSpacing(15); + vl->addLayout(hl=new QHBoxLayout); + hl->addStretch(1); + hl->addWidget(p=new QPushButton(tr("OK"))); + connect(p,SIGNAL(clicked()),this,SLOT(accept())); + connect(p,SIGNAL(clicked()),this,SLOT(savedata())); + hl->addWidget(p=new QPushButton(tr("Cancel"))); + connect(p,SIGNAL(clicked()),this,SLOT(reject())); +} + +void MOfficeConfig::savedata() +{ + QSettings set; + int cprn=printer->currentIndex(); + if(cprn==0)set.setValue("officePrinter",""); + else set.setValue("officePrinter",printer->currentText()); + + set.setValue("officePath",oopath->text()); + set.setValue("officeViewOnly",viewonly->isChecked()); + set.setValue("doOpenODFs",doopen->isChecked()); + set.setValue("officePrinterConfirm",askprint->isChecked()); + set.setValue("officePrinterSave",saveprint->isChecked()); +} + +void MOfficeConfig::selectpath() +{ + QString np=QFileDialog::getOpenFileName(this,tr("Select OpenOffice.org executable"),QFileInfo(oopath->text()).dir().absolutePath()); + if(np!=""){ + oopath->setText(np); + setCurrentDir(np); + } +} diff --git a/commonlib/templates/office.h b/commonlib/templates/office.h new file mode 100644 index 0000000..3af1de7 --- /dev/null +++ b/commonlib/templates/office.h @@ -0,0 +1,49 @@ +// +// C++ Interface: office +// +// Description: Wrapper and Config Dialog around OpenOffice.org +// +// +// Author: Konrad Rosenbaum , (C) 2008-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_OFFICE_H +#define MAGICSMOKE_OFFICE_H + +#include + +/**calls OpenOffice.org to open an ODF file*/ +void openOfficeFile(QString fname); + +/**calls OpenOffice.org to print an ODF file*/ +void printOfficeFile(QString fname); + +#include + +#include "commonexport.h" + +class QComboBox; +class QCheckBox; +class QLineEdit; + +/**configuration dialog for OpenOffice access*/ +class MAGICSMOKE_COMMON_EXPORT MOfficeConfig:public QDialog +{ + Q_OBJECT + public: + MOfficeConfig(QWidget*); + + private slots: + void savedata(); + void selectpath(); + private: + QComboBox*printer; + QCheckBox*viewonly,*doopen,*askprint,*saveprint; + QLineEdit*oopath; +}; + + +#endif diff --git a/commonlib/templates/templates.pri b/commonlib/templates/templates.pri new file mode 100644 index 0000000..6cc1d4f --- /dev/null +++ b/commonlib/templates/templates.pri @@ -0,0 +1,13 @@ +HEADERS += \ + $$PWD/odtrender.h \ + $$PWD/ticketrender.h \ + $$PWD/office.h \ + $$PWD/labeldlg.h + +SOURCES += \ + $$PWD/odtrender.cpp \ + $$PWD/ticketrender.cpp \ + $$PWD/office.cpp \ + $$PWD/labeldlg.cpp + +INCLUDEPATH += $$PWD diff --git a/commonlib/templates/ticketrender.cpp b/commonlib/templates/ticketrender.cpp new file mode 100644 index 0000000..2d31ae6 --- /dev/null +++ b/commonlib/templates/ticketrender.cpp @@ -0,0 +1,604 @@ +// +// C++ Implementation: odtrender +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2008-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "ticketrender.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "code39.h" + +#include "MOTicket" +#include "MOVoucher" + + +class MLabelRendererPrivate +{ + protected: + friend class MLabelRenderer; + + MLabelRendererPrivate(QString file,MLabelRenderer*p); + ~MLabelRendererPrivate(); + + //part of the constructor + void prepare(Unzip&); + + //called by MLabelRenderer + bool render(const MLabel&,QPaintDevice&,QPainter*,QPointF); + + //called by MLabelRenderer + QSizeF labelSize(const QPaintDevice&); + + private: + MLabelRenderer*parent; + //internal font-IDs + QList fdb; + QMapfdbl; + QMapgetfontdb; + //image cache: + QMap idb; + //XML template cache (template.xml) + QDomDocument txml; + //contains the unit of measurement + QString unit; + //contains the size of the Label in "unit" + QSizeF tsize; + //after constructor: contains whether this object is correctly initialized + bool canrender; + + //does the actual rendering work + void render(QDomElement&,const MLabel&,QPaintDevice&,QPainter*,QPointF); + + //renders a single line + QString renderLine(const MLabel&,QString); + + //parses element to extract offset + QPointF getoffset(QDomElement&,bool); + + //parses element to extract size + QSizeF getsize(QDomElement&,bool); + + //converts a point to "natural" coordinates + QPointF tonatural(const QPaintDevice&,QPointF); + + //converts a size to "natural" coordinates + QSizeF tonatural(const QPaintDevice&,QSizeF); + + //converts a size to "natural" coordinates + QSizeF tonatural(int dpi,QSizeF); + + //returns a system font name + QString getfont(QString); +}; + +MLabelRenderer::MLabelRenderer(MTemplate file) +{ + d=new MLabelRendererPrivate(file.cacheFileName(),this); +} + +MLabelRendererPrivate::MLabelRendererPrivate(QString file,MLabelRenderer*p) +{ + parent=p; + canrender=false; + //open ZIP + Unzip temp; + QFile tfile(file); + if(tfile.open(QIODevice::ReadOnly))temp.open(&tfile); + else return; + prepare(temp); + temp.close(); + tfile.close(); + qDebug("Label Renderer initialized: %s",canrender?"ready!":"error, can't render."); +} + +void MLabelRendererPrivate::prepare(Unzip&temp) +{ + //make sure this is a valid ZIP file + if(!temp.locateFile("template.xml")){ + qDebug("Label renderer: can't find template.xml"); + canrender=false; + return; + } + //load XML + QBuffer buffer; + buffer.open(QBuffer::ReadWrite); + temp.currentFile(buffer); + if(!txml.setContent(buffer.data())){ + qDebug("Label renderer: can't parse template.xml - XML fault."); + canrender=false; + return; + } + //assume we can render now + canrender=true; + //parse document element + QDomElement doc=txml.documentElement(); + unit=doc.attribute("unit","mm"); + if(unit!="mm"&&unit!="in"){ + qDebug("Label renderer: illegal unit in template.xml."); + canrender=false; + return; + } + tsize=getsize(doc,true); + if(!canrender)return; + //check for fonts + QDomNodeList nl=txml.elementsByTagName("LoadFont"); + QStringList fndb; + for(int i=0;itonatural(600,d->tsize); + QImage map(sz.toSize(),QImage::Format_RGB32); + map.setDotsPerMeterX(23622); + map.setDotsPerMeterY(23622); + map.fill(Qt::white); + // render to pixmap + success=d->render(label,map,nullptr,QPointF()); + // render to pdev + if(success){ + QPainter*paint=painter; + if(!painter)paint=new QPainter(&pdev); + QSizeF nsize=d->tonatural(pdev,d->tsize); + paint->setClipRect(QRectF(offset,nsize)); + paint->drawImage(QRectF(offset,nsize).toRect(),map,QRectF(QPointF(),map.size())); + if(!painter)delete paint; + } + }else + success=d->render(label,pdev,painter,offset); + return success; +} + +bool MLabelRendererPrivate::render(const MLabel&label,QPaintDevice&pdev,QPainter*painter,QPointF offset) +{ + //sanity check + if(!canrender){ + qDebug("Label Renderer: render called, but can't render."); + return false; + } + //actually render + QDomElement el=txml.documentElement(); + render(el,label,pdev,painter,offset); + //return result (canrender may be changed by renderer + return canrender; +} + +QPointF MLabelRendererPrivate::getoffset(QDomElement&el,bool isfatal) +{ + QStringList off=el.attribute("offset").split(" "); + if(off.size()!=2){ + if(isfatal){ + qDebug("Label renderer error: Illegal offset in %s at line %i column %i.",el.tagName().toLatin1().data(),el.lineNumber(),el.columnNumber()); + canrender=false; + } + return QPointF(); + } + QPointF ret; + bool b; + ret.setX(off[0].toDouble(&b)); + if(!b){ + if(isfatal){ + qDebug("Label renderer error: Illegal offset in %s at line %i column %i.",el.tagName().toLatin1().data(),el.lineNumber(),el.columnNumber()); + canrender=false; + } + return QPointF(); + } + ret.setY(off[1].toDouble(&b)); + if(!b){ + if(isfatal){ + qDebug("Label renderer error: Illegal offset in %s at line %i column %i.",el.tagName().toLatin1().data(),el.lineNumber(),el.columnNumber()); + canrender=false; + } + return QPointF(); + } + return ret; +} + +QSizeF MLabelRendererPrivate::getsize(QDomElement&el,bool isfatal) +{ + QStringList lst=el.attribute("size").split(" "); + if(lst.size()!=2){ + if(isfatal){ + qDebug("Label renderer error: Illegal size (%i items) in %s at line %i column %i.",lst.size(),el.tagName().toLatin1().data(),el.lineNumber(),el.columnNumber()); + canrender=false; + } + return QSizeF(); + } + QSizeF ret; + bool b; + ret.setWidth(lst[0].toDouble(&b)); + if(!b){ + if(isfatal){ + qDebug("Label renderer error: Illegal size (invalid width) in %s at line %i column %i.",el.tagName().toLatin1().data(),el.lineNumber(),el.columnNumber()); + canrender=false; + } + return QSizeF(); + } + ret.setHeight(lst[1].toDouble(&b)); + if(!b){ + if(isfatal){ + qDebug("Label renderer error: Illegal size (invalid height) in %s at line %i column %i.",el.tagName().toLatin1().data(),el.lineNumber(),el.columnNumber()); + canrender=false; + } + return QSizeF(); + } + return ret; +} + +QPointF MLabelRendererPrivate::tonatural(const QPaintDevice&dev,QPointF p) +{ + double fac; + if(unit=="mm")fac=25.4; + else fac=1.0; + p.setX(p.x()*dev.logicalDpiX()/fac); + p.setY(p.y()*dev.logicalDpiY()/fac); + return p; +} + +QSizeF MLabelRendererPrivate::tonatural(const QPaintDevice&dev,QSizeF s) +{ + double fac; + if(unit=="mm")fac=25.4; + else fac=1.0; + s.setWidth(s.width()*dev.logicalDpiX()/fac); + s.setHeight(s.height()*dev.logicalDpiY()/fac); + return s; +} + +QSizeF MLabelRendererPrivate::tonatural(int dpi,QSizeF s) +{ + double fac; + if(unit=="mm")fac=25.4; + else fac=1.0; + s.setWidth(s.width()*dpi/fac); + s.setHeight(s.height()*dpi/fac); + return s; +} + +void MLabelRendererPrivate::render(QDomElement&sup, const MLabel&tick, QPaintDevice&pdev, QPainter*painter, QPointF noff) +{ + //initialize painter + QPainter *paint; + if(painter) + paint=painter; + else + paint=new QPainter(&pdev); + QSizeF nsize=tonatural(pdev,tsize); + paint->setClipRect(QRectF(noff,nsize)); + //parse file + QDomNodeList nl=sup.childNodes(); + for(int i=0;idrawImage(QRectF(tonatural(pdev,off)+noff,tonatural(pdev,sz)),img); + }else + if(enm=="Text"){ + //get attributes + QPointF off=getoffset(el,true); + if(!canrender){ + return; + } + QSizeF sz=getsize(el,true); + if(!canrender){ + return; + } + //get text + QString text=renderLine(tick,el.text().trimmed()); + //get font; TODO: introduce weight and italic settings + QString font=getfont(el.attribute("font","%")); + int size=el.attribute("fontsize","10").toInt(); + if(size<1)size=10; + paint->setFont(QFont(font,size)); + //get alignment + int flag=0; + QString al=el.attribute("align","left"); + if(al=="left")flag=Qt::AlignLeft;else + if(al=="right")flag=Qt::AlignRight; + else flag=Qt::AlignHCenter; + al=el.attribute("valign","top"); + if(al=="top")flag|=Qt::AlignTop;else + if(al=="bottom")flag|=Qt::AlignBottom; + else flag|=Qt::AlignVCenter; + //render + paint->drawText(QRectF(tonatural(pdev,off)+noff,tonatural(pdev,sz)),flag,text); + qDebug("test %s",text.toLatin1().data()); + }else + if(enm=="Barcode"){ + //get attributes + QPointF off=getoffset(el,true); + if(!canrender){ + return; + } + QSizeF sz=getsize(el,true); + if(!canrender){ + return; + } + QString cd=tick.getVariable("BARCODE"); + //paint + //TODO: find a way to switch off antialiasing + QRectF rect(tonatural(pdev,off)+noff,tonatural(pdev,sz)); + paint->drawImage(rect,code39(cd)); + }else{ + qDebug("Label renderer error: unknown element %s in label template at line %i column %i.",enm.toLatin1().data(),el.lineNumber(),el.columnNumber()); + canrender=false; + return; + } + } + if(!painter) + delete paint; +} + +QString MLabelRendererPrivate::getfont(QString fnt) +{ + QString dfont=QSettings().value("defaultfont","Helvetica").toString(); + //did we already answer this? + if(getfontdb.contains(fnt))return getfontdb[fnt]; + if(fnt=="%")return dfont; + //is it a file name? + if(fnt.size())if(fnt[0]=='@'){ + QString font; + QString fnt2=fnt.mid(1); + if(fdbl.contains(fnt2))if(fdbl[fnt2].size()) + font=fdbl[fnt2][0]; + if(font.isEmpty()){ + qDebug("Label renderer warning: font file %s did not contain font families, using %s instead.",fnt.toLatin1().data(),dfont.toLatin1().data()); + font=dfont; + } + getfontdb.insert(fnt,font); + } + if(!getfontdb.contains(fnt)){ + QStringList fonts=QFontDatabase().families(); + if(!fonts.contains(fnt)){ + qDebug("Label renderer warning: font %s not found, searching a close match...",fnt.toLatin1().data()); + QString font; + for(int i=0;ilabelSize(dev); +} + +QSizeF MLabelRendererPrivate::labelSize(const QPaintDevice&dev) +{ + return tonatural(dev,tsize); +} + +MLabel::MLabel(){} +MLabel::~MLabel(){} + +class MTicketLabel:public MLabel +{ + public: + MTicketLabel(const MOTicket&t):tick(t){} + QString getVariable(QString var)const; + private: + MOTicket tick; +}; + + +//WARNING: if you add anything here, make sure you simulate it in ticketedit.cpp +QString MTicketLabel::getVariable(QString var)const +{ + if(var=="TICKETID"||var=="BARCODE")return tick.ticketid(); + if(var=="PRICE")return tick.priceString(); + if(var=="DATETIME")return tick.event().startTimeString(); + if(var=="ROOM")return tick.event().room(); + if(var=="TITLE")return tick.event().title(); + if(var=="ARTIST")return tick.event().artist().value().name(); + if(var=="PRICECATEGORY")return tick.priceCategoryName(); + if(var=="PRICECATEGORYABBR")return tick.priceCategoryShort(); + return ""; +} + +MTicketRenderer::MTicketRenderer(MTemplate f):MLabelRenderer(f){} +bool MTicketRenderer::render(const MOTicket&label,QPaintDevice&pdev,QPainter*painter,QPointF offset,bool usePixmap) +{ + return MLabelRenderer::render(MTicketLabel(label),pdev,painter,offset,usePixmap); +} + +class MVoucherLabel:public MLabel +{ + public: + MVoucherLabel(const MOVoucher&t):vouc(t){} + QString getVariable(QString var)const; + private: + MOVoucher vouc; +}; + +//WARNING: if you add anything here, make sure you simulate it in ticketedit.cpp +QString MVoucherLabel::getVariable(QString var)const +{ + if(var=="VOUCHERID"||var=="BARCODE")return vouc.voucherid(); + if(var=="PRICE")return vouc.priceString(); + if(var=="VALUE")return vouc.valueString(); + return ""; +} + +MVoucherRenderer::MVoucherRenderer(MTemplate f):MLabelRenderer(f){} +bool MVoucherRenderer::render(const MOVoucher&label,QPaintDevice&pdev,QPainter*painter,QPointF offset,bool usePixmap) +{ + return MLabelRenderer::render(MVoucherLabel(label),pdev,painter,offset,usePixmap); +} diff --git a/commonlib/templates/ticketrender.h b/commonlib/templates/ticketrender.h new file mode 100644 index 0000000..5e2a408 --- /dev/null +++ b/commonlib/templates/ticketrender.h @@ -0,0 +1,82 @@ +// +// C++ Interface: odtrender +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2008-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_TICKETRENDER_H +#define MAGICSMOKE_TICKETRENDER_H + +#include +#include +#include + +#include "templates.h" + +class MLabelRendererPrivate; +class MOTicket; +class MOVoucher; +class QPaintDevice; +class QPainter; + +#include "commonexport.h" + +/**base class that describes labels*/ +class MAGICSMOKE_COMMON_EXPORT MLabel +{ + public: + /**constructs the label*/ + MLabel(); + /**deconstructs the label*/ + virtual ~MLabel(); + + /**abstract: overwrite this to return data for a label*/ + virtual QString getVariable(QString)const=0; +}; + +/**base class for all label rendering classes*/ +class MAGICSMOKE_COMMON_EXPORT MLabelRenderer +{ + public: + /**instantiates a renderer loaded from template file*/ + MLabelRenderer(MTemplate file); + /**deletes the renderer*/ + virtual ~MLabelRenderer(); + + /**renders the ticket; returns whether the rendering was successful*/ + virtual bool render(const MLabel&label,QPaintDevice&pdev,QPainter*painter=0,QPointF offset=QPointF(),bool usePixmap=false); + + /**returns the size of the ticket in the coordinates of the specified paint device (used for preview)*/ + virtual QSizeF labelSize(const QPaintDevice&); + + protected: + friend class MLabelRendererPrivate; + + private: + MLabelRendererPrivate*d; +}; + +/**convenience class: renders vouchers directly*/ +class MAGICSMOKE_COMMON_EXPORT MVoucherRenderer:public MLabelRenderer +{ + public: + MVoucherRenderer(MTemplate f); + bool render(const MOVoucher&label,QPaintDevice&pdev,QPainter*painter=0,QPointF offset=QPointF(),bool usePixmap=false); +}; + +/**convenience class: renders vouchers directly*/ +class MAGICSMOKE_COMMON_EXPORT MTicketRenderer:public MLabelRenderer +{ + public: + MTicketRenderer(MTemplate f); + bool render(const MOTicket&label,QPaintDevice&pdev,QPainter*painter=0,QPointF offset=QPointF(),bool usePixmap=false); +}; + + +#endif diff --git a/commonlib/widgets/barcodeline.cpp b/commonlib/widgets/barcodeline.cpp new file mode 100644 index 0000000..d993a9a --- /dev/null +++ b/commonlib/widgets/barcodeline.cpp @@ -0,0 +1,41 @@ +// +// C++ Implementation: barcode line edit +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2014 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + + +#include "barcodeline.h" +#include "barcode-plugin.h" + +MBarcodeLine::MBarcodeLine(QWidget* parent): MBarcodeLine(QString(),parent) +{ +} + +MBarcodeLine::MBarcodeLine(const QString& cont, QWidget* parent): QLineEdit(cont,parent) +{ + setToolTip(tr("Type a barcode into this line or scan it with a barcode scanner.")); + setPlaceholderText(tr("Type or scan a barcode.")); + connect(MBarcodeHub::instance(),SIGNAL(newBarcode(QString)), this,SLOT(setBarcode(QString))); +} + +void MBarcodeLine::setBarcode(QString bc) +{ + if(bc.isEmpty())return; + //do we actually have focus? + //TODO: maybe this should be visibility? + if(scanMode()==ScanMode::InFocus && !hasFocus())return; + if(scanMode()==ScanMode::ForceFocus){ + setFocus(); + emit askForFocus(); + } + //enter barcode and emit ready signal + setText(bc); + emit returnPressed(); +} diff --git a/commonlib/widgets/barcodeline.h b/commonlib/widgets/barcodeline.h new file mode 100644 index 0000000..dcabc8c --- /dev/null +++ b/commonlib/widgets/barcodeline.h @@ -0,0 +1,48 @@ +// +// C++ Interface: barcode line edit +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2014 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_BARCODELINE_H +#define MAGICSMOKE_BARCODELINE_H + +#include + +#include "commonexport.h" + +class MAGICSMOKE_COMMON_EXPORT MBarcodeLine:public QLineEdit +{ + Q_OBJECT + public: + explicit MBarcodeLine(QWidget* parent = 0); + explicit MBarcodeLine(const QString& , QWidget* parent = 0); + + enum class ScanMode{ + InFocus, + InBackground, + ForceFocus, + }; + + ScanMode scanMode()const{return mscanmode;} + + private slots: + void setBarcode(QString); + + public slots: + void setScanMode(ScanMode mode){mscanmode=mode;} + + signals: + void askForFocus(); + + private: + ScanMode mscanmode=ScanMode::InFocus; +}; + +#endif diff --git a/commonlib/widgets/centbox.cpp b/commonlib/widgets/centbox.cpp new file mode 100644 index 0000000..34fbffa --- /dev/null +++ b/commonlib/widgets/centbox.cpp @@ -0,0 +1,126 @@ +// +// C++ Implementation: centbox +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2008-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "centbox.h" +#include "misc.h" + +#include +#include +#include +#include + +MCentSpinBox::MCentSpinBox(QWidget*parent,int value,int maxValue) + :QAbstractSpinBox(parent),mvalid(priceRegExp(),this) +{ + mmin=0; + mmax=maxValue; + if(mmin>mmax)mmin=mmax; + mval=value; + if(mvalmmax)mval=mmax; + + setButtonSymbols(UpDownArrows); + lineEdit()->setText(cent2str(mval)); + connect(this,SIGNAL(editingFinished()),this,SLOT(fixup())); +} + +int MCentSpinBox::value()const +{ +// qDebug("current value: %i",mval); + return mval; +} + +void MCentSpinBox::setValue(int m) +{ + if(m>mmax)m=mmax; + if(msetText(cent2str(m)); + emit valueChanged(m); +} + +MCentSpinBox::StepEnabled MCentSpinBox::stepEnabled () const +{ + return (mval>mmin?StepDownEnabled:StepNone)|(mvalma)return; + mmin=mi; + mmax=ma; + if(mval>mmax){ + setValue(mmax); + }else + if(mvaladdWidget(new QLabel(label)); + vl->addWidget(box=new MCentSpinBox(this,val,maxValue)); + QHBoxLayout *hl; + vl->addLayout(hl=new QHBoxLayout); + hl->addStretch(10); + QPushButton*p; + hl->addWidget(p=new QPushButton(tr("OK"))); + p->setDefault(true); + connect(p,SIGNAL(clicked()),this,SLOT(accept())); + hl->addWidget(p=new QPushButton(tr("Cancel"))); + connect(p,SIGNAL(clicked()),this,SLOT(reject())); +} + +int MCentDialog::value()const +{ + return box->value(); +} + +int MCentDialog::getCents(QWidget*parent,QString title,QString label,int val,int maxValue,bool*ok) +{ + MCentDialog d(parent,title,label,val,maxValue); + bool b=d.exec()==QDialog::Accepted; + if(ok)*ok=b; + if(b) + return d.value(); + else + return 0; +} diff --git a/commonlib/widgets/centbox.h b/commonlib/widgets/centbox.h new file mode 100644 index 0000000..80e9c23 --- /dev/null +++ b/commonlib/widgets/centbox.h @@ -0,0 +1,62 @@ +// +// C++ Interface: centbox +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2008-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_CENTBOX_H +#define MAGICSMOKE_CENTBOX_H + +#include +#include +#include + +#include "commonexport.h" + +class MAGICSMOKE_COMMON_EXPORT MCentSpinBox:public QAbstractSpinBox +{ + Q_OBJECT + public: + MCentSpinBox(QWidget*parent=0,int value=0,int maxValue=2147483647); + + virtual int value()const; + virtual void setValue(int); + + virtual void setRange(int,int); + + virtual int minimumValue()const; + virtual int maximumValue()const; + + void stepBy(int); + protected: + virtual QValidator::State validate(QString &input, int &pos) const; + virtual StepEnabled stepEnabled () const; + signals: + void valueChanged(int); + private slots: + void fixup(); + private: + int mval,mmax,mmin; + QRegExpValidator mvalid; +}; + +class MAGICSMOKE_COMMON_EXPORT MCentDialog:public QDialog +{ + Q_OBJECT + public: + MCentDialog(QWidget*parent=0,QString title=QString(),QString label=QString(),int value=0,int maxValue=2147483647); + + virtual int value()const; + + static int getCents(QWidget*parent=0,QString title=QString(),QString label=QString(),int value=0,int maxValue=2147483647,bool *ok=0); + private: + MCentSpinBox*box; +}; + +#endif diff --git a/commonlib/widgets/eventview.cpp b/commonlib/widgets/eventview.cpp new file mode 100644 index 0000000..e77bb5a --- /dev/null +++ b/commonlib/widgets/eventview.cpp @@ -0,0 +1,185 @@ +// +// C++ Implementation: event list tab +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007-2013 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "eventview.h" +#include "misc.h" +#include "msinterface.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +MEventView::MEventView ( QWidget* parent ) : QTextBrowser ( parent ) +{ + setReadOnly(true); + connect(this,SIGNAL(anchorClicked(QUrl)),this,SLOT(handleClick(QUrl))); + setOpenExternalLinks(false); + setOpenLinks(false); + qDebug()<<"Setting path"<parentUrl()<<"for URL"<url(); + setSearchPaths(QStringList()<parentUrl().toString()); + resetPattern(); +} + + +QVariant MEventView::loadResource ( int type, const QUrl& name ) +{ + Q_UNUSED(type); + qDebug()<<"Loading Resource"<url().resolved(name); + QNetworkAccessManager nam; + connect(&nam,SIGNAL(sslErrors(QNetworkReply*,QList)),req,SLOT(sslErrors(QNetworkReply*,QList))); + QNetworkReply*rpl= nam.get(QNetworkRequest(url)); + qDebug()<<"Trying to GET"<readAll(); + qDebug()<<"...got"<\n"; + detail+=tr("Artist: %1").arg(htmlize(event.artist().value().name()))+"

\n"; + detail+=tr("Starttime: %1").arg(htmlize(event.startTimeString()))+"
\n"; + detail+=tr("Endtime: %1").arg(htmlize(event.endTimeString()))+"

\n"; + detail+=tr("Room: %1").arg(htmlize(event.room()))+"
\n"; + detail+=tr("Seats: %1 max. (%2 sold out; %3 reserved; %4 free)").arg(event.capacity()).arg(event.amountSold()).arg(event.amountReserved()).arg(event.amountFree())+"

\n"; + + const QString bgsold=tr("

Sold Out!
","Colored display for sold out tickets"); + const QString bgavail=tr("
","Colored display for ordering tickets"); + const QString bghide=tr("
Unable to sell.
","Colored display for tickets unavailable to this user"); + + const bool showevent=req->checkFlags(event.flags()); + if(showevent) + detail+=event.amountFree()>0?bgavail.arg(QString("order:?ev=%1").arg(event.id())):bgsold; + else + detail+=bghide; + detail+="

"+tr("Prices")+"

\n"; + detail+="" + "\n"; + QListprices=event.price(); + qSort(prices.begin(),prices.end(),[](const MOEventPrice&p1,const MOEventPrice&p2){return p1.prio()checkFlags(ctg.flags())) + detail+=""; + } + detail+="
"+tr("Category")+""+tr("Price")+""+tr("Available")+""+tr("Max. Seats")+""+tr("Order")+"
"+ + (avail>0? + bgavail.arg(QString("order:?ev=%1&pr=%2").arg(event.id()).arg(ctg.pricecategoryid())) + :bgsold); + else + detail+=""+bghide; + detail+="

\n"; + + detail+="

"+tr("Description")+"

\n"+event.description()+"

\n"; + detail+="

"+tr("Comment")+"

\n"; + QString comment=event.comment(); + if(!comment.trimmed().startsWith(""))comment=htmlize(comment); + detail+=comment; + //set value + setHtml(detail); +} + +void MEventView::handleClick(const QUrl &url) +{ + //check whether it is order URL + if(url.scheme()=="order"){ + QUrlQuery query(url); + if(query.hasQueryItem("ev")){ + bool b=false; + qint64 evid=query.queryItemValue("ev").toLongLong(&b); + if(!b || evid<0){ + qDebug()<<"ordering tickets for current event (invalid EvID)..."; + emit eventOrderTicket(); + return; + } + qint64 prid=-1; + if(query.hasQueryItem("pr")){ + prid=query.queryItemValue("pr").toLongLong(&b); + if(!b)prid=-1; + } + qDebug()<<"ordering tickets for event"<url().resolved(url); + qDebug()<<"Relative URL"<url(); + qDebug()<<" ...opening"<{event.name|html}\n" + "Artist: {event.artist|html}

\n" + "Starttime: {event.startTimeString}
\n" + "Endtime: {event.endTimeString}

\n" + "Room: {event.room|html}
\n" + "Seats: {event.capacity} max. ({event.amountSold} sold out; {event.amountReserved} reserved; {event.amountFree} free)

\n" + "{% if(event.haveAccess) %}\n" + + "{% endif %}" + ); +} diff --git a/commonlib/widgets/eventview.h b/commonlib/widgets/eventview.h new file mode 100644 index 0000000..d336860 --- /dev/null +++ b/commonlib/widgets/eventview.h @@ -0,0 +1,47 @@ +// +// C++ Interface: event view` +// +// Description: widget for displaying event details +// +// +// Author: Konrad Rosenbaum , (C) 2016 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_EVENTVIEW_H +#define MAGICSMOKE_EVENTVIEW_H + +#include + +#include + +#include "commonexport.h" + +///Event Viewer +class MAGICSMOKE_COMMON_EXPORT MEventView:public QTextBrowser +{ + Q_OBJECT +public: + explicit MEventView ( QWidget* parent = 0 ); + QVariant loadResource(int type, const QUrl & name)override; + +public slots: + void setEvent(MOEvent); + void clearEvent(); + void setPattern(QString); + void resetPattern(); +private slots: + void handleClick(const QUrl&); +signals: + /**order ticket from event tab*/ + void eventOrderTicket(); + /**order ticket from event tab*/ + void eventOrderTicket(qint64,qint64); +private: + QString mPattern; +}; + + +#endif diff --git a/commonlib/widgets/listview.cpp b/commonlib/widgets/listview.cpp new file mode 100644 index 0000000..e268e66 --- /dev/null +++ b/commonlib/widgets/listview.cpp @@ -0,0 +1,21 @@ +// +// C++ Implementation: treeview +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "listview.h" + +void MListView::keyPressEvent(QKeyEvent *event) +{ + QModelIndex idx=currentIndex(); + QListView::keyPressEvent(event); + if(idx!=currentIndex()) + emit activated(currentIndex()); +} \ No newline at end of file diff --git a/commonlib/widgets/listview.h b/commonlib/widgets/listview.h new file mode 100644 index 0000000..a4ce6b6 --- /dev/null +++ b/commonlib/widgets/listview.h @@ -0,0 +1,30 @@ +// +// C++ Interface: treeview +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_LISTVIEW_H +#define MAGICSMOKE_LISTVIEW_H + +#include + +#include "commonexport.h" + +/**enhances QTreeView to react a bit friendlier on clicks*/ +class MAGICSMOKE_COMMON_EXPORT MListView:public QListView +{ + public: + MListView(QWidget*w=0):QListView(w){} + protected: + void keyPressEvent(QKeyEvent *event); + +}; + +#endif diff --git a/commonlib/widgets/treeview.cpp b/commonlib/widgets/treeview.cpp new file mode 100644 index 0000000..02d1738 --- /dev/null +++ b/commonlib/widgets/treeview.cpp @@ -0,0 +1,21 @@ +// +// C++ Implementation: treeview +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#include "treeview.h" + +void MTreeView::keyPressEvent(QKeyEvent *event) +{ + QModelIndex idx=currentIndex(); + QTreeView::keyPressEvent(event); + if(idx!=currentIndex()) + emit activated(currentIndex()); +} \ No newline at end of file diff --git a/commonlib/widgets/treeview.h b/commonlib/widgets/treeview.h new file mode 100644 index 0000000..06eb373 --- /dev/null +++ b/commonlib/widgets/treeview.h @@ -0,0 +1,30 @@ +// +// C++ Interface: treeview +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009-2011 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_TREEVIEW_H +#define MAGICSMOKE_TREEVIEW_H + +#include + +#include "commonexport.h" + +/**enhances QTreeView to react a bit friendlier on clicks*/ +class MAGICSMOKE_COMMON_EXPORT MTreeView:public QTreeView +{ + public: + MTreeView(QWidget*w=0):QTreeView(w){} + protected: + void keyPressEvent(QKeyEvent *event); + +}; + +#endif diff --git a/commonlib/widgets/widgets.pri b/commonlib/widgets/widgets.pri new file mode 100644 index 0000000..40f1ed2 --- /dev/null +++ b/commonlib/widgets/widgets.pri @@ -0,0 +1,15 @@ +HEADERS += \ + widgets/centbox.h \ + widgets/listview.h \ + widgets/treeview.h \ + widgets/barcodeline.h \ + widgets/eventview.h + +SOURCES += \ + widgets/centbox.cpp \ + widgets/listview.cpp \ + widgets/treeview.cpp \ + widgets/barcodeline.cpp \ + widgets/eventview.cpp + +INCLUDEPATH += ./widgets diff --git a/mainapp/main.cpp b/mainapp/main.cpp index 6c02f95..404121e 100644 --- a/mainapp/main.cpp +++ b/mainapp/main.cpp @@ -2,5 +2,5 @@ int main(int ac,char**av) { - return MApplication::realmain(ac,av); -} \ No newline at end of file + return MagicSmokeMain::realmain(ac,av); +} diff --git a/sessman/login.cpp b/sessman/login.cpp index 1566497..1233c66 100644 --- a/sessman/login.cpp +++ b/sessman/login.cpp @@ -4,17 +4,15 @@ // Description: // // -// Author: Konrad Rosenbaum , (C) 2007-2011 +// Author: Konrad Rosenbaum , (C) 2007-2016 // // Copyright: See README/COPYING.GPL files that come with this distribution // // -// #include "main.h" #include "login.h" #include "msinterface.h" -// #include "overview.h" -// #include "configdialog.h" +#include "configdialog.h" #include #include @@ -157,10 +155,10 @@ void MLogin::startLogin() void MLogin::configwin() { -// MConfigDialog cd; -// cd.exec(); -// initProfiles(); -// loadProfile(); + MConfigDialog cd; + cd.exec(); + initProfiles(); + loadProfile(); } void MLogin::resizeEvent(QResizeEvent* ) diff --git a/sessman/login.h b/sessman/login.h index 1035fa2..2bb39c4 100644 --- a/sessman/login.h +++ b/sessman/login.h @@ -4,7 +4,7 @@ // Description: // // -// Author: Konrad Rosenbaum , (C) 2007-2011 +// Author: Konrad Rosenbaum , (C) 2007-2016 // // Copyright: See README/COPYING.GPL files that come with this distribution // diff --git a/sessman/sessman.pro b/sessman/sessman.pro index 6b628ce..7733749 100644 --- a/sessman/sessman.pro +++ b/sessman/sessman.pro @@ -9,6 +9,7 @@ TARGET = magicsmoke-sessman include(../basics.pri) include(../sesscli/scrand.pri) include(../iface/iface.pri) +include(../commonlib/commonlib.pri) #Localization TRANSLATIONS = \ diff --git a/src/crypto/crypto.pri b/src/crypto/crypto.pri deleted file mode 100644 index 2958656..0000000 --- a/src/crypto/crypto.pri +++ /dev/null @@ -1,9 +0,0 @@ -HEADERS += \ - crypto/keygen.h \ - crypto/hmac.h - -SOURCES += \ - crypto/keygen.cpp \ - crypto/hmac.cpp - -INCLUDEPATH += ./crypto \ No newline at end of file diff --git a/src/crypto/hmac.cpp b/src/crypto/hmac.cpp deleted file mode 100644 index 972b29a..0000000 --- a/src/crypto/hmac.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// -// C++ Implementation: hmac -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2007-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "hmac.h" -#include - -SMHmac::SMHmac(QCryptographicHash::Algorithm algo,const QByteArray&key) - :subhashin(algo),subhashout(algo),state(Collecting) -{ - //calculate key schedules - QByteArray k2=key; - int hlen=blockWidth(algo); - if(k2.size()>hlen){ - //hash the key if it is too long - k2=QCryptographicHash::hash(k2,algo); - }else - if(k2.size(), (C) 2007-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef SMOKE_HMAC_H -#define SMOKE_HMAC_H - -#include - -/**Calculate a cryptographic HMAC (used by authentication algorithm)*/ -class SMHmac -{ - public: - /**constructs an object that calculates HMACs*/ - SMHmac(QCryptographicHash::Algorithm algo,const QByteArray&key); - /**adds length bytes of data to the hash-stream*/ - void addData(const char * data, int length ); - /**adds data to the hash-stream*/ - void addData(const QByteArray & data ); - /**reset the hash to the state immediately after construction*/ - void reset(); - /**finalize the hash and return the result*/ - QByteArray result(); - - /**returns the length of the results of given algorithm in bytes; this should have been implemented by QCryptographicHash! performs a test calculation if the algo is unknown*/ - static int resultWidth(QCryptographicHash::Algorithm); - /**returns the length of the blocks used internally in the given algorithm in bytes; this should have been implemented by QCryptographicHash! returns -1 if in doubt*/ - static int blockWidth(QCryptographicHash::Algorithm); - /**complete HMAC calculation in a can*/ - static QByteArray hmac(const QByteArray&data,const QByteArray&key,QCryptographicHash::Algorithm method); - private: - //the two key schedules - QByteArray keyA,keyB; - //remember where we are - enum State {Collecting,Finished}; - mutable State state; - //inner hash function - QCryptographicHash subhashin,subhashout; -}; - - -#endif diff --git a/src/crypto/keygen.cpp b/src/crypto/keygen.cpp deleted file mode 100644 index 408974b..0000000 --- a/src/crypto/keygen.cpp +++ /dev/null @@ -1,235 +0,0 @@ -// -// C++ Implementation: keygen -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2007-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "keygen.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hmac.h" - -//enable linux to read /dev/random -#ifdef __linux__ -#include -#include -#endif - -//amount of random bits needed: -#define RANDNEED 160 - -static QPointerefilter; - -MKeyGen::MKeyGen(QWidget*parentw) - :QDialog(parentw) -{ - setWindowTitle(tr("Magic Smoke Key Generator")); - - //pre-init random buffer - randstat=-1; - connect(efilter,SIGNAL(moreBits()),this,SLOT(updateProps())); - //make sure all mouse events arrive - setMouseTracking(true); - QVBoxLayout*vl; - setLayout(vl=new QVBoxLayout); - QLabel*lab; - //main explanation - vl->addWidget(lab=new QLabel(tr("

Key Generation

\nI am currently collecting random bits in order to generate a host key for this installation. Please use mouse and keyboard to generate more random. Alternatively you can load a key from an external medium.

\nAt least %1 Bits of random are required.").arg(RANDNEED)),0); - lab->setWordWrap(true); - lab->setMouseTracking(true); - //buffer display - int e=efilter->entropy(); - vl->addWidget(randlab=new QLabel(tr("Current random buffer: %n Bits","",e)),0); - randlab->setMouseTracking(true); - randlab->setFrameShape(QFrame::Box); - randlab->setAutoFillBackground(true); - - vl->addStretch(1); - - //buttons - QHBoxLayout*hl; - vl->addLayout(hl=new QHBoxLayout,0); - hl->addStretch(1); - hl->addWidget(okbtn=new QPushButton(tr("&OK")),0); - connect(okbtn,SIGNAL(clicked()),this,SLOT(accept())); - hl->addWidget(ccbtn=new QPushButton(tr("&Cancel")),0); - connect(ccbtn,SIGNAL(clicked()),this,SLOT(reject())); - - //make sure widgets look right - updateProps(); - - //make window really big - showMaximized(); -} - -MKeyGen::~MKeyGen() -{ -} - -void MKeyGen::updateProps() -{ - int e=efilter->entropy(); - randlab->setText(tr("Current random buffer: %n Bits","",e)); - if(efilter->entropy()palette(); - pal.setColor(QPalette::Window,QColor("#ff8080")); - randlab->setPalette(pal); - //set button - okbtn->setEnabled(false); - }else{ - //check whether we need to set it - if(randstat==1)return; - randstat=1; - //set label color - QPalette pal=randlab->palette(); - pal.setColor(QPalette::Window,QColor("#80ff80")); - randlab->setPalette(pal); - //set button - okbtn->setEnabled(true); - } -} - -QString MKeyGen::getKey(int len) -{ - if(efilter->entropy()getRandom(len).toHex(); -} - - -EFilter::EFilter() -{ - efilter=this; - randctr=0; - //preload seed - QSettings set; - randbuf.append(set.value("randomseed").toByteArray()); - randent=randbuf.size(); - if(randent>=RANDNEED)set.setValue("randomseed",getRandom(RANDNEED)); - //if Linux: try to pre-load some random -#ifdef __linux__ - int fd=::open("/dev/random",O_RDONLY|O_NONBLOCK); - if(fd>=0){ - char buf[RANDNEED/8]; - int rd=::read(fd,buf,sizeof(buf)); - if(rd>0){ - randbuf.append(QByteArray(buf,rd)); - randent+=rd*8; - } - ::close(fd); - } -#endif -} - -EFilter::~EFilter() -{ - QSettings set; - set.setValue("randomseed",getRandom(RANDNEED)); -} - -EFilter* EFilter::instance() -{ - return efilter; -} - -QByteArray EFilter::getRandom(int bytes) -{ - QByteArray ret; - while(ret.size()type()){ - case QEvent::KeyPress:case QEvent::KeyRelease: - { - QKeyEvent*ke=(QKeyEvent*)e; - addBit(ke->key()+(int)ke->modifiers()); - break; - } - case QEvent::MouseButtonPress:case QEvent::MouseButtonRelease: - case QEvent::MouseMove: - { - QMouseEvent*me=(QMouseEvent*)e; - addBit((int)me->buttons()+me->x()+me->y()); - break; - } - default: - //ignore - break; - } - return false; -} - -void EFilter::addBit(int b) -{ - //add bit to buffer - randbuf.append((b>>24)&0xff); - randbuf.append((b>>16)&0xff); - randbuf.append((b>>8)&0xff); - randbuf.append(b&0xff); - randent++; - //add time info as another bit - QTime ct=QTime::currentTime(); - if(ct.msec()!=0){ //don't use it if platform has no msecs - int t=ct.msec()+ct.second()+ct.minute(); - randbuf.append((t>>24)&0xff); - randbuf.append((t>>16)&0xff); - randbuf.append((t>>8)&0xff); - randbuf.append(t&0xff); - randent++; - } - //pack buffer if necessary (>10kB) - if(randbuf.size()>=10240){ - randbuf=getRandom(80); - if(randent>320)randent=320; - } - //update display - emit moreBits(); -} - -QByteArray getRandom(int num) -{ - if(efilter.isNull())return QByteArray(); - return efilter->getRandom(num); -} - -int getEntropy() -{ - if(efilter.isNull())return 0; - return efilter->entropy(); -} diff --git a/src/crypto/keygen.h b/src/crypto/keygen.h deleted file mode 100644 index b822974..0000000 --- a/src/crypto/keygen.h +++ /dev/null @@ -1,66 +0,0 @@ -// -// C++ Interface: keygen -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2007-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef MAGICSMOKE_KEYGEN_H -#define MAGICSMOKE_KEYGEN_H - -#include -#include - -class QLabel; -class QPushButton; - -class MKeyGen:public QDialog -{ - Q_OBJECT - public: - MKeyGen(QWidget*parent=0); - ~MKeyGen(); - - QString getKey(int len=40); - - private: - QLabel*randlab; - int randstat; - - QPushButton *okbtn,*ccbtn; - - private slots: - void updateProps(); -}; - -class EFilter:public QObject -{ - Q_OBJECT - public: - EFilter(); - ~EFilter(); - - static EFilter*instance(); - - int entropy(); - QByteArray getRandom(int); - signals: - void moreBits(); - protected: - bool eventFilter(QObject*,QEvent*); - private: - QByteArray randbuf,randlast; - int randent,randctr; - void addBit(int); -}; - -//shortcut: -QByteArray getRandom(int); -int getEntropy(); - -#endif diff --git a/src/dialogs/configdialog.cpp b/src/dialogs/configdialog.cpp deleted file mode 100644 index 6b03e50..0000000 --- a/src/dialogs/configdialog.cpp +++ /dev/null @@ -1,680 +0,0 @@ -// -// C++ Implementation: mainwindow -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2007-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "keygen.h" -#include "main.h" -#include "configdialog.h" -#include "office.h" -#include "listview.h" -#include "sslexception.h" -#include "misc.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MConfigDialog::MConfigDialog() -{ - setWindowTitle(tr("Magic Smoke Configuration")); - - oldrow=-1; - sslexcept=0; - //main layout - QHBoxLayout*hl; - QVBoxLayout*vl; - setLayout(hl=new QHBoxLayout); - //create Menu Bar - QMenuBar*mb; - hl->setMenuBar(mb=new QMenuBar); - QMenu*m=mb->addMenu(tr("&Profile")); - m->addAction(tr("&New Profile..."),this,SLOT(newProfile())); - m->addAction(tr("&Delete Profile"),this,SLOT(deleteProfile())); - m->addAction(tr("&Rename Profile"),this,SLOT(renameProfile())); - m->addAction(tr("C&lone Profile"),this,SLOT(cloneProfile())); - m->addAction(tr("&Make Default Profile"),this,SLOT(defaultProfile())); - m->addSeparator(); - m->addAction(tr("&Export Host Key..."),this,SLOT(exportKey())); - m->addAction(tr("&Import Host Key..."),this,SLOT(importKey())); - m->addAction(tr("&Generate Host Key..."),this,SLOT(generateKey())); - m->addSeparator(); - m->addAction(tr("&Close Window"),this,SLOT(close())); - m=mb->addMenu(tr("&Settings")); - m->addAction(tr("&Language..."),this,SLOT(changeLang())); - m->addAction(tr("&OpenOffice.org Settings..."),this,SLOT(openOfficeCfg())); - m->addAction(tr("Set &Default Label Font..."),this,SLOT(setDefaultFont())); - m->addAction(tr("Set &Application Style..."),this,SLOT(setAppStyle())); - mb->addMenu(MApplication::helpMenu()); - - //create list view - hl->addWidget(profiles=new MListView); - profilemodel=new QStandardItemModel(this); - profiles->setModel(profilemodel); - profiles->setEditTriggers(QListView::NoEditTriggers); - connect(profiles,SIGNAL(clicked(const QModelIndex&)),this,SLOT(loadProfile())); - connect(profiles,SIGNAL(activated(const QModelIndex&)),this,SLOT(loadProfile())); - //create tabs - QTabWidget*tab; - QWidget*w; - hl->addWidget(tab=new QTabWidget,10); - tab->addTab(w=new QWidget,tr("Connection")); - QGridLayout*gl; - w->setLayout(gl=new QGridLayout); - QLabel*lab; - int lctr=0; - gl->addWidget(lab=new QLabel(tr("Server URL:")),++lctr,0); - lab->setAlignment(Qt::AlignRight); - gl->addLayout(hl=new QHBoxLayout,lctr,1); - hl->addWidget(new QLabel("https://"),0); - hl->addWidget(serverurl=new QLineEdit,1); - gl->addWidget(useproxy=new QCheckBox(tr("Proxy:")),++lctr,0); - gl->addLayout(hl=new QHBoxLayout,lctr,1); - hl->addWidget(proxyname=new QLineEdit,1); - hl->addWidget(new QLabel(":"),0); - hl->addWidget(proxyport=new QSpinBox,0); - proxyport->setRange(1,65535); - connect(useproxy,SIGNAL(toggled(bool)),proxyname,SLOT(setEnabled(bool))); - connect(useproxy,SIGNAL(toggled(bool)),proxyport,SLOT(setEnabled(bool))); - gl->addWidget(lab=new QLabel(tr("Proxy Username:")),++lctr,0); - lab->setAlignment(Qt::AlignRight); - gl->addWidget(proxyuser=new QLineEdit,lctr,1); - gl->addWidget(lab=new QLabel(tr("Proxy Password:")),++lctr,0); - lab->setAlignment(Qt::AlignRight); - gl->addWidget(proxypass=new QLineEdit,lctr,1); - proxypass->setEchoMode(QLineEdit::Password); - connect(useproxy,SIGNAL(toggled(bool)),proxyuser,SLOT(setEnabled(bool))); - connect(useproxy,SIGNAL(toggled(bool)),proxypass,SLOT(setEnabled(bool))); - gl->setRowStretch(++lctr,10); - - tab->addTab(w=new QWidget,tr("Authentication")); - w->setLayout(gl=new QGridLayout); - lctr=0; - gl->addWidget(lab=new QLabel(tr("Hostname:")),++lctr,0); - lab->setAlignment(Qt::AlignRight); - gl->addWidget(hostname=new QLineEdit,lctr,1); - gl->addWidget(lab=new QLabel(tr("Hostkey:")),++lctr,0); - lab->setAlignment(Qt::AlignRight); - gl->addWidget(hostkey=new QLineEdit,lctr,1); - gl->addWidget(lab=new QLabel(tr("Default Username:")),++lctr,0); - lab->setAlignment(Qt::AlignRight); - gl->addWidget(username=new QLineEdit,lctr,1); - gl->addWidget(lab=new QLabel(tr("Hint for Username:")),++lctr,0); - lab->setAlignment(Qt::AlignRight); - gl->addWidget(userhint=new QLineEdit,lctr,1); - gl->setRowStretch(++lctr,10); - gl->addLayout(hl=new QHBoxLayout,++lctr,0,1,2); - - tab->addTab(w=new QWidget,tr("SSL Exceptions")); - w->setLayout(vl=new QVBoxLayout); - vl->addWidget(new QLabel(tr("List of non-fatal SSL exceptions:")),0); - vl->addWidget(ssltable=new QTableView,10); - ssltable->setModel(sslmodel=new QStandardItemModel(this)); - ssltable->setEditTriggers(QListView::NoEditTriggers); - vl->addSpacing(10); - vl->addLayout(hl=new QHBoxLayout,0); - hl->addStretch(10); - QPushButton*pb; - hl->addWidget(pb=new QPushButton(tr("Clear"))); - connect(pb,SIGNAL(clicked()),this,SLOT(clearSslExceptions())); - hl->addWidget(pb=new QPushButton(tr("Probe Server"))); - connect(pb,SIGNAL(clicked()),this,SLOT(serverProbe())); - - tab->addTab(w=new QWidget,tr("Scripting")); - w->setLayout(gl=new QGridLayout); - gl->setColumnStretch(4,1); - lctr=0; - gl->addWidget(lab=new QLabel(tr("You can set scripting preferences here. You have the following options:\nAllow: if active scripts from this source are allowed to run.\nPriority: locations with the lowest value are searched first, when a script it found the other locations are ignored.")),lctr,0,1,5); - lab->setWordWrap(true); - gl->addWidget(lab=new QLabel(tr("Server side scripts:")),++lctr,0); - lab->setAlignment(Qt::AlignRight); - gl->addWidget(asrscript=new QCheckBox(tr("allow")),lctr,1); - gl->addWidget(new QLabel(tr("Prio:")),lctr,2); - gl->addWidget(psrscript=new QSpinBox,lctr,3); - psrscript->setRange(0,100); - gl->addWidget(lab=new QLabel(tr("Built in scripts:")),++lctr,0); - lab->setAlignment(Qt::AlignRight); - gl->addWidget(abiscript=new QCheckBox(tr("allow")),lctr,1); - gl->addWidget(new QLabel(tr("Prio:")),lctr,2); - gl->addWidget(pbiscript=new QSpinBox,lctr,3); - pbiscript->setRange(0,100); - gl->addWidget(lab=new QLabel(tr("User local scripts:")),++lctr,0); - lab->setAlignment(Qt::AlignRight); - gl->addWidget(ausscript=new QCheckBox(tr("allow")),lctr,1); - gl->addWidget(new QLabel(tr("Prio:")),lctr,2); - gl->addWidget(pusscript=new QSpinBox,lctr,3); - pusscript->setRange(0,100); - gl->addWidget(lab=new QLabel(tr("User script path:")),++lctr,0); - lab->setAlignment(Qt::AlignRight); - gl->addWidget(usrscript=new QLineEdit,lctr,1,1,4); - gl->setRowStretch(++lctr,1); - - setSizeGripEnabled(true); - - initProfiles(); - loadProfile(); -} - -MConfigDialog::~MConfigDialog() -{ - saveProfile(); -} - -void MConfigDialog::initProfiles(QString selIdx) -{ - oldrow=-1; - QSettings set; - int defpro=set.value("defaultprofile",0).toInt(); - set.beginGroup("profiles"); - QStringList prf=set.childGroups(); - profilemodel->clear(); - if(profilemodel->columnCount()<1) - profilemodel->insertColumn(0); - profilemodel->insertRows(0,prf.size()); - int newrow=0; - for(int i=0;iindex(i,0); - profilemodel->setData(idx,set.value(prf[i]+"/name").toString()); - profilemodel->setData(idx,prf[i],Qt::UserRole); - if(i==defpro){ - QFont f=profiles->font(); - f.setBold(true); - profilemodel->setData(idx,f,Qt::FontRole); - } - if(prf[i]==selIdx)newrow=i; - } - profiles->setCurrentIndex(profilemodel->index(newrow,0)); -} - -void MConfigDialog::loadProfile() -{ - //save old - saveProfile(); - if(sslexcept)delete sslexcept; - sslexcept=0; - //get new - QModelIndex idx=profiles->currentIndex(); - if(!idx.isValid())return; - oldrow=idx.row(); - QString key=profilemodel->data(idx,Qt::UserRole).toString(); - const QString&dataDir=MApplication::dataDir(); - QSettings set; - set.beginGroup("profiles/"+key); - hostname->setText(set.value("hostname").toString()); - hostkey->setText(set.value("hostkey").toString()); - serverurl->setText(set.value("serverurl","my.host.com/path/machine.php").toString()); - useproxy->setChecked(set.value("useproxy",false).toBool()); - proxyname->setText(set.value("proxyname","proxy").toString()); - proxyport->setValue(set.value("proxyport",74).toInt()); - proxyuser->setText(set.value("proxyuser").toString()); - proxypass->setText(set.value("proxypass").toString()); - proxyname->setEnabled(useproxy->isChecked()); - proxyport->setEnabled(useproxy->isChecked()); - proxyuser->setEnabled(useproxy->isChecked()); - proxypass->setEnabled(useproxy->isChecked()); - username->setText(set.value("username").toString()); - userhint->setText(set.value("usernamehint").toString()); - sslexcept=new MSslExceptions(dataDir+"/profile."+key+"/sslexceptions.xml"); - sslFillModel(); - abiscript->setChecked(set.value("script/allowbuiltin",true).toBool()); - ausscript->setChecked(set.value("script/allowuser",false).toBool()); - asrscript->setChecked(set.value("script/allowserver",false).toBool()); - pbiscript->setValue(set.value("script/priobuiltin",10).toInt()); - pusscript->setValue(set.value("script/priouser",0).toInt()); - psrscript->setValue(set.value("script/prioserver",20).toInt()); - usrscript->setText(set.value("script/userpath",dataDir+"/userscripts").toString()); -} - -void MConfigDialog::saveProfile() -{ - if(oldrow<0 || oldrow>=profilemodel->rowCount())return; - QString key=profilemodel->data(profilemodel->index(oldrow,0),Qt::UserRole).toString(); - QSettings set; - set.beginGroup("profiles/"+key); - set.setValue("hostname",hostname->text()); - set.setValue("hostkey",hostkey->text()); - set.setValue("serverurl",serverurl->text()); - set.setValue("useproxy",useproxy->isChecked()); - set.setValue("proxyname",proxyname->text()); - set.setValue("proxyport",proxyport->value()); - set.setValue("proxyuser",proxyuser->text()); - set.setValue("proxypass",proxypass->text()); - set.setValue("username",username->text()); - set.setValue("usernamehint",userhint->text()); - QDir(MApplication::dataDir()).mkdir("profile."+key); - if(sslexcept)sslexcept->savesslexcept(); - set.setValue("script/allowbuiltin",abiscript->isChecked()); - set.setValue("script/allowuser",ausscript->isChecked()); - set.setValue("script/allowserver",asrscript->isChecked()); - set.setValue("script/priobuiltin",pbiscript->value()); - set.setValue("script/priouser",pusscript->value()); - set.setValue("script/prioserver",psrscript->value()); - set.setValue("script/userpath",usrscript->text()); -} - -void MConfigDialog::newProfile() -{ - saveProfile(); - //scan for existing ones... - QSettings set; - set.beginGroup("profiles"); - QStringList prf=set.childGroups(); - QStringList prn; - for(int i=0;icurrentIndex(); - if(!idx.isValid())return; - QString key=profilemodel->data(idx,Qt::UserRole).toString(); - QSettings set; - set.beginGroup("profiles"); - set.remove(key); - set.sync(); - oldrow=-1; - initProfiles(); - loadProfile(); -} - -void MConfigDialog::renameProfile() -{ - //get old name - QModelIndex idx=profiles->currentIndex(); - if(!idx.isValid())return; - QString key=profilemodel->data(idx,Qt::UserRole).toString(); - QString pname=profilemodel->data(idx).toString(); - //query - bool ok; - QString npname=QInputDialog::getText(this,tr("Rename Profile"),tr("Please enter a profile name. It must be non-empty and must not be used yet:"),QLineEdit::Normal,pname,&ok); - if(!ok)return; - //check - if(npname==pname)return; - for(int i=0;irowCount();i++){ - QString pn=profilemodel->data(profilemodel->index(i,0)).toString(); - if(pn==npname){ - QMessageBox::warning(this,tr("Warning"),tr("This profile name is already in use.")); - return; - } - } - //set - QSettings().setValue("profiles/"+key+"/name",npname); - profilemodel->setData(idx,npname); -} - -void MConfigDialog::cloneProfile() -{ - saveProfile(); - //get current - QModelIndex idx=profiles->currentIndex(); - if(!idx.isValid())return; - QString key=profilemodel->data(idx,Qt::UserRole).toString(); - //scan for existing ones... - QSettings set; - set.beginGroup("profiles"); - QStringList prf=set.childGroups(); - QStringList prn; - for(int i=0;icurrentIndex(); - if(!idx.isValid())return; - QString key=profilemodel->data(idx,Qt::UserRole).toString(); - QSettings().setValue("defaultprofile",key); - initProfiles(key); - loadProfile(); -} - - -void MConfigDialog::changeLang() -{ - choseLanguage(); -} - -void MConfigDialog::exportKey() -{ - QSettings st; - QModelIndex idx=profiles->currentIndex(); - if(!idx.isValid())return; - QString pkey=profilemodel->data(idx,Qt::UserRole).toString(); - st.beginGroup("profiles/"+pkey); - QString host=hostname->text().trimmed(); - QString key=hostkey->text().trimmed(); - saveKey(host,key); -} - -void MConfigDialog::generateKey() -{ - //ask nicely - if(hostkey->text()!="") - if(QMessageBox::question(this,tr("Generate Hostkey"), tr("Do you really want to generate a new host key for this profile? This may disable all accounts from this host."), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) - return; - //actually create new key - QString name; - MKeyGen mkg(this); - QString k=mkg.getKey(); - if(k=="") - if(mkg.exec()!=QDialog::Accepted) - return; - hostkey->setText(mkg.getKey()); -} - -void MConfigDialog::saveKey(QString host,QString key) -{ - QStringList fn; - QFileDialog fdlg(this,tr("Export Key to File"),QString(),"Magic Smoke Host Key (*.mshk)"); - fdlg.setDefaultSuffix("mshk"); - fdlg.setAcceptMode(QFileDialog::AcceptSave); - fdlg.setFileMode(QFileDialog::AnyFile); - fdlg.setDirectory(currentDir()); - if(!fdlg.exec())return; - fn=fdlg.selectedFiles(); - if(fn.size()!=1)return; - setCurrentDir(fn[0]); - QFile fd(fn[0]); - if(!fd.open(QIODevice::WriteOnly|QIODevice::Truncate)){ - QMessageBox::warning(this,tr("Warning"),tr("Unable to open file %1 for writing: %2").arg(fn[0]).arg(fd.errorString())); - return; - } - QString chk=QCryptographicHash::hash(key.toLatin1(),QCryptographicHash::Md5).toHex(); - QString out="MagicSmokeHostKey\n"+host+"\n"+key+"\n"+chk; - fd.write(out.toLatin1()); - fd.close(); -} - -void MConfigDialog::importKey() -{ - QModelIndex idx=profiles->currentIndex(); - if(!idx.isValid())return; - QString profkey=profilemodel->data(idx,Qt::UserRole).toString(); - - if(QMessageBox::warning(this,tr("Warning"),tr("Importing a key overwrites the host key that is currently used by this profile. This may disable your accounts. Do you still want to continue?"),QMessageBox::Yes|QMessageBox::Abort,QMessageBox::Abort)!=QMessageBox::Yes) - return; - QStringList fn; - QFileDialog fdlg(this,tr("Import Key from File"),QString(),"Magic Smoke Host Key (*.mshk)"); - fdlg.setDefaultSuffix("mshk"); - fdlg.setAcceptMode(QFileDialog::AcceptOpen); - fdlg.setFileMode(QFileDialog::ExistingFile); - fdlg.setDirectory(currentDir()); - if(!fdlg.exec())return; - fn=fdlg.selectedFiles(); - if(fn.size()!=1)return; - setCurrentDir(fn[0]); - QFile fd(fn[0]); - if(!fd.open(QIODevice::ReadOnly)){ - QMessageBox::warning(this,tr("Warning"),tr("Unable to open file %1 for reading: %2").arg(fn[0]).arg(fd.errorString())); - return; - } - //read content (max: 10k to limit potential damage) - QStringList fc=QString::fromLatin1(fd.read(10240)).split("\n",QString::SkipEmptyParts); - fd.close(); - //check content - if(fc.size()<3){ - QMessageBox::warning(this,tr("Warning"),tr("This is not a host key file.")); - return; - } - if(fc[0].trimmed()!="MagicSmokeHostKey"){ - QMessageBox::warning(this,tr("Warning"),tr("This is not a host key file.")); - return; - } - QString hname=fc[1].trimmed(); - if(!QRegExp("[A-Za-z][A-Za-z0-9_]*").exactMatch(hname)){ - QMessageBox::warning(this,tr("Warning"),tr("This host key file does not contain a valid host name.")); - return; - } - QString key=fc[2].trimmed(); - if(!QRegExp("[0-9a-fA-F]+").exactMatch(key) || key.size()<40){ - QMessageBox::warning(this,tr("Warning"),tr("This host key file does not contain a valid key.")); - return; - } - QString chk=QCryptographicHash::hash(key.toLatin1(),QCryptographicHash::Md5).toHex(); - if(chk!=fc[3].trimmed()){ - QMessageBox::warning(this,tr("Warning"),tr("The key check sum did not match. Please get a clean copy of the host key file.")); - return; - } - //save - hostname->setText(hname); - hostkey->setText(key); - QSettings set; - set.beginGroup("profiles/"+profkey); - set.setValue("hostkey",key); - set.setValue("hostname",hname); -} - -void MConfigDialog::openOfficeCfg() -{ - MOfficeConfig c(this); - c.exec(); -} - -void MConfigDialog::setDefaultFont() -{ - QStringList fonts=QFontDatabase().families(); - QString df=QInputDialog::getItem(this,tr("Chose Default Font"),tr("Please chose a default font:"),fonts,fonts.indexOf(QSettings().value("defaultfont","").toString()),false); - if(df.isEmpty())return; - QSettings().setValue("defaultfont",df); -} - -void MConfigDialog::setAppStyle() -{ - MAppStyleDialog d(this); - d.exec(); -} - -void MConfigDialog::serverProbe() -{ - //sanity check - if(!sslexcept)return; - sslexcept->clearRecorded(); - //set up mini-environment - QEventLoop loop; - QNetworkAccessManager man; - connect(&man,SIGNAL(finished(QNetworkReply*)),&loop,SLOT(quit())); - QTimer::singleShot(30000,&loop,SLOT(quit())); - connect(&man,SIGNAL(sslErrors(QNetworkReply*,const QList&)), this,SLOT(sslErrors(QNetworkReply*,QList))); - if(useproxy->isChecked()) - man.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy,proxyname->text(),proxyport->value(),proxyuser->text(),proxypass->text())); - //query server - QNetworkRequest rq(QUrl("https://"+serverurl->text())); - QNetworkReply *rp=man.get(rq); - //wait for result - setEnabled(false); - loop.exec(); - setEnabled(true); - //probe result - if(rp->error()==QNetworkReply::NoError){ - QMessageBox::information(this,tr("Server Probe"),tr("The request finished without errors.")); - }else{ - QMessageBox::warning(this,tr("Server Probe"),tr("The request finished with an error: %1").arg(rp->errorString())); - } - delete rp; - //save - sslexcept->savesslexcept(); -} - -void MConfigDialog::sslErrors(QNetworkReply*rp,QListerrs) -{ - if(!sslexcept)return; - //check/record/clear - if(sslexcept->checksslexcept(errs)){ - rp->ignoreSslErrors(); - return; - } - //convert to string - QString err=tr("SSL Errors encountered:\n"); - for(int i=0;i= 0x50000 - .value(0) -#endif - ) - .arg(QString::fromLatin1(c.digest(QCryptographicHash::Sha1).toHex())) - .arg(errs[i].errorString()); - } - err+=tr("Accept connection anyway?"); - if(QMessageBox::warning(this,tr("SSL Warning"),err,QMessageBox::Yes|QMessageBox::No) == QMessageBox::Yes){ - rp->ignoreSslErrors(); - sslexcept->acceptRecorded(); - } - sslFillModel(); -} - -void MConfigDialog::clearSslExceptions() -{ - if(sslexcept)sslexcept->clear(); - sslmodel->clear(); -} - -void MConfigDialog::sslFillModel() -{ - sslmodel->clear(); - if(!sslexcept)return; - sslmodel->insertColumns(0,3); - sslmodel->setHorizontalHeaderLabels(QStringList()< >lst=sslexcept->nonFatalExceptions(); - sslmodel->insertRows(0,lst.size()); - for(int i=0;isetData(sslmodel->index(i,0),lst[i].first.subjectInfo(QSslCertificate::CommonName)); - sslmodel->setData(sslmodel->index(i,1),QString::fromLatin1(lst[i].first.digest(QCryptographicHash::Sha1).toHex())); - sslmodel->setData(sslmodel->index(i,2),QSslError((QSslError::SslError)lst[i].second).errorString()); - } -} - -MAppStyleDialog::MAppStyleDialog(QWidget*par) - :QDialog(par) -{ - setWindowTitle(tr("Application Style")); - QGridLayout *gl; - setLayout(gl=new QGridLayout); - gl->addWidget(new QLabel(tr("GUI Style:")),0,0); - gl->addWidget(style=new QComboBox,0,1,1,2); - style->addItem(tr("System Default")); - style->setEditable(false); - QStringList k=QStyleFactory::keys(); - QString cs=QSettings().value("appstyle").toString(); - style->addItems(k); - if(k.contains(cs)) - style->setCurrentIndex(k.indexOf(cs)+1); - - gl->addWidget(new QLabel(tr("Stylesheet:")),1,0); - gl->addWidget(css=new QLineEdit,1,1); - css->setText(QSettings().value("appstylesheet").toString()); - QPushButton*p; - gl->addWidget(p=new QPushButton("..."),1,2); - connect(p,SIGNAL(clicked()),this,SLOT(selectCSS())); - - gl->setRowMinimumHeight(2,15); - QHBoxLayout*hl; - gl->addLayout(hl=new QHBoxLayout,3,0,1,3); - hl->addStretch(10); - hl->addWidget(p=new QPushButton(tr("Ok"))); - connect(p,SIGNAL(clicked()),this,SLOT(accept()),Qt::QueuedConnection); - connect(p,SIGNAL(clicked()),this,SLOT(save())); - hl->addWidget(p=new QPushButton(tr("Cancel"))); - connect(p,SIGNAL(clicked()),this,SLOT(reject())); -} - -void MAppStyleDialog::selectCSS() -{ - QString s=QFileDialog::getOpenFileName(this,tr("Select Stylesheet"),currentDir()); - if(s!=""){ - css->setText(s); - setCurrentDir(s); - } -} - -void MAppStyleDialog::save() -{ - if(style->currentIndex()==0) - QSettings().remove("appstyle"); - else - QSettings().setValue("appstyle",style->currentText()); - QSettings().setValue("appstylesheet",css->text()); -} - diff --git a/src/dialogs/configdialog.h b/src/dialogs/configdialog.h deleted file mode 100644 index 6200948..0000000 --- a/src/dialogs/configdialog.h +++ /dev/null @@ -1,95 +0,0 @@ -// -// C++ Interface: mainwindow -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2007-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef MAGICSMOKE_CONFIGDIALOG_H -#define MAGICSMOKE_CONFIGDIALOG_H - -#include -#include -#include - -class QCheckBox; -class QLineEdit; -class QListView; -class QNetworkReply; -class QSpinBox; -class QStandardItemModel; -class QTableView; - -class MSslExceptions; - -/**login and profile configuration window*/ -class MConfigDialog:public QDialog -{ - Q_OBJECT - public: - MConfigDialog(); - ~MConfigDialog(); - - private: - QCheckBox*useproxy,*abiscript,*ausscript,*asrscript; - QLineEdit*hostname,*hostkey,*serverurl,*proxyname,*username, - *userhint,*proxyuser,*proxypass,*usrscript; - QSpinBox*proxyport,*pbiscript,*pusscript,*psrscript; - QListView*profiles; - QStandardItemModel*profilemodel,*sslmodel; - QTableView*ssltable; - - MSslExceptions*sslexcept; - - int oldrow; - - //helper for exportKey and generateKey - void saveKey(QString hostname,QString hostkey); - - private slots: - //handling of login/profile screen - void initProfiles(QString idx=QString()); - void loadProfile(); - void saveProfile(); - void newProfile(); - void deleteProfile(); - void renameProfile(); - void cloneProfile(); - void defaultProfile(); - //settings - void changeLang(); - void exportKey(); - void importKey(); - void generateKey(); - void openOfficeCfg(); - void setDefaultFont(); - void setAppStyle(); - //ssl server probe - void serverProbe(); - void sslErrors(QNetworkReply*,QList); - void clearSslExceptions(); - void sslFillModel(); -}; - -class QComboBox; -class QLineEdit; - -class MAppStyleDialog:public QDialog -{ - Q_OBJECT - public: - MAppStyleDialog(QWidget*); - private slots: - void selectCSS(); - void save(); - private: - QComboBox*style; - QLineEdit*css; -}; - -#endif diff --git a/src/dialogs/dialogs.pri b/src/dialogs/dialogs.pri index ff60fff..597979a 100644 --- a/src/dialogs/dialogs.pri +++ b/src/dialogs/dialogs.pri @@ -1,5 +1,4 @@ HEADERS += \ - dialogs/configdialog.h \ dialogs/eventedit.h \ dialogs/eventsummary.h \ dialogs/orderwin.h \ @@ -16,7 +15,6 @@ HEADERS += \ dialogs/payedit.h SOURCES += \ - dialogs/configdialog.cpp \ dialogs/eventedit.cpp \ dialogs/eventsummary.cpp \ dialogs/orderwin.cpp \ diff --git a/src/dialogs/orderauditdlg.cpp b/src/dialogs/orderauditdlg.cpp index ed864bf..ecedb1d 100644 --- a/src/dialogs/orderauditdlg.cpp +++ b/src/dialogs/orderauditdlg.cpp @@ -14,7 +14,7 @@ #include "orderwin.h" #include "formula.h" -#include "main.h" +#include "mapplication.h" #include "msinterface.h" #include "MTGetTicketAudit" diff --git a/src/libs.pri b/src/libs.pri index 09bd6b8..196e9d9 100644 --- a/src/libs.pri +++ b/src/libs.pri @@ -12,6 +12,9 @@ include($$PWD/../taurus/aurora.pri) # Session Client library include($$PWD/../sesscli/sesscli.pri) +# Common classes +include($$PWD/../commonlib/commonlib.pri) + #make sure the correct Qt DLLs are used QT += xml network script scripttools QT += widgets printsupport diff --git a/src/main.cpp b/src/main.cpp index eb272f8..db3d7bf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,473 +4,23 @@ // Description: Main Program // // -// Author: Konrad Rosenbaum , (C) 2007-2014 +// Author: Konrad Rosenbaum , (C) 2007-2016 // // Copyright: See README/COPYING.GPL files that come with this distribution // // -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "configdialog.h" -#include "debug.h" -#include "barcode-plugin.h" -#include "hmac.h" -#include "keygen.h" -#include "main.h" -// #include "login.h" -#include "msinterface.h" -#include -#include "misc.h" -#include -#include "boxwrapper.h" #include "overview.h" #include +#include +#include "msinterface.h" -QString choseLanguage(bool warn) -{ - QString lang=QSettings().value("lang","--").toString(); - if(lang=="--"){ - lang=QLocale::system().name(); - } - int cur=0; - QStringList langs; - langs<<"C - default"; - QStringList files=QDir(QApplication::applicationDirPath()).entryList(QStringList()<<"smoke_*.qm", QDir::Files, QDir::Name); - for(int i=0;isetMinimumDuration(0); - pd->show(); - } - ~MProgressWrapperGui() - { - if(pd)pd->deleteLater(); - pd=0; - } - virtual void setLabelText(QString l) - { - pd->setLabelText(l); - } - virtual void setCancelButtonText(QString t) - { - pd->setCancelButtonText(t); - } - virtual void cancel() - { - pd->cancel(); - } - virtual void setRange(int mi,int ma) - { - pd->setRange(mi,ma); - } - virtual void setValue(int v) - { - pd->setValue(v); - } -}; - -#ifndef HOMEPAGE_BASEURL -#define HOMEPAGE_BASEURL "http://smoke.silmor.de" -#endif - -void MApplication::aboutMS() -{ - QMessageBox mb; - mb.setIconPixmap(QPixmap(":/icon.png")); - mb.setWindowTitle(tr("About MagicSmoke")); - MSInterface*ifc=MSInterface::instance(); - mb.setText(tr( "

MagicSmoke v. %1

" - "© Konrad Rosenbaum, 2007-2013
" - "© Peter Keller, 2007-2008
" - "protected under the GNU GPL v.3 or at your option any newer

" - "See also the MagicSmoke Homepage.

" - "This version was compiled from repository '%3' revision '%4'.

" - "The current application data base path is '%5'.") - .arg(MSInterface::staticVersionInfo(WOb::VersionHR)) //%1 - .arg(HOMEPAGE_BASEURL) //%2 - .arg(MSInterface::staticVersionInfo(WOb::VersionRootURL)) //%3 - .arg(MSInterface::staticVersionInfo(WOb::VersionNumber)) //%4 - .arg(ifc?ifc->dataDir(): dataDir()) - ); - mb.setStandardButtons(QMessageBox::Ok); - mb.exec(); -} - -void MApplication::versionDlg() -{ - QMessageBox mb; - mb.setIconPixmap(QPixmap(":/icon.png")); - mb.setWindowTitle(tr("MagicSmoke Version Information")); - TimeZoneLib::TZFile tzf=TimeStamp::defaultZoneFile(); - auto unknown=[](const QString&s)->QString{if(s.isEmpty())return "(unknown)";else return "'"+s+"'";}; - mb.setText(tr( "

MagicSmoke Version %3

" - "" - "" - "" - "" - "" - "" - "
Repository:%1
Revision:%2
Modification State:%4
Commit Time:%5
Committer:%6

\n" - "

Libraries

\n" - "" - "" - "" - "" - "" - "" - "
WOC:%7
%8
PACK Library:%9
%10
Qt:%11
ELAM:%12
Time Zone Default:%13 in directory %14
version %15
Time Zone Built-In:%16 (library: %17)
" - ) - .arg(htmlize(MSInterface::staticVersionInfo(WOb::VersionRootURL))) // %1 - .arg(htmlize(MSInterface::staticVersionInfo(WOb::VersionNumber))) //%2 - .arg(htmlize(MSInterface::staticVersionInfo(WOb::VersionHR))) //%3 - .arg(MSInterface::staticVersionInfo(WOb::VersionLocallyModified)) //%4 - .arg(htmlize(MSInterface::staticVersionInfo(WOb::VersionTime))) //%5 - .arg(htmlize(MSInterface::staticVersionInfo(WOb::VersionAuthor))) //&6 - .arg(htmlize(MSInterface::staticWocVersionInfo(WOb::VersionRootURL))) //%7 - .arg(htmlize(MSInterface::staticWocVersionInfo(WOb::VersionNumber))) - .arg(htmlize(WInterface::staticLibraryVersionInfo(WOb::VersionRootURL))) //%9 - .arg(htmlize(WInterface::staticLibraryVersionInfo(WOb::VersionNumber))) - .arg(htmlize(QT_VERSION_STR)) //%11 - .arg(htmlize(ELAM::versionInfo())) //%12 - .arg(unknown(tzf.name())) //%13 - .arg(unknown(tzf.dirName())) - .arg(unknown(tzf.version())) - .arg(TimeZoneLib::TZFile::builtinVersion()) //%16 - .arg(TimeZoneLib::TZFile::libraryVersion()) //%17 - ); - mb.setStandardButtons(QMessageBox::Ok); - mb.exec(); -} - - -struct HelpUrl { - enum Type {None, Item, Separator} type=None; - QString label,url; - HelpUrl(Type t,QString l,QString u=QString()):type(t),label(l),url(u){} -}; -static QList helpUrl; - -static void loadHelpUrlFile(const QString&fname) -{ - QFile fd(fname); - QList urls; - //try to open - if(fd.open(QIODevice::ReadOnly)){ - //read config - QDomDocument doc; - doc.setContent(&fd); - QDomNodeList nl=doc.documentElement().childNodes(); - for(int i=0;i0 && urls.size()>0)helpUrl.append(HelpUrl(HelpUrl::Separator,"")); - helpUrl.append(urls); -} - -void MApplication::initHelpUrl() -{ - //check file exists, if not initialize it - loadHelpUrlFile(dataDir()+"/helpMenu.xml"); - loadHelpUrlFile(applicationDirPath()+"/helpMenu.xml"); - //fallback - if(helpUrl.size()<1) - helpUrl<addSeparator()->setText(helpUrl[i].label); - }else{ - QAction*a=m->addAction(helpUrl[i].label,map,SLOT(map())); - map->setMapping(a,i); - } - } - m->addSeparator(); - m->addAction("About &MagicSmoke",qApp,SLOT(aboutMS())); - m->addAction("About &Qt",qApp,SLOT(aboutQt())); - m->addAction("&Version Info",qApp,SLOT(versionDlg())); - return m; -} - -static inline QUrl convHelpUrl(QUrl s) -{ - if(s.scheme()=="default"){ - static const QString ad=QApplication::applicationDirPath()+"/doc/"; - if(QFile(ad+"index.html").exists()) - return QUrl::fromLocalFile(ad+s.path()); - else - //TODO: allow different versions? - return HOMEPAGE_BASEURL "/doc/" + s.path(); - } - else return s; -} - - - -void MApplication::help() -{ - qDebug()<<"Opening default help..."; - QDesktopServices::openUrl(convHelpUrl(QUrl("default:/index.html"))); -} - -void MApplication::help(int idx) -{ - if(idx<0 || idx>=helpUrl.size()){ - help(); - return; - } - QUrl u=convHelpUrl(helpUrl[idx].url); - qDebug()<<"Opening help:"<MProgressWrapper*{ - return new MProgressWrapperGui(label,button); - }); - - //check parameters -// qDebug()<<"arguments"<load(prog+"_"+lang,lpath[i]); - QString msg=QString("...loading %1_%2 from %3 ...%4") - .arg(prog).arg(lang) - .arg(lpath[i]) - .arg(ok?"ok":"failed"); - qDebug("%s",msg.toLatin1().data()); - if(ok)return; - } -} - -void MApplication::initLanguage() -{ - //try to find appropriate locale - QString lang=QSettings().value("lang","--").toString(); - if(lang=="--"){ - lang=choseLanguage(false); - } - qDebug("Loading language %s",lang.toLatin1().data()); - //load Qt translation - loadTranslation(qttrans=new QTranslator(this),lang,"qt"); - installTranslator(qttrans); - //load magicSmoke translation - loadTranslation(mstrans=new QTranslator(this),lang,"smoke"); - installTranslator(mstrans); - //load Pack translation - QTranslator*xtrans; - loadTranslation(xtrans=new QTranslator(this),lang,"qwbase"); - installTranslator(xtrans); - //detect and load remaining modules - QStringList files=QDir(applicationDirPath()).entryList(QStringList()<<"smoke-*.qm",QDir::Files|QDir::Readable,QDir::Name); - QStringList loaded, modules; - // --> stage 1: find modules - for(auto file:files){ - QString m=file.split('_').value(0); - if(!m.isEmpty() && !modules.contains(m)) - modules.append(m); - } - // --> stage 2: go through modules and load - for(auto mod:modules){ - loadTranslation(xtrans=new QTranslator(this),lang,mod); - installTranslator(xtrans); - } - //defaults - if(lang!="--"&&lang!=""){ - QLocale::setDefault(lang); -#ifndef Q_OS_WIN - setenv("LANG",lang.toLatin1().data(),1); - }else{ - setenv("LANG","C",1); -#endif - } -} - -void MApplication::initialize() -{ - //load the correct style - setMyStyle(); - //initialize log file - initDebug(); - //init localization and profiles - initLanguage(); - initProfile(); - //init help menu layout - initHelpUrl(); - //init updater - initUpdater(); - //init plugins - MBarcodeHub::instance()->initialize(); -} - -void MApplication::initUpdater() -{ - updater=new Aurora(applicationDirPath()+"/magicsmoke.xml",this); - connect(updater,SIGNAL(newVersionAvailable(QString)),this,SLOT(updateReadyDownload(QString))); - connect(updater,SIGNAL(readyForInstallation()),this,SLOT(updaterReadyInstall())); - connect(updater,SIGNAL(installationFinished()),this,SLOT(updaterCompleted())); - connect(updater,SIGNAL(downloadFailed()),this,SLOT(updaterFailed())); - connect(updater,SIGNAL(installationFailed()),this,SLOT(updaterFailed())); - //we ignore all errors that happen prior to successful verification, since they - //would create too much noise -} - -void MApplication::updateReadyDownload(const QString& v) -{ - qDebug()<<"Asking for Download permission"; - QMessageBox::StandardButton r=QMessageBox::question(0,tr("New Update"),tr("A new version of MagicSmoke is available. Do you want to download the new version %1?").arg(v),QMessageBox::Yes|QMessageBox::No,QMessageBox::Yes); - if(r==QMessageBox::Yes) - updater->startDownload(); -} - -void MApplication::updaterReadyInstall() -{ - QMessageBox::Button r=QMessageBox::question(0,tr("New Update"),tr("A new version of MagicSmoke is ready for installation. Do you want to install?"),QMessageBox::Yes|QMessageBox::No,QMessageBox::Yes); - if(r==QMessageBox::Yes) - updater->startInstallation(); -} - -void MApplication::updaterCompleted() -{ - QMessageBox::information(0,tr("Update Complete"),tr("A new version of MagicSmoke has been installed. It will be used the next time you start MagicSmoke.")); -} - -void MApplication::updaterFailed() -{ - QMessageBox::warning(0,tr("Update Failed"),tr("An update of MagicSmoke failed.")); -} - -QString MApplication::dataDir() -{ - return MSInterface::appDataDir(); -} - -void MApplication::initProfile() -{ - //check/generate profile - if(!QSettings().childGroups().contains("profiles")){ - QMessageBox::warning(0,translate("initprofile","Initial Profile Warning"), translate("initprofile","You need a profile to work with Magic Smoke. Please create one now.")); - MConfigDialog().exec(); - } -} - +#include "main.h" -int MApplication::realmain(int argc,char**argv) +int MagicSmokeMain::realmain(int argc,char**argv) { //create global app MApplication app(argc,argv); diff --git a/src/main.h b/src/main.h index 020a189..49d34de 100644 --- a/src/main.h +++ b/src/main.h @@ -4,7 +4,7 @@ // Description: // // -// Author: Konrad Rosenbaum , (C) 2007-2014 +// Author: Konrad Rosenbaum , (C) 2007-2016 // // Copyright: See README/COPYING.GPL files that come with this distribution // @@ -13,11 +13,7 @@ #ifndef MAGICSMOKE_MAIN_H #define MAGICSMOKE_MAIN_H -#include -#include - -/**show a dialog to change the language*/ -QString choseLanguage(bool warn=true); +#include #ifdef MAGICSMOKE_LIB_BUILD #define MAGICSMOKE_EXPORT Q_DECL_EXPORT @@ -25,75 +21,11 @@ QString choseLanguage(bool warn=true); #define MAGICSMOKE_EXPORT Q_DECL_IMPORT #endif -class QMenu; -class EFilter; -namespace AuroraUpdater{class Aurora;}; -///Main application object of MagicSmoke -class MAGICSMOKE_EXPORT MApplication:public QApplication +///shortcut: the main function +class MAGICSMOKE_EXPORT MagicSmokeMain { - Q_OBJECT - public: - ///create MagicSmoke application - MApplication(int&ac,char**av); - - ///return the standard help menu - static QMenu*helpMenu(); - - ///shortcut: the main function - static int realmain(int,char**); - /**contains the directory that is used for external data storage*/ - static QString dataDir(); - - ///override the data directory - ///- call it before any of the init functions - ///- never call this while a session is active! - static void setDataDir(QString); - ///override the configuration directory - ///- call this before initialize - ///- on Windows and MacOS, this also switches the settings mode to ini-files - static void setConfigDir(QString); - public slots: - ///complete initialization: style, language, data dir - void initialize(); - ///set the configured application style - void setMyStyle(); - ///initialize the localization - void initLanguage(); - ///initialize the profiles - void initProfile(); - - ///show about dialog - void aboutMS(); - ///show version info - void versionDlg(); - ///start a browser with the help page - void help(); - private slots: - ///jump to a specific help page - void help(int); - - ///initialize the help menu from config files - void initHelpUrl(); - - ///initialize the updater - void initUpdater(); - - ///updater is ready for download - void updateReadyDownload(const QString&); - ///updater is ready for install - void updaterReadyInstall(); - ///update complete - void updaterCompleted(); - ///something failed for the updater - void updaterFailed(); - - private: - EFilter *ef=nullptr; - QTranslator*qttrans=nullptr,*mstrans=nullptr; - AuroraUpdater::Aurora*updater=nullptr; +public: + static int realmain(int,char**); }; -///return the instance of the MApplication -#define mApp (qobject_cast(qApp)) - #endif diff --git a/src/misc/barcode-plugin.cpp b/src/misc/barcode-plugin.cpp deleted file mode 100644 index 2542a43..0000000 --- a/src/misc/barcode-plugin.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// -// C++ Implementation: Barcode Plugin Basics -// -// -// Author: Konrad Rosenbaum , (C) 2013-2014 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "barcode-plugin.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -static QList >allscanners; -static QListallplugins; - -MBarcodeConfiguration::MBarcodeConfiguration(QWidget* parent): QDialog(parent) -{ - setWindowTitle(tr("Configure Barcode Plugins")); - - QVBoxLayout*vl; - QHBoxLayout*hl; - QPushButton*p; - setLayout(vl=new QVBoxLayout); - vl->addWidget(mtab=new QTabWidget,1); - vl->addLayout(hl=new QHBoxLayout); - hl->addStretch(1); - hl->addWidget(p=new QPushButton(tr("&Save"))); - connect(p,SIGNAL(clicked(bool)),this,SLOT(accept())); - hl->addWidget(p=new QPushButton(tr("&Cancel"))); - connect(p,SIGNAL(clicked(bool)),this,SLOT(reject())); - - setSizeGripEnabled(true); - - for(MBarcodePlugin*plug:allplugins) - if(plug)plug->configure(this); -} - -void MBarcodeConfiguration::addTab(QWidget* w, QString t) -{ - mtab->addTab(w,t); -} - - - -MBarcodeHub* MBarcodeHub::instance() -{ - static MBarcodeHub hub; - return &hub; -} - -MBarcodeHub::MBarcodeHub(): QObject() -{ - qDebug()<<"instantiating barcode hub"; -} - -MBarcodeHub::~MBarcodeHub() -{ - qDebug()<<"deleting barcode hub"; -} - -MBarcodeScanner::MBarcodeScanner(QObject* parent): QObject(parent) -{ -} - -void MBarcodePlugin::registerScanner(MBarcodeScanner* scanner) -{ - if(!scanner)return; - allscanners.append(scanner); - QObject::connect(scanner,SIGNAL(newBarcode(QString)), MBarcodeHub::instance(),SIGNAL(newBarcode(QString))); -} - -MBarcodePlugin::~MBarcodePlugin() -{} - -QList< MBarcodeScanner* > MBarcodeHub::allScanners() -{ - QListret; - for(MBarcodeScanner*s:allscanners) - if(s)ret<(oplug); - if(!plug)continue; - allplugins<(obj)); -} diff --git a/src/misc/barcode-plugin.h b/src/misc/barcode-plugin.h deleted file mode 100644 index dbeb6b3..0000000 --- a/src/misc/barcode-plugin.h +++ /dev/null @@ -1,117 +0,0 @@ -// -// C++ Interface: plugin base for barcode scanners -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2013-2014 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef MAGICSMOKE_BARCODE_PLUGIN_H -#define MAGICSMOKE_BARCODE_PLUGIN_H - -#ifdef MAGICSMOKE_LIB_BUILD -#define MAGICSMOKE_EXPORT Q_DECL_EXPORT -#else -#define MAGICSMOKE_EXPORT Q_DECL_IMPORT -#endif - -#include -#include -#include -#include - -class QTabWidget; - -///Scanner Configuration Dialog -class MAGICSMOKE_EXPORT MBarcodeConfiguration:public QDialog -{ - Q_OBJECT - public: - ///instantiates a new config dialog and asks plugins to display their tabs - MBarcodeConfiguration(QWidget*parent); - - public slots: - ///used by plugins to add configuration tabs, - ///tabs should connect to the accepted() and rejected() signals to store data - void addTab(QWidget*,QString); - private: - QTabWidget*mtab; -}; - -///base class of actual scanner implementations -class MAGICSMOKE_EXPORT MBarcodeScanner:public QObject -{ - Q_OBJECT - public: - explicit MBarcodeScanner(QObject* parent = 0); - - ///returns a human readable name for the scanner - virtual QString readableName()const=0; - - ///returns whether the scanner is currently active - virtual bool isActive()const=0; - - public slots: - ///attempts to activate the scanner - virtual void activate()=0; - ///attempts to de-activate the scanner - virtual void deactivate()=0; - signals: - ///emitted when the scanner becomes active - void activated(); - ///emitted when the scanner becomes inactive - void deactivated(); - ///emitted when a new barcode is available - void newBarcode(QString); -}; - -///base class of barcode scanner plugins -class MAGICSMOKE_EXPORT MBarcodePlugin -{ - public: - virtual ~MBarcodePlugin(); - - ///called whenever the user opens a configuration dialog - virtual void configure(MBarcodeConfiguration*)=0; - protected: - ///called by plugins to register a new scanner that has come online - static void registerScanner(MBarcodeScanner*); -}; - -///central barcode scanner hub, this is used by widgets that require barcodes, -///plugins report (indirectly) to the hub -class MAGICSMOKE_EXPORT MBarcodeHub:public QObject -{ - Q_OBJECT - public: - ///returns the hub object - static MBarcodeHub*instance(); - - ///initializes plugins (unless already initialized) - void initialize(); - - ///returns all currently active scanners - QListallScanners(); - - signals: - ///this is emitted whenever any of the barcode scanners find a new barcode - void newBarcode(QString); - - private slots: - ///automatically called by when a plugin destructs - void removePlugin(QObject*); - private: - MBarcodeHub(); - virtual ~MBarcodeHub(); -}; - -#define MBarcodePlugin_IID "de.silmor.MagicSmoke.BarcodePlugin/1.0" - -Q_DECLARE_INTERFACE(MBarcodePlugin, MBarcodePlugin_IID); - - -#endif diff --git a/src/misc/code39.cpp b/src/misc/code39.cpp deleted file mode 100644 index d559742..0000000 --- a/src/misc/code39.cpp +++ /dev/null @@ -1,111 +0,0 @@ -// -// C++ Implementation: code39 -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2007-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "code39.h" - -#include -#include - -//order of characters for checksum calculation and list of allowed chars -static const QString c39mod="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"; - -//init pixel map -static QMap initmap() -{ - QMapmap; - // 0=black 1=white pixel - map.insert('*',"0111010001000101"); - map.insert('-',"0111010100010001"); - map.insert('$',"0111011101110101"); - map.insert('%',"0101110111011101"); - map.insert(' ',"0111000101000101"); - map.insert('.',"0001110101000101"); - map.insert('/',"0111011101011101"); - map.insert('+',"0111010111011101"); - map.insert('0',"0101110001000101"); - map.insert('1',"0001011101010001"); - map.insert('2',"0100011101010001"); - map.insert('3',"0001000111010101"); - map.insert('4',"0101110001010001"); - map.insert('5',"0001011100010101"); - map.insert('6',"0100011100010101"); - map.insert('7',"0101110100010001"); - map.insert('8',"0001011101000101"); - map.insert('9',"0100011101000101"); - map.insert('A',"0001010111010001"); - map.insert('B',"0100010111010001"); - map.insert('C',"0001000101110101"); - map.insert('D',"0101000111010001"); - map.insert('E',"0001010001110101"); - map.insert('F',"0100010001110101"); - map.insert('G',"0101011100010001"); - map.insert('H',"0001010111000101"); - map.insert('I',"0100010111000101"); - map.insert('J',"0101000111000101"); - map.insert('K',"0001010101110001"); - map.insert('L',"0100010101110001"); - map.insert('M',"0001000101011101"); - map.insert('N',"0101000101110001"); - map.insert('O',"0001010001011101"); - map.insert('P',"0100010001011101"); - map.insert('Q',"0101010001110001"); - map.insert('R',"0001010100011101"); - map.insert('S',"0100010100011101"); - map.insert('T',"0101000100011101"); - map.insert('U',"0001110101010001"); - map.insert('V',"0111000101010001"); - map.insert('W',"0001110001010101"); - map.insert('X',"0111010001010001"); - map.insert('Y',"0001110100010101"); - map.insert('Z',"0111000100010101"); - return map; -} -//map characters on pixel codes -static const QMapc39map=initmap(); - -//calculate checksum -static char code39mod(QString str) -{ - int sum=0; - for(int i=0;i %c",str.toLatin1().data(),code39mod(str)); - //define xpm - const char *xpm[4]; - QByteArray xpmsz=QString().sprintf("%i 1 2 1",rstr.size()).toLatin1(); - xpm[0]=xpmsz.data(); - xpm[1]="0\tg #000000"; - xpm[2]="1\tg #FFFFFF"; - QByteArray xpmc=rstr.toLatin1(); - xpm[3]=xpmc.data(); - //create pixmap - return QImage(xpm); -} diff --git a/src/misc/code39.h b/src/misc/code39.h deleted file mode 100644 index 7d515f9..0000000 --- a/src/misc/code39.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// C++ Interface: code39 -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2007-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include -#include - -/**Takes a string and converts it into a code-39 bar code. -Code-39 allows letters (case-insensitive), digits, spaces and the special chars "-.$/+%". -The bar code pixmap will be 1 pixel high and 16 pixels wide for each character (plus start/stop character and checksum character) - it needs to be scaled up to fit the intended size.*/ -QImage code39(QString); diff --git a/src/misc/debug.cpp b/src/misc/debug.cpp deleted file mode 100644 index f2f92a8..0000000 --- a/src/misc/debug.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// -// C++ Implementation: debug -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2008-2012 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "debug.h" -#include "main.h" - -#include -#include -#include -#include -#include - -static QFile*mylogFile=0; - -static void mymsghandler(QtMsgType,const QMessageLogContext&, const QString&msg) -{ - if(mylogFile){ - mylogFile->write(msg.toLatin1()); - mylogFile->write("\n",1); - mylogFile->flush(); - } -#ifdef Q_OS_UNIX - fprintf(stderr,"%s\n",msg.toLatin1().data()); -#endif -} - -void initDebug() -{ - if(QCoreApplication::instance()->arguments().contains("-nolog")){ - qDebug()<<"-nolog argument was given, will not create a log file"; - } - //create new log file - const QString&dataDir=MApplication::dataDir(); - QDir(dataDir).mkpath("debuglog"); - mylogFile=new QFile(dataDir+"/debuglog/log-"+QDateTime::currentDateTime().toString("yyyy-MM-dd_hh.mm.ss.zzz")+".txt"); - //...open it - if(mylogFile->open(QIODevice::WriteOnly|QIODevice::Append|QIODevice::Text)){ - //install as default log - qDebug("Installing debuglog in %s",mylogFile->fileName().toLatin1().data()); - qInstallMessageHandler(mymsghandler); - }else{ - //hmm, failed to open, well hope that stderr is working... - delete mylogFile; - mylogFile=0; - qDebug("Failed to install debuglog."); - } - //delete old logs (older than 30 days) - QStringList fll=QDir(dataDir+"/debuglog").entryList(QDir::Files); - QDateTime old=QDateTime::currentDateTime().addDays(-30); - for(int i=0;i, (C) 2008-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef MAGICSMOKE_DEBUG_H -#define MAGICSMOKE_DEBUG_H - -void initDebug(); - -#endif diff --git a/src/misc/domiterator.h b/src/misc/domiterator.h deleted file mode 100644 index 5161c53..0000000 --- a/src/misc/domiterator.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// C++ Implementation: DOM node iterator for range based for loops -// -// -// Author: Konrad Rosenbaum , (C) 2013-2014 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// originally introduced at http://silmor.de/qtstuff.domfor.php - -#ifndef SMOKE_DOM_ITERATOR_H -#define SMOKE_DOM_ITERATOR_H - -class QDomNodeIterator -{ - int pos; - const QDomNodeList&container; -public: - //constructors and assignments - QDomNodeIterator(const QDomNodeList&l,int p):pos(p),container(l){} - QDomNodeIterator(const QDomNodeIterator&)=default; - QDomNodeIterator(QDomNodeIterator&&)=default; - QDomNodeIterator& operator=(const QDomNodeIterator&)=default; - QDomNodeIterator& operator=(QDomNodeIterator&&)=default; - - //increment - QDomNodeIterator& operator++(){pos++;return *this;} - - //comparison - bool operator==(const QDomNodeIterator&o){return pos==o.pos && container==o.container;} - bool operator!=(const QDomNodeIterator&o){return pos!=o.pos || container!=o.container;} - - //indirection - QDomNode operator*(){return container.at(pos);} -}; - -//begin and end -inline QDomNodeIterator begin(const QDomNodeList&l){return QDomNodeIterator(l,0);} -inline QDomNodeIterator end(const QDomNodeList&l){return QDomNodeIterator(l,l.size());} - - -#endif diff --git a/src/misc/dommodel.cpp b/src/misc/dommodel.cpp deleted file mode 100644 index 62f61ad..0000000 --- a/src/misc/dommodel.cpp +++ /dev/null @@ -1,556 +0,0 @@ -// -// C++ Implementation: DOM model -// -// -// Author: Konrad Rosenbaum , (C) 2012-2014 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "dommodel.h" - -#include -#include -#include -#include - -#include - -//switch this to en-/dis-able debug messages -static inline -// QDebug mDebug(){return QDebug(QtDebugMsg);} -QNoDebug mDebug(){return QNoDebug();} - -#include - -class DPTR_CLASS_NAME(MDomItemModel) -{ - public: - //nextid: counter for internal DOM node ids - //docid: id of the document node - int nextidx,docidx; - //cache structure that holds one node each - struct DomCache{ - QDomNode node; - QListchildren; - int parent; - DomCache():parent(-1){} - DomCache(const DomCache&)=default; - DomCache(const QDomNode&node_,int parent_=-1) - :node(node_),parent(parent_){} - }; - //cache of all DOM nodes, index is the internal ID - QMapdomCache; - //set of node types that are shown - QSetshowType; - //functors for generation of the display - QMap contentFromNode; - //config for element display - int elemAttrLen,elemTextLen; - bool showtypeLabel; - //header data - QMap,QVariant>horizHeader,vertHeader; - - Private(); - - int buildCache(const QDomNode&,int p=-1); - void removeNode(int nodeid,bool insideRecursion=false); -}; - -DEFINE_DPTR(MDomItemModel); - -MDomItemModel::MDomItemModel(QObject* parent) - : QAbstractItemModel(parent) -{ -} - -MDomItemModel::Private::Private() - :nextidx(1),docidx(-1) -{ - showType<domCache.clear(); - d->docidx=d->buildCache(doc); - mDebug()<<"DOM model setting new document - found"<domCache.size()<<"DOM nodes, root node is"<docidx; - endResetModel(); -} - -int MDomItemModel::Private::buildCache(const QDomNode& node,int parent) -{ - if(node.isNull())return -1; - //create this node - int idx=nextidx++; - DomCache dc(node,parent); - //recursively add children - QDomNodeList nl=node.childNodes(); - mDebug()<<"node"<& nt) -{ - if(nt==d->showType)return; - beginResetModel(); - d->showType=nt; - if(!d->showType.contains(QDomNode::ElementNode)) - d->showType.insert(QDomNode::ElementNode); - mDebug()<<"DOM Model - showing these types"<showType; - endResetModel(); -} - -void MDomItemModel::addShowNodeType(QDomNode::NodeType nt) -{ - if(d->showType.contains(nt))return; - beginResetModel(); - d->showType.insert(nt); - mDebug()<<"DOM Model - showing these types"<showType; - endResetModel(); -} - -void MDomItemModel::addShowNodeTypes(const QSet< QDomNode::NodeType >& nt) -{ - if(nt.isEmpty())return; - beginResetModel(); - foreach(QDomNode::NodeType n,nt) - if(!d->showType.contains(n)) - d->showType.insert(n); - mDebug()<<"DOM Model - showing these types"<showType; - endResetModel(); -} - -void MDomItemModel::showAllNodeTypes() -{ - showNodeTypes(QSet() - < MDomItemModel::shownNodeTypes()const -{ - return d->showType; -} - -void MDomItemModel::showElementProperties(int ma,int mt) -{ - //ignore if there is no change - if(d->elemAttrLen == ma && d->elemTextLen == mt)return; - //send a model reset if this has an actual effect, ie. if we do the rendering - bool b=!d->contentFromNode.contains(Qt::DisplayRole); - if(b)beginResetModel(); - //change params - d->elemAttrLen=ma; - d->elemTextLen=mt; - //tell the view - if(b)endResetModel(); -} - -void MDomItemModel::showTypeLabel(bool show) -{ - //ignore if there is no change - if(d->showtypeLabel == show)return; - //send a model reset if this has an actual effect, ie. if we do the rendering - bool b=!d->contentFromNode.contains(Qt::DisplayRole); - if(b)beginResetModel(); - //change params - d->showtypeLabel=show; - //tell the view - if(b)endResetModel(); -} - -QDomNode MDomItemModel::node(const QModelIndex& index) const -{ - if(!index.isValid()){ - if(!d->domCache.contains(d->docidx)) return QDomNode(); - else return d->domCache[d->docidx].node; - } - if(!d->domCache.contains(index.internalId()))return QDomNode(); - QDomNode node=d->domCache[index.internalId()].node; - qDebug()<<"returning node"<domCache.contains(nid))return; - int pid=d->domCache[nid].parent; - if(pid<=0 || !d->domCache.contains(pid))return; - //invalidate children - int csize=d->domCache[nid].children.size()-1; - if(csize<0)csize=0; - beginRemoveRows(index,0,csize); - for(int n:d->domCache[nid].children)d->removeNode(n); - d->domCache[nid].children.clear(); - endRemoveRows(); - //replace the node in DOM - qDebug()<<"replacing node"<domCache[nid].node.nodeValue()<<"new"<domCache[pid].node.replaceChild(nnode,d->domCache[nid].node); - d->domCache[nid].node=nnode; - qDebug()<<" new nodes type is"<domCache[nid].children.append(d->buildCache(nl.at(i),nid)); - endInsertRows(); - //tell the view we are finished - dataChanged(index,index); -} - -void MDomItemModel::insertNodes(const QDomNodeList& newnodes, const QModelIndex& parent, int row) -{ - QListnnl; - for(int i=0;i()<& newnodes, const QModelIndex& parent, int row) -{ - if(newnodes.size()<1)return; - //check parent validity - if(!parent.isValid())return; - int pid=parent.internalId(); - if(!d->domCache.contains(pid))return; - //only add to tags (TODO: there are a few other node types that can have children) - if(!d->domCache[pid].node.isElement())return; - //get the parent and a clone of the new node - QDomElement pn=d->domCache[pid].node.toElement(); - const int rcnt=rowCount(parent); - //handle appending - if(row<0 || row>=rcnt){ - const int rmax=rcnt+newnodes.size()-1; - beginInsertRows(parent,rcnt,rmax); - for(QDomNode nd:newnodes){ - QDomNode nn=nd.cloneNode(); - pn.appendChild(nn); - d->domCache[pid].children.append(d->buildCache(nn,pid)); - } - endInsertRows(); - return; - } - //handle inserting - //get current occupant of this row - QDomNode sibl=node(index(row,0,parent)); - const int rmax=row+newnodes.size()-1; - beginInsertRows(parent,row,rmax); - //insert - for(QDomNode nd:newnodes){ - QDomNode nn=nd.cloneNode(); - qDebug()<<"Attempting insert with"<domCache[pid].children.insert(row,d->buildCache(nn,pid)); - } - endInsertRows(); -} - -int MDomItemModel::columnCount(const QModelIndex&) const -{ - return 1; -} - -QDomDocument MDomItemModel::domDocument() const -{ - if(d->docidx>=0 && d->domCache.contains(d->docidx)) - return d->domCache[d->docidx].node.cloneNode().toDocument(); - else - return QDomDocument(); -} - -QVariant MDomItemModel::data(const QModelIndex& index, int role) const -{ - if(role==DomNodeRole)return QVariant::fromValue(node(index)); - //root index - QDomNode node; - if(!index.isValid()){ - if(d->domCache.contains(d->docidx)) - node=d->domCache[d->docidx].node; - }else{ - if(d->domCache.contains(index.internalId())) - node=d->domCache[index.internalId()].node; - } - //check node - if(node.isNull())return QVariant(); - //try to find callback - if(d->contentFromNode.contains(role))return d->contentFromNode[role](node); - //no callback: display role - if(role==Qt::DisplayRole)return displayFromNode(node); - //fall back - return QVariant(); -} - -QVariant MDomItemModel::displayFromNode(const QDomNode& node) const -{ - if(node.isNull())return "NULL node"; - switch(node.nodeType()){ - case QDomNode::ElementNode:{ - QString r; - if(d->showtypeLabel)r+="tag "; - r+="<"+node.nodeName(); - QString a,t; - //append attribs - if(d->elemAttrLen>=0 && node.hasAttributes()){ - auto attrs=node.attributes(); - QString a; - for(int i=0;id->elemAttrLen){ - a.truncate(d->elemAttrLen); - a+="..."; - } - r+=" "+a.trimmed(); - } - r+=">"; - //append text - if(d->elemTextLen>0){ - QString t; - QDomNodeList nl=node.childNodes(); - for(int i=0;i0)t+=" "; - t+=QString(nd.nodeValue()).replace('\n',' '); - } - } - if(t.size()>d->elemTextLen){ - t.truncate(d->elemTextLen); - t+="..."; - } - r+=t.trimmed(); - } - return r; - } - case QDomNode::AttributeNode: - return (d->showtypeLabel?"attribute ":"")+node.nodeName()+"="+node.nodeValue(); - case QDomNode::TextNode: - case QDomNode::CDATASectionNode: - return QString(d->showtypeLabel?"text ":"")+"\""+QString(node.nodeValue()).replace('\n',' ')+"\""; - case QDomNode::CommentNode: - return QString(d->showtypeLabel?"comment ":"")+""; - default: - return (d->showtypeLabel?("node ("+QString::number(node.nodeType())+"): "):QString())+node.nodeName()+" - \""+node.nodeValue()+"\""; - } -} - -int MDomItemModel::rowCount(const QModelIndex& parent) const -{ - int pid=-1; - if(!parent.isValid())pid=d->docidx; - else pid=parent.internalId(); - if(!d->domCache.contains(pid)){ - mDebug()<<"DOM Model - index"<domCache[pid].children) - if(d->domCache.contains(cid) && d->showType.contains(d->domCache[cid].node.nodeType())) - ret++; - mDebug()<<"DOM Model - index"<domCache[pid].children.size()<<"items"; - return ret; -} - -QModelIndex MDomItemModel::index(int row, int column, const QModelIndex& parent) const -{ - //only col 0 is valid for now - if(column!=0){ - mDebug()<<"DOM Model - index for wrong column requested"<docidx; - else pid=parent.internalId(); - if(pid<=0 || !d->domCache.contains(pid)){ - mDebug()<<"DOM Model - index for invalid node requested"<=d->domCache[pid].children.size()){ - mDebug()<<"DOM Model - index of empty parent requested, parent:"<domCache[pid].children){ - if(!d->showType.contains(d->domCache[cid].node.nodeType())) - continue; - if(row==rc++){ - mDebug()<<"DOM Model - creating index"<domCache.contains(index.internalId())){ - mDebug()<<"DOM Model - requesting parent of"<domCache[index.internalId()].parent; - if(pid<=0 || !d->domCache.contains(pid)){ - mDebug()<<"DOM Model - requesting parent of"<domCache[pid].parent; - //is grand-parent invalid? (parent must be the root node) - if(gpid<=0 || !d->domCache.contains(gpid)){ - mDebug()<<"DOM Model - requesting parent of"<domCache[gpid].children){ - if(nid==pid)break; - if(d->showType.contains(d->domCache[nid].node.nodeType()))row++; - } - mDebug()<<"DOM Model - requesting parent of"<domCache.contains(nid))return; - //find parent index and warn the view - QModelIndex pidx=parent(index); - if(pidx.isValid())beginRemoveRows(pidx,index.row(),index.row()); - else beginResetModel(); - //remove the node - d->removeNode(nid); - //tell the view we are done - if(pidx.isValid())endRemoveRows(); - else endResetModel(); -} - -void MDomItemModel::Private::removeNode(int nid,bool inrecurs) -{ - //sanity check - if(!domCache.contains(nid))return; - //remove main node from model - if(!inrecurs){ - int pid=domCache[nid].parent; - if(domCache.contains(pid)){ - domCache[pid].node.removeChild(domCache[nid].node); - domCache[pid].children.removeAll(nid); - } - } - //remove children - foreach(int cid,domCache[nid].children) - removeNode(cid,true); - //remove self - domCache.remove(nid); -} - - -bool MDomItemModel::removeRows(int row, int count, const QModelIndex& parent) -{ - //sanity check - if(row<0 || count<=0)return false; - //find the parent - int pid=-1; - if(parent.isValid())pid=parent.internalId(); - else pid=d->docidx; - if(!d->domCache.contains(pid)) - return false; - //check the parent has those children - if(rowCount(parent)<(row+count)) - return false; - //warn the view - beginRemoveRows(parent,row,row+count-1); - //find the children's IDs - QListcids; - int cnt=0; - foreach(int cid,d->domCache[pid].children){ - if(cnt>=(row+count))break; - if(!d->showType.contains(d->domCache[cid].node.nodeType())) - continue; - if(cnt++>=row)cids<removeNode(cid); - //update view - endRemoveRows(); - return true; -} - -void MDomItemModel::setContentFromNodeCall(int role,MDomModelFunctor f) -{ - if(role==DomNodeRole)return; - beginResetModel(); - if(f) - d->contentFromNode.insert(role,f); - else - d->contentFromNode.remove(role); - endResetModel(); -} - -QVariant MDomItemModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if(orientation==Qt::Horizontal) - return d->horizHeader.value(QPair(section,role)); - else - return d->vertHeader.value(QPair(section,role)); -} - -bool MDomItemModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant& value, int role) -{ - if(orientation==Qt::Horizontal) - d->horizHeader.insert(QPair(section,role),value); - else - d->vertHeader.insert(QPair(section,role),value); - return true; -} diff --git a/src/misc/dommodel.h b/src/misc/dommodel.h deleted file mode 100644 index 6086fe7..0000000 --- a/src/misc/dommodel.h +++ /dev/null @@ -1,138 +0,0 @@ -// -// C++ Interface: odtrender -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2008-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef MAGICSMOKE_DOMMODEL_H -#define MAGICSMOKE_DOMMODEL_H - -#include -#include -#include - -#include - -class QDomNode; -class QDomDocument; - -/** \brief Special functor that can be used to customize MDomItemModel. -Any static function or lambda that takes a QDomNode as argument and returns a QVariant can be used to specialize MDomItemModel. The type of data returned through the QVariant depends on the role the function is supposed to serve. Only one function/lambda can be registered for each role in any given model instance.*/ -typedef std::function MDomModelFunctor; - -/** \brief This is a specialized model type that shows and allows to manipulate a DOM tree. -The model holds a copy of the DOM tree, so the original is not changed even if the model changes. -You can retrieve a current copy of the model's DOM tree by calling domDocument(). -This model can not carry application specific user data. It is only editable through its specialized node methods.*/ -class MDomItemModel:public QAbstractItemModel -{ - Q_OBJECT - DECLARE_DPTR(d); - public: - ///instantiate an empty DOM model - MDomItemModel(QObject* parent = 0); - ///instantiate a DOM model with an initial DOM tree - ///\param xml the model will be fed with a copy of this DOM tree - MDomItemModel(const QDomDocument&xml, QObject* parent = 0); - - /**returns a copy of the DOM tree represented by this model, - you can safely manipulate this copy without influencing the model. If you want - to change the model's content use the node methods provided here.*/ - virtual QDomDocument domDocument()const; - - ///alias for Qt::UserRole that is used to retrieve the DOM node of an index. - static const int DomNodeRole=Qt::UserRole; - - ///always returns 1 - the DOM tree has only one column corresponding to the node - virtual int columnCount(const QModelIndex&parent=QModelIndex())const; - ///returns data corresponding to the node represented by index; - ///this method can be customized through setContentFromNodeCall(...) - virtual QVariant data(const QModelIndex&index, int role=Qt::DisplayRole)const; - - ///returns an index corresponding to the row, column, and parent node - /// \param row the row beneith the parent node - the row number depends on which node types are shown, only visible node types are counted - /// \param column must be 0, otherwise an invalid index is returned - /// \param parent an invalid node for the root node (QDomDocument) or any valid index returned through index(...) - virtual QModelIndex index(int row, int column, const QModelIndex&parent=QModelIndex())const; - ///returns the parent index of a node - if it has a parent - virtual QModelIndex parent(const QModelIndex&index)const; - ///returns the amount of visible nodes beneith parent - virtual int rowCount(const QModelIndex&parent=QModelIndex())const; - - ///returns a set of node types that are configured to be visible in this model - virtual QSet shownNodeTypes()const; - - ///returns the QDomNode corresponding to index, for the invalid index the QDomDocument is returned - virtual QDomNode node(const QModelIndex&index)const; - - ///sets header data - it is currently possible to set any header for any role, although only few are actually shown in views - bool setHeaderData(int section, Qt::Orientation orientation, const QVariant & value, int role = Qt::EditRole); - ///returns the header data for a specific header position and role - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole)const; - - public slots: - /** sets the document represented by this model; - the model makes a deep copy of the document, so that the original stays intact even if the model changes. Use domDocument() to retrieve a fresh copy of the models version of the document.*/ - virtual void setDomDocument(const QDomDocument&); - - ///changes the settings of what kinds of nodes are shown in the model, - ///element nodes cannot be switched off, - ///all model indexes become invalid after a call to this method - void showNodeTypes(const QSet&); - ///changes the settings of what kinds of nodes are shown in the model, - ///all model indexes become invalid after a call to this method - void addShowNodeType(QDomNode::NodeType); - ///changes the settings of what kinds of nodes are shown in the model, - ///all model indexes become invalid after a call to this method - void addShowNodeTypes(const QSet&); - ///changes the settings of what kinds of nodes are shown in the model, - ///all model indexes become invalid after a call to this method - void showAllNodeTypes(); - - /**changes the way element nodes are displayed, - this method has no effect if you customize Qt::DisplayRole through setContentFromNodeCall(...) - \param maxattr the amount of characters shown for attributes, if this is 0 the model will just show "..." if the element has attributes, if this is <0 the model will ignore attributes - \param maxtext the amount of characters shown for character data (QDomText and QDomCDATASection), if this is 0 the model will just show "..." if the element has text, if this is <0 the model will ignore any text - */ - void showElementProperties(int maxattr,int maxtext); - - ///if true the default display routine will show a node type label - void showTypeLabel(bool show=true); - - ///replaces the node at the index, you cannot replace the entire document with this function - use setDomDocument for this - virtual void setNode(const QModelIndex&index,const QDomNode&); - ///insert a node into the parent at given position (if no position is given: append) - virtual void insertNode(const QDomNode&newnode,const QModelIndex&parent,int row=-1); - ///insert a list of nodes into the parent at given position (if no position is given: append) - virtual void insertNodes(const QDomNodeList&newnodes,const QModelIndex&parent,int row=-1); - ///insert a list of nodes into the parent at given position (if no position is given: append) - virtual void insertNodes(const QList&newnodes,const QModelIndex&parent,int row=-1); - ///removes the nodes at the given position and their child nodes - virtual bool removeRows(int row, int count, const QModelIndex&parent=QModelIndex()); - ///removes the node at the given position and its child nodes - virtual void removeNode(const QModelIndex&); - - /**Customize the way the model returns data to the view, per default the model only has code to generate a text representation for Qt::DisplayRole. You can override any role, including Qt::DisplayRole, except for DomNodeRole. The callback takes a const reference to QDomNode as argument and should convert it to a QVariant appropriate for the role. - \param role the role to be customized - \param callback a static function, functor or lambda that takes a node as argument and returns a variant as result, use nullptr to delete a customization - */ - void setContentFromNodeCall(int role,MDomModelFunctor callback); - - ///resets the model to an invalid/empty QDomDocument - virtual void clear(){setDomDocument(QDomDocument());} - - private: - ///default implementation for Display-Role - QVariant displayFromNode(const QDomNode&)const; -}; - -Q_DECLARE_METATYPE(QDomNode); -Q_DECLARE_METATYPE(MDomModelFunctor); - -#endif diff --git a/src/misc/misc.pri b/src/misc/misc.pri deleted file mode 100644 index 565a3d5..0000000 --- a/src/misc/misc.pri +++ /dev/null @@ -1,16 +0,0 @@ -HEADERS += \ - $$PWD/debug.h \ - $$PWD/waitcursor.h \ - $$PWD/sclock.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/barcode-plugin.cpp - -INCLUDEPATH += $$PWD diff --git a/src/misc/sclock.cpp b/src/misc/sclock.cpp deleted file mode 100644 index 3284d12..0000000 --- a/src/misc/sclock.cpp +++ /dev/null @@ -1,155 +0,0 @@ -// -// C++ Implementation: overview -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2007-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "sclock.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "misc.h" - -MServerClock::MServerClock() -{ - QTimer *tm=new QTimer(this); - tm->setSingleShot(false); - tm->start(1000); - connect(tm,SIGNAL(timeout()),this,SLOT(updateClock())); - - connect(this,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(contextMenu(QPoint))); - setContextMenuPolicy(Qt::CustomContextMenu); - setFrameStyle(QFrame::Panel|QFrame::Sunken); - - contextmenu=new QMenu(this); - contextmenu->addAction(tr("Show Format Info"),this,SLOT(showInfo())); - contextmenu->addSeparator(); - QActionGroup*ag=new QActionGroup(this); - QAction*ac=ag->addAction(tr("Show Full Time")); - ac->setCheckable(true);ac->setChecked(true); - ac->setData(tr("%W, %D %N %Y %a:%I %p %t","full time format")); - contextmenu->addAction(ac);showfull=ac; - ac=ag->addAction(tr("Show Date Only"));ac->setCheckable(true); - ac->setData(tr("%w, %M/%D/%Y","date only format")); - contextmenu->addAction(ac);showdate=ac; - ac=ag->addAction(tr("Show Time Only"));ac->setCheckable(true); - ac->setData(tr("%a:%I %p %t","time only format")); - contextmenu->addAction(ac);showtime=ac; - ac=ag->addAction(tr("Show Short Date/Time"));ac->setCheckable(true); - ac->setData(tr("%w %Y-%M-%D %h:%I %t","ISO like short time format")); - contextmenu->addAction(ac);showiso=ac; - connect(ag,SIGNAL(triggered(QAction*)),this,SLOT(updateClock())); - - updateClock(); -} - -void MServerClock::updateClock() -{ - //get time and format - TimeStamp ts=TimeStamp::now(); - QString fm=showfull->data().toString(); - if(showdate->isChecked())fm=showdate->data().toString(); - if(showtime->isChecked())fm=showtime->data().toString(); - if(showiso->isChecked())fm=showiso->data().toString(); - //set it - setText(MLocalFormat().formatDateTime(ts,fm)); - //make sure tool tip is up to date - int off=ts.offsetFromUTC()/60; - QString tz=tr("Server Time Zone: %1\nOffset from UTC: %2 minutes %3") - .arg(MLocalFormat().timeZone()) - .arg(off<0?-off:off) - .arg(off>=0?tr("east","positive time zone offset"):tr("west","negative time zone offset")); - if(toolTip()!=tz)setToolTip(tz); -} - -void MServerClock::mouseDoubleClickEvent(QMouseEvent* event) -{ - QWidget::mouseDoubleClickEvent(event); - if(event->button()!=Qt::LeftButton)return; - showInfo(); -} - -static inline QString list2str(const QStringList&l) -{ - QString ret,r; - for(int i=0;i=30){ - ret+=r+"\n"; - r=""; - } - } - ret+=r; - return ret.trimmed(); -} - -void MServerClock::showInfo() -{ - QDialog d(this); - d.setWindowTitle(tr("Server Format Info")); - QVBoxLayout*vl; - QFormLayout*fl; - QHBoxLayout*hl; - d.setLayout(vl=new QVBoxLayout); - vl->addLayout(fl=new QFormLayout,10); - fl->setLabelAlignment(Qt::AlignRight|Qt::AlignTop); - MLocalFormat lf; - fl->addRow(new QLabel(tr("Number Format:"))); - fl->addRow(tr("Decimal Dot:"),new QLabel(lf.decimalDot())); - fl->addRow(tr("Separator:"),new QLabel(tr("'%1' every %2 digits").arg(lf.thousandSeparator()).arg(lf.thousandDigits()))); - - fl->addRow(new QLabel); - fl->addRow(new QLabel(tr("Currency Settings:"))); - fl->addRow(tr("Currency Symbol:"),new QLabel(lf.currency())); - fl->addRow(tr("Division Digits:"),new QLabel(QString::number(lf.moneyDecimals()))); - fl->addRow(tr("Negative Sign:"),new QLabel(lf.moneyNegativeSign())); - fl->addRow(tr("Positive Sign:"),new QLabel(lf.moneyPositiveSign())); - fl->addRow(tr("Example:"),new QLabel(lf.formatMoney(-1234567890))); - - fl->addRow(new QLabel); - fl->addRow(new QLabel(tr("Date and Time Settings:"))); - fl->addRow(tr("Day of the Week:"),new QLabel(list2str(lf.weekDayNames()))); - fl->addRow(tr("Day of the Week Abbreviated:"),new QLabel(list2str(lf.shortWeekDayNames()))); - fl->addRow(tr("Month Names:"),new QLabel(list2str(lf.monthNames()))); - fl->addRow(tr("Month Names Abbreviated:"),new QLabel(list2str(lf.shortMonthNames()))); - fl->addRow(tr("Date Format:"),new QLabel(lf.dateFormat())); - fl->addRow(tr("Time Format:"),new QLabel(lf.timeFormat())); - fl->addRow(tr("Date and Time Format:"),new QLabel(lf.dateTimeFormat())); - MLocalFormat lfs;lfs.setTimeZone(TimeStamp::systemLocalZone()); - TimeStamp now=TimeStamp::now(); - fl->addRow(tr("System Time Zone:"),new QLabel(lfs.timeZone())); - fl->addRow(tr("Current Local Time:"),new QLabel(lfs.formatDateTime(now))); - fl->addRow(tr("Theater/Server Time Zone:"),new QLabel(lf.timeZone())); - fl->addRow(tr("Current Theater/Server Time:"),new QLabel(lf.formatDateTime(now))); - - vl->addLayout(hl=new QHBoxLayout,0); - hl->addStretch(10); - QPushButton*p; - hl->addWidget(p=new QPushButton(tr("Close"))); - p->setDefault(true); - connect(p,SIGNAL(clicked()),&d,SLOT(close())); - - d.exec(); -} - -void MServerClock::contextMenu(const QPoint& p) -{ - contextmenu->popup(mapToGlobal(p)); -} diff --git a/src/misc/sclock.h b/src/misc/sclock.h deleted file mode 100644 index 6fbb7de..0000000 --- a/src/misc/sclock.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// C++ Interface: overview -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2007-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef MAGICSMOKE_SCLOCK_H -#define MAGICSMOKE_SCLOCK_H - -#include - - -class QMenu; -class QAction; - - -class MServerClock:public QLabel -{ - Q_OBJECT - public: - MServerClock(); - private slots: - void updateClock(); - void contextMenu(const QPoint&); - void showInfo(); - protected: - virtual void mouseDoubleClickEvent ( QMouseEvent * event ); - private: - QMenu*contextmenu; - QAction*showfull,*showtime,*showdate,*showiso; -}; - -#endif diff --git a/src/misc/waitcursor.cpp b/src/misc/waitcursor.cpp deleted file mode 100644 index 21410ce..0000000 --- a/src/misc/waitcursor.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// C++ Implementation: waitcursor -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2009-2013 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "waitcursor.h" -#include - -#include -#include - -WaitCursor::WaitCursor() -{ - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); -} - -WaitCursor::~WaitCursor() -{ - QApplication::restoreOverrideCursor(); -} - -static int transactionCursor() -{ - MTransaction::setStartStopActions( - []{QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));}, - []{QApplication::restoreOverrideCursor();} - ); - return 0; -} - -static int tcdummy=transactionCursor(); \ No newline at end of file diff --git a/src/misc/waitcursor.h b/src/misc/waitcursor.h deleted file mode 100644 index f1082cf..0000000 --- a/src/misc/waitcursor.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// C++ Interface: waitcursor -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2009-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef MAGICSMOKE_WAITCURSOR_H -#define MAGICSMOKE_WAITCURSOR_H - -/**simple class to show a busy-cursor while an instance of it exists*/ -class WaitCursor -{ - public: - /**displays a wait cursor (Qt::WaitCursor)*/ - WaitCursor(); - /**restores the last normal cursor*/ - ~WaitCursor(); -}; - - -#endif diff --git a/src/mwin/overview.cpp b/src/mwin/overview.cpp index 237b672..23c6632 100644 --- a/src/mwin/overview.cpp +++ b/src/mwin/overview.cpp @@ -4,14 +4,14 @@ // Description: // // -// Author: Konrad Rosenbaum , (C) 2007-2011 +// Author: Konrad Rosenbaum , (C) 2007-2016 // // Copyright: See README/COPYING.GPL files that come with this distribution // // #include "customerdlg.h" -#include "main.h" +#include "mapplication.h" #include "msinterface.h" #include "passwdchg.h" #include "shipping.h" @@ -590,7 +590,7 @@ void MOverview::displaySettings() void MOverview::changeLang() { - choseLanguage(); + MApplication::choseLanguage(); } diff --git a/src/mwin/overview.h b/src/mwin/overview.h index 512504b..8d4abd7 100644 --- a/src/mwin/overview.h +++ b/src/mwin/overview.h @@ -4,7 +4,7 @@ // Description: // // -// Author: Konrad Rosenbaum , (C) 2007-2011 +// Author: Konrad Rosenbaum , (C) 2007-2016 // // Copyright: See README/COPYING.GPL files that come with this distribution // diff --git a/src/mwin/tabwin.cpp b/src/mwin/tabwin.cpp index bb22acb..267ba6d 100644 --- a/src/mwin/tabwin.cpp +++ b/src/mwin/tabwin.cpp @@ -11,7 +11,7 @@ // #include "customerdlg.h" -#include "main.h" +#include "mapplication.h" #include "msinterface.h" #include "passwdchg.h" #include "shipping.h" diff --git a/src/script/jsengine.cpp b/src/script/jsengine.cpp index e229e1a..b3a8372 100644 --- a/src/script/jsengine.cpp +++ b/src/script/jsengine.cpp @@ -13,7 +13,7 @@ #include "jsengine.h" #include "overview.h" #include "msinterface.h" -#include "main.h" +#include "mapplication.h" #include "templates.h" #include diff --git a/src/smoke.pri b/src/smoke.pri index 08bfa38..829c8b2 100644 --- a/src/smoke.pri +++ b/src/smoke.pri @@ -7,11 +7,8 @@ include (libs.pri) LIBS += -lmagicsmoke INCLUDEPATH += \ $$PWD \ - $$PWD/crypto \ $$PWD/dialogs \ - $$PWD/misc \ $$PWD/mwin \ $$PWD/script \ - $$PWD/templates \ - $$PWD/widgets + $$PWD/templates diff --git a/src/smoke.pro b/src/smoke.pro index 6e91bc0..17bd52d 100644 --- a/src/smoke.pro +++ b/src/smoke.pro @@ -29,10 +29,7 @@ DEFINES += HOMEPAGE_BASEURL=\\\"http://smoke.silmor.de\\\" RESOURCES += images/files.qrc #libraries, modules, stuff... -include(widgets/widgets.pri) include(templates/templates.pri) -include(misc/misc.pri) -include(crypto/crypto.pri) include(dialogs/dialogs.pri) include(mwin/mwin.pri) include(script/script.pri) diff --git a/src/templates/labeldlg.cpp b/src/templates/labeldlg.cpp deleted file mode 100644 index 324acef..0000000 --- a/src/templates/labeldlg.cpp +++ /dev/null @@ -1,863 +0,0 @@ -// -// C++ Implementation: labeldlg -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2008-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "labeldlg.h" - -#include "msinterface.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -// #include -#include -#include -#include -#include -#include -#include -#include - -#define ROWS 20 -#define COLS 20 - -MLabelDialog::MLabelDialog(QWidget*par,QPrinter* pn,int nl,QSizeF ls) - :QDialog(par) -{ - printer=pn; - numlabels=nl; - labelsize=ls; - maxrows=ROWS; - maxcols=COLS; - - setWindowTitle(tr("Label Printing Setup")); - - //get settings - QSettings set; - set.beginGroup("printer/"+printer->printerName()); - double ox=set.value("offsetx",0.0).toDouble(); - double oy=set.value("offsety",0.0).toDouble(); - double lsx=set.value("sizex",0.0).toDouble(); - double lsy=set.value("sizey",0.0).toDouble(); - QString mtrc=set.value("metric",tr("mm","defaultmetric: mm, in, cm")).toString(); - if(lsx==0.0 || lsy==0.0){ - //convert ticket template size - double dx=printer->logicalDpiX(); - double dy=printer->logicalDpiY(); - if(mtrc=="in"){ - lsx=ls.width()/dx; - lsy=ls.height()/dy; - }else - if(mtrc=="cm"){ - lsx=ls.width()/dx*2.54; - lsy=ls.height()/dy*2.54; - }else{//mm - lsx=ls.width()/dx*25.4; - lsy=ls.height()/dy*25.4; - } - } - - //display - - QVBoxLayout*vl; - QGridLayout*gl; - setLayout(vl=new QVBoxLayout); - vl->addLayout(gl=new QGridLayout,0); - - int ln=0; - gl->addWidget(new QLabel(tr("Label offset:")),ln,0); - gl->addWidget(offx=new QLineEdit(QString::number(ox)),ln,1); - offx->setValidator(new QDoubleValidator(0.0,1000.0,2,this)); - gl->addWidget(new QLabel("x"),ln,2); - gl->addWidget(offy=new QLineEdit(QString::number(oy)),ln,3); - offy->setValidator(new QDoubleValidator(0.0,1000.0,2,this)); - gl->addWidget(new QLabel(tr("Label size:")),++ln,0); - gl->addWidget(sizex=new QLineEdit(QString::number(lsx)),ln,1); - sizex->setValidator(new QDoubleValidator(0.0,1000.0,2,this)); - gl->addWidget(new QLabel("x"),ln,2); - gl->addWidget(sizey=new QLineEdit(QString::number(lsy)),ln,3); - sizey->setValidator(new QDoubleValidator(0.0,1000.0,2,this)); - gl->addWidget(new QLabel(tr("Unit:")),++ln,0); - gl->addWidget(metric=new QComboBox,ln,1,1,3); - metric->addItem(tr("Millimeter"),"mm"); - metric->addItem(tr("Centimeter"),"cm"); - metric->addItem(tr("Inch"),"in"); - gl->addWidget(warning=new QLabel(""),++ln,0,1,4); - QPalette pal=warning->palette(); - pal.setColor(QPalette::WindowText,Qt::red); - warning->setPalette(pal); - gl->setColumnStretch(++ln,10); - - vl->addSpacing(10); - vl->addWidget(new QLabel(tr("Page usage:")),0); - vl->addWidget(page=new QComboBox,0); - for(int i=0;iaddItem(tr("Page %1").arg(i+1),i); - oldpage=0; - - QScrollArea *sa; - QWidget*w=new QWidget; - vl->addWidget(sa=new QScrollArea,10); - w->setLayout(gl=new QGridLayout); - QToolButton*t; - gl->addWidget(t=new QToolButton,0,0); - t->setIcon(QIcon(":/arrowdiag.png")); - connect(t,SIGNAL(clicked()),this,SLOT(toggleAll())); - QSignalMapper *cmap=new QSignalMapper(this); - connect(cmap,SIGNAL(mapped(int)),this,SLOT(toggleColumn(int))); - for(int i=1;i<=COLS;i++){ - gl->addWidget(t=new QToolButton,0,i); - t->setIcon(QIcon(":/arrowdown.png")); - connect(t,SIGNAL(clicked()),cmap,SLOT(map())); - cmap->setMapping(t,i-1); - } - QSignalMapper *rmap=new QSignalMapper(this); - connect(rmap,SIGNAL(mapped(int)),this,SLOT(toggleRow(int))); - for(int i=1;i<=ROWS;i++){ - gl->addWidget(t=new QToolButton,i,0); - t->setIcon(QIcon(":/arrowright.png")); - connect(t,SIGNAL(clicked()),rmap,SLOT(map())); - rmap->setMapping(t,i-1); - for(int j=1;j<=COLS;j++){ - QCheckBox*b; - gl->addWidget(b=new QCheckBox,i,j); - checks.append(b); - connect(b,SIGNAL(clicked()),this,SLOT(savePage())); - } - } - sa->setWidget(w); - connect(page,SIGNAL(currentIndexChanged(int)),this,SLOT(updatePage())); - connect(sizex,SIGNAL(textChanged(const QString&)),this,SLOT(updatePage())); - connect(sizey,SIGNAL(textChanged(const QString&)),this,SLOT(updatePage())); - connect(metric,SIGNAL(currentIndexChanged(int)),this,SLOT(updatePage())); - - vl->addSpacing(15); - QHBoxLayout*hl; - vl->addLayout(hl=new QHBoxLayout); - hl->addStretch(10); - QPushButton*p; - hl->addWidget(p=new QPushButton(tr("Ok")),0); - connect(p,SIGNAL(clicked()),this,SLOT(accept())); - connect(p,SIGNAL(clicked()),this,SLOT(saveSettings())); - p->setDefault(true); - hl->addWidget(p=new QPushButton(tr("Cancel")),0); - connect(p,SIGNAL(clicked()),this,SLOT(reject())); - - //initialize - QListtpl; - for(int i=0;i<(ROWS*COLS);i++)tpl.append(true); - for(int i=0;i>(QDataStream &in, MLabelConfig &myObj) -{ - char *t; - uint l; - in.readBytes(t,l); - if(t && l>0) - myObj.m_type=(MLabelConfig::LabelType)(*t); - if(t)delete t; - return in; -} - -void MLabelConfig::initMeta() -{ - static int mt=-1; - if(mt>=0)return; - mt=qRegisterMetaType(); - qRegisterMetaTypeStreamOperators(); -} - -MLabelDialog::~MLabelDialog(){} - -int MLabelDialog::findLabel(int n,int&row,int&col)const -{ - //search allowed labels - int ctr=-1; - for(int p=0;p=0;r--) - for(int c=0;ctext().toDouble(); - double py=offy->text().toDouble(); - //add rows/cols - px+=col*sizex->text().toDouble(); - py+=row*sizey->text().toDouble(); - //correct to DPI - QString mtrc=metric->itemData(metric->currentIndex()).toString(); - if(mtrc=="in"){ - px*=printer->logicalDpiX(); - py*=printer->logicalDpiY(); - }else - if(mtrc=="cm"){ - px*=printer->logicalDpiX()/2.54; - py*=printer->logicalDpiY()/2.54; - }else{ - px*=printer->logicalDpiX()/25.4; - py*=printer->logicalDpiY()/25.4; - } - //return - return QPointF(px,py); -} - -bool MLabelDialog::labelNeedsPageTurn(int n)const -{ - //find it - int pg,row=0,col=0; - pg=findLabel(n,row,col); - //page 0 needs no turn - if(pg<=0)return false; - //scan that page (all rows below label) - for(int r=maxrows-1;r>row;r--) - for(int c=0;csetChecked(checked[oldpage][i]); - } -} - -void MLabelDialog::toggleColumn(int c) -{ - for(int r=0;rsetChecked(checked[oldpage][i]); - } -} - -void MLabelDialog::toggleAll() -{ - for(int i=0;i<(ROWS*COLS);i++){ - checked[oldpage][i]^=true; - checks[i]->setChecked(checked[oldpage][i]); - } -} - -void MLabelDialog::savePage() -{ - for(int i=0;i<(ROWS*COLS);i++) - checked[oldpage][i]=checks[i]->isChecked(); -} - -void MLabelDialog::updatePage() -{ - //find how many rows/cols fit on the page - double lx=sizex->text().toDouble(); - double ly=sizey->text().toDouble(); - QRect pr=printer->pageRect(); - QString mtrc=metric->itemData(metric->currentIndex()).toString(); - if(mtrc=="in"){ - lx*=printer->logicalDpiX(); - ly*=printer->logicalDpiY(); - }else - if(mtrc=="cm"){ - lx*=printer->logicalDpiX()/2.54; - ly*=printer->logicalDpiY()/2.54; - }else{ - lx*=printer->logicalDpiX()/25.4; - ly*=printer->logicalDpiY()/25.4; - } - - bool dowarn=false; - if(ly>0.0){ - maxrows=pr.height()/ly; - if(maxrows>ROWS)maxrows=ROWS; - if(maxrows<1){ - maxrows=1; - dowarn=true; - } - }else maxrows=ROWS; - if(lx>0.0){ - maxcols=pr.width()/lx; - if(maxcols>COLS)maxcols=COLS; - if(maxcols<1){ - maxcols=1; - dowarn=true; - } - }else maxcols=COLS; - //update - oldpage=page->itemData(page->currentIndex()).toInt(); - for(int r=0;rsetChecked(b && checked[oldpage][i]); - checks[i]->setEnabled(b); - } - if(dowarn) - warning->setText(tr("Warning: the label may not fit on the page!")); - else - warning->setText(""); -} - -void MLabelDialog::saveSettings() -{ - QSettings set; - set.beginGroup("printer/"+printer->printerName()); - set.setValue("offsetx",offx->text().toDouble()); - set.setValue("offsety",offy->text().toDouble()); - set.setValue("sizex",sizex->text().toDouble()); - set.setValue("sizey",sizey->text().toDouble()); - set.setValue("metric",metric->itemData(metric->currentIndex()).toString()); -} - - -//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -void MLabelConfig::configDialog(QWidget* parent) -{ - QDialog d(parent); - MLabelConfig ticket(MLabelConfig::Ticket),voucher(MLabelConfig::Voucher); - d.setWindowTitle(tr("Label Configuration")); - QFormLayout*fl; - d.setLayout(fl=new QFormLayout); - fl->addRow(new QLabel(tr("Ticket Labels:"))); - //each one: ask printer mode, ask label-page mode, printer/settings - QComboBox*t_prnmode,*t_pagmode,*t_prnbufmode; - fl->addRow(tr("Print Dialog:"),t_prnmode=new QComboBox); - t_prnmode->addItem(tr("Always ask for printer"),PrintAskAlways); - t_prnmode->addItem(tr("Ask if unknown or not present"),PrintAskIfUnknown); - t_prnmode->addItem(tr("Never ask for printer"),PrintAskNever); - t_prnmode->setCurrentIndex(ticket.printAskMode()); - fl->addRow(tr("Page Dialog:"),t_pagmode=new QComboBox); - t_pagmode->addItem(tr("Always ask for page layout"),PageAskAlways); - t_pagmode->addItem(tr("Ask if more than one label per page"),PageAskIfNeeded); - t_pagmode->addItem(tr("Never ask for page layout"),PageAskNever); - t_pagmode->setCurrentIndex(ticket.pageAskMode()); - QHBoxLayout*hl; - QLabel*t_prn;QMapt_prnset; - QToolButton*p; - QPrinter t_printer; - ticket.configurePrinter(t_printer); - fl->addRow(tr("Printer:"),hl=new QHBoxLayout); - hl->addWidget(t_prn=new QLabel(ticket.printerName()),1); - hl->addWidget(p=new QToolButton); - p->setText("..."); - auto settprn=[&]{ - MLabelPrintDialog pd(&t_printer,&d); - pd.setWindowTitle(tr("Chose Printer for Tickets")); - pd.setButtonLabel(tr("Set Printer")); -// pd.setOptions(QAbstractPrintDialog::PrintShowPageSize); - if(pd.exec()!=QDialog::Accepted)return; - t_prn->setText(t_printer.printerName()); - }; - d.connect(p,&QToolButton::clicked,settprn); - fl->addRow(tr("Print Mode:"),t_prnbufmode=new QComboBox); - t_prnbufmode->addItem(tr("Direct Print")); - t_prnbufmode->addItem(tr("Use Buffer Pixmap")); - t_prnbufmode->setCurrentIndex((int)ticket.printMode()); - QFrame*frm; - fl->addRow(frm=new QFrame); - frm->setFrameStyle(QFrame::HLine|QFrame::Sunken); - //Vouchers... - fl->addRow(new QLabel(tr("Voucher Labels:"))); - //each one: ask printer mode, ask label-page mode, printer/settings - QComboBox*v_prnmode,*v_pagmode,*v_prnbufmode; - fl->addRow(tr("Print Dialog:"),v_prnmode=new QComboBox); - v_prnmode->addItem(tr("Always ask for printer"),PrintAskAlways); - v_prnmode->addItem(tr("Ask if unknown or not present"),PrintAskIfUnknown); - v_prnmode->addItem(tr("Never ask for printer"),PrintAskNever); - v_prnmode->setCurrentIndex(voucher.printAskMode()); - fl->addRow(tr("Page Dialog:"),v_pagmode=new QComboBox); - v_pagmode->addItem(tr("Always ask for page layout"),PageAskAlways); - v_pagmode->addItem(tr("Ask if more than one label per page"),PageAskIfNeeded); - v_pagmode->addItem(tr("Never ask for page layout"),PageAskNever); - v_pagmode->setCurrentIndex(voucher.pageAskMode()); - QLabel*v_prn;QMapv_prnset; - QPrinter v_printer; - voucher.configurePrinter(v_printer); - fl->addRow(tr("Printer:"),hl=new QHBoxLayout); - hl->addWidget(v_prn=new QLabel(voucher.printerName()),1); - hl->addWidget(p=new QToolButton); - p->setText("..."); - auto setvprn=[&]{ - MLabelPrintDialog pd(&v_printer,&d); - pd.setWindowTitle(tr("Chose Printer for Vouchers")); - pd.setButtonLabel(tr("Set Printer")); -// pd.setOptions(QAbstractPrintDialog::PrintShowPageSize); - if(pd.exec()!=QDialog::Accepted)return; - v_prn->setText(v_printer.printerName()); - }; - d.connect(p,&QToolButton::clicked,setvprn); - fl->addRow(tr("Print Mode:"),v_prnbufmode=new QComboBox); - v_prnbufmode->addItem(tr("Direct Print")); - v_prnbufmode->addItem(tr("Use Buffer Pixmap")); - v_prnbufmode->setCurrentIndex((int)voucher.printMode()); - //button... - fl->addRow(new QLabel(" ")); - fl->addRow(hl=new QHBoxLayout); - hl->addStretch(1); - QPushButton*b; - hl->addWidget(b=new QPushButton(tr("Ok"))); - d.connect(b,SIGNAL(clicked()),&d,SLOT(accept())); - hl->addWidget(b=new QPushButton(tr("Cancel"))); - d.connect(b,SIGNAL(clicked()),&d,SLOT(reject())); - //show dialog - if(d.exec()!=QDialog::Accepted)return; - //save settings - ticket.storePrinter(t_printer); - ticket.storeAskModes( - (MLabelConfig::PrintAskMode)t_prnmode->currentIndex(), - (MLabelConfig::PageAskMode)t_pagmode->currentIndex() - ); - ticket.storePrintMode((MLabelConfig::PrintMode)t_prnbufmode->currentIndex()); - voucher.storePrinter(v_printer); - voucher.storeAskModes( - (MLabelConfig::PrintAskMode)v_prnmode->currentIndex(), - (MLabelConfig::PageAskMode)v_pagmode->currentIndex() - ); - voucher.storePrintMode((MLabelConfig::PrintMode)v_prnbufmode->currentIndex()); -} - -QString MLabelConfig::tr(const char* s, const char* c) -{ - return QCoreApplication::translate("MLabelConfig",s,c); -} - -QString MLabelConfig::printerName() const -{ - QString key=m_type==Ticket?"ticket":"voucher"; - QSettings set; - set.beginGroup(req->settingsGroup()+"/"+key); - if(!set.contains("name"))return QString(); - return set.value("name").toString(); -} - -bool MLabelConfig::selectPrinter(QPrinter& printer, bool force) -{ - bool gotit=configurePrinter(printer); - if(!force) - switch(printAskMode()){ - case PrintAskAlways:force=true;break; - case PrintAskIfUnknown:if(!gotit)force=true;break; - case PrintAskNever:/*do not override the force*/ break; - } - if(force){ - MLabelPrintDialog pd(&printer); - return pd.exec()==QDialog::Accepted; - }else - return gotit; -} - -QString MLabelConfig::cgroup() const -{ - const QString key=m_type==Ticket?"ticket":"voucher"; - return req->settingsGroup()+"/"+key; -} - -static inline void dumpPrn(QPrinter&p,QString s) -{ - qDebug()<<"printer"< paperTypes; - -void MLabelPrintDialog::initPaper() -{ - if(paperTypes.size())return; - paperTypes=QList() - << Paper_s(tr("Custom Size","paper type"),QPrinter::Custom,0,0) - << Paper_s(tr("A0","paper type"),QPrinter::A0,841,1189) - << Paper_s(tr("A1","paper type"),QPrinter::A1,594,841) - << Paper_s(tr("A2","paper type"),QPrinter::A2,420,594) - << Paper_s(tr("A3","paper type"),QPrinter::A3,297,420) - << Paper_s(tr("A4","paper type"),QPrinter::A4,210,297) - << Paper_s(tr("A5","paper type"),QPrinter::A5,148,210) - << Paper_s(tr("A6","paper type"),QPrinter::A6,105,148) - << Paper_s(tr("A7","paper type"),QPrinter::A7,74,105) - << Paper_s(tr("A8","paper type"),QPrinter::A8,52,74) - << Paper_s(tr("A9","paper type"),QPrinter::A9,37,52) - << Paper_s(tr("B0","paper type"),QPrinter::B0,1000,1414) - << Paper_s(tr("B1","paper type"),QPrinter::B1,707,1000) - << Paper_s(tr("B2","paper type"),QPrinter::B2,500,707) - << Paper_s(tr("B3","paper type"),QPrinter::B3,353,500) - << Paper_s(tr("B4","paper type"),QPrinter::B4,250,353) - << Paper_s(tr("B5","paper type"),QPrinter::B5,176,250) - << Paper_s(tr("B6","paper type"),QPrinter::B6,125,176) - << Paper_s(tr("B7","paper type"),QPrinter::B7,88,125) - << Paper_s(tr("B8","paper type"),QPrinter::B8,62,88) - << Paper_s(tr("B9","paper type"),QPrinter::B9,33,62) - << Paper_s(tr("B10","paper type"),QPrinter::B10,31,44) - << Paper_s(tr("C5E","paper type"),QPrinter::C5E,163,229) - << Paper_s(tr("U.S. Common 10 Envelope","paper type"),QPrinter::Comm10E,105,241) - << Paper_s(tr("DLE","paper type"),QPrinter::DLE,110,220) - << Paper_s(tr("Executive","paper type"),QPrinter::Executive,190.5,254) - << Paper_s(tr("Folio","paper type"),QPrinter::Folio,210,330) - << Paper_s(tr("Ledger","paper type"),QPrinter::Ledger,431.8,279.4) - << Paper_s(tr("Legal","paper type"),QPrinter::Legal,215.9,355.6) - << Paper_s(tr("Letter","paper type"),QPrinter::Letter,215.9,279.4) - << Paper_s(tr("Tabloid","paper type"),QPrinter::Tabloid,279.4,431.8) - ; -} - - - -MLabelPrintDialog::MLabelPrintDialog(QPrinter* prn, QWidget* parent, Qt::WindowFlags f) - : QDialog(parent, f) - , mprinter(prn) -{ - setWindowTitle(tr("Chose Printer")); - QFormLayout*fl; - setLayout(fl=new QFormLayout); - fl->addRow(tr("Printer:"),mprnselect=new QComboBox); - int cur=-1,def=-1; - for(const QPrinterInfo&info:QPrinterInfo::availablePrinters()){ - if(info.printerName()==prn->printerName())cur=mprnselect->count(); - if(info.isDefault())def=mprnselect->count(); - mprnselect->addItem(info.printerName()); - } - if(cur>=0)mprnselect->setCurrentIndex(cur); - else if(def>=0)mprnselect->setCurrentIndex(def); - connect(mprnselect,SIGNAL(currentIndexChanged(int)), this,SLOT(printerChanged(int))); - fl->addRow(tr("Make & Model:"),mmakemodel=new QLabel); - fl->addRow(tr("Location:"),mlocation=new QLabel); - fl->addRow(tr("Description:"),mdescript=new QLabel); - fl->addRow(tr("Unit of Measure:"),munit=new QComboBox); - munit->addItem(tr("Millimeter"),1.); - munit->addItem(tr("Centimeter"),10.); - munit->addItem(tr("Inch"),25.4); - connect(munit,SIGNAL(currentIndexChanged(int)),this,SLOT(unitChanged(int))); - fl->addRow(tr("Paper Type:"),mpaper=new QComboBox); - initPaper(); - cur=0; - for(const auto&paper:paperTypes){ - if(mprinter->paperSize()==paper.ptype)cur=mpaper->count(); - mpaper->addItem(paper.pname,paper.ptype); - } - mpaper->setCurrentIndex(cur); - connect(mpaper,SIGNAL(currentIndexChanged(int)), this,SLOT(paperChanged(int))); - QHBoxLayout*hl; - fl->addRow(tr("Paper Size:"),hl=new QHBoxLayout); - hl->addWidget(msizex=new QDoubleSpinBox,1); - msizex->setRange(0,10000); - hl->addWidget(new QLabel(tr("wide x","paper size: width"))); - hl->addWidget(msizey=new QDoubleSpinBox); - msizey->setRange(0,10000); - hl->addWidget(new QLabel(tr("high","paper size: height"))); - QGridLayout*gl; - fl->addRow(tr("Margins:"),gl=new QGridLayout); - qreal ml,mr,mt,mb; - mprinter->getPageMargins(&ml,&mt,&mr,&mb,QPrinter::Millimeter); - gl->addWidget(mmargtop=new QDoubleSpinBox,0,1); - mmargtop->setValue(mt/moldunit); - gl->addWidget(mmargleft=new QDoubleSpinBox,1,0); - mmargleft->setValue(ml/moldunit); - gl->addWidget(mmargright=new QDoubleSpinBox,1,2); - mmargright->setValue(mr/moldunit); - gl->addWidget(mmargbottom=new QDoubleSpinBox,2,1); - mmargbottom->setValue(mb/moldunit); - fl->addRow(tr("Resolution:"),mresolution=new QComboBox); - fl->addRow(new QLabel(" ")); - fl->addRow(hl=new QHBoxLayout); - hl->addStretch(1); - hl->addWidget(mokbtn=new QPushButton(tr("Print"))); - connect(mokbtn,SIGNAL(clicked(bool)),this,SLOT(okBtnPressed())); - QPushButton *cc; - hl->addWidget(cc=new QPushButton(tr("Cancel"))); - connect(cc,SIGNAL(clicked(bool)),this,SLOT(reject())); - - //make sure it is selected - printerChanged(mprnselect->currentIndex()); - - //reset selected paper type and size from printer - paperChanged(mpaper->currentIndex()); - //reset margins from printer -} - -void MLabelPrintDialog::setButtonLabel(const QString& l) -{ - mokbtn->setText(l); -} - -// QString MLabelPrintDialog::paperSourceStr(int p) -// { -// switch(p){ -// case QPrinter::Auto:return tr("Automatic","paper source"); -// case QPrinter::Cassette:return tr("Cassette","paper source"); -// case QPrinter::Envelope:return tr("Envelope","paper source"); -// case QPrinter::EnvelopeManual:return tr("Manual Envelope","paper source"); -// case QPrinter::FormSource:return tr("Forms","paper source"); -// case QPrinter::LargeCapacity:return tr("Large Capacity","paper source"); -// case QPrinter::LargeFormat:return tr("Large Format","paper source"); -// case QPrinter::Lower:return tr("Lower Tray","paper source"); -// case QPrinter::MaxPageSource:return tr("Maximum Page Source","paper source"); -// case QPrinter::Middle:return tr("Middle Tray","paper source"); -// case QPrinter::Manual:return tr("Manual Feed","paper source"); -// case QPrinter::OnlyOne:return tr("Only One Source","paper source"); -// case QPrinter::Tractor:return tr("Tractor","paper source"); -// case QPrinter::SmallFormat:return tr("Small Format","paper source"); -// default:return tr("Unknown","paper source"); -// } -// } - -void MLabelPrintDialog::printerChanged(int idx) -{ - //get printer - const QString &pname=mprnselect->itemText(idx); - if(pname.isEmpty())return; - //set location and description - const QPrinterInfo info=QPrinterInfo::printerInfo(pname); - if(info.isNull())return; - mmakemodel->setText(info.makeAndModel()); - mlocation->setText(info.location()); - mdescript->setText(info.description()); - //set resolution - QPrinter prn(info); - mresolution->clear(); - const int cur=mresolution->itemData(mresolution->currentIndex()).toInt(); - int curidx=-1; - const int def=prn.resolution(); - int defidx=-1; - for(auto r:prn.supportedResolutions()){ - if(r==cur)curidx=mresolution->count(); - if(r==def)defidx=mresolution->count(); - mresolution->addItem(QString("%1 dpi").arg(r),r); - } - if(curidx>=0)defidx=curidx; - if(defidx>=0)mresolution->setCurrentIndex(defidx); -} - -void MLabelPrintDialog::paperChanged(int idx) -{ - const int ptype=mpaper->itemData(idx).toInt(); - for(const auto&paper:paperTypes){ - if(paper==ptype){ - //set paper size - if(ptype == QPrinter::Custom){ - msizex->setValue(mprinter->pageSizeMM().width()/moldunit); - msizey->setValue(mprinter->pageSizeMM().height()/moldunit); - }else{ - msizex->setValue(paper.psize.width()/moldunit); - msizey->setValue(paper.psize.height()/moldunit); - } - break; - } - } - msizex->setEnabled(ptype==QPrinter::Custom); - msizey->setEnabled(ptype==QPrinter::Custom); -} - -void MLabelPrintDialog::unitChanged(int idx) -{ - const double fac=munit->itemData(idx).toDouble(); - //recalculate everything - msizex->setValue(msizex->value()*moldunit/fac); - msizey->setValue(msizey->value()*moldunit/fac); - mmargbottom->setValue(mmargbottom->value()*moldunit/fac); - mmargleft->setValue(mmargleft->value()*moldunit/fac); - mmargright->setValue(mmargright->value()*moldunit/fac); - mmargtop->setValue(mmargtop->value()*moldunit/fac); - //remember - moldunit=fac; -} - -void MLabelPrintDialog::okBtnPressed() -{ - //save data to printer - mprinter->setPrinterName(mprnselect->itemText(mprnselect->currentIndex())); - mprinter->setPaperSize(QPrinter::PaperSize(mpaper->itemData(mpaper->currentIndex()).toInt())); - mprinter->setPageSizeMM(QSizeF(msizex->value()*moldunit,msizey->value()*moldunit)); - mprinter->setPageMargins(mmargleft->value()*moldunit, mmargtop->value()*moldunit, mmargright->value()*moldunit, mmargbottom->value()*moldunit, QPrinter::Millimeter); - mprinter->setResolution(mresolution->itemData(mresolution->currentIndex()).toInt()); - - //close the dialog - accept(); -} diff --git a/src/templates/labeldlg.h b/src/templates/labeldlg.h deleted file mode 100644 index 5bd0e4b..0000000 --- a/src/templates/labeldlg.h +++ /dev/null @@ -1,228 +0,0 @@ -// -// C++ Interface: labeldlg -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2008-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef MAGICSMOKE_LABELDLG_H -#define MAGICSMOKE_LABELDLG_H - -#include -#include -#include - -class QDoubleSpinBox; -class QPaintDevice; -class QCheckBox; -class QComboBox; -class QLineEdit; -class QPrinter; -class QLabel; - -///access to the label specific configuration -class MLabelConfig -{ - public: - ///shows the configuration dialog - static void configDialog(QWidget*parent=0); - - ///the type of label whose configuration is being queried - enum LabelType { - ///invalid config object - Invalid=0, - ///ticket label - Ticket=1, - ///voucher label - Voucher=2 - }; - ///instantiate an empty configuration object - MLabelConfig(){initMeta();} - ///instantiates a configuration object for the given label type - MLabelConfig(LabelType lt):m_type(lt){initMeta();} - ///copies the config object - MLabelConfig(const MLabelConfig&lc):m_type(lc.m_type){initMeta();} - ///copies the config object - MLabelConfig& operator=(const MLabelConfig&lc){m_type=lc.m_type;return *this;} - - ///returns the type represented by this config object - LabelType labelType()const{return m_type;} - - ///returns the configured printer name (even if not available on the local system) - QString printerName()const; - - ///configures the QPrinter object to the printer set for this label type; - ///use selectPrinter if you want to fall back to a selection dialog - /// \returns true if the printer was successfully configured - bool configurePrinter(QPrinter&)const; - - ///configures the printer for this particular label type; - ///whether the dialog is shown depends on settings and printer availability; - ///if the dialog is shown the function remembers the new printer settings - /// \param printer pointer to the QPrinter object to be configured - /// \param force if true: force showing the printer dialog - /// \returns true if the selection was successful - bool selectPrinter(QPrinter&printer,bool force=false); - - ///whether to ask for a printer when printing labels - enum PrintAskMode{ - //do not change the order of these entries! - //their numerical value is used as index in configDialog() - ///always ask for a printer - PrintAskAlways=0, - ///only ask if the currently set printer is not known/connected - PrintAskIfUnknown=1, - ///never ask for a printer, just fail if the printer is unavailable - PrintAskNever=2 - }; - ///whether to ask for the page layout when printing labels - enum PageAskMode{ - //do not change the order of these entries! - //their numerical value is used as index in configDialog() - ///always ask - PageAskAlways=0, - ///only ask if there are more than 1 labels on the page - PageAskIfNeeded=1, - ///never ask, just assume the whole page is available - PageAskNever=2, - }; - - ///returns the policy for asking for a printer - PrintAskMode printAskMode()const; - - ///returns the policy for asking for page layout - PageAskMode pageAskMode()const; - - ///how to send data to the printer - enum PrintMode{ - //do not change the order of these entries! - //their numerical value is used as index in configDialog() - ///print directly through the printer driver - PrintDirect=0, - ///use a buffer pixmap to render fonts/graphics in memory first - PrintPixmap=1 - }; - - ///returns how to send data to the printer - PrintMode printMode()const; - - private: - LabelType m_type; - static QString tr(const char*,const char*c=0); - - /// \internal helper to store printer settings for next time - void storePrinter(QPrinter&); - /// \internal helper to store ask modes - void storeAskModes(PrintAskMode,PageAskMode); - /// \internal helper to store print mode - void storePrintMode(PrintMode); - /// \internal return the config group - QString cgroup()const; - - /// \internal initialize meta type info - void initMeta(); - - friend QDataStream&operator<<(QDataStream&,const MLabelConfig&); - friend QDataStream&operator>>(QDataStream&,MLabelConfig&); -}; -QDataStream &operator<<(QDataStream &out, const MLabelConfig &myObj); -QDataStream &operator>>(QDataStream &in, MLabelConfig &myObj); - -Q_DECLARE_METATYPE(MLabelConfig); - -///dialog that allows to select which labels on a sheet of paper are used -class MLabelDialog:public QDialog -{ - Q_OBJECT - public: - /**creates a label dialog*/ - MLabelDialog(QWidget*parent,QPrinter*printer,int numlabels,QSizeF labelsize); - /**deletes the label dialog and stores its current settings*/ - ~MLabelDialog(); - - /**returns the offset of label number n; relative to the coordinate system of the given paint device; starts at the bottom left of the page*/ - QPointF labelOffset(int n)const; - /**returns whether this label is on a new page*/ - bool labelNeedsPageTurn(int n)const; - ///returns whether there is only one label per page - bool oneLabelPerPage()const; - - ///configures the printer for this particular label type - ///whether the dialog is shown depends on settings and printer availability - /// \param type type of label - /// \param printer pointer to the QPrinter object to be configured - /// \param force if true: force showing the printer dialog - /// \returns true if the selection was successful - static inline bool selectPrinter(MLabelConfig::LabelType type, QPrinter&printer, bool force=false) - {return MLabelConfig(type).selectPrinter(printer,force);} - - public slots: - ///shows the dialog if necessary - this depends on the local configuration for - ///this label type - ///if not shown it returns true (presuming the user would have wanted to print) - ///if shown it returns true if the user clicked "Ok" and false otherwise - bool conditionalExec(MLabelConfig::LabelType); - - private slots: - /**internal: toggle Row button clicked*/ - void toggleRow(int); - /**internal: toggle Column button clicked*/ - void toggleColumn(int); - /**internal: toggle all button clicked*/ - void toggleAll(); - - /**internal: display correct page*/ - void updatePage(); - /**helper: save current/old page*/ - void savePage(); - /**internal: save settings for next time*/ - void saveSettings(); - - private: - QLineEdit *offx,*offy,*sizex,*sizey; - QLabel *warning; - QSizeF labelsize; - QComboBox *metric,*page; - QListchecks; - QList >checked; - QPrinter* printer; - int numlabels,oldpage,maxrows,maxcols; - - /**internal helper: find coordinates of label n; returns page id; returns -1 on failure*/ - int findLabel(int n,int&row,int&col)const; -}; - - -///Dialog that allows to configure details on how to print a label. -class MLabelPrintDialog:public QDialog -{ - Q_OBJECT - public: - explicit MLabelPrintDialog(QPrinter*,QWidget* parent = 0, Qt::WindowFlags f = 0); - public slots: - void setButtonLabel(const QString&); - private slots: - void printerChanged(int); - void paperChanged(int); - void unitChanged(int); - - void okBtnPressed(); - private: - QPrinter*mprinter; - QComboBox*mprnselect,*mresolution,*mpaper,*munit; - QDoubleSpinBox*mmargleft,*mmargright,*mmargtop,*mmargbottom; - QDoubleSpinBox*msizex,*msizey; - QLabel*mdescript,*mlocation,*mmakemodel; - QPushButton*mokbtn; - double moldunit=1.; - - //internal: initialize paper types - void initPaper(); -}; - -#endif diff --git a/src/templates/odtrender.cpp b/src/templates/odtrender.cpp deleted file mode 100644 index 18e8ba8..0000000 --- a/src/templates/odtrender.cpp +++ /dev/null @@ -1,500 +0,0 @@ -// -// C++ Implementation: odtrender -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2008-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "misc.h" -#include "odtrender.h" -#include "office.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "formula.h" -using namespace ELAM; - -class MOdfEngine:public MElamEngine -{ - MOdtRenderer*parent; - public: - MOdfEngine(MOdtRenderer* pa):parent(pa) - { - CharacterClassSettings cs=characterClasses(); - cs.setAssignmentChars(0,'='); - cs.setOperatorClass(cs.operatorClass().remove(':')); - QPairnc=cs.nameClass(); - nc.second+=':'; - cs.setNameClass(nc); - } - bool hasConstant(QString v)const - { - if(parent->getVariable(v).isValid()) - return true; - else - return MElamEngine::hasConstant(v); - } - QVariant getConstant(QString v)const - { - QVariant vv=parent->getVariable(v); - if(vv.isValid()) - return vv; - else - return MElamEngine::getConstant(v); - } -}; - -class MOdtRendererPrivate -{ - protected: - friend class MOdtRenderer; - - //methods that the parent uses - MOdtRendererPrivate(QString file,MOdtRenderer*p); - ~MOdtRendererPrivate(); - - bool renderToFile(QFile&); - - //data the parent uses - QString extension; - MOdtRenderer::FileFormat fileformat; - - private: - //methods that the parent does not call - - ///overall rendering: copies the templates content, calls render() - void render(QIODevice*); - - ///content.xml rendering - QList render(QDomNode node); - - ///scan string and replace variable values - QString renderString(QString); - - ///gets a scalar variable - QString getVariable(QString varname); - - //data the parent does not access - //parent - MOdtRenderer*parent; - //the template file - Unzip temp; - QFile tfile; - //xml representation of the content.xml file in the template - QDomDocument cdoc; - - //local variables and calculation engine - Engine *calc; -}; - -MOdtRenderer::MOdtRenderer(MTemplate file) -{ - d=new MOdtRendererPrivate(file.cacheFileName(),this); - d->extension=file.targetExtension(); - d->calc=new MOdfEngine(this); -} - -const QString OdfTemplateNS("http://smoke.silmor.de/odftemplate/namespace"); -const QString OdfTemplatePrefix("msmoketpl"); -MOdtRendererPrivate::MOdtRendererPrivate(QString file,MOdtRenderer*p) - :fileformat(MOdtRenderer::FileFormat::None),tfile(file) -{ - parent=p; - //open ZIP - if(tfile.open(QIODevice::ReadOnly))temp.open(&tfile); - else { - qDebug()<<"Error opening ODF template file"<calc!=nullptr)delete d->calc; - d->calc=nullptr; - delete d; - d=nullptr; -} -MOdtRendererPrivate::~MOdtRendererPrivate() -{ - temp.close(); - tfile.close(); -} - -MOdtRenderer::FileFormat MOdtRenderer::fileFormat()const -{ - return d->fileformat; -} - -void MOdtRenderer::renderToFile(QString file) -{ - QFile f(file); - if(f.open(QIODevice::ReadWrite)){ - renderToFile(f); - f.close(); - } -} - -void MOdtRenderer::renderToFile(QFile &file) -{ - if(d->renderToFile(file)) - if(QSettings().value("doOpenODFs",false).toBool()) - openOfficeFile(file.fileName()); -} -bool MOdtRendererPrivate::renderToFile(QFile &file) -{ - if(!file.isWritable()) - if(!file.open(QIODevice::ReadWrite))return false; - file.seek(0); - file.resize(0); - render(&file); - return true; -} - -void MOdtRenderer::renderToPrinter() -{ - //generate temporary file - QTemporaryFile tfile; - tfile.setAutoRemove(false);//we don't want it to be auto-deleted on close() - tfile.setFileTemplate(QDir::tempPath()+"/msmoke_XXXXXX."+d->extension); - tfile.open(); - QString tname=tfile.fileName(); - //render - d->renderToFile(tfile); - tfile.close(); - //call ooffice and print - printOfficeFile(tname); - //remove temporary file - QFile(tname).remove(); -} - -void MOdtRendererPrivate::render(QIODevice*out) -{ - //sanity check - if(!temp.isOpen()){ - qDebug()<<"ODF Renderer: I don't have a valid template, cannot render."; - return; - } - if(!out->isWritable()){ - qDebug()<<"ODF Renderer Ooops: output device not writeable when trying to render."; - return; - } - //rewind input - if(!temp.firstFile())return; - //create output - Zip ozip; - ozip.open(out); - //copy contents - do{ - ZipFileInfo info= temp.currentFile(); - if(info.fileName()=="content.xml"){ - //render - QByteArray cont=render(cdoc.cloneNode()).value(0).toDocument().toByteArray(); - //write - QBuffer buffer; - buffer.setData(cont); - buffer.open(QBuffer::ReadWrite); - buffer.seek(0); - ozip.storeFile(info.fileName(),buffer,info.createTime()); - }else{ - //copy unchanged - temp.copyCurrentFile(ozip); - } - }while(temp.nextFile()); - ozip.close(); -} - -static inline QList n2q(const QDomNodeList&nl){ - QListret; - for(int i=0;i MOdtRendererPrivate::render(QDomNode node) -{ - //trivial cases - if(node.isComment()||node.isDocumentType()||node.isNotation()||node.isProcessingInstruction()){ - qDebug()<<"trivial type"<<(int)node.nodeType()<()<()<ret; - if(tnl.value(1)=="if"){ -// qDebug()<<"????????it's a bit iffy"<evaluate(el.attribute("select")); - if(!res.canConvert()){ - qDebug()<<"!!!!!!!! ODF Engine error: if has been called with instructions that do not convert to bool"< tag found, ignoring it."; - }else if(tnl.value(1)=="calculate"){ -// qDebug()<<"????????calculatin'"<evaluate(form); - qDebug()<<"!!!!!!!! ODF Engine Calculation"<getLoopIterations(lvn); - qDebug()<<"!!!!!!!! entering loop"<setLoopIteration(lvn,i); - foreach(QDomNode nd,n2q(nl)) - if(nd.isElement()) - ret<()<ret; - if(node.isText()) - ret<()<0) - ret+=calc->evaluate(vname).toString(); - else - ret+="@"; - //reset mode - isvar=false; - vname=""; - }else - //continuation of var - vname+=c; - }else{//not inside variable name - //is this the start of a var? - if(c=='@'){ - isvar=true; - vname=""; - }else{ - ret+=c; - } - } - } - //anything left over? - if(isvar){ - //reset - ret+="@"+vname; - } - //return transformed line - return ret; -} - -QByteArray MOdtRenderer::convertV1toV2(const QByteArray& old) -{ - QByteArray nba; - QListolst=old.split('\n'); - bool hstarted=false; - foreach(QByteArray line,olst){ - //is this the start of the file? - if(!hstarted){ - QByteArray st=line.trimmed().left(2); - //find the first real tag and insert the new start tag there - if(st!="\n"; - hstarted=true; - } - //add the line just scanned... - nba+=line; - nba+='\n'; - continue; - } - //is this a special line? - QByteArray lnt=line.trimmed(); - if(lnt.size()>1 && lnt.at(0)=='#'){ - //extract command - int cnt=lnt.indexOf(':'); - QByteArray parm; - if(cnt>0){ - parm=lnt.mid(cnt+1); - lnt=lnt.left(cnt); -// qDebug()<<"found command"<"; - }else if(lnt=="#ELSE") - nba+=""; - else if(lnt=="#ENDIF") - nba+=""; - else if(lnt=="#SETNEWLINE"){ - nba+=""; - }else if(lnt=="#CALC"){ - nba+=""; - }else if(lnt=="#LOOP"){ - nba+=""; - }else if(lnt=="#ENDLOOP"){ - nba+=""; - }else{ - nba+=""; - } - }else //no, not special: just store it - nba+=line; - //add a newline anyway - nba+='\n'; - } - //close the template - nba+=""; -// qDebug()<<"conversion test"<, (C) 2008-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef MAGICSMOKE_ODTRENDER_H -#define MAGICSMOKE_ODTRENDER_H - -#include -#include - -#include "templates.h" - -class MOdtRendererPrivate; -class QFile; - -extern const QString OdfTemplateNS; -extern const QString OdfTemplatePrefix; - -/**abstract base class for all ODT rendering classes*/ -class MOdtRenderer -{ - public: - /**instantiates a renderer loaded from template file*/ - MOdtRenderer(MTemplate file); - /**deletes the renderer*/ - virtual ~MOdtRenderer(); - - /**starts the internal rendering routine and outputs to file*/ - virtual void renderToFile(QString file); - - /**starts the internal rendering routine and outputs to file*/ - virtual void renderToFile(QFile& file); - - /**starts the internal rendering routine and outputs to printer (calls OpenOffice to print)*/ - virtual void renderToPrinter(); - - ///helper routine: converts a V1 template to V2 - ///you have to make sure to not do a double conversion on an already converted document - static QByteArray convertV1toV2(const QByteArray&); - - ///format of the file represented by this renderer - enum class FileFormat{ - ///no file loaded or loading was not successful - None, - ///file was a valid v2 format - Version2, - ///file was probably v1 or plain ODF, it has been converted - ConvertedV1, - }; - ///returns the format of the file - FileFormat fileFormat()const; - - protected: - friend class MOdtRendererPrivate; - friend class MOdfEngine; - /**implement this to return the value of a variable during rendering; should return empty string if the variable does not exist*/ - virtual QVariant getVariable(QString varname)=0; - - /**implement this to return the amount of iterations for a defined loop; should return 0 if the loop does not exist*/ - virtual int getLoopIterations(QString loopname)=0; - - /**implement this to populate the variables used in a specific iteration of the loop*/ - virtual void setLoopIteration(QString loopname, int interation)=0; - private: - MOdtRendererPrivate*d; -}; - -/**generic class that implements MOdtRenderer by calling signals; the signals must be connected using a direct or blocking connection; if any of them is not used it will behave as if the variable/loop did not exist*/ -class MOdtSignalRenderer:public QObject,public MOdtRenderer -{ - Q_OBJECT - public: - /**instantiates a renderer loaded from template file*/ - MOdtSignalRenderer(MTemplate file); - /**deletes the renderer*/ - ~MOdtSignalRenderer(); - - signals: - /**connect this to return the value of a variable during rendering; should return empty string if the variable does not exist*/ - void getVariable(QString varname,QVariant&value); - - /**connect this to return the amount of iterations for a defined loop; should return 0 if the loop does not exist*/ - void getLoopIterations(QString loopname,int&iterations); - - void setLoopIteration(QString loopname, int interation); - - protected: - QVariant getVariable(QString varname); - int getLoopIterations(QString loopname); -}; - -#endif diff --git a/src/templates/office.cpp b/src/templates/office.cpp deleted file mode 100644 index 398b855..0000000 --- a/src/templates/office.cpp +++ /dev/null @@ -1,181 +0,0 @@ -// -// C++ Implementation: office -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2008-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "office.h" -#include "misc.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static QString getofficepath() -{ - return QSettings().value("officePath","soffice").toString(); -} - -void openOfficeFile(QString fname) -{ - //calculate parameters - QStringList r; - if(QSettings().value("officeViewOnly",false).toBool())r<<"-view"; - r<addWidget(new QLabel(QCoreApplication::translate("office","Please chose a printer:")),0); - QComboBox*printer; - vl->addWidget(printer=new QComboBox,0); - printer->setEditable(false); - printer->addItem(QCoreApplication::translate("office","(Default Printer)")); - QListaprn=QPrinterInfo::availablePrinters(); - int cprn=0; - for(int i=0;iaddItem(s); - if(s==prn)cprn=i+1; - } - printer->setCurrentIndex(cprn); -// qDebug()<<"printer selection"<addSpacing(10); - vl->addStretch(1); - QHBoxLayout*hl; - vl->addLayout(hl=new QHBoxLayout,0); - hl->addStretch(10); - QPushButton*p; - hl->addWidget(p=new QPushButton(QCoreApplication::translate("office","Ok"))); - QObject::connect(p,SIGNAL(clicked()),&d,SLOT(accept())); - d.exec(); - if(printer->currentIndex()==0)prn=""; - else prn=printer->currentText(); -} - -void printOfficeFile(QString fname) -{ - //calculate parameters - QStringList r; - QString p=QSettings().value("officePrinter","").toString(); - if(QSettings().value("officePrinterConfirm",false).toBool())confirmPrinter(p); - if(p=="")r<<"-p"; - else r<<"-pt"<addWidget(gb=new QGroupBox(tr("OpenOffice.org"))); - gb->setLayout(hl=new QHBoxLayout); - hl->addWidget(new QLabel(tr("Path to Executable:"))); - hl->addWidget(oopath=new QLineEdit(set.value("officePath","soffice").toString()),1); - hl->addWidget(p=new QPushButton(tr("...","select OpenOffice path button"))); - connect(p,SIGNAL(clicked()),this,SLOT(selectpath())); - - vl->addWidget(gb=new QGroupBox(tr("Printing ODF"))); - gb->setLayout(vl2=new QVBoxLayout); - vl2->addLayout(hl=new QHBoxLayout); - hl->addWidget(new QLabel(tr("Printer:"))); - hl->addWidget(printer=new QComboBox,1); - printer->setEditable(false); - printer->addItem(tr("(Default Printer)")); - QListaprn=QPrinterInfo::availablePrinters(); - int cprn=0; - QString cp=set.value("officePrinter","").toString(); - for(int i=0;iaddItem(s); - if(cp==s)cprn=i+1; - } - printer->setCurrentIndex(cprn); - vl2->addWidget(askprint=new QCheckBox(tr("Always confirm printer when printing ODF"))); - askprint->setChecked(set.value("officePrinterConfirm",false).toBool()); - vl2->addWidget(saveprint=new QCheckBox(tr("Save printed files"))); - saveprint->setChecked(set.value("officePrinterSave",false).toBool()); - - vl->addWidget(gb=new QGroupBox(tr("Opening ODF"))); - gb->setLayout(vl2=new QVBoxLayout); - vl2->addWidget(viewonly=new QCheckBox(tr("Always open as Read-Only"))); - viewonly->setChecked(set.value("officeViewOnly",false).toBool()); - vl2->addWidget(doopen=new QCheckBox(tr("Automatically open all newly created files"))); - doopen->setChecked(set.value("doOpenODFs",false).toBool()); - - vl->addSpacing(15); - vl->addLayout(hl=new QHBoxLayout); - hl->addStretch(1); - hl->addWidget(p=new QPushButton(tr("OK"))); - connect(p,SIGNAL(clicked()),this,SLOT(accept())); - connect(p,SIGNAL(clicked()),this,SLOT(savedata())); - hl->addWidget(p=new QPushButton(tr("Cancel"))); - connect(p,SIGNAL(clicked()),this,SLOT(reject())); -} - -void MOfficeConfig::savedata() -{ - QSettings set; - int cprn=printer->currentIndex(); - if(cprn==0)set.setValue("officePrinter",""); - else set.setValue("officePrinter",printer->currentText()); - - set.setValue("officePath",oopath->text()); - set.setValue("officeViewOnly",viewonly->isChecked()); - set.setValue("doOpenODFs",doopen->isChecked()); - set.setValue("officePrinterConfirm",askprint->isChecked()); - set.setValue("officePrinterSave",saveprint->isChecked()); -} - -void MOfficeConfig::selectpath() -{ - QString np=QFileDialog::getOpenFileName(this,tr("Select OpenOffice.org executable"),QFileInfo(oopath->text()).dir().absolutePath()); - if(np!=""){ - oopath->setText(np); - setCurrentDir(np); - } -} diff --git a/src/templates/office.h b/src/templates/office.h deleted file mode 100644 index 6c7286b..0000000 --- a/src/templates/office.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// C++ Interface: office -// -// Description: Wrapper and Config Dialog around OpenOffice.org -// -// -// Author: Konrad Rosenbaum , (C) 2008-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef MAGICSMOKE_OFFICE_H -#define MAGICSMOKE_OFFICE_H - -#include - -/**calls OpenOffice.org to open an ODF file*/ -void openOfficeFile(QString fname); - -/**calls OpenOffice.org to print an ODF file*/ -void printOfficeFile(QString fname); - -#include - -class QComboBox; -class QCheckBox; -class QLineEdit; - -/**configuration dialog for OpenOffice access*/ -class MOfficeConfig:public QDialog -{ - Q_OBJECT - public: - MOfficeConfig(QWidget*); - - private slots: - void savedata(); - void selectpath(); - private: - QComboBox*printer; - QCheckBox*viewonly,*doopen,*askprint,*saveprint; - QLineEdit*oopath; -}; - - -#endif diff --git a/src/templates/templates.pri b/src/templates/templates.pri index cb72c6f..b66ec54 100644 --- a/src/templates/templates.pri +++ b/src/templates/templates.pri @@ -1,19 +1,11 @@ HEADERS += \ - $$PWD/odtrender.h \ - $$PWD/ticketrender.h \ - $$PWD/office.h \ - $$PWD/labeldlg.h \ - $$PWD/templatedlg.h \ $$PWD/ticketedit.h \ - $$PWD/odfedit.h + $$PWD/odfedit.h \ + $$PWD/templatedlg.h SOURCES += \ - $$PWD/odtrender.cpp \ - $$PWD/ticketrender.cpp \ - $$PWD/office.cpp \ - $$PWD/labeldlg.cpp \ - $$PWD/templatedlg.cpp \ $$PWD/ticketedit.cpp \ - $$PWD/odfedit.cpp + $$PWD/odfedit.cpp \ + $$PWD/templatedlg.cpp -INCLUDEPATH += $$PWD \ No newline at end of file +INCLUDEPATH += $$PWD diff --git a/src/templates/ticketrender.cpp b/src/templates/ticketrender.cpp deleted file mode 100644 index 2d31ae6..0000000 --- a/src/templates/ticketrender.cpp +++ /dev/null @@ -1,604 +0,0 @@ -// -// C++ Implementation: odtrender -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2008-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "ticketrender.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "code39.h" - -#include "MOTicket" -#include "MOVoucher" - - -class MLabelRendererPrivate -{ - protected: - friend class MLabelRenderer; - - MLabelRendererPrivate(QString file,MLabelRenderer*p); - ~MLabelRendererPrivate(); - - //part of the constructor - void prepare(Unzip&); - - //called by MLabelRenderer - bool render(const MLabel&,QPaintDevice&,QPainter*,QPointF); - - //called by MLabelRenderer - QSizeF labelSize(const QPaintDevice&); - - private: - MLabelRenderer*parent; - //internal font-IDs - QList fdb; - QMapfdbl; - QMapgetfontdb; - //image cache: - QMap idb; - //XML template cache (template.xml) - QDomDocument txml; - //contains the unit of measurement - QString unit; - //contains the size of the Label in "unit" - QSizeF tsize; - //after constructor: contains whether this object is correctly initialized - bool canrender; - - //does the actual rendering work - void render(QDomElement&,const MLabel&,QPaintDevice&,QPainter*,QPointF); - - //renders a single line - QString renderLine(const MLabel&,QString); - - //parses element to extract offset - QPointF getoffset(QDomElement&,bool); - - //parses element to extract size - QSizeF getsize(QDomElement&,bool); - - //converts a point to "natural" coordinates - QPointF tonatural(const QPaintDevice&,QPointF); - - //converts a size to "natural" coordinates - QSizeF tonatural(const QPaintDevice&,QSizeF); - - //converts a size to "natural" coordinates - QSizeF tonatural(int dpi,QSizeF); - - //returns a system font name - QString getfont(QString); -}; - -MLabelRenderer::MLabelRenderer(MTemplate file) -{ - d=new MLabelRendererPrivate(file.cacheFileName(),this); -} - -MLabelRendererPrivate::MLabelRendererPrivate(QString file,MLabelRenderer*p) -{ - parent=p; - canrender=false; - //open ZIP - Unzip temp; - QFile tfile(file); - if(tfile.open(QIODevice::ReadOnly))temp.open(&tfile); - else return; - prepare(temp); - temp.close(); - tfile.close(); - qDebug("Label Renderer initialized: %s",canrender?"ready!":"error, can't render."); -} - -void MLabelRendererPrivate::prepare(Unzip&temp) -{ - //make sure this is a valid ZIP file - if(!temp.locateFile("template.xml")){ - qDebug("Label renderer: can't find template.xml"); - canrender=false; - return; - } - //load XML - QBuffer buffer; - buffer.open(QBuffer::ReadWrite); - temp.currentFile(buffer); - if(!txml.setContent(buffer.data())){ - qDebug("Label renderer: can't parse template.xml - XML fault."); - canrender=false; - return; - } - //assume we can render now - canrender=true; - //parse document element - QDomElement doc=txml.documentElement(); - unit=doc.attribute("unit","mm"); - if(unit!="mm"&&unit!="in"){ - qDebug("Label renderer: illegal unit in template.xml."); - canrender=false; - return; - } - tsize=getsize(doc,true); - if(!canrender)return; - //check for fonts - QDomNodeList nl=txml.elementsByTagName("LoadFont"); - QStringList fndb; - for(int i=0;itonatural(600,d->tsize); - QImage map(sz.toSize(),QImage::Format_RGB32); - map.setDotsPerMeterX(23622); - map.setDotsPerMeterY(23622); - map.fill(Qt::white); - // render to pixmap - success=d->render(label,map,nullptr,QPointF()); - // render to pdev - if(success){ - QPainter*paint=painter; - if(!painter)paint=new QPainter(&pdev); - QSizeF nsize=d->tonatural(pdev,d->tsize); - paint->setClipRect(QRectF(offset,nsize)); - paint->drawImage(QRectF(offset,nsize).toRect(),map,QRectF(QPointF(),map.size())); - if(!painter)delete paint; - } - }else - success=d->render(label,pdev,painter,offset); - return success; -} - -bool MLabelRendererPrivate::render(const MLabel&label,QPaintDevice&pdev,QPainter*painter,QPointF offset) -{ - //sanity check - if(!canrender){ - qDebug("Label Renderer: render called, but can't render."); - return false; - } - //actually render - QDomElement el=txml.documentElement(); - render(el,label,pdev,painter,offset); - //return result (canrender may be changed by renderer - return canrender; -} - -QPointF MLabelRendererPrivate::getoffset(QDomElement&el,bool isfatal) -{ - QStringList off=el.attribute("offset").split(" "); - if(off.size()!=2){ - if(isfatal){ - qDebug("Label renderer error: Illegal offset in %s at line %i column %i.",el.tagName().toLatin1().data(),el.lineNumber(),el.columnNumber()); - canrender=false; - } - return QPointF(); - } - QPointF ret; - bool b; - ret.setX(off[0].toDouble(&b)); - if(!b){ - if(isfatal){ - qDebug("Label renderer error: Illegal offset in %s at line %i column %i.",el.tagName().toLatin1().data(),el.lineNumber(),el.columnNumber()); - canrender=false; - } - return QPointF(); - } - ret.setY(off[1].toDouble(&b)); - if(!b){ - if(isfatal){ - qDebug("Label renderer error: Illegal offset in %s at line %i column %i.",el.tagName().toLatin1().data(),el.lineNumber(),el.columnNumber()); - canrender=false; - } - return QPointF(); - } - return ret; -} - -QSizeF MLabelRendererPrivate::getsize(QDomElement&el,bool isfatal) -{ - QStringList lst=el.attribute("size").split(" "); - if(lst.size()!=2){ - if(isfatal){ - qDebug("Label renderer error: Illegal size (%i items) in %s at line %i column %i.",lst.size(),el.tagName().toLatin1().data(),el.lineNumber(),el.columnNumber()); - canrender=false; - } - return QSizeF(); - } - QSizeF ret; - bool b; - ret.setWidth(lst[0].toDouble(&b)); - if(!b){ - if(isfatal){ - qDebug("Label renderer error: Illegal size (invalid width) in %s at line %i column %i.",el.tagName().toLatin1().data(),el.lineNumber(),el.columnNumber()); - canrender=false; - } - return QSizeF(); - } - ret.setHeight(lst[1].toDouble(&b)); - if(!b){ - if(isfatal){ - qDebug("Label renderer error: Illegal size (invalid height) in %s at line %i column %i.",el.tagName().toLatin1().data(),el.lineNumber(),el.columnNumber()); - canrender=false; - } - return QSizeF(); - } - return ret; -} - -QPointF MLabelRendererPrivate::tonatural(const QPaintDevice&dev,QPointF p) -{ - double fac; - if(unit=="mm")fac=25.4; - else fac=1.0; - p.setX(p.x()*dev.logicalDpiX()/fac); - p.setY(p.y()*dev.logicalDpiY()/fac); - return p; -} - -QSizeF MLabelRendererPrivate::tonatural(const QPaintDevice&dev,QSizeF s) -{ - double fac; - if(unit=="mm")fac=25.4; - else fac=1.0; - s.setWidth(s.width()*dev.logicalDpiX()/fac); - s.setHeight(s.height()*dev.logicalDpiY()/fac); - return s; -} - -QSizeF MLabelRendererPrivate::tonatural(int dpi,QSizeF s) -{ - double fac; - if(unit=="mm")fac=25.4; - else fac=1.0; - s.setWidth(s.width()*dpi/fac); - s.setHeight(s.height()*dpi/fac); - return s; -} - -void MLabelRendererPrivate::render(QDomElement&sup, const MLabel&tick, QPaintDevice&pdev, QPainter*painter, QPointF noff) -{ - //initialize painter - QPainter *paint; - if(painter) - paint=painter; - else - paint=new QPainter(&pdev); - QSizeF nsize=tonatural(pdev,tsize); - paint->setClipRect(QRectF(noff,nsize)); - //parse file - QDomNodeList nl=sup.childNodes(); - for(int i=0;idrawImage(QRectF(tonatural(pdev,off)+noff,tonatural(pdev,sz)),img); - }else - if(enm=="Text"){ - //get attributes - QPointF off=getoffset(el,true); - if(!canrender){ - return; - } - QSizeF sz=getsize(el,true); - if(!canrender){ - return; - } - //get text - QString text=renderLine(tick,el.text().trimmed()); - //get font; TODO: introduce weight and italic settings - QString font=getfont(el.attribute("font","%")); - int size=el.attribute("fontsize","10").toInt(); - if(size<1)size=10; - paint->setFont(QFont(font,size)); - //get alignment - int flag=0; - QString al=el.attribute("align","left"); - if(al=="left")flag=Qt::AlignLeft;else - if(al=="right")flag=Qt::AlignRight; - else flag=Qt::AlignHCenter; - al=el.attribute("valign","top"); - if(al=="top")flag|=Qt::AlignTop;else - if(al=="bottom")flag|=Qt::AlignBottom; - else flag|=Qt::AlignVCenter; - //render - paint->drawText(QRectF(tonatural(pdev,off)+noff,tonatural(pdev,sz)),flag,text); - qDebug("test %s",text.toLatin1().data()); - }else - if(enm=="Barcode"){ - //get attributes - QPointF off=getoffset(el,true); - if(!canrender){ - return; - } - QSizeF sz=getsize(el,true); - if(!canrender){ - return; - } - QString cd=tick.getVariable("BARCODE"); - //paint - //TODO: find a way to switch off antialiasing - QRectF rect(tonatural(pdev,off)+noff,tonatural(pdev,sz)); - paint->drawImage(rect,code39(cd)); - }else{ - qDebug("Label renderer error: unknown element %s in label template at line %i column %i.",enm.toLatin1().data(),el.lineNumber(),el.columnNumber()); - canrender=false; - return; - } - } - if(!painter) - delete paint; -} - -QString MLabelRendererPrivate::getfont(QString fnt) -{ - QString dfont=QSettings().value("defaultfont","Helvetica").toString(); - //did we already answer this? - if(getfontdb.contains(fnt))return getfontdb[fnt]; - if(fnt=="%")return dfont; - //is it a file name? - if(fnt.size())if(fnt[0]=='@'){ - QString font; - QString fnt2=fnt.mid(1); - if(fdbl.contains(fnt2))if(fdbl[fnt2].size()) - font=fdbl[fnt2][0]; - if(font.isEmpty()){ - qDebug("Label renderer warning: font file %s did not contain font families, using %s instead.",fnt.toLatin1().data(),dfont.toLatin1().data()); - font=dfont; - } - getfontdb.insert(fnt,font); - } - if(!getfontdb.contains(fnt)){ - QStringList fonts=QFontDatabase().families(); - if(!fonts.contains(fnt)){ - qDebug("Label renderer warning: font %s not found, searching a close match...",fnt.toLatin1().data()); - QString font; - for(int i=0;ilabelSize(dev); -} - -QSizeF MLabelRendererPrivate::labelSize(const QPaintDevice&dev) -{ - return tonatural(dev,tsize); -} - -MLabel::MLabel(){} -MLabel::~MLabel(){} - -class MTicketLabel:public MLabel -{ - public: - MTicketLabel(const MOTicket&t):tick(t){} - QString getVariable(QString var)const; - private: - MOTicket tick; -}; - - -//WARNING: if you add anything here, make sure you simulate it in ticketedit.cpp -QString MTicketLabel::getVariable(QString var)const -{ - if(var=="TICKETID"||var=="BARCODE")return tick.ticketid(); - if(var=="PRICE")return tick.priceString(); - if(var=="DATETIME")return tick.event().startTimeString(); - if(var=="ROOM")return tick.event().room(); - if(var=="TITLE")return tick.event().title(); - if(var=="ARTIST")return tick.event().artist().value().name(); - if(var=="PRICECATEGORY")return tick.priceCategoryName(); - if(var=="PRICECATEGORYABBR")return tick.priceCategoryShort(); - return ""; -} - -MTicketRenderer::MTicketRenderer(MTemplate f):MLabelRenderer(f){} -bool MTicketRenderer::render(const MOTicket&label,QPaintDevice&pdev,QPainter*painter,QPointF offset,bool usePixmap) -{ - return MLabelRenderer::render(MTicketLabel(label),pdev,painter,offset,usePixmap); -} - -class MVoucherLabel:public MLabel -{ - public: - MVoucherLabel(const MOVoucher&t):vouc(t){} - QString getVariable(QString var)const; - private: - MOVoucher vouc; -}; - -//WARNING: if you add anything here, make sure you simulate it in ticketedit.cpp -QString MVoucherLabel::getVariable(QString var)const -{ - if(var=="VOUCHERID"||var=="BARCODE")return vouc.voucherid(); - if(var=="PRICE")return vouc.priceString(); - if(var=="VALUE")return vouc.valueString(); - return ""; -} - -MVoucherRenderer::MVoucherRenderer(MTemplate f):MLabelRenderer(f){} -bool MVoucherRenderer::render(const MOVoucher&label,QPaintDevice&pdev,QPainter*painter,QPointF offset,bool usePixmap) -{ - return MLabelRenderer::render(MVoucherLabel(label),pdev,painter,offset,usePixmap); -} diff --git a/src/templates/ticketrender.h b/src/templates/ticketrender.h deleted file mode 100644 index 10e2023..0000000 --- a/src/templates/ticketrender.h +++ /dev/null @@ -1,80 +0,0 @@ -// -// C++ Interface: odtrender -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2008-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef MAGICSMOKE_TICKETRENDER_H -#define MAGICSMOKE_TICKETRENDER_H - -#include -#include -#include - -#include "templates.h" - -class MLabelRendererPrivate; -class MOTicket; -class MOVoucher; -class QPaintDevice; -class QPainter; - -/**base class that describes labels*/ -class MLabel -{ - public: - /**constructs the label*/ - MLabel(); - /**deconstructs the label*/ - virtual ~MLabel(); - - /**abstract: overwrite this to return data for a label*/ - virtual QString getVariable(QString)const=0; -}; - -/**base class for all label rendering classes*/ -class MLabelRenderer -{ - public: - /**instantiates a renderer loaded from template file*/ - MLabelRenderer(MTemplate file); - /**deletes the renderer*/ - virtual ~MLabelRenderer(); - - /**renders the ticket; returns whether the rendering was successful*/ - virtual bool render(const MLabel&label,QPaintDevice&pdev,QPainter*painter=0,QPointF offset=QPointF(),bool usePixmap=false); - - /**returns the size of the ticket in the coordinates of the specified paint device (used for preview)*/ - virtual QSizeF labelSize(const QPaintDevice&); - - protected: - friend class MLabelRendererPrivate; - - private: - MLabelRendererPrivate*d; -}; - -/**convenience class: renders vouchers directly*/ -class MVoucherRenderer:public MLabelRenderer -{ - public: - MVoucherRenderer(MTemplate f); - bool render(const MOVoucher&label,QPaintDevice&pdev,QPainter*painter=0,QPointF offset=QPointF(),bool usePixmap=false); -}; - -/**convenience class: renders vouchers directly*/ -class MTicketRenderer:public MLabelRenderer -{ - public: - MTicketRenderer(MTemplate f); - bool render(const MOTicket&label,QPaintDevice&pdev,QPainter*painter=0,QPointF offset=QPointF(),bool usePixmap=false); -}; - - -#endif diff --git a/src/widgets/barcodeline.cpp b/src/widgets/barcodeline.cpp deleted file mode 100644 index d993a9a..0000000 --- a/src/widgets/barcodeline.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// C++ Implementation: barcode line edit -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2014 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - - -#include "barcodeline.h" -#include "barcode-plugin.h" - -MBarcodeLine::MBarcodeLine(QWidget* parent): MBarcodeLine(QString(),parent) -{ -} - -MBarcodeLine::MBarcodeLine(const QString& cont, QWidget* parent): QLineEdit(cont,parent) -{ - setToolTip(tr("Type a barcode into this line or scan it with a barcode scanner.")); - setPlaceholderText(tr("Type or scan a barcode.")); - connect(MBarcodeHub::instance(),SIGNAL(newBarcode(QString)), this,SLOT(setBarcode(QString))); -} - -void MBarcodeLine::setBarcode(QString bc) -{ - if(bc.isEmpty())return; - //do we actually have focus? - //TODO: maybe this should be visibility? - if(scanMode()==ScanMode::InFocus && !hasFocus())return; - if(scanMode()==ScanMode::ForceFocus){ - setFocus(); - emit askForFocus(); - } - //enter barcode and emit ready signal - setText(bc); - emit returnPressed(); -} diff --git a/src/widgets/barcodeline.h b/src/widgets/barcodeline.h deleted file mode 100644 index dccda13..0000000 --- a/src/widgets/barcodeline.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// C++ Interface: barcode line edit -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2014 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef MAGICSMOKE_BARCODELINE_H -#define MAGICSMOKE_BARCODELINE_H - -#include - -class MBarcodeLine:public QLineEdit -{ - Q_OBJECT - public: - explicit MBarcodeLine(QWidget* parent = 0); - explicit MBarcodeLine(const QString& , QWidget* parent = 0); - - enum class ScanMode{ - InFocus, - InBackground, - ForceFocus, - }; - - ScanMode scanMode()const{return mscanmode;} - - private slots: - void setBarcode(QString); - - public slots: - void setScanMode(ScanMode mode){mscanmode=mode;} - - signals: - void askForFocus(); - - private: - ScanMode mscanmode=ScanMode::InFocus; -}; - -#endif diff --git a/src/widgets/centbox.cpp b/src/widgets/centbox.cpp deleted file mode 100644 index 34fbffa..0000000 --- a/src/widgets/centbox.cpp +++ /dev/null @@ -1,126 +0,0 @@ -// -// C++ Implementation: centbox -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2008-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "centbox.h" -#include "misc.h" - -#include -#include -#include -#include - -MCentSpinBox::MCentSpinBox(QWidget*parent,int value,int maxValue) - :QAbstractSpinBox(parent),mvalid(priceRegExp(),this) -{ - mmin=0; - mmax=maxValue; - if(mmin>mmax)mmin=mmax; - mval=value; - if(mvalmmax)mval=mmax; - - setButtonSymbols(UpDownArrows); - lineEdit()->setText(cent2str(mval)); - connect(this,SIGNAL(editingFinished()),this,SLOT(fixup())); -} - -int MCentSpinBox::value()const -{ -// qDebug("current value: %i",mval); - return mval; -} - -void MCentSpinBox::setValue(int m) -{ - if(m>mmax)m=mmax; - if(msetText(cent2str(m)); - emit valueChanged(m); -} - -MCentSpinBox::StepEnabled MCentSpinBox::stepEnabled () const -{ - return (mval>mmin?StepDownEnabled:StepNone)|(mvalma)return; - mmin=mi; - mmax=ma; - if(mval>mmax){ - setValue(mmax); - }else - if(mvaladdWidget(new QLabel(label)); - vl->addWidget(box=new MCentSpinBox(this,val,maxValue)); - QHBoxLayout *hl; - vl->addLayout(hl=new QHBoxLayout); - hl->addStretch(10); - QPushButton*p; - hl->addWidget(p=new QPushButton(tr("OK"))); - p->setDefault(true); - connect(p,SIGNAL(clicked()),this,SLOT(accept())); - hl->addWidget(p=new QPushButton(tr("Cancel"))); - connect(p,SIGNAL(clicked()),this,SLOT(reject())); -} - -int MCentDialog::value()const -{ - return box->value(); -} - -int MCentDialog::getCents(QWidget*parent,QString title,QString label,int val,int maxValue,bool*ok) -{ - MCentDialog d(parent,title,label,val,maxValue); - bool b=d.exec()==QDialog::Accepted; - if(ok)*ok=b; - if(b) - return d.value(); - else - return 0; -} diff --git a/src/widgets/centbox.h b/src/widgets/centbox.h deleted file mode 100644 index 80a42dd..0000000 --- a/src/widgets/centbox.h +++ /dev/null @@ -1,60 +0,0 @@ -// -// C++ Interface: centbox -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2008-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef MAGICSMOKE_CENTBOX_H -#define MAGICSMOKE_CENTBOX_H - -#include -#include -#include - -class MCentSpinBox:public QAbstractSpinBox -{ - Q_OBJECT - public: - MCentSpinBox(QWidget*parent=0,int value=0,int maxValue=2147483647); - - virtual int value()const; - virtual void setValue(int); - - virtual void setRange(int,int); - - virtual int minimumValue()const; - virtual int maximumValue()const; - - void stepBy(int); - protected: - virtual QValidator::State validate(QString &input, int &pos) const; - virtual StepEnabled stepEnabled () const; - signals: - void valueChanged(int); - private slots: - void fixup(); - private: - int mval,mmax,mmin; - QRegExpValidator mvalid; -}; - -class MCentDialog:public QDialog -{ - Q_OBJECT - public: - MCentDialog(QWidget*parent=0,QString title=QString(),QString label=QString(),int value=0,int maxValue=2147483647); - - virtual int value()const; - - static int getCents(QWidget*parent=0,QString title=QString(),QString label=QString(),int value=0,int maxValue=2147483647,bool *ok=0); - private: - MCentSpinBox*box; -}; - -#endif diff --git a/src/widgets/eventview.cpp b/src/widgets/eventview.cpp deleted file mode 100644 index e77bb5a..0000000 --- a/src/widgets/eventview.cpp +++ /dev/null @@ -1,185 +0,0 @@ -// -// C++ Implementation: event list tab -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2007-2013 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "eventview.h" -#include "misc.h" -#include "msinterface.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -MEventView::MEventView ( QWidget* parent ) : QTextBrowser ( parent ) -{ - setReadOnly(true); - connect(this,SIGNAL(anchorClicked(QUrl)),this,SLOT(handleClick(QUrl))); - setOpenExternalLinks(false); - setOpenLinks(false); - qDebug()<<"Setting path"<parentUrl()<<"for URL"<url(); - setSearchPaths(QStringList()<parentUrl().toString()); - resetPattern(); -} - - -QVariant MEventView::loadResource ( int type, const QUrl& name ) -{ - Q_UNUSED(type); - qDebug()<<"Loading Resource"<url().resolved(name); - QNetworkAccessManager nam; - connect(&nam,SIGNAL(sslErrors(QNetworkReply*,QList)),req,SLOT(sslErrors(QNetworkReply*,QList))); - QNetworkReply*rpl= nam.get(QNetworkRequest(url)); - qDebug()<<"Trying to GET"<readAll(); - qDebug()<<"...got"<\n"; - detail+=tr("Artist: %1").arg(htmlize(event.artist().value().name()))+"

\n"; - detail+=tr("Starttime: %1").arg(htmlize(event.startTimeString()))+"
\n"; - detail+=tr("Endtime: %1").arg(htmlize(event.endTimeString()))+"

\n"; - detail+=tr("Room: %1").arg(htmlize(event.room()))+"
\n"; - detail+=tr("Seats: %1 max. (%2 sold out; %3 reserved; %4 free)").arg(event.capacity()).arg(event.amountSold()).arg(event.amountReserved()).arg(event.amountFree())+"

\n"; - - const QString bgsold=tr("

Sold Out!
","Colored display for sold out tickets"); - const QString bgavail=tr("
","Colored display for ordering tickets"); - const QString bghide=tr("
Unable to sell.
","Colored display for tickets unavailable to this user"); - - const bool showevent=req->checkFlags(event.flags()); - if(showevent) - detail+=event.amountFree()>0?bgavail.arg(QString("order:?ev=%1").arg(event.id())):bgsold; - else - detail+=bghide; - detail+="

"+tr("Prices")+"

\n"; - detail+="" - "\n"; - QListprices=event.price(); - qSort(prices.begin(),prices.end(),[](const MOEventPrice&p1,const MOEventPrice&p2){return p1.prio()checkFlags(ctg.flags())) - detail+=""; - } - detail+="
"+tr("Category")+""+tr("Price")+""+tr("Available")+""+tr("Max. Seats")+""+tr("Order")+"
"+ - (avail>0? - bgavail.arg(QString("order:?ev=%1&pr=%2").arg(event.id()).arg(ctg.pricecategoryid())) - :bgsold); - else - detail+=""+bghide; - detail+="

\n"; - - detail+="

"+tr("Description")+"

\n"+event.description()+"

\n"; - detail+="

"+tr("Comment")+"

\n"; - QString comment=event.comment(); - if(!comment.trimmed().startsWith(""))comment=htmlize(comment); - detail+=comment; - //set value - setHtml(detail); -} - -void MEventView::handleClick(const QUrl &url) -{ - //check whether it is order URL - if(url.scheme()=="order"){ - QUrlQuery query(url); - if(query.hasQueryItem("ev")){ - bool b=false; - qint64 evid=query.queryItemValue("ev").toLongLong(&b); - if(!b || evid<0){ - qDebug()<<"ordering tickets for current event (invalid EvID)..."; - emit eventOrderTicket(); - return; - } - qint64 prid=-1; - if(query.hasQueryItem("pr")){ - prid=query.queryItemValue("pr").toLongLong(&b); - if(!b)prid=-1; - } - qDebug()<<"ordering tickets for event"<url().resolved(url); - qDebug()<<"Relative URL"<url(); - qDebug()<<" ...opening"<{event.name|html}\n" - "Artist: {event.artist|html}

\n" - "Starttime: {event.startTimeString}
\n" - "Endtime: {event.endTimeString}

\n" - "Room: {event.room|html}
\n" - "Seats: {event.capacity} max. ({event.amountSold} sold out; {event.amountReserved} reserved; {event.amountFree} free)

\n" - "{% if(event.haveAccess) %}\n" - - "{% endif %}" - ); -} diff --git a/src/widgets/eventview.h b/src/widgets/eventview.h deleted file mode 100644 index 6fa58e5..0000000 --- a/src/widgets/eventview.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// C++ Interface: event view` -// -// Description: widget for displaying event details -// -// -// Author: Konrad Rosenbaum , (C) 2016 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef MAGICSMOKE_EVENTVIEW_H -#define MAGICSMOKE_EVENTVIEW_H - -#include - -#include - -///Event Viewer -class MEventView:public QTextBrowser -{ - Q_OBJECT -public: - explicit MEventView ( QWidget* parent = 0 ); - QVariant loadResource(int type, const QUrl & name)override; - -public slots: - void setEvent(MOEvent); - void clearEvent(); - void setPattern(QString); - void resetPattern(); -private slots: - void handleClick(const QUrl&); -signals: - /**order ticket from event tab*/ - void eventOrderTicket(); - /**order ticket from event tab*/ - void eventOrderTicket(qint64,qint64); -private: - QString mPattern; -}; - - -#endif diff --git a/src/widgets/listview.cpp b/src/widgets/listview.cpp deleted file mode 100644 index e268e66..0000000 --- a/src/widgets/listview.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// C++ Implementation: treeview -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2009-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "listview.h" - -void MListView::keyPressEvent(QKeyEvent *event) -{ - QModelIndex idx=currentIndex(); - QListView::keyPressEvent(event); - if(idx!=currentIndex()) - emit activated(currentIndex()); -} \ No newline at end of file diff --git a/src/widgets/listview.h b/src/widgets/listview.h deleted file mode 100644 index c66c465..0000000 --- a/src/widgets/listview.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// C++ Interface: treeview -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2009-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef MAGICSMOKE_LISTVIEW_H -#define MAGICSMOKE_LISTVIEW_H - -#include - -/**enhances QTreeView to react a bit friendlier on clicks*/ -class MListView:public QListView -{ - public: - MListView(QWidget*w=0):QListView(w){} - protected: - void keyPressEvent(QKeyEvent *event); - -}; - -#endif diff --git a/src/widgets/treeview.cpp b/src/widgets/treeview.cpp deleted file mode 100644 index 02d1738..0000000 --- a/src/widgets/treeview.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// C++ Implementation: treeview -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2009-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#include "treeview.h" - -void MTreeView::keyPressEvent(QKeyEvent *event) -{ - QModelIndex idx=currentIndex(); - QTreeView::keyPressEvent(event); - if(idx!=currentIndex()) - emit activated(currentIndex()); -} \ No newline at end of file diff --git a/src/widgets/treeview.h b/src/widgets/treeview.h deleted file mode 100644 index b79f952..0000000 --- a/src/widgets/treeview.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// C++ Interface: treeview -// -// Description: -// -// -// Author: Konrad Rosenbaum , (C) 2009-2011 -// -// Copyright: See README/COPYING.GPL files that come with this distribution -// -// - -#ifndef MAGICSMOKE_TREEVIEW_H -#define MAGICSMOKE_TREEVIEW_H - -#include - -/**enhances QTreeView to react a bit friendlier on clicks*/ -class MTreeView:public QTreeView -{ - public: - MTreeView(QWidget*w=0):QTreeView(w){} - protected: - void keyPressEvent(QKeyEvent *event); - -}; - -#endif diff --git a/src/widgets/widgets.pri b/src/widgets/widgets.pri deleted file mode 100644 index 40f1ed2..0000000 --- a/src/widgets/widgets.pri +++ /dev/null @@ -1,15 +0,0 @@ -HEADERS += \ - widgets/centbox.h \ - widgets/listview.h \ - widgets/treeview.h \ - widgets/barcodeline.h \ - widgets/eventview.h - -SOURCES += \ - widgets/centbox.cpp \ - widgets/listview.cpp \ - widgets/treeview.cpp \ - widgets/barcodeline.cpp \ - widgets/eventview.cpp - -INCLUDEPATH += ./widgets -- 1.7.2.5