annotate multichoicedialog.cpp @ 109:1721c580c10e

* Add a queueing mechanism for Hg actions, instead of refusing to start an action if something else is already happening. This is essential now that actions can be prompted by asynchronous events (e.g. filesystem watcher). * Make Revert behave sensibly
author Chris Cannam
date Fri, 26 Nov 2010 12:48:29 +0000
parents aaeabc920ca8
children 01580704de3e
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@67 8 Copyright (c) 2010 Chris Cannam
Chris@67 9 Copyright (c) 2010 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@72 30 #include <QUrl>
Chris@68 31
Chris@68 32 MultiChoiceDialog::MultiChoiceDialog(QString title, QString heading, QWidget *parent) :
Chris@67 33 QDialog(parent)
Chris@67 34 {
Chris@68 35 setModal(true);
Chris@68 36 setWindowTitle(title);
Chris@68 37
Chris@68 38 QGridLayout *outer = new QGridLayout;
Chris@68 39 setLayout(outer);
Chris@68 40
Chris@68 41 outer->addWidget(new QLabel(heading), 0, 0, 1, 3);
Chris@68 42
Chris@68 43 QWidget *innerWidget = new QWidget;
Chris@69 44 outer->addWidget(innerWidget, 1, 0, 1, 3);
Chris@69 45 m_choiceLayout = new QHBoxLayout;
Chris@68 46 innerWidget->setLayout(m_choiceLayout);
Chris@68 47
Chris@68 48 m_descriptionLabel = new QLabel;
Chris@68 49 outer->addWidget(m_descriptionLabel, 2, 0, 1, 3);
Chris@68 50
Chris@69 51 QFont f = m_descriptionLabel->font();
Chris@69 52 f.setPointSize(f.pointSize() * 0.9);
Chris@69 53 m_descriptionLabel->setFont(f);
Chris@69 54
Chris@74 55 m_urlLabel = new QLabel(tr("&URL:"));
Chris@72 56 outer->addWidget(m_urlLabel, 3, 0);
Chris@68 57
Chris@72 58 m_urlCombo = new QComboBox();
Chris@72 59 m_urlCombo->setEditable(true);
Chris@74 60 m_urlLabel->setBuddy(m_urlCombo);
Chris@72 61 connect(m_urlCombo, SIGNAL(editTextChanged(const QString &)),
Chris@72 62 this, SLOT(urlChanged(const QString &)));
Chris@72 63 outer->addWidget(m_urlCombo, 3, 1, 1, 2);
Chris@72 64
Chris@74 65 m_fileLabel = new QLabel(tr("&File:"));
Chris@72 66 outer->addWidget(m_fileLabel, 4, 0);
Chris@72 67
Chris@72 68 m_fileCombo = new QComboBox();
Chris@72 69 m_fileCombo->setEditable(true);
Chris@74 70 m_fileLabel->setBuddy(m_fileCombo);
Chris@74 71 connect(m_fileCombo, SIGNAL(editTextChanged(const QString &)),
Chris@74 72 this, SLOT(fileChanged(const QString &)));
Chris@72 73 outer->addWidget(m_fileCombo, 4, 1);
Chris@69 74 outer->setColumnStretch(1, 20);
Chris@68 75
Chris@68 76 m_browseButton = new QPushButton(tr("Browse..."));
Chris@72 77 outer->addWidget(m_browseButton, 4, 2);
Chris@69 78 connect(m_browseButton, SIGNAL(clicked()), this, SLOT(browse()));
Chris@68 79
Chris@68 80 QDialogButtonBox *bbox = new QDialogButtonBox(QDialogButtonBox::Ok |
Chris@68 81 QDialogButtonBox::Cancel);
Chris@68 82 connect(bbox, SIGNAL(accepted()), this, SLOT(accept()));
Chris@68 83 connect(bbox, SIGNAL(rejected()), this, SLOT(reject()));
Chris@72 84 outer->addWidget(bbox, 5, 0, 1, 3);
Chris@74 85
Chris@74 86 m_okButton = bbox->button(QDialogButtonBox::Ok);
Chris@74 87 m_okButton->setEnabled(false);
Chris@74 88
Chris@69 89 setMinimumWidth(480);
Chris@67 90 }
Chris@68 91
Chris@69 92 QString
Chris@69 93 MultiChoiceDialog::getCurrentChoice()
Chris@69 94 {
Chris@69 95 return m_currentChoice;
Chris@69 96 }
Chris@69 97
Chris@69 98 void
Chris@69 99 MultiChoiceDialog::setCurrentChoice(QString c)
Chris@69 100 {
Chris@69 101 m_currentChoice = c;
Chris@69 102 choiceChanged();
Chris@69 103 }
Chris@69 104
Chris@69 105 QString
Chris@69 106 MultiChoiceDialog::getArgument()
Chris@69 107 {
Chris@72 108 if (m_argTypes[m_currentChoice] == UrlArg ||
Chris@72 109 m_argTypes[m_currentChoice] == UrlToDirectoryArg) {
Chris@72 110 return m_urlCombo->currentText();
Chris@72 111 } else {
Chris@72 112 return m_fileCombo->currentText();
Chris@72 113 }
Chris@72 114 }
Chris@72 115
Chris@72 116 QString
Chris@72 117 MultiChoiceDialog::getAdditionalArgument()
Chris@72 118 {
Chris@72 119 if (m_argTypes[m_currentChoice] == UrlToDirectoryArg) {
Chris@72 120 return m_fileCombo->currentText();
Chris@72 121 } else {
Chris@72 122 return "";
Chris@72 123 }
Chris@69 124 }
Chris@69 125
Chris@69 126 void
Chris@72 127 MultiChoiceDialog::addRecentArgument(QString id, QString arg,
Chris@72 128 bool additionalArgument)
Chris@69 129 {
Chris@72 130 if (additionalArgument) {
Chris@72 131 RecentFiles(QString("Recent-%1-add").arg(id)).addFile(arg);
Chris@72 132 } else {
Chris@72 133 RecentFiles(QString("Recent-%1").arg(id)).addFile(arg);
Chris@72 134 }
Chris@69 135 }
Chris@69 136
Chris@69 137 void
Chris@69 138 MultiChoiceDialog::addChoice(QString id, QString text,
Chris@69 139 QString description, ArgType arg)
Chris@69 140 {
Chris@69 141 bool first = (m_texts.empty());
Chris@69 142
Chris@69 143 m_texts[id] = text;
Chris@69 144 m_descriptions[id] = description;
Chris@69 145 m_argTypes[id] = arg;
Chris@69 146
Chris@69 147 if (arg != NoArg) {
Chris@69 148 m_recentFiles[id] = QSharedPointer<RecentFiles>
Chris@69 149 (new RecentFiles(QString("Recent-%1").arg(id)));
Chris@69 150 }
Chris@69 151
Chris@69 152 SelectableLabel *cb = new SelectableLabel;
Chris@69 153 cb->setSelectedText(text);
Chris@69 154 cb->setUnselectedText(text);
Chris@69 155
Chris@69 156 m_choiceLayout->addWidget(cb);
Chris@69 157 m_choiceButtons[cb] = id;
Chris@69 158
Chris@69 159 connect(cb, SIGNAL(selectionChanged()), this, SLOT(choiceChanged()));
Chris@69 160
Chris@69 161 if (first) {
Chris@69 162 m_currentChoice = id;
Chris@69 163 choiceChanged();
Chris@69 164 }
Chris@69 165 }
Chris@69 166
Chris@69 167 void
Chris@69 168 MultiChoiceDialog::browse()
Chris@69 169 {
Chris@69 170 QString origin = getArgument();
Chris@69 171
Chris@69 172 if (origin == "") {
Chris@69 173 #ifdef Q_OS_WIN32
Chris@69 174 origin = "c:";
Chris@69 175 #else
Chris@69 176 origin = QDir::homePath();
Chris@69 177 #endif
Chris@69 178 }
Chris@69 179
Chris@69 180 QString path = origin;
Chris@69 181
Chris@72 182 if (m_argTypes[m_currentChoice] == DirectoryArg ||
Chris@72 183 m_argTypes[m_currentChoice] == UrlToDirectoryArg) {
Chris@69 184
Chris@69 185 path = QFileDialog::getExistingDirectory
Chris@69 186 (this, tr("Open Directory"), origin,
Chris@69 187 QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
Chris@69 188 if (path != QString()) {
Chris@72 189 m_fileCombo->lineEdit()->setText(path + QDir::separator());
Chris@69 190 }
Chris@69 191
Chris@69 192 } else {
Chris@69 193
Chris@69 194 path = QFileDialog::getOpenFileName
Chris@69 195 (this, tr("Open File"), origin);
Chris@69 196 if (path != QString()) {
Chris@72 197 m_fileCombo->lineEdit()->setText(path);
Chris@69 198 }
Chris@69 199 }
Chris@69 200 }
Chris@69 201
Chris@69 202 void
Chris@72 203 MultiChoiceDialog::urlChanged(const QString &s)
Chris@72 204 {
Chris@79 205 /* This doesn't work well
Chris@72 206 if (m_argTypes[m_currentChoice] != UrlToDirectoryArg) {
Chris@72 207 return;
Chris@72 208 }
Chris@72 209 QDir dirPath(m_fileCombo->currentText());
Chris@72 210 if (!dirPath.exists()) {
Chris@72 211 if (!dirPath.cdUp()) return;
Chris@72 212 }
Chris@72 213 QString url = m_urlCombo->currentText();
Chris@72 214 if (QRegExp("^\\w+://").indexIn(url) < 0) {
Chris@72 215 return;
Chris@72 216 }
Chris@72 217 QString urlDirName = url;
Chris@79 218 urlDirName.replace(QRegExp("^.*\\//.*\\/"), "");
Chris@72 219 if (urlDirName == "" || urlDirName == url) {
Chris@72 220 return;
Chris@72 221 }
Chris@72 222 m_fileCombo->lineEdit()->setText(dirPath.filePath(urlDirName));
Chris@79 223 */
Chris@79 224 if (m_argTypes[m_currentChoice] == UrlToDirectoryArg) {
Chris@79 225 m_okButton->setEnabled(getArgument() != "" &&
Chris@79 226 getAdditionalArgument() != "");
Chris@79 227 } else {
Chris@79 228 m_okButton->setEnabled(getArgument() != "");
Chris@79 229 }
Chris@72 230 }
Chris@72 231
Chris@72 232 void
Chris@74 233 MultiChoiceDialog::fileChanged(const QString &s)
Chris@74 234 {
Chris@74 235 if (m_argTypes[m_currentChoice] == UrlToDirectoryArg) {
Chris@74 236 m_okButton->setEnabled(getArgument() != "" &&
Chris@74 237 getAdditionalArgument() != "");
Chris@74 238 } else {
Chris@74 239 m_okButton->setEnabled(getArgument() != "");
Chris@74 240 }
Chris@74 241 }
Chris@74 242
Chris@74 243 void
Chris@69 244 MultiChoiceDialog::choiceChanged()
Chris@69 245 {
Chris@69 246 DEBUG << "choiceChanged" << endl;
Chris@69 247
Chris@69 248 if (m_choiceButtons.empty()) return;
Chris@69 249
Chris@69 250 QString id = "";
Chris@69 251
Chris@69 252 QObject *s = sender();
Chris@69 253 QWidget *w = qobject_cast<QWidget *>(s);
Chris@69 254 if (w) id = m_choiceButtons[w];
Chris@69 255
Chris@69 256 if (id == m_currentChoice) return;
Chris@69 257 if (id == "") {
Chris@69 258 // Happens when this is called for the very first time, when
Chris@69 259 // m_currentChoice has been set to the intended ID but no
Chris@69 260 // button has actually been pressed -- then we need to
Chris@69 261 // initialise
Chris@69 262 id = m_currentChoice;
Chris@69 263 }
Chris@69 264
Chris@69 265 m_currentChoice = id;
Chris@69 266
Chris@69 267 foreach (QWidget *cw, m_choiceButtons.keys()) {
Chris@69 268 SelectableLabel *sl = qobject_cast<SelectableLabel *>(cw);
Chris@69 269 if (sl) {
Chris@69 270 sl->setSelected(m_choiceButtons[cw] == id);
Chris@69 271 }
Chris@69 272 }
Chris@69 273
Chris@69 274 m_descriptionLabel->setText(m_descriptions[id]);
Chris@69 275
Chris@72 276 m_fileLabel->hide();
Chris@72 277 m_fileCombo->hide();
Chris@72 278 m_browseButton->hide();
Chris@72 279 m_urlLabel->hide();
Chris@72 280 m_urlCombo->hide();
Chris@72 281
Chris@72 282 QSharedPointer<RecentFiles> rf = m_recentFiles[id];
Chris@72 283 m_fileCombo->clear();
Chris@72 284 m_urlCombo->clear();
Chris@72 285
Chris@69 286 switch (m_argTypes[id]) {
Chris@69 287
Chris@69 288 case NoArg:
Chris@69 289 break;
Chris@69 290
Chris@69 291 case FileArg:
Chris@74 292 m_fileLabel->setText(tr("&File:"));
Chris@72 293 m_fileLabel->show();
Chris@72 294 m_fileCombo->show();
Chris@72 295 m_fileCombo->addItems(rf->getRecent());
Chris@69 296 m_browseButton->show();
Chris@69 297 break;
Chris@69 298
Chris@69 299 case DirectoryArg:
Chris@74 300 m_fileLabel->setText(tr("&Folder:"));
Chris@72 301 m_fileLabel->show();
Chris@72 302 m_fileCombo->show();
Chris@72 303 m_fileCombo->addItems(rf->getRecent());
Chris@69 304 m_browseButton->show();
Chris@69 305 break;
Chris@69 306
Chris@69 307 case UrlArg:
Chris@72 308 m_urlLabel->show();
Chris@72 309 m_urlCombo->show();
Chris@69 310 break;
Chris@69 311
Chris@72 312 case UrlToDirectoryArg:
Chris@72 313 m_urlLabel->show();
Chris@72 314 m_urlCombo->show();
Chris@72 315 m_urlCombo->addItems(rf->getRecent());
Chris@74 316 m_fileLabel->setText(tr("&Folder:"));
Chris@72 317 m_fileLabel->show();
Chris@72 318 m_fileCombo->show();
Chris@72 319 m_fileCombo->lineEdit()->setText(QDir::homePath());
Chris@69 320 m_browseButton->show();
Chris@69 321 break;
Chris@69 322 }
Chris@69 323
Chris@69 324 adjustSize();
Chris@69 325 }
Chris@69 326
Chris@69 327