Chris@67
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@67
|
2
|
Chris@67
|
3 /*
|
Chris@67
|
4 EasyMercurial
|
Chris@67
|
5
|
Chris@67
|
6 Based on HgExplorer by Jari Korhonen
|
Chris@67
|
7 Copyright (c) 2010 Jari Korhonen
|
Chris@644
|
8 Copyright (c) 2013 Chris Cannam
|
Chris@644
|
9 Copyright (c) 2013 Queen Mary, University of London
|
Chris@67
|
10
|
Chris@67
|
11 This program is free software; you can redistribute it and/or
|
Chris@67
|
12 modify it under the terms of the GNU General Public License as
|
Chris@67
|
13 published by the Free Software Foundation; either version 2 of the
|
Chris@67
|
14 License, or (at your option) any later version. See the file
|
Chris@67
|
15 COPYING included with this distribution for more information.
|
Chris@67
|
16 */
|
Chris@67
|
17
|
Chris@67
|
18 #include "multichoicedialog.h"
|
Chris@67
|
19
|
Chris@69
|
20 #include "selectablelabel.h"
|
Chris@69
|
21
|
Chris@69
|
22 #include "debug.h"
|
Chris@69
|
23
|
Chris@68
|
24 #include <QDialogButtonBox>
|
Chris@69
|
25 #include <QToolButton>
|
Chris@69
|
26 #include <QPushButton>
|
Chris@69
|
27 #include <QFont>
|
Chris@69
|
28 #include <QDir>
|
Chris@69
|
29 #include <QFileDialog>
|
Chris@341
|
30 #include <QDesktopServices>
|
Chris@72
|
31 #include <QUrl>
|
Chris@68
|
32
|
Chris@341
|
33 MultiChoiceDialog::MultiChoiceDialog(QString title, QString heading,
|
Chris@341
|
34 QString helpUrl, QWidget *parent) :
|
Chris@341
|
35 QDialog(parent),
|
Chris@341
|
36 m_helpUrl(helpUrl)
|
Chris@67
|
37 {
|
Chris@68
|
38 setModal(true);
|
Chris@68
|
39 setWindowTitle(title);
|
Chris@68
|
40
|
Chris@68
|
41 QGridLayout *outer = new QGridLayout;
|
Chris@68
|
42 setLayout(outer);
|
Chris@68
|
43
|
Chris@68
|
44 outer->addWidget(new QLabel(heading), 0, 0, 1, 3);
|
Chris@68
|
45
|
Chris@68
|
46 QWidget *innerWidget = new QWidget;
|
Chris@69
|
47 outer->addWidget(innerWidget, 1, 0, 1, 3);
|
Chris@69
|
48 m_choiceLayout = new QHBoxLayout;
|
Chris@68
|
49 innerWidget->setLayout(m_choiceLayout);
|
Chris@68
|
50
|
Chris@68
|
51 m_descriptionLabel = new QLabel;
|
Chris@68
|
52 outer->addWidget(m_descriptionLabel, 2, 0, 1, 3);
|
Chris@68
|
53
|
Chris@69
|
54 QFont f = m_descriptionLabel->font();
|
Chris@202
|
55 f.setPointSize(f.pointSize() * 0.95);
|
Chris@69
|
56 m_descriptionLabel->setFont(f);
|
Chris@69
|
57
|
Chris@74
|
58 m_urlLabel = new QLabel(tr("&URL:"));
|
Chris@72
|
59 outer->addWidget(m_urlLabel, 3, 0);
|
Chris@68
|
60
|
Chris@72
|
61 m_urlCombo = new QComboBox();
|
Chris@72
|
62 m_urlCombo->setEditable(true);
|
Chris@74
|
63 m_urlLabel->setBuddy(m_urlCombo);
|
Chris@72
|
64 connect(m_urlCombo, SIGNAL(editTextChanged(const QString &)),
|
Chris@72
|
65 this, SLOT(urlChanged(const QString &)));
|
Chris@72
|
66 outer->addWidget(m_urlCombo, 3, 1, 1, 2);
|
Chris@72
|
67
|
Chris@74
|
68 m_fileLabel = new QLabel(tr("&File:"));
|
Chris@72
|
69 outer->addWidget(m_fileLabel, 4, 0);
|
Chris@72
|
70
|
Chris@72
|
71 m_fileCombo = new QComboBox();
|
Chris@72
|
72 m_fileCombo->setEditable(true);
|
Chris@74
|
73 m_fileLabel->setBuddy(m_fileCombo);
|
Chris@74
|
74 connect(m_fileCombo, SIGNAL(editTextChanged(const QString &)),
|
Chris@74
|
75 this, SLOT(fileChanged(const QString &)));
|
Chris@72
|
76 outer->addWidget(m_fileCombo, 4, 1);
|
Chris@69
|
77 outer->setColumnStretch(1, 20);
|
Chris@68
|
78
|
Chris@68
|
79 m_browseButton = new QPushButton(tr("Browse..."));
|
Chris@72
|
80 outer->addWidget(m_browseButton, 4, 2);
|
Chris@69
|
81 connect(m_browseButton, SIGNAL(clicked()), this, SLOT(browse()));
|
Chris@68
|
82
|
Chris@341
|
83 outer->addItem(new QSpacerItem(2, 12), 5, 0);
|
Chris@341
|
84
|
Chris@341
|
85 QDialogButtonBox *bbox;
|
Chris@341
|
86 if (helpUrl != "") {
|
Chris@341
|
87 bbox = new QDialogButtonBox(QDialogButtonBox::Help |
|
Chris@341
|
88 QDialogButtonBox::Ok |
|
Chris@341
|
89 QDialogButtonBox::Cancel);
|
Chris@341
|
90 } else {
|
Chris@341
|
91 bbox = new QDialogButtonBox(QDialogButtonBox::Ok |
|
Chris@341
|
92 QDialogButtonBox::Cancel);
|
Chris@341
|
93 }
|
Chris@68
|
94 connect(bbox, SIGNAL(accepted()), this, SLOT(accept()));
|
Chris@68
|
95 connect(bbox, SIGNAL(rejected()), this, SLOT(reject()));
|
Chris@341
|
96 connect(bbox, SIGNAL(helpRequested()), this, SLOT(helpRequested()));
|
Chris@341
|
97 outer->addWidget(bbox, 6, 0, 1, 3);
|
Chris@74
|
98
|
Chris@74
|
99 m_okButton = bbox->button(QDialogButtonBox::Ok);
|
Chris@199
|
100 updateOkButton();
|
Chris@74
|
101
|
Chris@69
|
102 setMinimumWidth(480);
|
Chris@67
|
103 }
|
Chris@68
|
104
|
Chris@341
|
105 void
|
Chris@341
|
106 MultiChoiceDialog::helpRequested()
|
Chris@341
|
107 {
|
Chris@341
|
108 QDesktopServices::openUrl(m_helpUrl);
|
Chris@341
|
109 }
|
Chris@341
|
110
|
Chris@69
|
111 QString
|
Chris@69
|
112 MultiChoiceDialog::getCurrentChoice()
|
Chris@69
|
113 {
|
Chris@69
|
114 return m_currentChoice;
|
Chris@69
|
115 }
|
Chris@69
|
116
|
Chris@69
|
117 void
|
Chris@69
|
118 MultiChoiceDialog::setCurrentChoice(QString c)
|
Chris@69
|
119 {
|
Chris@69
|
120 m_currentChoice = c;
|
Chris@69
|
121 choiceChanged();
|
Chris@69
|
122 }
|
Chris@69
|
123
|
Chris@69
|
124 QString
|
Chris@69
|
125 MultiChoiceDialog::getArgument()
|
Chris@69
|
126 {
|
Chris@72
|
127 if (m_argTypes[m_currentChoice] == UrlArg ||
|
Chris@72
|
128 m_argTypes[m_currentChoice] == UrlToDirectoryArg) {
|
Chris@72
|
129 return m_urlCombo->currentText();
|
Chris@72
|
130 } else {
|
Chris@72
|
131 return m_fileCombo->currentText();
|
Chris@72
|
132 }
|
Chris@72
|
133 }
|
Chris@72
|
134
|
Chris@72
|
135 QString
|
Chris@72
|
136 MultiChoiceDialog::getAdditionalArgument()
|
Chris@72
|
137 {
|
Chris@72
|
138 if (m_argTypes[m_currentChoice] == UrlToDirectoryArg) {
|
Chris@72
|
139 return m_fileCombo->currentText();
|
Chris@72
|
140 } else {
|
Chris@72
|
141 return "";
|
Chris@72
|
142 }
|
Chris@69
|
143 }
|
Chris@69
|
144
|
Chris@69
|
145 void
|
Chris@72
|
146 MultiChoiceDialog::addRecentArgument(QString id, QString arg,
|
Chris@72
|
147 bool additionalArgument)
|
Chris@69
|
148 {
|
Chris@72
|
149 if (additionalArgument) {
|
Chris@72
|
150 RecentFiles(QString("Recent-%1-add").arg(id)).addFile(arg);
|
Chris@72
|
151 } else {
|
Chris@72
|
152 RecentFiles(QString("Recent-%1").arg(id)).addFile(arg);
|
Chris@72
|
153 }
|
Chris@69
|
154 }
|
Chris@69
|
155
|
Chris@69
|
156 void
|
Chris@69
|
157 MultiChoiceDialog::addChoice(QString id, QString text,
|
Chris@553
|
158 QString description, ArgType arg,
|
Chris@553
|
159 bool defaultEmpty)
|
Chris@69
|
160 {
|
Chris@69
|
161 bool first = (m_texts.empty());
|
Chris@69
|
162
|
Chris@69
|
163 m_texts[id] = text;
|
Chris@69
|
164 m_descriptions[id] = description;
|
Chris@69
|
165 m_argTypes[id] = arg;
|
Chris@553
|
166 m_defaultEmpty[id] = defaultEmpty;
|
Chris@69
|
167
|
Chris@69
|
168 if (arg != NoArg) {
|
Chris@69
|
169 m_recentFiles[id] = QSharedPointer<RecentFiles>
|
Chris@69
|
170 (new RecentFiles(QString("Recent-%1").arg(id)));
|
Chris@69
|
171 }
|
Chris@69
|
172
|
Chris@69
|
173 SelectableLabel *cb = new SelectableLabel;
|
Chris@69
|
174 cb->setSelectedText(text);
|
Chris@69
|
175 cb->setUnselectedText(text);
|
Chris@183
|
176 cb->setMaximumWidth(270);
|
Chris@69
|
177
|
Chris@69
|
178 m_choiceLayout->addWidget(cb);
|
Chris@69
|
179 m_choiceButtons[cb] = id;
|
Chris@69
|
180
|
Chris@69
|
181 connect(cb, SIGNAL(selectionChanged()), this, SLOT(choiceChanged()));
|
Chris@69
|
182
|
Chris@69
|
183 if (first) {
|
Chris@69
|
184 m_currentChoice = id;
|
Chris@69
|
185 choiceChanged();
|
Chris@69
|
186 }
|
Chris@69
|
187 }
|
Chris@69
|
188
|
Chris@342
|
189 QString
|
Chris@342
|
190 MultiChoiceDialog::getDefaultPath() const
|
Chris@342
|
191 {
|
Chris@342
|
192 QDir home(QDir::home());
|
Chris@342
|
193 QDir dflt;
|
Chris@342
|
194
|
Chris@483
|
195 dflt = QDir(home.filePath(tr("Documents")));
|
Chris@483
|
196 DEBUG << "testing " << dflt << endl;
|
Chris@483
|
197 if (dflt.exists()) return dflt.canonicalPath();
|
Chris@483
|
198
|
Chris@342
|
199 dflt = QDir(home.filePath(tr("My Documents")));
|
Chris@342
|
200 DEBUG << "testing " << dflt << endl;
|
Chris@342
|
201 if (dflt.exists()) return dflt.canonicalPath();
|
Chris@342
|
202
|
Chris@483
|
203 dflt = QDir(home.filePath(tr("Desktop")));
|
Chris@342
|
204 DEBUG << "testing " << dflt << endl;
|
Chris@342
|
205 if (dflt.exists()) return dflt.canonicalPath();
|
Chris@342
|
206
|
Chris@342
|
207 DEBUG << "all failed, returning " << home << endl;
|
Chris@342
|
208 return home.canonicalPath();
|
Chris@342
|
209 }
|
Chris@342
|
210
|
Chris@69
|
211 void
|
Chris@69
|
212 MultiChoiceDialog::browse()
|
Chris@69
|
213 {
|
Chris@69
|
214 QString origin = getArgument();
|
Chris@69
|
215
|
Chris@69
|
216 if (origin == "") {
|
Chris@342
|
217 origin = getDefaultPath();
|
Chris@69
|
218 }
|
Chris@69
|
219
|
Chris@69
|
220 QString path = origin;
|
Chris@69
|
221
|
Chris@72
|
222 if (m_argTypes[m_currentChoice] == DirectoryArg ||
|
Chris@72
|
223 m_argTypes[m_currentChoice] == UrlToDirectoryArg) {
|
Chris@69
|
224
|
Chris@69
|
225 path = QFileDialog::getExistingDirectory
|
Chris@69
|
226 (this, tr("Open Directory"), origin,
|
Chris@69
|
227 QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
Chris@69
|
228 if (path != QString()) {
|
Chris@72
|
229 m_fileCombo->lineEdit()->setText(path + QDir::separator());
|
Chris@69
|
230 }
|
Chris@69
|
231
|
Chris@69
|
232 } else {
|
Chris@69
|
233
|
Chris@69
|
234 path = QFileDialog::getOpenFileName
|
Chris@69
|
235 (this, tr("Open File"), origin);
|
Chris@69
|
236 if (path != QString()) {
|
Chris@72
|
237 m_fileCombo->lineEdit()->setText(path);
|
Chris@69
|
238 }
|
Chris@69
|
239 }
|
Chris@69
|
240 }
|
Chris@69
|
241
|
Chris@69
|
242 void
|
Chris@671
|
243 MultiChoiceDialog::urlChanged(const QString &)
|
Chris@72
|
244 {
|
Chris@199
|
245 updateOkButton();
|
Chris@483
|
246 updateFileComboFromURL();
|
Chris@199
|
247 }
|
Chris@199
|
248
|
Chris@199
|
249 void
|
Chris@671
|
250 MultiChoiceDialog::fileChanged(const QString &)
|
Chris@199
|
251 {
|
Chris@199
|
252 updateOkButton();
|
Chris@199
|
253 }
|
Chris@199
|
254
|
Chris@199
|
255 void
|
Chris@483
|
256 MultiChoiceDialog::updateFileComboFromURL()
|
Chris@199
|
257 {
|
Chris@72
|
258 if (m_argTypes[m_currentChoice] != UrlToDirectoryArg) {
|
Chris@72
|
259 return;
|
Chris@72
|
260 }
|
Chris@72
|
261 QString url = m_urlCombo->currentText();
|
Chris@72
|
262 if (QRegExp("^\\w+://").indexIn(url) < 0) {
|
Chris@72
|
263 return;
|
Chris@72
|
264 }
|
Chris@72
|
265 QString urlDirName = url;
|
Chris@79
|
266 urlDirName.replace(QRegExp("^.*\\//.*\\/"), "");
|
Chris@72
|
267 if (urlDirName == "" || urlDirName == url) {
|
Chris@72
|
268 return;
|
Chris@72
|
269 }
|
Chris@483
|
270 QString dirPath = m_fileCombo->currentText();
|
Chris@483
|
271 QString defaultPath = getDefaultPath();
|
Chris@483
|
272 if (dirPath == defaultPath) {
|
Chris@483
|
273 dirPath += QDir::separator() + urlDirName;
|
Chris@483
|
274 } else if (dirPath == defaultPath + QDir::separator()) {
|
Chris@483
|
275 dirPath += urlDirName;
|
Chris@483
|
276 } else {
|
Chris@483
|
277 QDir d(dirPath);
|
Chris@483
|
278 d.cdUp();
|
Chris@483
|
279 dirPath = d.filePath(urlDirName);
|
Chris@483
|
280 }
|
Chris@483
|
281 m_fileCombo->lineEdit()->setText(dirPath);
|
Chris@483
|
282 }
|
Chris@483
|
283
|
Chris@483
|
284 void
|
Chris@483
|
285 MultiChoiceDialog::updateOkButton()
|
Chris@483
|
286 {
|
Chris@565
|
287 if (m_defaultEmpty[m_currentChoice]) {
|
Chris@565
|
288 m_okButton->setEnabled(true);
|
Chris@565
|
289 } else if (m_argTypes[m_currentChoice] == UrlToDirectoryArg) {
|
Chris@79
|
290 m_okButton->setEnabled(getArgument() != "" &&
|
Chris@79
|
291 getAdditionalArgument() != "");
|
Chris@79
|
292 } else {
|
Chris@79
|
293 m_okButton->setEnabled(getArgument() != "");
|
Chris@79
|
294 }
|
Chris@72
|
295 }
|
Chris@72
|
296
|
Chris@604
|
297 bool
|
Chris@604
|
298 MultiChoiceDialog::urlComboNotUrl() const
|
Chris@604
|
299 {
|
Chris@604
|
300 QString url = m_urlCombo->currentText();
|
Chris@604
|
301 if (QRegExp("^\\w+://").indexIn(url) < 0) {
|
Chris@604
|
302 return true;
|
Chris@604
|
303 } else {
|
Chris@604
|
304 return false;
|
Chris@604
|
305 }
|
Chris@604
|
306 }
|
Chris@604
|
307
|
Chris@72
|
308 void
|
Chris@69
|
309 MultiChoiceDialog::choiceChanged()
|
Chris@69
|
310 {
|
Chris@69
|
311 DEBUG << "choiceChanged" << endl;
|
Chris@69
|
312
|
Chris@69
|
313 if (m_choiceButtons.empty()) return;
|
Chris@69
|
314
|
Chris@69
|
315 QString id = "";
|
Chris@69
|
316
|
Chris@69
|
317 QObject *s = sender();
|
Chris@69
|
318 QWidget *w = qobject_cast<QWidget *>(s);
|
Chris@69
|
319 if (w) id = m_choiceButtons[w];
|
Chris@69
|
320
|
Chris@69
|
321 if (id == m_currentChoice) return;
|
Chris@69
|
322 if (id == "") {
|
Chris@69
|
323 // Happens when this is called for the very first time, when
|
Chris@69
|
324 // m_currentChoice has been set to the intended ID but no
|
Chris@69
|
325 // button has actually been pressed -- then we need to
|
Chris@69
|
326 // initialise
|
Chris@69
|
327 id = m_currentChoice;
|
Chris@69
|
328 }
|
Chris@69
|
329
|
Chris@69
|
330 m_currentChoice = id;
|
Chris@69
|
331
|
Chris@69
|
332 foreach (QWidget *cw, m_choiceButtons.keys()) {
|
Chris@69
|
333 SelectableLabel *sl = qobject_cast<SelectableLabel *>(cw);
|
Chris@69
|
334 if (sl) {
|
Chris@69
|
335 sl->setSelected(m_choiceButtons[cw] == id);
|
Chris@69
|
336 }
|
Chris@69
|
337 }
|
Chris@69
|
338
|
Chris@69
|
339 m_descriptionLabel->setText(m_descriptions[id]);
|
Chris@69
|
340
|
Chris@72
|
341 m_browseButton->hide();
|
Chris@483
|
342
|
Chris@72
|
343 m_urlLabel->hide();
|
Chris@483
|
344 m_urlCombo->clear();
|
Chris@72
|
345 m_urlCombo->hide();
|
Chris@72
|
346
|
Chris@483
|
347 m_fileLabel->hide();
|
Chris@483
|
348 m_fileCombo->clear();
|
Chris@483
|
349 m_fileCombo->hide();
|
Chris@483
|
350
|
Chris@72
|
351 QSharedPointer<RecentFiles> rf = m_recentFiles[id];
|
Chris@72
|
352
|
Chris@69
|
353 switch (m_argTypes[id]) {
|
Chris@69
|
354
|
Chris@69
|
355 case NoArg:
|
Chris@69
|
356 break;
|
Chris@69
|
357
|
Chris@69
|
358 case FileArg:
|
Chris@74
|
359 m_fileLabel->setText(tr("&File:"));
|
Chris@72
|
360 m_fileLabel->show();
|
Chris@72
|
361 m_fileCombo->show();
|
Chris@72
|
362 m_fileCombo->addItems(rf->getRecent());
|
Chris@553
|
363 if (m_defaultEmpty[id]) m_fileCombo->lineEdit()->setText("");
|
Chris@69
|
364 m_browseButton->show();
|
Chris@69
|
365 break;
|
Chris@69
|
366
|
Chris@69
|
367 case DirectoryArg:
|
Chris@74
|
368 m_fileLabel->setText(tr("&Folder:"));
|
Chris@72
|
369 m_fileLabel->show();
|
Chris@72
|
370 m_fileCombo->show();
|
Chris@72
|
371 m_fileCombo->addItems(rf->getRecent());
|
Chris@553
|
372 if (m_defaultEmpty[id]) m_fileCombo->lineEdit()->setText("");
|
Chris@69
|
373 m_browseButton->show();
|
Chris@69
|
374 break;
|
Chris@69
|
375
|
Chris@69
|
376 case UrlArg:
|
Chris@72
|
377 m_urlLabel->show();
|
Chris@72
|
378 m_urlCombo->show();
|
Chris@183
|
379 m_urlCombo->addItems(rf->getRecent());
|
Chris@604
|
380 if (m_defaultEmpty[id] || urlComboNotUrl()) {
|
Chris@604
|
381 m_urlCombo->lineEdit()->setText("");
|
Chris@604
|
382 }
|
Chris@69
|
383 break;
|
Chris@69
|
384
|
Chris@72
|
385 case UrlToDirectoryArg:
|
Chris@72
|
386 m_urlLabel->show();
|
Chris@72
|
387 m_urlCombo->show();
|
Chris@72
|
388 m_urlCombo->addItems(rf->getRecent());
|
Chris@604
|
389 if (m_defaultEmpty[id] || urlComboNotUrl()) {
|
Chris@604
|
390 m_urlCombo->lineEdit()->setText("");
|
Chris@604
|
391 }
|
Chris@74
|
392 m_fileLabel->setText(tr("&Folder:"));
|
Chris@72
|
393 m_fileLabel->show();
|
Chris@72
|
394 m_fileCombo->show();
|
Chris@342
|
395 m_fileCombo->lineEdit()->setText(getDefaultPath());
|
Chris@483
|
396 updateFileComboFromURL();
|
Chris@69
|
397 m_browseButton->show();
|
Chris@69
|
398 break;
|
Chris@69
|
399 }
|
Chris@69
|
400
|
Chris@199
|
401 updateOkButton();
|
Chris@69
|
402 adjustSize();
|
Chris@69
|
403 }
|
Chris@69
|
404
|
Chris@69
|
405
|