annotate src/multichoicedialog.cpp @ 737:4f3a8aa8d384 tip

Markdown
author Chris Cannam
date Wed, 28 Aug 2019 17:40:54 +0100
parents 0329bbd4b57c
children
rev   line source
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