]> git.lyx.org Git - features.git/blob - src/frontends/qt/BulletsModule.cpp
BulletsModule: disable size widget with custom bullet (#12011)
[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                 bulletsizeCO->setEnabled(false);
231                 sizeL->setEnabled(false);
232         } else {
233                 customCB->setCheckState(Qt::Unchecked);
234                 customLE->clear();
235                 current_char_ = bullets_[level].getCharacter();
236                 selectItem(current_font_, current_char_, true);
237                 bulletpaneCO->setCurrentIndex(current_font_);
238                 bulletpaneSW->setCurrentIndex(current_font_);
239                 bulletsizeCO->setEnabled(true);
240                 sizeL->setEnabled(true);
241         }
242         bulletsizeCO->setCurrentIndex(bullets_[level].getSize() + 1);
243 }
244
245
246 void BulletsModule::init()
247 {
248         levelLW->setCurrentRow(0);
249         showLevel(0);
250 }
251
252
253 void BulletsModule::bulletSelected(QListWidgetItem * item, QListWidgetItem *)
254 {
255         // unselect previous item
256         selectItem(current_font_, current_char_, false);
257
258         int const level = levelLW->currentRow();
259         bullets_[level].setCharacter(item->type());
260         bullets_[level].setFont(bulletpaneCO->currentIndex());
261         current_font_ = bulletpaneCO->currentIndex();
262         current_char_ = item->type();
263         changed();
264 }
265
266
267 void BulletsModule::on_customCB_clicked(bool custom)
268 {
269         bulletsizeCO->setEnabled(!custom);
270         sizeL->setEnabled(!custom);
271
272         if (!custom) {
273                 if (current_font_ < 0)
274                         current_font_ = bulletpaneCO->currentIndex();
275                 return;
276         }
277
278         // unselect previous item
279         selectItem(current_font_, current_char_, false);
280         current_font_ = -1;
281         changed();
282 }
283
284
285 void BulletsModule::selectItem(int font, int character, bool select)
286 {
287         if (font < 0)
288                 return;
289
290         QListWidget * lw = static_cast<QListWidget *>(bulletpaneSW->widget(font));
291         lw->item(character)->setSelected(select);
292 }
293
294
295 void BulletsModule::on_customLE_textEdited(const QString & text)
296 {
297         if (customCB->checkState() == Qt::Unchecked)
298                 return;
299
300         bullets_[levelLW->currentRow()].setFont(current_font_);
301         bullets_[levelLW->currentRow()].setText(qstring_to_ucs4(text));
302         changed();
303 }
304
305
306 void BulletsModule::on_bulletsizeCO_activated(int size)
307 {
308         // -1 apparently means default...
309         bullets_[levelLW->currentRow()].setSize(size - 1);
310         changed();
311 }
312
313
314 void BulletsModule::setBullet(int level, Bullet const & bullet)
315 {
316         bullets_[level] = bullet;
317 }
318
319
320 Bullet const & BulletsModule::bullet(int level) const
321 {
322         return bullets_[level];
323 }
324
325 } // namespace frontend
326
327 } // namespace lyx
328
329
330 #include "moc_BulletsModule.cpp"