#include "MOVoucher"
#include <DPtr>
+
#include <QAction>
#include <QBoxLayout>
#include <QComboBox>
#include <QSignalMapper>
#include <QSizeF>
#include <QSplitter>
+#include <QStackedWidget>
#include <QStandardItemModel>
#include <QStatusBar>
#include <QTableView>
#include <QTemporaryFile>
+#include <QTextEdit>
+#include <QTreeView>
#include <QUnZip>
#include <QZip>
-#include <QTreeView>
class DPTR_CLASS_NAME(MOdfEditor)
//widgets
QTreeView*mDomTree;
MDomItemModel*mDomModel;
+ //stack indexes
+ int st_none,st_tag,st_text,st_loop,st_calc,st_comment,st_cond;
+ //stack widgets
+ QLineEdit*mLoopVar,*mCalcExpr,*mTagName,*mCondExpr;
+ QTextEdit*mText,*mComment;
+ QTableView*mTagAttrs;
+ QStandardItemModel*mTagAttrModel;
+ //tree menu
+ QAction*maAddCalc,*maAddCond,*maAddComment,*maAddElse,*maAddLoop;
+ QAction*maInsCalc,*maInsComment,*maUnwrap,*maDelItem;
+ void setActions(const QList<QAction*>&);
+ //current node
+ QModelIndex mCurIndex;
+ QDomNode mCurNode;
//file contents
struct File{
QString name;
DEFINE_DPTR(MOdfEditor);
+static QVariant displayColorHelper(const QDomNode& node)
+{
+ static const QColor textbg("#c0c0ff"),commentbg("#c0c0c0"),specialbg("#ffc0c0");
+ switch(node.nodeType()){
+ case QDomNode::CommentNode:return commentbg;
+ case QDomNode::TextNode:
+ case QDomNode::CDATASectionNode:
+ return textbg;
+ case QDomNode::ElementNode:
+ if(node.nodeName().startsWith(OdfTemplatePrefix+":"))
+ return specialbg;
+ //fall through
+ default: //use default color
+ return QVariant();
+ }
+}
+
+
MOdfEditor::MOdfEditor(QWidget* parent, Qt::WindowFlags f): QMainWindow(parent, f)
{
setWindowTitle(tr("ODF Template Editor"));
m->addAction(tr("&Close"),this,SLOT(close()));
m=mb->addMenu(tr("&Edit"));
- m->addAction(tr("Insert &Calculation"));
- m->addAction(tr("Insert C&ondition"));
- m->addAction(tr("Insert &Else"));
- m->addAction(tr("Insert &Loop"));
+ d->maAddCalc=m->addAction(tr("Insert &Calculation into current"));
+ d->maInsCalc=m->addAction(tr("Insert Calculation behind current"));
+ d->maAddCond=m->addAction(tr("&Wrap in Condition"));
+ d->maAddLoop=m->addAction(tr("Wrap in &Loop"));
+ d->maAddElse=m->addAction(tr("Insert &Else behind current"));
+ d->maAddComment=m->addAction(tr("Insert Comment into current"));
+ d->maInsComment=m->addAction(tr("Insert Comment behind current"));
m->addSeparator();
- m->addAction(tr("&Remove Item"),this,SLOT(delItem()));
+ d->maUnwrap=m->addAction(tr("Unwrap Loop/Condition"));
+ d->maDelItem=m->addAction(tr("&Remove Item"),this,SLOT(delItem()));
m=mb->addMenu(tr("&Data"));
m->addAction(tr("Import from Order..."));
//central
QSplitter*central=new QSplitter(Qt::Vertical);
setCentralWidget(central);
- QVBoxLayout*vl,*vl2;
- QHBoxLayout*hl,*hl2;
- QPushButton*p;
+ QVBoxLayout*vl;
+ QHBoxLayout*hl;
+ central->setStretchFactor(0,1);
+ central->setStretchFactor(1,5);
+ central->setOrientation(Qt::Horizontal);
+ //DOM tree
central->addWidget(d->mDomTree=new QTreeView);
d->mDomTree->setModel(d->mDomModel=new MDomItemModel(this));
d->mDomTree->setEditTriggers(QAbstractItemView::NoEditTriggers);
d->mDomModel->setHeaderData(0,Qt::Horizontal,tr("Document XML Tree"),Qt::DisplayRole);
d->mDomModel->showAllNodeTypes();
-// d->mDomModel->addShowNodeType(QDomNode::AttributeNode);
- d->mDomTree->setSelectionMode(QAbstractItemView::SingleSelection);
+ d->mDomModel->showTypeLabel(false);
+ d->mDomModel->setContentFromNodeCall(Qt::BackgroundColorRole,displayColorHelper);
+ d->mDomTree->setSelectionMode(QAbstractItemView::ContiguousSelection);
d->mDomTree->setSelectionBehavior(QAbstractItemView::SelectRows);
d->mDomTree->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
d->mDomTree->header()->setResizeMode(0,QHeaderView::ResizeToContents);
d->mDomTree->header()->setStretchLastSection(false);
+ connect(d->mDomTree->selectionModel(),SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this,SLOT(selectionChange()));
+
+ //the editors...
+ QStackedWidget*stack;
+ central->addWidget(stack=new QStackedWidget);
+ connect(this,SIGNAL(switchStack(int)),stack,SLOT(setCurrentIndex(int)));
+ d->st_none=stack->addWidget(new QWidget);
+ QWidget*w;
+ //text node editor
+ d->st_text=stack->addWidget(w=new QWidget);
+ w->setLayout(vl=new QVBoxLayout);
+ vl->addWidget(new QLabel(tr("<h1>Plain Text<h1>")));
+ vl->addWidget(d->mText=new QTextEdit);
+ //tag editor
+ d->st_tag=stack->addWidget(w=new QWidget);
+ w->setLayout(vl=new QVBoxLayout);
+ vl->addWidget(new QLabel(tr("<h1>Tag</h1>")));
+ vl->addLayout(hl=new QHBoxLayout);
+ hl->addWidget(new QLabel(tr("Tag Name:")));
+ hl->addWidget(d->mTagName=new QLineEdit,1);
+ vl->addSpacing(15);
+ vl->addWidget(new QLabel(tr("Attributes:")));
+ vl->addWidget(d->mTagAttrs=new QTableView,1);
+ d->mTagAttrs->setModel(d->mTagAttrModel=new QStandardItemModel);
+ //loop editor
+ d->st_loop=stack->addWidget(w=new QWidget);
+ w->setLayout(vl=new QVBoxLayout);
+ vl->addWidget(new QLabel(tr("<h1>Loop</h1>")));
+ vl->addLayout(hl=new QHBoxLayout);
+ hl->addWidget(new QLabel(tr("Loop Variable")));
+ hl->addWidget(d->mLoopVar=new QLineEdit);
+ vl->addStretch(1);
+ //calc editor
+ d->st_calc=stack->addWidget(w=new QWidget);
+ w->setLayout(vl=new QVBoxLayout);
+ vl->addWidget(new QLabel(tr("<h1>Calculation</h1>")));
+ vl->addLayout(hl=new QHBoxLayout);
+ hl->addWidget(new QLabel(tr("Expression")));
+ hl->addWidget(d->mCalcExpr=new QLineEdit);
+ vl->addStretch(1);
+ //calc editor
+ d->st_cond=stack->addWidget(w=new QWidget);
+ w->setLayout(vl=new QVBoxLayout);
+ vl->addWidget(new QLabel(tr("<h1>Condition</h1>")));
+ vl->addLayout(hl=new QHBoxLayout);
+ hl->addWidget(new QLabel(tr("Expression")));
+ hl->addWidget(d->mCondExpr=new QLineEdit);
+ vl->addStretch(1);
+ //comment editor
+ d->st_comment=stack->addWidget(w=new QWidget);
+ w->setLayout(vl=new QVBoxLayout);
+ vl->addWidget(new QLabel(tr("<h1>Comment</h1>")));
+ vl->addWidget(d->mComment=new QTextEdit,1);
//statusbar
statusBar()->setSizeGripEnabled(true);
setAttribute(Qt::WA_DeleteOnClose);
+ updateDisplay();
}
if(!dov1){
d->mDomModel->setDomDocument(d->mContent);
d->mDomTree->expandAll();
+ qDebug()<<"done parsing template";
return;
}
//try again
// qDebug()<<"dump\n"<<d->mContent.toByteArray();
d->mDomModel->setDomDocument(d->mContent);
d->mDomTree->expandAll();
+ qDebug()<<"done converting and parsing template";
}
void MOdfEditor::openFile()
void MOdfEditor::updateDisplay()
{
if(d->mFileName=="")
- setWindowTitle(tr("Label Template Editor"));
+ setWindowTitle(tr("ODF Template Editor"));
else
- setWindowTitle(tr("Label Template Editor [%1]").arg(d->mFileName));
+ setWindowTitle(tr("ODF Template Editor [%1]").arg(d->mFileName));
//basics
+ selectionChange();
}
void MOdfEditor::saveTemplate(QFile& fd)
//save
fd.write(d->mContent.toByteArray());
}
+
+void MOdfEditor::selectionChange()
+{
+ saveCurrentNode();
+ d->mCurIndex=QModelIndex();
+ d->mCurNode=QDomNode();
+ d->setActions(QList<QAction*>());
+ //get selection
+ QModelIndexList idxl=d->mDomTree->selectionModel()->selectedRows();
+ if(idxl.size()!=1){
+ emit switchStack(d->st_none);
+ if(idxl.size()>1)
+ d->setActions(QList<QAction*>()<<d->maAddCond<<d->maAddLoop);
+ return;
+ }
+ //check element type
+ d->mCurIndex=idxl[0];
+ d->mCurNode=d->mDomModel->node(idxl[0]);
+ QDomNode pn=d->mDomModel->node(idxl[0].parent());
+ bool allowElse=pn.isElement() && pn.nodeName()==(OdfTemplatePrefix+":if");
+ //comment?
+ if(d->mCurNode.isComment()){
+ emit switchStack(d->st_comment);
+ d->mComment->setText(d->mCurNode.nodeValue());
+ d->setActions(QList<QAction*>()<<d->maAddCalc<<d->maInsComment<<d->maDelItem<<(allowElse?d->maAddElse:nullptr));
+ return;
+ }
+ //is it normal text?
+ if(d->mCurNode.isCharacterData()){
+ emit switchStack(d->st_text);
+ d->mText->setText(d->mCurNode.nodeValue());
+ d->setActions(QList<QAction*>()<<d->maAddCalc<<d->maAddComment<<d->maAddCond<<d->maAddLoop<<d->maDelItem<<(allowElse?d->maAddElse:nullptr));
+ return;
+ }
+ //henceforth we are only interested in elements.
+ if(!d->mCurNode.isElement()){
+ emit switchStack(d->st_none);
+ d->setActions(QList<QAction*>()<<d->maAddCalc<<d->maAddComment<<d->maDelItem<<(allowElse?d->maAddElse:nullptr));
+ return;
+ }
+ //is it special?
+ const QStringList nn=d->mCurNode.nodeName().split(':');
+ if(nn.size()==2 && nn[0]==OdfTemplatePrefix){
+ QDomElement el=d->mCurNode.toElement();
+ if(nn[1]=="loop"){
+ emit switchStack(d->st_loop);
+ d->mLoopVar->setText(el.attribute("variable"));
+ #warning implement correct actions for special tags
+ return;
+ }
+ if(nn[1]=="calculate"){
+ emit switchStack(d->st_calc);
+ d->mCalcExpr->setText(el.attribute("exec"));
+ return;
+ }
+ if(nn[1]=="if"){
+ emit switchStack(d->st_cond);
+ d->mCondExpr->setText(el.attribute("select"));
+ return;
+ }
+ //else
+ emit switchStack(d->st_none);
+ return;
+ }else{
+ emit switchStack(d->st_tag);
+ #warning implement correct actions for normal tags
+ displayTag();
+ return;
+ }
+}
+
+void MOdfEditor::displayTag()
+{
+ QDomElement el=d->mCurNode.toElement();
+ d->mTagAttrModel->clear();
+ if(el.isNull()){
+ d->mTagName->setText("");
+ return;
+ }
+ d->mTagName->setText(el.tagName());
+ //redo model
+ if(d->mTagAttrModel->columnCount()<2){
+ d->mTagAttrModel->insertColumns(0,2);
+ d->mTagAttrModel->setHorizontalHeaderLabels(QStringList()<<tr("Attribute")<<tr("Value"));
+ }
+ QDomNamedNodeMap al=el.attributes();
+ d->mTagAttrModel->insertRows(0,al.size());
+ for(int i=0;i<al.size();i++){
+ QDomAttr at=al.item(i).toAttr();
+ d->mTagAttrModel->setData(d->mTagAttrModel->index(i,0),at.name());
+ d->mTagAttrModel->setData(d->mTagAttrModel->index(i,1),at.value());
+ }
+ d->mTagAttrs->resizeColumnsToContents();
+}
+
+void MOdfEditor::saveCurrentNode()
+{
+#warning implement
+}
+
+void MOdfEditor::Private::setActions(const QList< QAction* >& act)
+{
+ maAddCalc->setEnabled(act.contains(maAddCalc));
+ maAddCond->setEnabled(act.contains(maAddCond));
+ maAddComment->setEnabled(act.contains(maAddComment));
+ maAddElse->setEnabled(act.contains(maAddElse));
+ maAddLoop->setEnabled(act.contains(maAddLoop));
+ maInsCalc->setEnabled(act.contains(maInsCalc));
+ maInsComment->setEnabled(act.contains(maInsComment));
+ maUnwrap->setEnabled(act.contains(maUnwrap));
+ maDelItem->setEnabled(act.contains(maDelItem));
+}