]> git.lyx.org Git - lyx.git/blob - src/frontends/qt/GuiBranches.cpp
Allow semantic colors in branches and use semantic background color by default
[lyx.git] / src / frontends / qt / GuiBranches.cpp
1 /**
2  * \file GuiBranches.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  * \author Abdelrazak Younes
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "GuiBranches.h"
15
16 #include "ColorCache.h"
17 #include "GuiApplication.h"
18 #include "Validator.h"
19 #include "qt_helpers.h"
20
21 #include "ui_BranchesUnknownUi.h"
22
23 #include "frontends/alert.h"
24
25 #include "Buffer.h"
26 #include "BufferParams.h"
27
28 #include "support/gettext.h"
29 #include "support/lstrings.h"
30
31 #include <QKeyEvent>
32 #include <QListWidget>
33 #include <QTreeWidget>
34 #include <QTreeWidgetItem>
35 #include <QPixmap>
36 #include <QIcon>
37 #include <QColor>
38 #include <QColorDialog>
39
40 #ifdef KeyPress
41 #undef KeyPress
42 #endif
43
44 namespace lyx {
45 namespace frontend {
46
47
48 GuiBranches::GuiBranches(QWidget * parent)
49         : QWidget(parent)
50 {
51         setupUi(this);
52         branchesTW->setColumnCount(3);
53         branchesTW->headerItem()->setText(0, qt_("Branch"));
54         branchesTW->headerItem()->setText(1, qt_("Activated"));
55         branchesTW->headerItem()->setText(2, qt_("Color"));
56         branchesTW->headerItem()->setText(3, qt_("Filename Suffix"));
57         branchesTW->setSortingEnabled(true);
58         branchesTW->resizeColumnToContents(1);
59         branchesTW->resizeColumnToContents(2);
60
61         undef_ = new BranchesUnknownDialog(this);
62         undef_bc_.setPolicy(ButtonPolicy::OkCancelPolicy);
63         undef_bc_.setCancel(undef_->cancelPB);
64
65         connect(undef_->branchesLW, SIGNAL(itemSelectionChanged()),
66                 this, SLOT(unknownBranchSelChanged()));
67         connect(undef_->addSelectedPB, SIGNAL(clicked()),
68                 this, SLOT(addUnknown()));
69         connect(undef_->addAllPB, SIGNAL(clicked()),
70                 this, SLOT(addAllUnknown()));
71         connect(undef_->addSelectedPB, SIGNAL(clicked()),
72                 undef_, SLOT(accept()));
73         connect(undef_->addAllPB, SIGNAL(clicked()),
74                 undef_, SLOT(accept()));
75         connect(undef_->cancelPB, SIGNAL(clicked()),
76                 undef_, SLOT(reject()));
77
78         newBranchLE->installEventFilter(this);
79         newBranchLE->setValidator(new NoNewLineValidator(newBranchLE));
80 }
81
82
83 bool GuiBranches::eventFilter(QObject * obj, QEvent * event)
84 {
85         QEvent::Type etype = event->type();
86         if (etype == QEvent::KeyPress
87                   && obj == newBranchLE
88                   && addBranchPB->isEnabled()) {
89                 QKeyEvent * keyEvent = static_cast<QKeyEvent *>(event);
90                 int const keyPressed = keyEvent->key();
91                 Qt::KeyboardModifiers const keyModifiers = keyEvent->modifiers();
92
93                 if (keyPressed == Qt::Key_Enter || keyPressed == Qt::Key_Return) {
94                         if (!keyModifiers) {
95                                 on_addBranchPB_pressed();
96                         } else if (keyModifiers == Qt::ControlModifier
97                                   || keyModifiers == Qt::KeypadModifier
98                                   || keyModifiers == (Qt::ControlModifier | Qt::KeypadModifier)) {
99                                 on_addBranchPB_pressed();
100                                 newBranchLE->clearFocus();
101                                 okPressed();
102                         }
103                         event->accept();
104                         return true;
105                 }
106         }
107         return QObject::eventFilter(obj, event);
108 }
109
110
111 void GuiBranches::update(BufferParams const & params)
112 {
113         branchlist_ = params.branchlist();
114         updateView();
115 }
116
117
118 void GuiBranches::updateView()
119 {
120         // store the selected branch
121         QTreeWidgetItem * item = branchesTW->currentItem();
122         QString sel_branch;
123         if (item != 0)
124                 sel_branch = item->text(0);
125
126         branchesTW->clear();
127
128         BranchList::const_iterator it = branchlist_.begin();
129         BranchList::const_iterator const end = branchlist_.end();
130         for (; it != end; ++it) {
131                 QTreeWidgetItem * newItem = new QTreeWidgetItem(branchesTW);
132
133                 QString const bname = toqstr(it->branch());
134                 newItem->setText(0, bname);
135                 newItem->setText(1, it->isSelected() ? qt_("Yes") : qt_("No"));
136
137                 std::string bcolor = it->color();
138                 RGBColor rgbcol;
139                 if (bcolor.size() == 7 && bcolor[0] == '#')
140                         rgbcol = lyx::rgbFromHexName(bcolor);
141                 else
142                         guiApp->getRgbColor(lcolor.getFromLyXName(bcolor), rgbcol);
143                 QColor const itemcolor = rgb2qcolor(rgbcol);
144                 if (itemcolor.isValid()) {
145                         QPixmap coloritem(30, 10);
146                         coloritem.fill(itemcolor);
147                         newItem->setIcon(2, QIcon(coloritem));
148                 }
149                 newItem->setText(3, it->hasFileNameSuffix() ? qt_("Yes") : qt_("No"));
150                 // restore selected branch
151                 if (bname == sel_branch) {
152                         branchesTW->setCurrentItem(newItem);
153                         newItem->setSelected(true);
154                 }
155         }
156         unknownPB->setEnabled(!unknown_branches_.isEmpty());
157         bool const have_sel =
158                 !branchesTW->selectedItems().isEmpty();
159         removePB->setEnabled(have_sel);
160         renamePB->setEnabled(have_sel);
161         colorPB->setEnabled(have_sel);
162         resetColorPB->setEnabled(have_sel);
163         activatePB->setEnabled(have_sel);
164         suffixPB->setEnabled(have_sel);
165         // emit signal
166         changed();
167 }
168
169
170 void GuiBranches::apply(BufferParams & params) const
171 {
172         params.branchlist() = branchlist_;
173 }
174
175
176 void GuiBranches::on_newBranchLE_textChanged(QString)
177 {
178         QString const new_branch = newBranchLE->text();
179         addBranchPB->setEnabled(!new_branch.isEmpty());
180 }
181
182
183 void GuiBranches::on_addBranchPB_pressed()
184 {
185         QString const new_branch = newBranchLE->text();
186         branchlist_.add(qstring_to_ucs4(new_branch));
187         newBranchLE->clear();
188         addBranchPB->setEnabled(false);
189         updateView();
190 }
191
192
193 void GuiBranches::on_removePB_pressed()
194 {
195         QTreeWidgetItem * selItem = branchesTW->currentItem();
196         QString sel_branch;
197         if (selItem != 0)
198                 sel_branch = selItem->text(0);
199         if (!sel_branch.isEmpty()) {
200                 branchlist_.remove(qstring_to_ucs4(sel_branch));
201                 newBranchLE->clear();
202                 updateView();
203         }
204 }
205
206
207 void GuiBranches::on_renamePB_pressed()
208 {
209         QTreeWidgetItem * selItem = branchesTW->currentItem();
210         QString sel_branch;
211         if (selItem != 0)
212                 sel_branch = selItem->text(0);
213         if (!sel_branch.isEmpty()) {
214                 docstring newname;
215                 docstring const oldname = qstring_to_ucs4(sel_branch);
216                 if (Alert::askForText(newname, _("Enter new branch name"), oldname)) {
217                         if (newname.empty() || oldname == newname)
218                                 return;
219                         bool success = false;
220                         if (branchlist_.find(newname)) {
221                                 docstring text = support::bformat(
222                                         _("A branch with the name \"%1$s\" already exists.\n"
223                                           "Do you want to merge branch \"%2$s\" with that one?"),
224                                         newname, oldname);
225                                 if (frontend::Alert::prompt(_("Branch already exists"),
226                                           text, 0, 1, _("&Merge"), _("&Cancel")) == 0)
227                                         success = branchlist_.rename(oldname, newname, true);
228                         } else
229                                 success = branchlist_.rename(oldname, newname);
230                         newBranchLE->clear();
231                         updateView();
232
233                         if (!success)
234                                 Alert::error(_("Renaming failed"),
235                                       _("The branch could not be renamed."));
236                         else
237                                 // emit signal
238                                 renameBranches(oldname, newname);
239                 }
240         }
241 }
242
243
244 void GuiBranches::on_activatePB_pressed()
245 {
246         toggleBranch(branchesTW->currentItem());
247 }
248
249
250 void GuiBranches::on_suffixPB_pressed()
251 {
252         toggleSuffix(branchesTW->currentItem());
253 }
254
255
256 void GuiBranches::on_branchesTW_itemDoubleClicked(QTreeWidgetItem * item, int col)
257 {
258         if (col < 2)
259                 toggleBranch(item);
260         else if (col == 2)
261                 toggleColor(item);
262         else if (col == 3)
263                 toggleSuffix(item);
264 }
265
266
267 void GuiBranches::on_branchesTW_itemSelectionChanged()
268 {
269         bool const have_sel =
270                 !branchesTW->selectedItems().isEmpty();
271         removePB->setEnabled(have_sel);
272         renamePB->setEnabled(have_sel);
273         colorPB->setEnabled(have_sel);
274         resetColorPB->setEnabled(have_sel);
275         activatePB->setEnabled(have_sel);
276         suffixPB->setEnabled(have_sel);
277 }
278
279
280 void GuiBranches::toggleBranch(QTreeWidgetItem * item)
281 {
282         if (item == 0)
283                 return;
284
285         QString sel_branch = item->text(0);
286         if (sel_branch.isEmpty())
287                 return;
288
289         Branch * branch = branchlist_.find(qstring_to_ucs4(sel_branch));
290         if (branch && branch->setSelected(!branch->isSelected())) {
291                 newBranchLE->clear();
292                 updateView();
293         }
294 }
295
296
297 void GuiBranches::on_colorPB_clicked()
298 {
299         toggleColor(branchesTW->currentItem());
300 }
301
302
303 void GuiBranches::on_resetColorPB_clicked()
304 {
305         QTreeWidgetItem * item = branchesTW->currentItem();
306         if (item == 0)
307                 return;
308
309         QString sel_branch = item->text(0);
310         if (sel_branch.isEmpty())
311                 return;
312
313         docstring current_branch = qstring_to_ucs4(sel_branch);
314         Branch * branch = branchlist_.find(current_branch);
315         if (!branch)
316                 return;
317         branch->setColor("background");
318         newBranchLE->clear();
319         updateView();
320 }
321
322
323 void GuiBranches::toggleColor(QTreeWidgetItem * item)
324 {
325         if (item == 0)
326                 return;
327
328         QString sel_branch = item->text(0);
329         if (sel_branch.isEmpty())
330                 return;
331
332         docstring current_branch = qstring_to_ucs4(sel_branch);
333         Branch * branch = branchlist_.find(current_branch);
334         if (!branch)
335                 return;
336
337         std::string bcolor = branch->color();
338         RGBColor rgbcol;
339         if (bcolor.size() == 7 && bcolor[0] == '#')
340                 rgbcol = lyx::rgbFromHexName(bcolor);
341         else
342                 guiApp->getRgbColor(lcolor.getFromLyXName(bcolor), rgbcol);
343         QColor const initial = rgb2qcolor(rgbcol);
344         QColor ncol = QColorDialog::getColor(initial, qApp->focusWidget());
345         if (!ncol.isValid())
346                 return;
347
348         // add the color to the branchlist
349         branch->setColor(fromqstr(ncol.name()));
350         newBranchLE->clear();
351         updateView();
352 }
353
354
355 void GuiBranches::toggleSuffix(QTreeWidgetItem * item)
356 {
357         if (item == 0)
358                 return;
359
360         QString sel_branch = item->text(0);
361         if (sel_branch.isEmpty())
362                 return;
363
364         Branch * branch = branchlist_.find(qstring_to_ucs4(sel_branch));
365         if (branch) {
366                 branch->setFileNameSuffix(!branch->hasFileNameSuffix());
367                 newBranchLE->clear();
368                 updateView();
369         }
370 }
371
372
373 void GuiBranches::on_unknownPB_pressed()
374 {
375         undef_->branchesLW->clear();
376         for (int i = 0; i != unknown_branches_.count(); ++i) {
377                 if (branchesTW->findItems(unknown_branches_[i], Qt::MatchExactly, 0).empty())
378                         undef_->branchesLW->addItem(unknown_branches_[i]);
379         }
380         unknownBranchSelChanged();
381         undef_->exec();
382 }
383
384
385 void GuiBranches::addUnknown()
386 {
387         QList<QListWidgetItem *> selItems =
388                 undef_->branchesLW->selectedItems();
389
390         QList<QListWidgetItem *>::const_iterator it = selItems.begin();
391         for (; it != selItems.end() ; ++it) {
392                 QListWidgetItem const * new_branch = *it;
393                 if (new_branch) {
394                         branchlist_.add(qstring_to_ucs4(new_branch->text()));
395                         updateView();
396                 }
397         }
398 }
399
400
401 void GuiBranches::addAllUnknown()
402 {
403         undef_->branchesLW->selectAll();
404         addUnknown();
405 }
406
407
408 void GuiBranches::unknownBranchSelChanged()
409 {
410         undef_->addSelectedPB->setEnabled(
411                 !undef_->branchesLW->selectedItems().isEmpty());
412 }
413
414
415 } // namespace frontend
416 } // namespace lyx
417
418 #include "moc_GuiBranches.cpp"