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 
GuiBranches(QWidget * parent)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 
eventFilter(QObject * obj,QEvent * event)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 
update(BufferParams const & params)111 void GuiBranches::update(BufferParams const & params)
112 {
113 	branchlist_ = params.branchlist();
114 	updateView();
115 }
116 
117 
updateView()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 		QColor const itemcolor = rgb2qcolor(it->color());
138 		if (itemcolor.isValid()) {
139 			QPixmap coloritem(30, 10);
140 			coloritem.fill(itemcolor);
141 			newItem->setIcon(2, QIcon(coloritem));
142 		}
143 		newItem->setText(3, it->hasFileNameSuffix() ? qt_("Yes") : qt_("No"));
144 		// restore selected branch
145 		if (bname == sel_branch) {
146 			branchesTW->setCurrentItem(newItem);
147 			branchesTW->setItemSelected(newItem, true);
148 		}
149 	}
150 	unknownPB->setEnabled(!unknown_branches_.isEmpty());
151 	bool const have_sel =
152 		!branchesTW->selectedItems().isEmpty();
153 	removePB->setEnabled(have_sel);
154 	renamePB->setEnabled(have_sel);
155 	colorPB->setEnabled(have_sel);
156 	activatePB->setEnabled(have_sel);
157 	suffixPB->setEnabled(have_sel);
158 	// emit signal
159 	changed();
160 }
161 
162 
apply(BufferParams & params) const163 void GuiBranches::apply(BufferParams & params) const
164 {
165 	params.branchlist() = branchlist_;
166 }
167 
168 
on_newBranchLE_textChanged(QString)169 void GuiBranches::on_newBranchLE_textChanged(QString)
170 {
171 	QString const new_branch = newBranchLE->text();
172 	addBranchPB->setEnabled(!new_branch.isEmpty());
173 }
174 
175 
on_addBranchPB_pressed()176 void GuiBranches::on_addBranchPB_pressed()
177 {
178 	QString const new_branch = newBranchLE->text();
179 	branchlist_.add(qstring_to_ucs4(new_branch));
180 	newBranchLE->clear();
181 	addBranchPB->setEnabled(false);
182 	updateView();
183 }
184 
185 
on_removePB_pressed()186 void GuiBranches::on_removePB_pressed()
187 {
188 	QTreeWidgetItem * selItem = branchesTW->currentItem();
189 	QString sel_branch;
190 	if (selItem != 0)
191 		sel_branch = selItem->text(0);
192 	if (!sel_branch.isEmpty()) {
193 		branchlist_.remove(qstring_to_ucs4(sel_branch));
194 		newBranchLE->clear();
195 		updateView();
196 	}
197 }
198 
199 
on_renamePB_pressed()200 void GuiBranches::on_renamePB_pressed()
201 {
202 	QTreeWidgetItem * selItem = branchesTW->currentItem();
203 	QString sel_branch;
204 	if (selItem != 0)
205 		sel_branch = selItem->text(0);
206 	if (!sel_branch.isEmpty()) {
207 		docstring newname;
208 		docstring const oldname = qstring_to_ucs4(sel_branch);
209 		if (Alert::askForText(newname, _("Enter new branch name"), oldname)) {
210 			if (newname.empty() || oldname == newname)
211 				return;
212 			bool success = false;
213 			if (branchlist_.find(newname)) {
214 				docstring text = support::bformat(
215 					_("A branch with the name \"%1$s\" already exists.\n"
216 					  "Do you want to merge branch \"%2$s\" with that one?"),
217 					newname, oldname);
218 				if (frontend::Alert::prompt(_("Branch already exists"),
219 					  text, 0, 1, _("&Merge"), _("&Cancel")) == 0)
220 					success = branchlist_.rename(oldname, newname, true);
221 			} else
222 				success = branchlist_.rename(oldname, newname);
223 			newBranchLE->clear();
224 			updateView();
225 
226 			if (!success)
227 				Alert::error(_("Renaming failed"),
228 				      _("The branch could not be renamed."));
229 			else
230 				// emit signal
231 				renameBranches(oldname, newname);
232 		}
233 	}
234 }
235 
236 
on_activatePB_pressed()237 void GuiBranches::on_activatePB_pressed()
238 {
239 	toggleBranch(branchesTW->currentItem());
240 }
241 
242 
on_suffixPB_pressed()243 void GuiBranches::on_suffixPB_pressed()
244 {
245 	toggleSuffix(branchesTW->currentItem());
246 }
247 
248 
on_branchesTW_itemDoubleClicked(QTreeWidgetItem * item,int col)249 void GuiBranches::on_branchesTW_itemDoubleClicked(QTreeWidgetItem * item, int col)
250 {
251 	if (col < 2)
252 		toggleBranch(item);
253 	else if (col == 2)
254 		toggleColor(item);
255 	else if (col == 3)
256 		toggleSuffix(item);
257 }
258 
259 
on_branchesTW_itemSelectionChanged()260 void GuiBranches::on_branchesTW_itemSelectionChanged()
261 {
262 	bool const have_sel =
263 		!branchesTW->selectedItems().isEmpty();
264 	removePB->setEnabled(have_sel);
265 	renamePB->setEnabled(have_sel);
266 	colorPB->setEnabled(have_sel);
267 	activatePB->setEnabled(have_sel);
268 	suffixPB->setEnabled(have_sel);
269 }
270 
271 
toggleBranch(QTreeWidgetItem * item)272 void GuiBranches::toggleBranch(QTreeWidgetItem * item)
273 {
274 	if (item == 0)
275 		return;
276 
277 	QString sel_branch = item->text(0);
278 	if (sel_branch.isEmpty())
279 		return;
280 
281 	Branch * branch = branchlist_.find(qstring_to_ucs4(sel_branch));
282 	if (branch && branch->setSelected(!branch->isSelected())) {
283 		newBranchLE->clear();
284 		updateView();
285 	}
286 }
287 
288 
on_colorPB_clicked()289 void GuiBranches::on_colorPB_clicked()
290 {
291 	toggleColor(branchesTW->currentItem());
292 }
293 
294 
toggleColor(QTreeWidgetItem * item)295 void GuiBranches::toggleColor(QTreeWidgetItem * item)
296 {
297 	if (item == 0)
298 		return;
299 
300 	QString sel_branch = item->text(0);
301 	if (sel_branch.isEmpty())
302 		return;
303 
304 	docstring current_branch = qstring_to_ucs4(sel_branch);
305 	Branch * branch = branchlist_.find(current_branch);
306 	if (!branch)
307 		return;
308 
309 	QColor const initial = rgb2qcolor(branch->color());
310 	QColor ncol = QColorDialog::getColor(initial, qApp->focusWidget());
311 	if (!ncol.isValid())
312 		return;
313 
314 	// add the color to the branchlist
315 	branch->setColor(fromqstr(ncol.name()));
316 	newBranchLE->clear();
317 	updateView();
318 }
319 
320 
toggleSuffix(QTreeWidgetItem * item)321 void GuiBranches::toggleSuffix(QTreeWidgetItem * item)
322 {
323 	if (item == 0)
324 		return;
325 
326 	QString sel_branch = item->text(0);
327 	if (sel_branch.isEmpty())
328 		return;
329 
330 	Branch * branch = branchlist_.find(qstring_to_ucs4(sel_branch));
331 	if (branch) {
332 		branch->setFileNameSuffix(!branch->hasFileNameSuffix());
333 		newBranchLE->clear();
334 		updateView();
335 	}
336 }
337 
338 
on_unknownPB_pressed()339 void GuiBranches::on_unknownPB_pressed()
340 {
341 	undef_->branchesLW->clear();
342 	for (int i = 0; i != unknown_branches_.count(); ++i) {
343 		if (branchesTW->findItems(unknown_branches_[i], Qt::MatchExactly, 0).empty())
344 			undef_->branchesLW->addItem(unknown_branches_[i]);
345 	}
346 	unknownBranchSelChanged();
347 	undef_->exec();
348 }
349 
350 
addUnknown()351 void GuiBranches::addUnknown()
352 {
353 	QList<QListWidgetItem *> selItems =
354 		undef_->branchesLW->selectedItems();
355 
356 	QList<QListWidgetItem *>::const_iterator it = selItems.begin();
357 	for (; it != selItems.end() ; ++it) {
358 		QListWidgetItem const * new_branch = *it;
359 		if (new_branch) {
360 			branchlist_.add(qstring_to_ucs4(new_branch->text()));
361 			updateView();
362 		}
363 	}
364 }
365 
366 
addAllUnknown()367 void GuiBranches::addAllUnknown()
368 {
369 	undef_->branchesLW->selectAll();
370 	addUnknown();
371 }
372 
373 
unknownBranchSelChanged()374 void GuiBranches::unknownBranchSelChanged()
375 {
376 	undef_->addSelectedPB->setEnabled(
377 		!undef_->branchesLW->selectedItems().isEmpty());
378 }
379 
380 
381 } // namespace frontend
382 } // namespace lyx
383 
384 #include "moc_GuiBranches.cpp"
385