1 /*
2     TikZiT - a GUI diagram editor for TikZ
3     Copyright (C) 2018 Aleks Kissinger
4 
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18 
19 #include <QColorDialog>
20 #include <QDebug>
21 #include <QMessageBox>
22 
23 #include "tikzit.h"
24 #include "styleeditor.h"
25 #include "delimitedstringvalidator.h"
26 #include "ui_styleeditor.h"
27 #include "delimitedstringitemdelegate.h"
28 
StyleEditor(QWidget * parent)29 StyleEditor::StyleEditor(QWidget *parent) :
30     QMainWindow(parent),
31     ui(new Ui::StyleEditor)
32 {
33     ui->setupUi(this);
34     _formWidgets << ui->name << ui->category <<
35         ui->fillColor << ui->noFill << ui->hasTikzitFillColor << ui->tikzitFillColor <<
36         ui->drawColor << ui->noDraw << ui->hasTikzitDrawColor << ui->tikzitDrawColor <<
37         ui->shape << ui->hasTikzitShape << ui->tikzitShape <<
38         ui->leftArrow << ui->rightArrow <<
39         ui->properties;
40 
41     DelimitedStringValidator *v = new DelimitedStringValidator(this);
42     ui->name->setValidator(v);
43     ui->category->lineEdit()->setValidator(v);
44     ui->shape->lineEdit()->setValidator(v);
45 
46     DelimitedStringItemDelegate *delegate = new DelimitedStringItemDelegate(ui->properties);
47     ui->properties->setItemDelegate(delegate);
48 
49     setWindowIcon(QIcon(":/images/tikzit.png"));
50     _styles = nullptr;
51     _activeStyle = nullptr;
52 
53     ui->styleListView->setViewMode(QListView::IconMode);
54     ui->styleListView->setMovement(QListView::Static);
55     ui->styleListView->setGridSize(QSize(48,48));
56 
57     ui->edgeStyleListView->setViewMode(QListView::IconMode);
58     ui->edgeStyleListView->setMovement(QListView::Static);
59     ui->edgeStyleListView->setGridSize(QSize(48,48));
60 
61     connect(ui->category->lineEdit(),
62             SIGNAL(editingFinished()),
63             this, SLOT(categoryChanged()));
64     connect(ui->category,
65             SIGNAL(currentIndexChanged(int)),
66             this, SLOT(categoryChanged()));
67 
68     connect(ui->shape->lineEdit(),
69             SIGNAL(editingFinished()),
70             this, SLOT(shapeChanged()));
71     connect(ui->shape,
72             SIGNAL(currentIndexChanged(int)),
73             this, SLOT(shapeChanged()));
74 
75     refreshDisplay();
76 }
77 
~StyleEditor()78 StyleEditor::~StyleEditor()
79 {
80     delete ui;
81 }
82 
open()83 void StyleEditor::open() {
84     if (_styles != nullptr) delete _styles;
85     _styles = new TikzStyles;
86     _activeStyle = nullptr;
87     ui->styleListView->setModel(_styles->nodeStyles());
88     ui->edgeStyleListView->setModel(_styles->edgeStyles());
89     connect(ui->styleListView->selectionModel(),
90             SIGNAL(currentChanged(QModelIndex,QModelIndex)),
91             this, SLOT(nodeItemChanged(QModelIndex)));
92     connect(ui->edgeStyleListView->selectionModel(),
93             SIGNAL(currentChanged(QModelIndex,QModelIndex)),
94             this, SLOT(edgeItemChanged(QModelIndex)));
95 
96     if (_styles->loadStyles(tikzit->styleFilePath())) {
97         setDirty(false);
98         refreshCategories();
99         refreshDisplay();
100         show();
101     } else {
102         QMessageBox::warning(0,
103             "Bad style file.",
104             "Bad style file: '" + tikzit->styleFile() + "'. Check that the file exists and is properly formatted.");
105     }
106 }
107 
closeEvent(QCloseEvent * event)108 void StyleEditor::closeEvent(QCloseEvent *event)
109 {
110     if (dirty()) {
111         QMessageBox::StandardButton resBtn = QMessageBox::question(
112                     this, "Save Changes",
113                     "Do you wish to save changes to " + tikzit->styleFile() + "?",
114                     QMessageBox::Cancel | QMessageBox::No | QMessageBox::Yes,
115                     QMessageBox::Yes);
116 
117         if (resBtn == QMessageBox::Yes) {
118             save();
119             event->accept();
120         } else if (resBtn == QMessageBox::No) {
121             event->accept();
122         } else {
123             event->ignore();
124         }
125     } else {
126         event->accept();
127     }
128 }
129 
nodeItemChanged(QModelIndex sel)130 void StyleEditor::nodeItemChanged(QModelIndex sel)
131 {
132     //qDebug() << "nodeItemChanged, new index:" << sel.row();
133     if (sel.isValid()) {
134         ui->edgeStyleListView->selectionModel()->clear();
135         _activeStyle = _styles->nodeStyles()->styleInCategory(sel.row());
136     }
137     _nodeStyleIndex = sel;
138     refreshDisplay();
139 }
140 
edgeItemChanged(QModelIndex sel)141 void StyleEditor::edgeItemChanged(QModelIndex sel)
142 {
143     if (sel.isValid()) {
144         ui->styleListView->selectionModel()->clear();
145         _activeStyle = _styles->edgeStyles()->styleInCategory(sel.row());
146     }
147     _edgeStyleIndex = sel;
148     refreshDisplay();
149 }
150 
categoryChanged()151 void StyleEditor::categoryChanged()
152 {
153     Style *s = activeStyle();
154     QString cat = ui->category->currentText();
155     //qDebug() << "got category: " << cat;
156 
157     if (s != nullptr && s->data()->property("tikzit category") != cat) {
158         if (cat.isEmpty()) s->data()->unsetProperty("tikzit category");
159         else s->data()->setProperty("tikzit category", cat);
160         setDirty(true);
161         refreshCategories();
162 
163         if (_styles->nodeStyles()->category() != "") {
164             ui->currentCategory->setCurrentText(cat);
165             //qDebug() << "after cat change, cat reports:" << _styles->nodeStyles()->category();
166         }
167         //refreshDisplay();
168     }
169 }
170 
currentCategoryChanged()171 void StyleEditor::currentCategoryChanged()
172 {
173     if (_styles != nullptr) {
174         QString cat = ui->currentCategory->currentText();
175         if (cat != _styles->nodeStyles()->category()) {
176             ui->styleListView->selectionModel()->clear();
177             _styles->nodeStyles()->setCategory(cat);
178 
179             if (_activeStyle != nullptr && !_activeStyle->isEdgeStyle()) {
180                 for (int i = 0; i < _styles->nodeStyles()->numInCategory(); ++i) {
181                     if (_styles->nodeStyles()->styleInCategory(i) == _activeStyle) {
182                         ui->styleListView->selectionModel()->setCurrentIndex(
183                                     _styles->nodeStyles()->index(i),
184                                     QItemSelectionModel::ClearAndSelect);
185                         break;
186                     }
187                 }
188                 if (!_nodeStyleIndex.isValid()) _activeStyle = nullptr;
189             }
190         }
191     }
192 }
193 
shapeChanged()194 void StyleEditor::shapeChanged()
195 {
196     Style *s = activeStyle();
197     if (s != 0) {
198         s->data()->setProperty("shape", ui->shape->currentText());
199         refreshActiveStyle();
200         refreshDisplay();
201         setDirty(true);
202     }
203 }
204 
refreshCategories()205 void StyleEditor::refreshCategories()
206 {
207     ui->currentCategory->blockSignals(true);
208     ui->category->blockSignals(true);
209     QString curCat = ui->currentCategory->currentText();
210     QString cat = ui->category->currentText();
211     ui->currentCategory->clear();
212     ui->category->clear();
213 
214     if (_styles != nullptr) {
215         foreach(QString c, _styles->categories()) {
216             ui->category->addItem(c);
217             ui->currentCategory->addItem(c);
218         }
219     }
220 
221     ui->currentCategory->setCurrentText(curCat);
222     ui->category->setCurrentText(cat);
223     ui->currentCategory->blockSignals(false);
224     ui->category->blockSignals(false);
225 }
226 
propertyChanged()227 void StyleEditor::propertyChanged()
228 {
229     if (_nodeStyleIndex.isValid()) {
230         emit _styles->nodeStyles()->dataChanged(_nodeStyleIndex, _nodeStyleIndex);
231 
232         if (_activeStyle->category() != _styles->nodeStyles()->category()) {
233             refreshCategories();
234             if (_styles->nodeStyles()->category() != "")
235                 ui->currentCategory->setCurrentText(_activeStyle->category());
236         }
237     } else if (_edgeStyleIndex.isValid()) {
238         emit _styles->edgeStyles()->dataChanged(_edgeStyleIndex, _edgeStyleIndex);
239     }
240     setDirty(true);
241     refreshDisplay();
242 }
243 
refreshDisplay()244 void StyleEditor::refreshDisplay()
245 {
246     // enable all fields and block signals while we set their values
247     foreach (QWidget *w, _formWidgets) {
248         w->blockSignals(true);
249     }
250 
251     // set to default values
252     ui->name->setText("none");
253     ui->category->setCurrentText("");
254     //ui->category->clear();
255 
256     setColor(ui->fillColor, QColor(Qt::gray));
257     setColor(ui->drawColor, QColor(Qt::gray));
258     setColor(ui->tikzitFillColor, QColor(Qt::gray));
259     setColor(ui->tikzitDrawColor, QColor(Qt::gray));
260     ui->hasTikzitDrawColor->setChecked(false);
261     ui->hasTikzitFillColor->setChecked(false);
262     ui->shape->setCurrentText("");
263     ui->hasTikzitShape->setChecked(false);
264     ui->tikzitShape->setCurrentText("");
265     ui->leftArrow->setCurrentText("");
266     ui->rightArrow->setCurrentText("");
267     ui->properties->setModel(0);
268 
269     Style *s = activeStyle();
270 
271 //    qDebug() << "style" << s;
272     if (s != nullptr && !s->isNone()) {
273 //        qDebug() << "non-null style update";
274 
275         // name
276         ui->name->setEnabled(true);
277         ui->name->setText(s->name());
278 
279         // property list
280         ui->properties->setEnabled(true);
281         setPropertyModel(s->data());
282 
283         // draw
284         QColor realDraw = s->strokeColor(false);
285         QColor draw = s->strokeColor();
286 
287         ui->noDraw->setEnabled(true);
288         if (s->hasStroke()) {
289             ui->drawColor->setEnabled(true);
290             setColor(ui->drawColor, realDraw);
291             ui->noDraw->setChecked(false);
292         } else {
293             ui->noDraw->setChecked(true);
294             ui->drawColor->setEnabled(false);
295         }
296 
297         // tikzit draw
298         bool drawOverride = s->data()->hasProperty("tikzit draw");
299         ui->hasTikzitDrawColor->setEnabled(true);
300         ui->hasTikzitDrawColor->setChecked(drawOverride);
301 
302         ui->tikzitDrawColor->setEnabled(drawOverride);
303         if (drawOverride) setColor(ui->tikzitDrawColor, draw);
304 
305         // fill
306         QColor realFill = s->fillColor(false);
307         QColor fill = s->fillColor();
308 
309         ui->noFill->setEnabled(true);
310         if (s->hasFill()) {
311             ui->fillColor->setEnabled(true);
312             setColor(ui->fillColor, realFill);
313             ui->noFill->setChecked(false);
314         } else {
315             ui->noFill->setChecked(true);
316             ui->fillColor->setEnabled(false);
317         }
318 
319         // tikzit fill
320         bool fillOverride = s->data()->hasProperty("tikzit fill");
321         ui->hasTikzitFillColor->setEnabled(true);
322         ui->hasTikzitFillColor->setChecked(fillOverride);
323         ui->tikzitFillColor->setEnabled(fillOverride);
324         if (fillOverride) setColor(ui->tikzitFillColor, fill);
325 
326         if (!s->isEdgeStyle()) {
327 //            qDebug() << "node style update";
328             // category
329             ui->category->setEnabled(true);
330             ui->category->setCurrentText(
331                 s->propertyWithDefault("tikzit category", "", false));
332 
333             // shape
334             QString realShape = s->propertyWithDefault("shape", "", false);
335             QString shape = s->propertyWithDefault("tikzit shape", "", false);
336             ui->shape->setEnabled(true);
337             ui->shape->setCurrentText(realShape);
338 
339             // tikzit shape
340             bool shapeOverride = s->data()->hasProperty("tikzit shape");
341             ui->hasTikzitShape->setEnabled(true);
342             ui->hasTikzitShape->setChecked(shapeOverride);
343             ui->tikzitShape->setEnabled(shapeOverride);
344             if (shapeOverride) ui->tikzitShape->setCurrentText(shape);
345         } else {
346             ui->shape->setEnabled(false);
347             ui->tikzitShape->setEnabled(false);
348             ui->hasTikzitShape->setEnabled(false);
349 
350 
351             // arrow tail
352             ui->leftArrow->setEnabled(true);
353 
354             switch (s->arrowTail()) {
355             case Style::NoTip:
356                 ui->leftArrow->setCurrentText("");
357                 break;
358             case Style::Pointer:
359                 ui->leftArrow->setCurrentText("<");
360                 break;
361             case Style::Flat:
362                 ui->leftArrow->setCurrentText("|");
363                 break;
364             }
365 
366             // arrow head
367             ui->rightArrow->setEnabled(true);
368             switch (s->arrowHead()) {
369             case Style::NoTip:
370                 ui->rightArrow->setCurrentText("");
371                 break;
372             case Style::Pointer:
373                 ui->rightArrow->setCurrentText(">");
374                 break;
375             case Style::Flat:
376                 ui->rightArrow->setCurrentText("|");
377                 break;
378             }
379         }
380 
381     } else {
382 //        qDebug() << "null style update";
383 
384         foreach (QWidget *w, _formWidgets) {
385             w->setEnabled(false);
386         }
387     }
388 
389     // unblock signals so we are ready for user input
390     foreach (QWidget *w, _formWidgets) {
391         w->blockSignals(false);
392     }
393 }
394 
on_fillColor_clicked()395 void StyleEditor::on_fillColor_clicked()
396 {
397     updateColor(ui->fillColor, "Fill Color", "fill");
398 }
399 
on_drawColor_clicked()400 void StyleEditor::on_drawColor_clicked()
401 {
402     updateColor(ui->drawColor, "Draw Color", "draw");
403 }
404 
on_tikzitFillColor_clicked()405 void StyleEditor::on_tikzitFillColor_clicked()
406 {
407     updateColor(ui->tikzitFillColor, "TikZiT Fill Color", "tikzit fill");
408 }
409 
on_tikzitDrawColor_clicked()410 void StyleEditor::on_tikzitDrawColor_clicked()
411 {
412     updateColor(ui->tikzitDrawColor, "TikZiT Draw Color", "tikzit draw");
413 }
414 
on_hasTikzitFillColor_stateChanged(int state)415 void StyleEditor::on_hasTikzitFillColor_stateChanged(int state)
416 {
417     Style *s = activeStyle();
418     if (s != nullptr) {
419         if (state == Qt::Checked) s->data()->setProperty("tikzit fill", s->data()->property("fill"));
420         else s->data()->unsetProperty("tikzit fill");
421         refreshDisplay();
422         setDirty(true);
423     }
424 }
425 
on_hasTikzitDrawColor_stateChanged(int state)426 void StyleEditor::on_hasTikzitDrawColor_stateChanged(int state)
427 {
428     Style *s = activeStyle();
429     if (s != nullptr) {
430         if (state == Qt::Checked) s->data()->setProperty("tikzit draw", s->data()->property("draw"));
431         else s->data()->unsetProperty("tikzit draw");
432         refreshDisplay();
433         setDirty(true);
434     }
435 }
436 
on_noFill_stateChanged(int state)437 void StyleEditor::on_noFill_stateChanged(int state)
438 {
439     Style *s = activeStyle();
440     if (s != nullptr) {
441         if (state == Qt::Checked) s->data()->setProperty("fill", "none");
442         else s->data()->setProperty("fill", "white");
443         refreshActiveStyle();
444         refreshDisplay();
445         setDirty(true);
446     }
447 }
448 
on_noDraw_stateChanged(int state)449 void StyleEditor::on_noDraw_stateChanged(int state)
450 {
451     Style *s = activeStyle();
452     if (s != nullptr) {
453         if (state == Qt::Checked) s->data()->setProperty("draw", "none");
454         else s->data()->setProperty("draw", "black");
455         refreshActiveStyle();
456         refreshDisplay();
457         setDirty(true);
458     }
459 }
460 
on_hasTikzitShape_stateChanged(int state)461 void StyleEditor::on_hasTikzitShape_stateChanged(int state)
462 {
463     Style *s = activeStyle();
464     if (s != nullptr) {
465         if (state == Qt::Checked) s->data()->setProperty("tikzit shape", s->data()->property("shape"));
466         else s->data()->unsetProperty("tikzit shape");
467         refreshDisplay();
468         setDirty(true);
469     }
470 }
471 
on_tikzitShape_currentIndexChanged(int)472 void StyleEditor::on_tikzitShape_currentIndexChanged(int)
473 {
474     Style *s = activeStyle();
475     if (s != nullptr) {
476         s->data()->setProperty("tikzit shape", ui->tikzitShape->currentText());
477         refreshActiveStyle();
478         refreshDisplay();
479         setDirty(true);
480     }
481 }
482 
on_leftArrow_currentIndexChanged(int)483 void StyleEditor::on_leftArrow_currentIndexChanged(int)
484 {
485     Style *s = activeStyle();
486     if (s != nullptr) {
487         s->setArrowAtom(ui->leftArrow->currentText() + "-" +
488                         ui->rightArrow->currentText());
489         refreshActiveStyle();
490         refreshDisplay();
491         setDirty(true);
492     }
493 }
494 
on_rightArrow_currentIndexChanged(int)495 void StyleEditor::on_rightArrow_currentIndexChanged(int)
496 {
497     Style *s = activeStyle();
498     if (s != nullptr) {
499         s->setArrowAtom(ui->leftArrow->currentText() + "-" +
500                         ui->rightArrow->currentText());
501         refreshActiveStyle();
502         refreshDisplay();
503         setDirty(true);
504     }
505 }
506 
on_addProperty_clicked()507 void StyleEditor::on_addProperty_clicked()
508 {
509     Style *s = activeStyle();
510     if (s != nullptr) {
511         s->data()->add(GraphElementProperty("new property", ""));
512         setDirty(true);
513     }
514 }
515 
on_addAtom_clicked()516 void StyleEditor::on_addAtom_clicked()
517 {
518     Style *s = activeStyle();
519     if (s != 0) {
520         s->data()->add(GraphElementProperty("new atom"));
521         setDirty(true);
522     }
523 }
524 
on_removeProperty_clicked()525 void StyleEditor::on_removeProperty_clicked()
526 {
527     Style *s = activeStyle();
528     if (s != 0) {
529         QModelIndexList sel = ui->properties->selectionModel()->selectedRows();
530         if (!sel.isEmpty()) {
531             s->data()->removeRows(sel[0].row(), 1, sel[0].parent());
532             setDirty(true);
533         }
534     }
535 }
536 
on_propertyUp_clicked()537 void StyleEditor::on_propertyUp_clicked()
538 {
539     Style *s = activeStyle();
540     if (s != 0) {
541         QModelIndexList sel = ui->properties->selectionModel()->selectedRows();
542         if (!sel.isEmpty()) {
543             s->data()->moveRows(
544                     sel[0].parent(),
545                     sel[0].row(), 1,
546                     sel[0].parent(),
547                     sel[0].row() - 1);
548             setDirty(true);
549         }
550     }
551 }
552 
on_propertyDown_clicked()553 void StyleEditor::on_propertyDown_clicked()
554 {
555     Style *s = activeStyle();
556     if (s != 0) {
557         QModelIndexList sel = ui->properties->selectionModel()->selectedRows();
558         if (!sel.isEmpty()) {
559             s->data()->moveRows(
560                     sel[0].parent(),
561                     sel[0].row(), 1,
562                     sel[0].parent(),
563                     sel[0].row() + 2);
564             setDirty(true);
565         }
566     }
567 }
568 
on_addStyle_clicked()569 void StyleEditor::on_addStyle_clicked()
570 {
571     int i = 0;
572 
573     // get a fresh name
574     QString name;
575     while (true) {
576         name = QString("new style ") + QString::number(i);
577         if (_styles->nodeStyles()->style(name) == nullptr) break;
578         ++i;
579     }
580 
581     // add the style to the current category
582     Style *s;
583     if (_styles->nodeStyles()->category() == "") {
584         s = new Style(name, new GraphElementData({
585           GraphElementProperty("fill", "white"),
586           GraphElementProperty("draw", "black"),
587           GraphElementProperty("shape", "circle")
588         }));
589     } else {
590         s = new Style(name, new GraphElementData({
591           GraphElementProperty("fill", "white"),
592           GraphElementProperty("draw", "black"),
593           GraphElementProperty("shape", "circle"),
594           GraphElementProperty("category", _styles->nodeStyles()->category()),
595         }));
596     }
597     _styles->nodeStyles()->addStyle(s);
598 
599     // set dirty flag and select the newly-added style
600     setDirty(true);
601     selectNodeStyle(_styles->nodeStyles()->numInCategory()-1);
602 }
603 
on_removeStyle_clicked()604 void StyleEditor::on_removeStyle_clicked()
605 {
606     if (_nodeStyleIndex.isValid()) {
607         int i = _nodeStyleIndex.row();
608         if (i > 0) {
609             ui->styleListView->selectionModel()->clear();
610             _styles->nodeStyles()->removeNthStyle(i);
611             setDirty(true);
612             if (i < _styles->nodeStyles()->numInCategory()) {
613                 selectNodeStyle(i);
614             }
615         }
616     }
617 }
618 
on_styleUp_clicked()619 void StyleEditor::on_styleUp_clicked()
620 {
621     if (_nodeStyleIndex.isValid()) {
622         int r = _nodeStyleIndex.row();
623         if (_styles->nodeStyles()->moveRows(
624                     _nodeStyleIndex.parent(),
625                     r, 1,
626                     _nodeStyleIndex.parent(),
627                     r - 1))
628         {
629             setDirty(true);
630             nodeItemChanged(_styles->nodeStyles()->index(r - 1));
631         }
632     }
633 }
634 
on_styleDown_clicked()635 void StyleEditor::on_styleDown_clicked()
636 {
637     if (_nodeStyleIndex.isValid()) {
638         int r = _nodeStyleIndex.row();
639         if (_styles->nodeStyles()->moveRows(
640                     _nodeStyleIndex.parent(),
641                     r, 1,
642                     _nodeStyleIndex.parent(),
643                     r + 2))
644         {
645             setDirty(true);
646             nodeItemChanged(_styles->nodeStyles()->index(r + 1));
647         }
648     }
649 }
650 
on_addEdgeStyle_clicked()651 void StyleEditor::on_addEdgeStyle_clicked()
652 {
653     int i = 0;
654 
655     // get a fresh name
656     QString name;
657     while (true) {
658         name = QString("new edge style ") + QString::number(i);
659         if (_styles->edgeStyles()->style(name) == nullptr) break;
660         ++i;
661     }
662 
663     // add the style (edge styles only have one category: "")
664     Style *s = new Style(name, new GraphElementData({GraphElementProperty("-")}));
665     _styles->edgeStyles()->addStyle(s);
666 
667     // set dirty flag and select the newly-added style
668     setDirty(true);
669     selectEdgeStyle(_styles->edgeStyles()->numInCategory()-1);
670 }
671 
on_removeEdgeStyle_clicked()672 void StyleEditor::on_removeEdgeStyle_clicked()
673 {
674     if (_edgeStyleIndex.isValid()) {
675         int i = _edgeStyleIndex.row();
676         if (i > 0) {
677             ui->edgeStyleListView->selectionModel()->clear();
678             _styles->edgeStyles()->removeNthStyle(i);
679             setDirty(true);
680             if (i < _styles->edgeStyles()->numInCategory()) {
681                 selectEdgeStyle(i);
682             }
683         }
684     }
685 }
686 
on_edgeStyleUp_clicked()687 void StyleEditor::on_edgeStyleUp_clicked()
688 {
689     if (_edgeStyleIndex.isValid()) {
690         int r = _edgeStyleIndex.row();
691         if (_styles->edgeStyles()->moveRows(
692                     _edgeStyleIndex.parent(),
693                     r, 1,
694                     _edgeStyleIndex.parent(),
695                     r - 1))
696         {
697             setDirty(true);
698             edgeItemChanged(_styles->edgeStyles()->index(r - 1));
699         }
700     }
701 }
702 
on_edgeStyleDown_clicked()703 void StyleEditor::on_edgeStyleDown_clicked()
704 {
705     if (_edgeStyleIndex.isValid()) {
706         int r = _edgeStyleIndex.row();
707         if (_styles->edgeStyles()->moveRows(
708                     _edgeStyleIndex.parent(),
709                     r, 1,
710                     _edgeStyleIndex.parent(),
711                     r + 2))
712         {
713             setDirty(true);
714             edgeItemChanged(_styles->edgeStyles()->index(r + 1));
715         }
716     }
717 }
718 
on_save_clicked()719 void StyleEditor::on_save_clicked()
720 {
721     save();
722     close();
723 }
724 
on_currentCategory_currentIndexChanged(int)725 void StyleEditor::on_currentCategory_currentIndexChanged(int)
726 {
727     currentCategoryChanged();
728 }
729 
730 
save()731 void StyleEditor::save()
732 {
733     QString p = tikzit->styleFilePath();
734 
735     if (_styles->saveStyles(p)) {
736         setDirty(false);
737         tikzit->loadStyles(p);
738     } else {
739         QMessageBox::warning(0,
740             "Unabled to save style file",
741             "Unable to write to file: '" + tikzit->styleFile() + "'.");
742     }
743 }
744 
on_styleListView_clicked()745 void StyleEditor::on_styleListView_clicked()
746 {
747 }
748 
on_edgeStyleListView_clicked()749 void StyleEditor::on_edgeStyleListView_clicked()
750 {
751 }
752 
on_name_editingFinished()753 void StyleEditor::on_name_editingFinished()
754 {
755     Style *s = activeStyle();
756 
757     if (s != 0) {
758         s->setName(ui->name->text());
759         refreshActiveStyle();
760 //        refreshDisplay();
761         setDirty(true);
762     }
763 }
764 
765 
setColor(QPushButton * btn,QColor col)766 void StyleEditor::setColor(QPushButton *btn, QColor col)
767 {
768     QPalette pal = btn->palette();
769     pal.setColor(QPalette::Button, col);
770     btn->setPalette(pal);
771     btn->update();
772 }
773 
setPropertyModel(GraphElementData * d)774 void StyleEditor::setPropertyModel(GraphElementData *d)
775 {
776     if (ui->properties->model() != 0) {
777         disconnect(ui->properties->model(), SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
778                    this, SLOT(propertyChanged()));
779     }
780     ui->properties->setModel(d);
781     connect(d, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
782             this, SLOT(propertyChanged()));
783 }
784 
color(QPushButton * btn)785 QColor StyleEditor::color(QPushButton *btn)
786 {
787     QPalette pal = btn->palette();
788     return pal.color(QPalette::Button);
789 }
790 
activeStyle()791 Style *StyleEditor::activeStyle()
792 {
793 //    if (_styles != nullptr) {
794 //        if (_nodeStyleIndex.isValid())
795 //            return _styles->nodeStyles()->styleInCategory(_nodeStyleIndex.row());
796 
797 //        if (_edgeStyleIndex.isValid())
798 //            return _styles->edgeStyles()->styleInCategory(_edgeStyleIndex.row());
799 //    }
800 
801     return _activeStyle;
802 }
803 
refreshActiveStyle()804 void StyleEditor::refreshActiveStyle()
805 {
806     if (_styles != nullptr) {
807         if (_nodeStyleIndex.isValid()) {
808             emit _styles->nodeStyles()->dataChanged(_nodeStyleIndex, _nodeStyleIndex);
809 
810             // force a re-layout
811             ui->styleListView->setGridSize(QSize(48,48));
812         }
813 
814         if (_edgeStyleIndex.isValid()) {
815             emit _styles->edgeStyles()->dataChanged(_edgeStyleIndex, _edgeStyleIndex);
816 
817             // force a re-layout
818             ui->edgeStyleListView->setGridSize(QSize(48,48));
819         }
820     }
821 }
822 
updateColor(QPushButton * btn,QString name,QString propName)823 void StyleEditor::updateColor(QPushButton *btn, QString name, QString propName)
824 {
825     QColor col = QColorDialog::getColor(
826                 color(btn),
827                 this,
828                 name,
829                 QColorDialog::DontUseNativeDialog);
830     if (col.isValid()) {
831         setColor(btn, col);
832         Style *s = activeStyle();
833         if (s != nullptr) {
834             s->data()->setProperty(propName, tikzit->nameForColor(col));
835             refreshActiveStyle();
836             refreshDisplay();
837             setDirty(true);
838         }
839     }
840 }
841 
selectNodeStyle(int i)842 void StyleEditor::selectNodeStyle(int i)
843 {
844     ui->styleListView->selectionModel()->setCurrentIndex(
845                 _styles->nodeStyles()->index(i),
846                 QItemSelectionModel::ClearAndSelect);
847 }
848 
selectEdgeStyle(int i)849 void StyleEditor::selectEdgeStyle(int i)
850 {
851     ui->edgeStyleListView->selectionModel()->setCurrentIndex(
852                 _styles->edgeStyles()->index(i),
853                 QItemSelectionModel::ClearAndSelect);
854 }
855 
dirty() const856 bool StyleEditor::dirty() const
857 {
858     return _dirty;
859 }
860 
setDirty(bool dirty)861 void StyleEditor::setDirty(bool dirty)
862 {
863     _dirty = dirty;
864     if (dirty) {
865         setWindowTitle("Style Editor* - TikZiT");
866     } else {
867         setWindowTitle("Style Editor - TikZiT");
868     }
869 }
870