]> git.lyx.org Git - features.git/blob - src/frontends/qt/BulletsModule.cpp
Use SVG icons in itemize bullet selector
[features.git] / src / frontends / qt / BulletsModule.cpp
1 /**
2  * \file BulletsModule.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Edwin Leuven
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "Bullet.h"
14
15 #include "BulletsModule.h"
16 #include "GuiApplication.h"
17 #include "qt_helpers.h"
18
19 #include <QBitmap>
20 #include <QPixmap>
21 #include <QPainter>
22 #include <QScrollBar>
23
24 using namespace std;
25
26 namespace lyx {
27
28 namespace frontend {
29
30 int const CHARMAX = 36;
31 int const FONTMAX = 6;
32
33 BulletsModule::BulletsModule(QWidget * parent)
34     : QWidget(parent)
35 {
36         setupUi(this);
37
38         for (int iter = 0; iter < 4; ++iter)
39                 bullets_[iter] = ITEMIZE_DEFAULTS[iter];
40
41         current_font_ = -1;
42         current_char_ = 0;
43
44         // add levels
45         levelLW->addItem("1");
46         levelLW->addItem("2");
47         levelLW->addItem("3");
48         levelLW->addItem("4");
49
50         // insert pixmaps
51         setupPanel(new QListWidget(bulletpaneSW), qt_("Standard[[Bullets]]"), 0);
52         setupPanel(new QListWidget(bulletpaneSW), qt_("Maths"), 1, "math");
53         setupPanel(new QListWidget(bulletpaneSW), qt_("Dings 1"), 2);
54         setupPanel(new QListWidget(bulletpaneSW), qt_("Dings 2"), 3);
55         setupPanel(new QListWidget(bulletpaneSW), qt_("Dings 3"), 4);
56         setupPanel(new QListWidget(bulletpaneSW), qt_("Dings 4"), 5);
57
58         connect(levelLW, SIGNAL(currentRowChanged(int)),
59                 this, SLOT(showLevel(int)));
60         connect(bulletpaneCO, SIGNAL(activated(int)), bulletpaneSW,
61                 SLOT(setCurrentIndex(int)));
62 }
63
64
65 string const bulletIcon(int f, int c)
66 {
67         static char const * BulletPanelIcons0[CHARMAX] = {
68                 /* standard */
69                 "bfendash", "vdash", "dashv", "flat", "natural",
70                 "sharp", "ast", "star", "bullet", "circ", "cdot",
71                 "dagger", "bigtriangleup", "bigtriangledown", "triangleleft",
72                 "triangleright", "lhd", "rhd", "oplus", "ominus", "otimes",
73                 "oslash", "odot", "spadesuit", "diamond", "diamond2", "box",
74                 "diamondsuit", "heartsuit",  "clubsuit", "rightarrow", "leadsto",
75                 "rightharpoonup", "rightharpoondown", "rightarrow2", "succ"
76         };
77         static char const * BulletPanelIcons1[CHARMAX] = {
78                 /* amssymb */
79                 "Rrightarrow", "rightarrowtail", "twoheadrightarrow", "rightsquigarrow",
80                 "looparrowright", "multimap", "boxtimes", "boxplus", "boxminus",
81                 "boxdot", "divideontimes", "Vvdash", "lessdot", "gtrdot", "maltese",
82                 "bigstar", "checkmark", "vdash2", "backsim", "thicksim",
83                 "centerdot", "circleddash", "circledast", "circledcirc",
84                 "vartriangleleft", "vartriangleright", "vartriangle", "triangledown",
85                 "lozenge", "square", "blacktriangleleft", "blacktriangleright", "blacktriangle",
86                 "blacktriangledown", "blacklozenge", "blacksquare"
87         };
88         static char const * BulletPanelIcons2[CHARMAX] = {
89                 /* psnfss1 */
90                 "ding108", "ding109", "ding119", "pisymbol_psy197",
91                 "pisymbol_psy196", "pisymbol_psy183", "ding71", "ding70",
92                 "ding118", "ding117", "pisymbol_psy224", "pisymbol_psy215",
93                 "ding111", "ding112", "ding113", "ding114",
94                 "pisymbol_psy68", "pisymbol_psy209", "ding120", "ding121",
95                 "ding122", "ding110", "ding115", "ding116",
96                 "pisymbol_psy42", "ding67", "ding66", "ding82",
97                 "ding81", "ding228", "ding162", "ding163",
98                 "ding166", "ding167", "ding226", "ding227"
99         };
100         static char const * BulletPanelIcons3[CHARMAX] = {
101                 /* psnfss2 */
102                 "ding37", "ding38", "ding34", "ding36",
103                 "ding39", "ding40", "ding41", "ding42",
104                 "ding43", "ding44", "ding45", "ding47",
105                 "ding53", "ding54", "ding59", "ding57",
106                 "ding62", "ding61", "ding55", "ding56",
107                 "ding58", "ding60", "ding63", "ding64",
108                 "ding51", "ding52", "pisymbol_psy170", "pisymbol_psy167",
109                 "pisymbol_psy168", "pisymbol_psy169",  "ding164", "ding165",
110                 "ding171", "ding168", "ding169", "ding170"
111         };
112         static char const * BulletPanelIcons4[CHARMAX] = {
113                 /* psnfss3 */
114                 "ding65", "ding76", "ding75", "ding72",
115                 "ding80", "ding74", "ding78", "ding77",
116                 "ding79", "ding85", "ding90", "ding98",
117                 "ding83", "ding84", "ding86", "ding87",
118                 "ding88", "ding89", "ding92", "ding91",
119                 "ding93", "ding105", "ding94", "ding99",
120                 "ding103", "ding104", "ding106", "ding107",
121                 "ding68", "ding69", "ding100", "ding101",
122                 "ding102", "ding96", "ding95", "ding97"
123         };
124         static char const * BulletPanelIcons5[CHARMAX] = {
125                 /* psnfss4 */
126                 "ding223", "ding224", "ding225", "ding232",
127                 "ding229", "ding230", "ding238", "ding237",
128                 "ding236", "ding235", "ding234", "ding233",
129                 "ding239", "ding241", "ding250", "ding251",
130                 "ding49", "ding50", "ding217", "ding245",
131                 "ding243", "ding248", "ding252", "ding253",
132                 "ding219", "ding213", "ding221", "ding222",
133                 "ding220", "ding212", "pisymbol_psy174", "pisymbol_psy222",
134                 "ding254", "ding242", "ding231", "pisymbol_psy45"
135         };
136
137         static char const ** BulletPanelIcons[FONTMAX] = {
138                 BulletPanelIcons0, BulletPanelIcons1,
139                 BulletPanelIcons2, BulletPanelIcons3,
140                 BulletPanelIcons4, BulletPanelIcons5
141         };
142
143         return BulletPanelIcons[f][c];
144 }
145
146
147 QPixmap getSelectedPixmap(QPixmap pixmap, QSize const icon_size)
148 {
149         QPalette palette = QPalette();
150         QColor text_color = (guiApp->isInDarkMode())
151                         ? palette.color(QPalette::Active, QPalette::WindowText)
152                         : Qt::black;
153         QColor highlight_color = palette.color(QPalette::Active, QPalette::HighlightedText);
154         QColor highlight_bg = palette.color(QPalette::Active, QPalette::Highlight);
155
156         // create a layer with black text turned to QPalette::HighlightedText
157         QPixmap hl_overlay(pixmap.size());
158         hl_overlay.fill(highlight_color);
159         hl_overlay.setMask(pixmap.createMaskFromColor(text_color, Qt::MaskOutColor));
160
161         // Create highlighted background
162         QPixmap hl_background(icon_size);
163         hl_background.fill(highlight_bg);
164
165         // put layers on top of existing pixmap
166         QPainter painter(&pixmap);
167         painter.drawPixmap(pixmap.rect(), hl_background);
168         painter.drawPixmap(pixmap.rect(), hl_overlay);
169
170         return pixmap;
171 }
172
173
174 void BulletsModule::setupPanel(QListWidget * lw, QString const & panelname,
175         int const font, string const folder)
176 {
177         connect(lw, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)),
178                 this, SLOT(bulletSelected(QListWidgetItem *, QListWidgetItem*)));
179
180         // add panelname to combox
181         bulletpaneCO->addItem(panelname);
182
183         lw->setViewMode(QListView::IconMode);
184         lw->setDragDropMode(QAbstractItemView::NoDragDrop);
185         lw->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
186         lw->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
187         lw->setFlow(QListView::LeftToRight);
188         lw->setSpacing(12);
189         lw->setUniformItemSizes(true);
190
191         QSize icon_size(26, 26);
192         lw->setIconSize(icon_size);
193
194         // we calculate the appropriate width to fit 6 icons in a row
195         lw->setFixedWidth((6 * (icon_size.width() + lw->spacing()))
196                                 + (lw->frameWidth() * 2)
197                                 + lw->verticalScrollBar()->height());
198         // and six rows
199         lw->setFixedHeight((6 * (icon_size.height() + lw->spacing()))
200                                 + (lw->frameWidth() * 2)
201                                 + lw->horizontalScrollBar()->height());
202
203         for (int i = 0; i < CHARMAX; ++i) {
204                 string const iconname = bulletIcon(font, i);
205                 // get pixmap with bullets
206                 QPixmap pixmap = getPixmap("images/" + toqstr(folder) + "/", toqstr(iconname), "svgz");
207                 QIcon icon(pixmap);
208                 icon.addPixmap(getSelectedPixmap(pixmap, icon_size), QIcon::Selected);
209                 QListWidgetItem * lwi = new QListWidgetItem(icon, QString());
210                 lwi->setToolTip(toqstr(Bullet::bulletEntry(font, i)));
211                 lwi->setSizeHint(icon_size);
212                 lw->addItem(lwi);
213         }
214
215         // add bulletpanel to stackedwidget
216         bulletpaneSW->addWidget(lw);
217 }
218
219
220 void BulletsModule::showLevel(int level)
221 {
222         // unselect previous item
223         selectItem(current_font_, current_char_, false);
224
225         current_font_ = bullets_[level].getFont();
226
227         if (bullets_[level].getFont() < 0) {
228                 customCB->setCheckState(Qt::Checked);
229                 customLE->setText(toqstr(bullets_[level].getText()));
230         } else {
231                 customCB->setCheckState(Qt::Unchecked);
232                 customLE->clear();
233                 current_char_ = bullets_[level].getCharacter();
234                 selectItem(current_font_, current_char_, true);
235                 bulletpaneCO->setCurrentIndex(current_font_);
236                 bulletpaneSW->setCurrentIndex(current_font_);
237         }
238         bulletsizeCO->setCurrentIndex(bullets_[level].getSize() + 1);
239 }
240
241
242 void BulletsModule::init()
243 {
244         levelLW->setCurrentRow(0);
245         showLevel(0);
246 }
247
248
249 void BulletsModule::bulletSelected(QListWidgetItem * item, QListWidgetItem *)
250 {
251         // unselect previous item
252         selectItem(current_font_, current_char_, false);
253
254         int const level = levelLW->currentRow();
255         bullets_[level].setCharacter(item->type());
256         bullets_[level].setFont(bulletpaneCO->currentIndex());
257         current_font_ = bulletpaneCO->currentIndex();
258         current_char_ = item->type();
259         changed();
260 }
261
262
263 void BulletsModule::on_customCB_clicked(bool custom)
264 {
265         if (!custom) {
266                 if (current_font_ < 0)
267                         current_font_ = bulletpaneCO->currentIndex();
268                 return;
269         }
270
271         // unselect previous item
272         selectItem(current_font_, current_char_, false);
273         current_font_ = -1;
274         changed();
275 }
276
277
278 void BulletsModule::selectItem(int font, int character, bool select)
279 {
280         if (font < 0)
281                 return;
282
283         QListWidget * lw = static_cast<QListWidget *>(bulletpaneSW->widget(font));
284         lw->item(character)->setSelected(select);
285 }
286
287
288 void BulletsModule::on_customLE_textEdited(const QString & text)
289 {
290         if (customCB->checkState() == Qt::Unchecked)
291                 return;
292
293         bullets_[levelLW->currentRow()].setFont(current_font_);
294         bullets_[levelLW->currentRow()].setText(qstring_to_ucs4(text));
295         changed();
296 }
297
298
299 void BulletsModule::on_bulletsizeCO_activated(int size)
300 {
301         // -1 apparently means default...
302         bullets_[levelLW->currentRow()].setSize(size - 1);
303         changed();
304 }
305
306
307 void BulletsModule::setBullet(int level, Bullet const & bullet)
308 {
309         bullets_[level] = bullet;
310 }
311
312
313 Bullet const & BulletsModule::bullet(int level) const
314 {
315         return bullets_[level];
316 }
317
318 } // namespace frontend
319
320 } // namespace lyx
321
322
323 #include "moc_BulletsModule.cpp"