1 /* This file is part of the KDE project
2    Copyright (C) 2010 KO GmbH <ben.martin@kogmbh.com>
3 
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public
6    License as published by the Free Software Foundation; either
7    version 2 of the License, or (at your option) any later version.
8 
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13 
14    You should have received a copy of the GNU Library General Public License
15    along with this library; see the file COPYING.LIB.  If not, write to
16    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18 */
19 
20 #include "KoSemanticStylesheetsEditor.h"
21 
22 #include "ui_KoSemanticStylesheetsEditor.h"
23 
24 #include "KoRdfSemanticItem.h"
25 #include "KoRdfSemanticItemRegistry.h"
26 #include "KoDocumentRdf.h"
27 
28 #include <kdebug.h>
29 
30 class Q_DECL_HIDDEN KoSemanticStylesheetsEditor::Private
31 {
32 public:
33     Ui::KoSemanticStylesheetsEditor *m_ui;
34     KoDocumentRdf *m_rdf;
35     QTreeWidgetItem *m_systemSheetsParentItem;
36     QTreeWidgetItem *m_userSheetsParentItem;
37     QMap<QString, QTreeWidgetItem*> m_systemSheetsItems;
38     QMap<QString, QTreeWidgetItem*> m_userSheetsItems;
Private()39     Private()
40             : m_systemSheetsParentItem(0)
41             , m_userSheetsParentItem(0) {}
~Private()42     ~Private() {
43 	    delete m_ui;
44     }
45 };
46 
47 enum {
48     ColName = 0,
49     ColSemobj = 1,
50     ColVar = 0,
51     ColDesc = 1
52 };
53 
54 class KoSemanticStylesheetWidgetItem : public QTreeWidgetItem
55 {
56 public:
57     KoDocumentRdf *m_rdf;
58     hKoSemanticStylesheet m_ss;
59     hKoRdfSemanticItem m_si;
KoSemanticStylesheetWidgetItem(KoDocumentRdf * rdf,hKoSemanticStylesheet ss,hKoRdfSemanticItem si,QTreeWidgetItem * parent,int type=Type)60     KoSemanticStylesheetWidgetItem(KoDocumentRdf *rdf,
61                                    hKoSemanticStylesheet ss,
62                                    hKoRdfSemanticItem si,
63                                    QTreeWidgetItem *parent,
64                                    int type = Type)
65             : QTreeWidgetItem(parent, type)
66             , m_rdf(rdf)
67             , m_ss(ss)
68             , m_si(si)
69     {
70     }
KoSemanticStylesheetWidgetItem(KoDocumentRdf * rdf,hKoRdfSemanticItem si,QTreeWidgetItem * parent,int type=Type)71     KoSemanticStylesheetWidgetItem(KoDocumentRdf *rdf,
72                                    hKoRdfSemanticItem si,
73                                    QTreeWidgetItem *parent,
74                                    int type = Type)
75         : QTreeWidgetItem(parent, type)
76         , m_rdf(rdf)
77         , m_ss(0)
78         , m_si(si)
79     {
80     }
81 
setData(int column,int role,const QVariant & value)82     virtual void setData(int column, int role, const QVariant &value)
83     {
84         if (m_ss && m_ss->isMutable() && column == ColName) {
85             QString newName = value.toString();
86             kDebug(30015) << "update to value:" << newName;
87             m_ss->name(newName);
88             QVariant v = m_ss->name();
89             QTreeWidgetItem::setData(column, role, v);
90         } else {
91             QTreeWidgetItem::setData(column, role, value);
92         }
93     }
94 };
95 
96 
KoSemanticStylesheetsEditor(QWidget * parent,KoDocumentRdf * rdf)97 KoSemanticStylesheetsEditor::KoSemanticStylesheetsEditor(QWidget *parent, KoDocumentRdf *rdf)
98         : KoDialog(parent),
99         d(new Private())
100 {
101     d->m_rdf = rdf;
102     QWidget *widget = new QWidget(this);
103     setMainWidget(widget);
104     d->m_ui = new Ui::KoSemanticStylesheetsEditor();
105     d->m_ui->setupUi(widget);
106     d->m_ui->newStylesheet->setEnabled(false);
107     d->m_ui->deleteStylesheet->setEnabled(false);
108     connect(d->m_ui->newStylesheet, SIGNAL(clicked()),
109             this, SLOT(newStylesheet()));
110     connect(d->m_ui->deleteStylesheet, SIGNAL(clicked()),
111             this, SLOT(deleteStylesheet()));
112     connect(d->m_ui->stylesheets, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
113             this, SLOT(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
114     d->m_ui->stylesheets->setSelectionBehavior(QAbstractItemView::SelectRows);
115     d->m_ui->stylesheets->sortItems(ColName, Qt::DescendingOrder);
116     connect(d->m_ui->definition, SIGNAL(textChanged()),
117             this, SLOT(definitionChanged()));
118     // setup system/user parent treewidgets
119     d->m_systemSheetsParentItem = new QTreeWidgetItem(d->m_ui->stylesheets);
120     d->m_systemSheetsParentItem->setText(ColName, i18n("System"));
121     d->m_systemSheetsParentItem->setText(ColSemobj, "");
122     d->m_ui->stylesheets->expandItem(d->m_systemSheetsParentItem);
123 
124     QTreeWidgetItem *treewidget = 0;
125     treewidget = d->m_systemSheetsParentItem;
126     const QStringList classNames = KoRdfSemanticItemRegistry::instance()->classNames();
127     foreach (const QString &semanticClass, classNames) {
128 	hKoRdfSemanticItem si(static_cast<KoRdfSemanticItem *>(
129 	    rdf->createSemanticItem(semanticClass, this).data()));
130         KoSemanticStylesheetWidgetItem *item = new KoSemanticStylesheetWidgetItem(rdf, si, treewidget);
131         item->setText(ColName, semanticClass);
132         d->m_systemSheetsItems[semanticClass] = item;
133         d->m_ui->stylesheets->expandItem(item);
134     }
135     d->m_userSheetsParentItem = new QTreeWidgetItem(d->m_ui->stylesheets);
136     d->m_userSheetsParentItem->setText(ColName, i18n("User"));
137     d->m_userSheetsParentItem->setText(ColSemobj, "");
138     d->m_ui->stylesheets->expandItem(d->m_userSheetsParentItem);
139 
140     treewidget = d->m_userSheetsParentItem;
141     foreach (const QString &semanticClass, classNames) {
142 	hKoRdfSemanticItem si(static_cast<KoRdfSemanticItem *>(
143 	    rdf->createSemanticItem(semanticClass, this).data()));
144         KoSemanticStylesheetWidgetItem* item = new KoSemanticStylesheetWidgetItem(rdf, si, treewidget);
145         item->setText(ColName, semanticClass);
146         d->m_userSheetsItems[semanticClass] = item;
147         d->m_ui->stylesheets->expandItem(item);
148     }
149 
150     // initialize stylesheets tree
151     foreach (const QString &semanticClass, classNames) {
152         kDebug(30015) << "semanticClass:" << semanticClass;
153 	hKoRdfSemanticItem p(static_cast<KoRdfSemanticItem *>(
154 	    rdf->createSemanticItem(semanticClass, this).data()));
155         setupStylesheetsItems(semanticClass, p, p->stylesheets(), d->m_systemSheetsItems);
156         setupStylesheetsItems(semanticClass, p, p->userStylesheets(), d->m_userSheetsItems, true);
157     }
158     connect(d->m_ui->variables, SIGNAL(itemActivated(QTableWidgetItem*)),
159             this, SLOT(onVariableActivated(QTableWidgetItem*)));
160     d->m_ui->variables->horizontalHeader()->setResizeMode(ColVar, QHeaderView::ResizeToContents);
161     d->m_ui->variables->horizontalHeader()->setResizeMode(ColDesc, QHeaderView::ResizeToContents);
162 }
163 
~KoSemanticStylesheetsEditor()164 KoSemanticStylesheetsEditor::~KoSemanticStylesheetsEditor()
165 {
166 }
167 
setupStylesheetsItems(const QString & semanticClass,hKoRdfSemanticItem si,const QList<hKoSemanticStylesheet> & ssl,const QMap<QString,QTreeWidgetItem * > & m,bool editable)168 void KoSemanticStylesheetsEditor::setupStylesheetsItems(const QString& semanticClass,
169                                                         hKoRdfSemanticItem si,
170                                                         const QList<hKoSemanticStylesheet> &ssl,
171                                                         const QMap<QString, QTreeWidgetItem*> &m,
172                                                         bool editable)
173 {
174     foreach (hKoSemanticStylesheet ss, ssl) {
175         kDebug(30015) << "ss:" << ss->name();
176         QTreeWidgetItem *parent = m[semanticClass];
177         KoSemanticStylesheetWidgetItem *item = new KoSemanticStylesheetWidgetItem(d->m_rdf, ss, si, parent);
178         item->setText(ColName, ss->name());
179         item->setText(ColSemobj, semanticClass);
180         if (editable) {
181             item->setFlags(item->flags() | Qt::ItemIsEditable);
182         }
183     }
184 }
185 
slotOk()186 void KoSemanticStylesheetsEditor::slotOk()
187 {
188 }
189 
maskButtonsDependingOnCurrentItem(QTreeWidgetItem * current)190 void KoSemanticStylesheetsEditor::maskButtonsDependingOnCurrentItem(QTreeWidgetItem *current)
191 {
192     bool newEnabled = true;
193     bool delEnabled = true;
194     for (QMap< QString, QTreeWidgetItem* >::iterator iter = d->m_userSheetsItems.begin();
195             iter != d->m_userSheetsItems.end(); ++iter) {
196         if (iter.value() == current) {
197             delEnabled = false;
198         }
199     }
200     if (d->m_userSheetsParentItem == current) {
201         newEnabled = false;
202         delEnabled = false;
203     } else {
204         while (current) {
205             kDebug(30015) << "current:" << current->text(ColName);
206             if (d->m_systemSheetsParentItem == current) {
207                 newEnabled = false;
208                 delEnabled = false;
209                 break;
210             }
211             current = current->parent();
212         }
213     }
214     d->m_ui->newStylesheet->setEnabled(newEnabled);
215     d->m_ui->deleteStylesheet->setEnabled(delEnabled);
216 }
217 
definitionChanged()218 void KoSemanticStylesheetsEditor::definitionChanged()
219 {
220     if (KoSemanticStylesheetWidgetItem *ssitem
221             = dynamic_cast<KoSemanticStylesheetWidgetItem*>(d->m_ui->stylesheets->currentItem())) {
222         if (!ssitem->m_ss) {
223             return;
224         }
225         QString desc = d->m_ui->definition->toPlainText();
226         kDebug(30015) << "ss:" << ssitem->m_ss->name() << " desc:" << desc;
227         ssitem->m_ss->templateString(desc);
228     }
229 }
230 
231 struct SignalBlockerRAII {
232     QObject *obj;
233     bool oldval;
SignalBlockerRAIISignalBlockerRAII234     SignalBlockerRAII(QObject *o)
235             : obj(o) {
236         oldval = obj->blockSignals(true);
237     }
~SignalBlockerRAIISignalBlockerRAII238     ~SignalBlockerRAII() {
239         obj->blockSignals(oldval);
240     }
241 };
242 
243 
currentItemChanged(QTreeWidgetItem * current,QTreeWidgetItem * previous)244 void KoSemanticStylesheetsEditor::currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
245 {
246     SignalBlockerRAII _blocker1(d->m_ui->definition);
247     kDebug(30015) << "current:" << current;
248     kDebug(30015) << "previous:" << previous;
249     maskButtonsDependingOnCurrentItem(current);
250     if (previous) {
251         QString desc = d->m_ui->definition->toPlainText();
252         kDebug(30015) << "desc:" << desc;
253         if (KoSemanticStylesheetWidgetItem *ssitem
254                 = dynamic_cast<KoSemanticStylesheetWidgetItem*>(previous)) {
255             kDebug(30015) << "ssitem, ss?:" << ssitem->m_ss;
256 
257             if (ssitem->m_ss) {
258                 ssitem->m_ss->templateString(desc);
259             }
260         }
261     }
262     if (KoSemanticStylesheetWidgetItem *ssitem
263             = dynamic_cast<KoSemanticStylesheetWidgetItem*>(current)) {
264         d->m_ui->definition->setPlainText(QString());
265         d->m_ui->variables->clear();
266         if (!ssitem->m_ss) {
267             return;
268         }
269         d->m_ui->definition->setPlainText(ssitem->m_ss->templateString());
270         // update the list of available variables
271         QTableWidget *v = d->m_ui->variables;
272         v->clear();
273         int row = 0;
274         QMap<QString, QString> m;
275         ssitem->m_si->setupStylesheetReplacementMapping(m);
276         QMap< QString, QString >::const_iterator mi = m.constBegin();
277         QMap< QString, QString >::const_iterator me = m.constEnd();
278         for (; mi != me; ++mi) {
279             QTableWidgetItem *item = 0;
280             QString varName = mi.key();
281             QString desc("t");
282             v->setRowCount(row + 1);
283             item = new QTableWidgetItem(varName);
284             v->setItem(row, ColVar, item);
285             item = new QTableWidgetItem(desc);
286             v->setItem(row, ColDesc, item);
287             ++row;
288         }
289     }
290 }
291 
newStylesheet()292 void KoSemanticStylesheetsEditor::newStylesheet()
293 {
294     kDebug(30015);
295     if (KoSemanticStylesheetWidgetItem *ssitem
296             = dynamic_cast<KoSemanticStylesheetWidgetItem*>(d->m_ui->stylesheets->currentItem())) {
297         if (ssitem->m_ss) {
298             ssitem = dynamic_cast<KoSemanticStylesheetWidgetItem*>(ssitem->parent());
299             if (!ssitem) {
300                 return;
301             }
302         }
303         kDebug(30015) << ssitem;
304         hKoRdfSemanticItem si = ssitem->m_si;
305         hKoSemanticStylesheet ss = si->createUserStylesheet(
306                                      QString("new stylesheet %1").arg(QDateTime::currentDateTime().toTime_t()), "");
307         QTreeWidgetItem *parent = ssitem;
308         KoSemanticStylesheetWidgetItem* item =
309             new KoSemanticStylesheetWidgetItem(d->m_rdf, ss, si, parent);
310         item->setText(ColName, ss->name());
311         item->setFlags(item->flags() | Qt::ItemIsEditable);
312 
313         d->m_ui->stylesheets->setCurrentItem(item);
314         d->m_ui->stylesheets->scrollToItem(item);
315     }
316 }
317 
deleteStylesheet()318 void KoSemanticStylesheetsEditor::deleteStylesheet()
319 {
320     kDebug(30015);
321     if (KoSemanticStylesheetWidgetItem *ssitem
322             = dynamic_cast<KoSemanticStylesheetWidgetItem*>(d->m_ui->stylesheets->currentItem())) {
323         if (!ssitem->m_ss) {
324             return;
325         }
326         hKoSemanticStylesheet sheet = ssitem->m_ss;
327         ssitem->m_ss = 0;
328         ssitem->m_si->destroyUserStylesheet(sheet);
329         ssitem->parent()->removeChild(ssitem);
330     }
331 }
332 
onVariableActivated(QTableWidgetItem * item)333 void KoSemanticStylesheetsEditor::onVariableActivated(QTableWidgetItem* item)
334 {
335     QTableWidgetItem *vitem = d->m_ui->variables->item(item->row(), ColVar);
336     QString vtext = vitem->text();
337     QTextCursor cursor(d->m_ui->definition->textCursor());
338     cursor.insertText(vtext);
339 }
340 
341 #include <KoSemanticStylesheetsEditor.moc>
342