Chris@67: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@67: Chris@67: /* Chris@67: EasyMercurial Chris@67: Chris@67: Based on HgExplorer by Jari Korhonen Chris@67: Copyright (c) 2010 Jari Korhonen Chris@644: Copyright (c) 2013 Chris Cannam Chris@644: Copyright (c) 2013 Queen Mary, University of London Chris@67: Chris@67: This program is free software; you can redistribute it and/or Chris@67: modify it under the terms of the GNU General Public License as Chris@67: published by the Free Software Foundation; either version 2 of the Chris@67: License, or (at your option) any later version. See the file Chris@67: COPYING included with this distribution for more information. Chris@67: */ Chris@67: Chris@67: #include "multichoicedialog.h" Chris@67: Chris@69: #include "selectablelabel.h" Chris@69: Chris@69: #include "debug.h" Chris@69: Chris@68: #include Chris@69: #include Chris@69: #include Chris@69: #include Chris@69: #include Chris@69: #include Chris@72: #include Chris@68: Chris@68: MultiChoiceDialog::MultiChoiceDialog(QString title, QString heading, QWidget *parent) : Chris@67: QDialog(parent) Chris@67: { Chris@68: setModal(true); Chris@68: setWindowTitle(title); Chris@68: Chris@68: QGridLayout *outer = new QGridLayout; Chris@68: setLayout(outer); Chris@68: Chris@68: outer->addWidget(new QLabel(heading), 0, 0, 1, 3); Chris@68: Chris@68: QWidget *innerWidget = new QWidget; Chris@69: outer->addWidget(innerWidget, 1, 0, 1, 3); Chris@69: m_choiceLayout = new QHBoxLayout; Chris@68: innerWidget->setLayout(m_choiceLayout); Chris@68: Chris@68: m_descriptionLabel = new QLabel; Chris@68: outer->addWidget(m_descriptionLabel, 2, 0, 1, 3); Chris@68: Chris@69: QFont f = m_descriptionLabel->font(); Chris@202: f.setPointSize(f.pointSize() * 0.95); Chris@69: m_descriptionLabel->setFont(f); Chris@69: Chris@74: m_urlLabel = new QLabel(tr("&URL:")); Chris@72: outer->addWidget(m_urlLabel, 3, 0); Chris@68: Chris@72: m_urlCombo = new QComboBox(); Chris@72: m_urlCombo->setEditable(true); Chris@74: m_urlLabel->setBuddy(m_urlCombo); Chris@72: connect(m_urlCombo, SIGNAL(editTextChanged(const QString &)), Chris@72: this, SLOT(urlChanged(const QString &))); Chris@72: outer->addWidget(m_urlCombo, 3, 1, 1, 2); Chris@72: Chris@74: m_fileLabel = new QLabel(tr("&File:")); Chris@72: outer->addWidget(m_fileLabel, 4, 0); Chris@72: Chris@72: m_fileCombo = new QComboBox(); Chris@72: m_fileCombo->setEditable(true); Chris@74: m_fileLabel->setBuddy(m_fileCombo); Chris@74: connect(m_fileCombo, SIGNAL(editTextChanged(const QString &)), Chris@74: this, SLOT(fileChanged(const QString &))); Chris@72: outer->addWidget(m_fileCombo, 4, 1); Chris@69: outer->setColumnStretch(1, 20); Chris@68: Chris@68: m_browseButton = new QPushButton(tr("Browse...")); Chris@72: outer->addWidget(m_browseButton, 4, 2); Chris@69: connect(m_browseButton, SIGNAL(clicked()), this, SLOT(browse())); Chris@68: Chris@68: QDialogButtonBox *bbox = new QDialogButtonBox(QDialogButtonBox::Ok | Chris@68: QDialogButtonBox::Cancel); Chris@68: connect(bbox, SIGNAL(accepted()), this, SLOT(accept())); Chris@68: connect(bbox, SIGNAL(rejected()), this, SLOT(reject())); Chris@72: outer->addWidget(bbox, 5, 0, 1, 3); Chris@74: Chris@74: m_okButton = bbox->button(QDialogButtonBox::Ok); Chris@199: updateOkButton(); Chris@74: Chris@69: setMinimumWidth(480); Chris@67: } Chris@68: Chris@69: QString Chris@69: MultiChoiceDialog::getCurrentChoice() Chris@69: { Chris@69: return m_currentChoice; Chris@69: } Chris@69: Chris@69: void Chris@69: MultiChoiceDialog::setCurrentChoice(QString c) Chris@69: { Chris@69: m_currentChoice = c; Chris@69: choiceChanged(); Chris@69: } Chris@69: Chris@69: QString Chris@69: MultiChoiceDialog::getArgument() Chris@69: { Chris@72: if (m_argTypes[m_currentChoice] == UrlArg || Chris@72: m_argTypes[m_currentChoice] == UrlToDirectoryArg) { Chris@72: return m_urlCombo->currentText(); Chris@72: } else { Chris@72: return m_fileCombo->currentText(); Chris@72: } Chris@72: } Chris@72: Chris@72: QString Chris@72: MultiChoiceDialog::getAdditionalArgument() Chris@72: { Chris@72: if (m_argTypes[m_currentChoice] == UrlToDirectoryArg) { Chris@72: return m_fileCombo->currentText(); Chris@72: } else { Chris@72: return ""; Chris@72: } Chris@69: } Chris@69: Chris@69: void Chris@72: MultiChoiceDialog::addRecentArgument(QString id, QString arg, Chris@72: bool additionalArgument) Chris@69: { Chris@72: if (additionalArgument) { Chris@72: RecentFiles(QString("Recent-%1-add").arg(id)).addFile(arg); Chris@72: } else { Chris@72: RecentFiles(QString("Recent-%1").arg(id)).addFile(arg); Chris@72: } Chris@69: } Chris@69: Chris@69: void Chris@69: MultiChoiceDialog::addChoice(QString id, QString text, Chris@553: QString description, ArgType arg, Chris@553: bool defaultEmpty) Chris@69: { Chris@69: bool first = (m_texts.empty()); Chris@69: Chris@69: m_texts[id] = text; Chris@69: m_descriptions[id] = description; Chris@69: m_argTypes[id] = arg; Chris@553: m_defaultEmpty[id] = defaultEmpty; Chris@69: Chris@69: if (arg != NoArg) { Chris@69: m_recentFiles[id] = QSharedPointer Chris@69: (new RecentFiles(QString("Recent-%1").arg(id))); Chris@69: } Chris@69: Chris@69: SelectableLabel *cb = new SelectableLabel; Chris@69: cb->setSelectedText(text); Chris@69: cb->setUnselectedText(text); Chris@183: cb->setMaximumWidth(270); Chris@69: Chris@69: m_choiceLayout->addWidget(cb); Chris@69: m_choiceButtons[cb] = id; Chris@69: Chris@69: connect(cb, SIGNAL(selectionChanged()), this, SLOT(choiceChanged())); Chris@69: Chris@69: if (first) { Chris@69: m_currentChoice = id; Chris@69: choiceChanged(); Chris@69: } Chris@69: } Chris@69: Chris@342: QString Chris@342: MultiChoiceDialog::getDefaultPath() const Chris@342: { Chris@342: QDir home(QDir::home()); Chris@342: QDir dflt; Chris@342: Chris@483: dflt = QDir(home.filePath(tr("Documents"))); Chris@483: DEBUG << "testing " << dflt << endl; Chris@483: if (dflt.exists()) return dflt.canonicalPath(); Chris@483: Chris@342: dflt = QDir(home.filePath(tr("My Documents"))); Chris@342: DEBUG << "testing " << dflt << endl; Chris@342: if (dflt.exists()) return dflt.canonicalPath(); Chris@342: Chris@483: dflt = QDir(home.filePath(tr("Desktop"))); Chris@342: DEBUG << "testing " << dflt << endl; Chris@342: if (dflt.exists()) return dflt.canonicalPath(); Chris@342: Chris@342: DEBUG << "all failed, returning " << home << endl; Chris@342: return home.canonicalPath(); Chris@342: } Chris@342: Chris@69: void Chris@69: MultiChoiceDialog::browse() Chris@69: { Chris@69: QString origin = getArgument(); Chris@69: Chris@69: if (origin == "") { Chris@342: origin = getDefaultPath(); Chris@69: } Chris@69: Chris@69: QString path = origin; Chris@69: Chris@72: if (m_argTypes[m_currentChoice] == DirectoryArg || Chris@72: m_argTypes[m_currentChoice] == UrlToDirectoryArg) { Chris@69: Chris@69: path = QFileDialog::getExistingDirectory Chris@69: (this, tr("Open Directory"), origin, Chris@69: QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); Chris@69: if (path != QString()) { Chris@72: m_fileCombo->lineEdit()->setText(path + QDir::separator()); Chris@69: } Chris@69: Chris@69: } else { Chris@69: Chris@69: path = QFileDialog::getOpenFileName Chris@69: (this, tr("Open File"), origin); Chris@69: if (path != QString()) { Chris@72: m_fileCombo->lineEdit()->setText(path); Chris@69: } Chris@69: } Chris@69: } Chris@69: Chris@69: void Chris@671: MultiChoiceDialog::urlChanged(const QString &) Chris@72: { Chris@199: updateOkButton(); Chris@483: updateFileComboFromURL(); Chris@199: } Chris@199: Chris@199: void Chris@671: MultiChoiceDialog::fileChanged(const QString &) Chris@199: { Chris@199: updateOkButton(); Chris@199: } Chris@199: Chris@199: void Chris@483: MultiChoiceDialog::updateFileComboFromURL() Chris@199: { Chris@72: if (m_argTypes[m_currentChoice] != UrlToDirectoryArg) { Chris@72: return; Chris@72: } Chris@72: QString url = m_urlCombo->currentText(); Chris@72: if (QRegExp("^\\w+://").indexIn(url) < 0) { Chris@72: return; Chris@72: } Chris@72: QString urlDirName = url; Chris@79: urlDirName.replace(QRegExp("^.*\\//.*\\/"), ""); Chris@72: if (urlDirName == "" || urlDirName == url) { Chris@72: return; Chris@72: } Chris@483: QString dirPath = m_fileCombo->currentText(); Chris@483: QString defaultPath = getDefaultPath(); Chris@483: if (dirPath == defaultPath) { Chris@483: dirPath += QDir::separator() + urlDirName; Chris@483: } else if (dirPath == defaultPath + QDir::separator()) { Chris@483: dirPath += urlDirName; Chris@483: } else { Chris@483: QDir d(dirPath); Chris@483: d.cdUp(); Chris@483: dirPath = d.filePath(urlDirName); Chris@483: } Chris@483: m_fileCombo->lineEdit()->setText(dirPath); Chris@483: } Chris@483: Chris@483: void Chris@483: MultiChoiceDialog::updateOkButton() Chris@483: { Chris@565: if (m_defaultEmpty[m_currentChoice]) { Chris@565: m_okButton->setEnabled(true); Chris@565: } else if (m_argTypes[m_currentChoice] == UrlToDirectoryArg) { Chris@79: m_okButton->setEnabled(getArgument() != "" && Chris@79: getAdditionalArgument() != ""); Chris@79: } else { Chris@79: m_okButton->setEnabled(getArgument() != ""); Chris@79: } Chris@72: } Chris@72: Chris@604: bool Chris@604: MultiChoiceDialog::urlComboNotUrl() const Chris@604: { Chris@604: QString url = m_urlCombo->currentText(); Chris@604: if (QRegExp("^\\w+://").indexIn(url) < 0) { Chris@604: return true; Chris@604: } else { Chris@604: return false; Chris@604: } Chris@604: } Chris@604: Chris@72: void Chris@69: MultiChoiceDialog::choiceChanged() Chris@69: { Chris@69: DEBUG << "choiceChanged" << endl; Chris@69: Chris@69: if (m_choiceButtons.empty()) return; Chris@69: Chris@69: QString id = ""; Chris@69: Chris@69: QObject *s = sender(); Chris@69: QWidget *w = qobject_cast(s); Chris@69: if (w) id = m_choiceButtons[w]; Chris@69: Chris@69: if (id == m_currentChoice) return; Chris@69: if (id == "") { Chris@69: // Happens when this is called for the very first time, when Chris@69: // m_currentChoice has been set to the intended ID but no Chris@69: // button has actually been pressed -- then we need to Chris@69: // initialise Chris@69: id = m_currentChoice; Chris@69: } Chris@69: Chris@69: m_currentChoice = id; Chris@69: Chris@69: foreach (QWidget *cw, m_choiceButtons.keys()) { Chris@69: SelectableLabel *sl = qobject_cast(cw); Chris@69: if (sl) { Chris@69: sl->setSelected(m_choiceButtons[cw] == id); Chris@69: } Chris@69: } Chris@69: Chris@69: m_descriptionLabel->setText(m_descriptions[id]); Chris@69: Chris@72: m_browseButton->hide(); Chris@483: Chris@72: m_urlLabel->hide(); Chris@483: m_urlCombo->clear(); Chris@72: m_urlCombo->hide(); Chris@72: Chris@483: m_fileLabel->hide(); Chris@483: m_fileCombo->clear(); Chris@483: m_fileCombo->hide(); Chris@483: Chris@72: QSharedPointer rf = m_recentFiles[id]; Chris@72: Chris@69: switch (m_argTypes[id]) { Chris@69: Chris@69: case NoArg: Chris@69: break; Chris@69: Chris@69: case FileArg: Chris@74: m_fileLabel->setText(tr("&File:")); Chris@72: m_fileLabel->show(); Chris@72: m_fileCombo->show(); Chris@72: m_fileCombo->addItems(rf->getRecent()); Chris@553: if (m_defaultEmpty[id]) m_fileCombo->lineEdit()->setText(""); Chris@69: m_browseButton->show(); Chris@69: break; Chris@69: Chris@69: case DirectoryArg: Chris@74: m_fileLabel->setText(tr("&Folder:")); Chris@72: m_fileLabel->show(); Chris@72: m_fileCombo->show(); Chris@72: m_fileCombo->addItems(rf->getRecent()); Chris@553: if (m_defaultEmpty[id]) m_fileCombo->lineEdit()->setText(""); Chris@69: m_browseButton->show(); Chris@69: break; Chris@69: Chris@69: case UrlArg: Chris@72: m_urlLabel->show(); Chris@72: m_urlCombo->show(); Chris@183: m_urlCombo->addItems(rf->getRecent()); Chris@604: if (m_defaultEmpty[id] || urlComboNotUrl()) { Chris@604: m_urlCombo->lineEdit()->setText(""); Chris@604: } Chris@69: break; Chris@69: Chris@72: case UrlToDirectoryArg: Chris@72: m_urlLabel->show(); Chris@72: m_urlCombo->show(); Chris@72: m_urlCombo->addItems(rf->getRecent()); Chris@604: if (m_defaultEmpty[id] || urlComboNotUrl()) { Chris@604: m_urlCombo->lineEdit()->setText(""); Chris@604: } Chris@74: m_fileLabel->setText(tr("&Folder:")); Chris@72: m_fileLabel->show(); Chris@72: m_fileCombo->show(); Chris@342: m_fileCombo->lineEdit()->setText(getDefaultPath()); Chris@483: updateFileComboFromURL(); Chris@69: m_browseButton->show(); Chris@69: break; Chris@69: } Chris@69: Chris@199: updateOkButton(); Chris@69: adjustSize(); Chris@69: } Chris@69: Chris@69: