annotate src/settingsdialog.cpp @ 385:5cc0d897eb26

Avoid crash when one of the data output callbacks is called after m_proc has already been reset (fixing #132)
author Chris Cannam <chris.cannam@eecs.qmul.ac.uk>
date Tue, 24 May 2011 13:29:27 +0100
parents b9c153e00e84
children c567fed39559
rev   line source
Chris@175 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@175 2
Chris@175 3 /*
Chris@175 4 EasyMercurial
Chris@175 5
Chris@175 6 Based on HgExplorer by Jari Korhonen
Chris@175 7 Copyright (c) 2010 Jari Korhonen
Chris@244 8 Copyright (c) 2011 Chris Cannam
Chris@244 9 Copyright (c) 2011 Queen Mary, University of London
Chris@175 10
Chris@175 11 This program is free software; you can redistribute it and/or
Chris@175 12 modify it under the terms of the GNU General Public License as
Chris@175 13 published by the Free Software Foundation; either version 2 of the
Chris@175 14 License, or (at your option) any later version. See the file
Chris@175 15 COPYING included with this distribution for more information.
Chris@175 16 */
Chris@175 17
Chris@175 18 #include "settingsdialog.h"
Chris@175 19 #include "common.h"
Chris@177 20 #include "debug.h"
Chris@175 21
Chris@175 22 #include <QGridLayout>
Chris@175 23 #include <QGroupBox>
Chris@175 24 #include <QDialogButtonBox>
Chris@175 25 #include <QSettings>
Chris@181 26 #include <QDir>
Chris@181 27 #include <QFileDialog>
Chris@273 28 #include <QMessageBox>
Chris@175 29
Chris@239 30 QString
Chris@239 31 SettingsDialog::m_installPath;
Chris@239 32
Chris@175 33 SettingsDialog::SettingsDialog(QWidget *parent) :
Chris@230 34 QDialog(parent),
Chris@230 35 m_presentationChanged(false)
Chris@175 36 {
Chris@175 37 setModal(true);
Chris@175 38 setWindowTitle(tr("Settings"));
Chris@175 39
Chris@175 40 QGridLayout *mainLayout = new QGridLayout;
Chris@175 41 setLayout(mainLayout);
Chris@175 42
Chris@230 43
Chris@230 44
Chris@181 45 QGroupBox *meBox = new QGroupBox(tr("User details"));
Chris@175 46 mainLayout->addWidget(meBox, 0, 0);
Chris@175 47 QGridLayout *meLayout = new QGridLayout;
Chris@175 48 meBox->setLayout(meLayout);
Chris@175 49
Chris@175 50 int row = 0;
Chris@175 51
Chris@175 52 meLayout->addWidget(new QLabel(tr("Name:")), row, 0);
Chris@175 53
Chris@175 54 m_nameEdit = new QLineEdit();
Chris@175 55 meLayout->addWidget(m_nameEdit, row++, 1);
Chris@175 56
Chris@175 57 meLayout->addWidget(new QLabel(tr("Email address:")), row, 0);
Chris@175 58
Chris@175 59 m_emailEdit = new QLineEdit();
Chris@175 60 meLayout->addWidget(m_emailEdit, row++, 1);
Chris@175 61
Chris@230 62
Chris@230 63
Chris@230 64 QGroupBox *lookBox = new QGroupBox(tr("Presentation"));
Chris@230 65 mainLayout->addWidget(lookBox, 1, 0);
Chris@230 66 QGridLayout *lookLayout = new QGridLayout;
Chris@230 67 lookBox->setLayout(lookLayout);
Chris@230 68
Chris@230 69 row = 0;
Chris@230 70
Chris@230 71 m_showIconLabels = new QCheckBox(tr("Show labels on toolbar icons"));
Chris@273 72 lookLayout->addWidget(m_showIconLabels, row++, 0, 1, 2);
Chris@230 73
Chris@230 74 m_showExtraText = new QCheckBox(tr("Show long descriptions for file status headings"));
Chris@273 75 lookLayout->addWidget(m_showExtraText, row++, 0, 1, 2);
Chris@273 76
Chris@273 77 #ifdef NOT_IMPLEMENTED_YET
Chris@273 78 lookLayout->addWidget(new QLabel(tr("Place the work and history views")), row, 0);
Chris@273 79 m_workHistoryArrangement = new QComboBox();
Chris@273 80 m_workHistoryArrangement->addItem(tr("In separate tabs"));
Chris@273 81 m_workHistoryArrangement->addItem(tr("Side-by-side in a single pane"));
Chris@273 82 lookLayout->addWidget(m_workHistoryArrangement, row++, 1, Qt::AlignLeft);
Chris@273 83 lookLayout->setColumnStretch(1, 20);
Chris@273 84 #endif
Chris@230 85
Chris@273 86 lookLayout->addWidget(new QLabel(tr("Label the history timeline with")), row, 0);
Chris@273 87 m_dateFormat = new QComboBox();
Chris@273 88 m_dateFormat->addItem(tr("Ages, for example \"5 weeks ago\""));
Chris@273 89 m_dateFormat->addItem(tr("Dates, for example \"2010-06-23\""));
Chris@273 90 lookLayout->addWidget(m_dateFormat, row++, 1, Qt::AlignLeft);
Chris@273 91 lookLayout->setColumnStretch(1, 20);
Chris@273 92
Chris@230 93
Chris@175 94 QGroupBox *pathsBox = new QGroupBox(tr("System application locations"));
Chris@230 95 mainLayout->addWidget(pathsBox, 2, 0);
Chris@175 96 QGridLayout *pathsLayout = new QGridLayout;
Chris@175 97 pathsBox->setLayout(pathsLayout);
Chris@175 98
Chris@175 99 row = 0;
Chris@175 100
Chris@175 101 pathsLayout->addWidget(new QLabel(tr("Mercurial (hg) program:")), row, 0);
Chris@175 102
Chris@195 103 m_hgPathLabel = new QLineEdit();
Chris@181 104 pathsLayout->addWidget(m_hgPathLabel, row, 2);
Chris@175 105
Chris@175 106 QPushButton *browse = new QPushButton(tr("Browse..."));
Chris@181 107 pathsLayout->addWidget(browse, row++, 1);
Chris@175 108 connect(browse, SIGNAL(clicked()), this, SLOT(hgPathBrowse()));
Chris@175 109
Chris@175 110 pathsLayout->addWidget(new QLabel(tr("External diff program:")), row, 0);
Chris@175 111
Chris@195 112 m_diffPathLabel = new QLineEdit();
Chris@181 113 pathsLayout->addWidget(m_diffPathLabel, row, 2);
Chris@175 114
Chris@175 115 browse = new QPushButton(tr("Browse..."));
Chris@181 116 pathsLayout->addWidget(browse, row++, 1);
Chris@175 117 connect(browse, SIGNAL(clicked()), this, SLOT(diffPathBrowse()));
Chris@178 118
Chris@175 119 pathsLayout->addWidget(new QLabel(tr("External file-merge program:")), row, 0);
Chris@175 120
Chris@195 121 m_mergePathLabel = new QLineEdit();
Chris@181 122 pathsLayout->addWidget(m_mergePathLabel, row, 2);
Chris@175 123
Chris@175 124 browse = new QPushButton(tr("Browse..."));
Chris@181 125 pathsLayout->addWidget(browse, row++, 1);
Chris@175 126 connect(browse, SIGNAL(clicked()), this, SLOT(mergePathBrowse()));
Chris@175 127
Chris@178 128 pathsLayout->addWidget(new QLabel(tr("External text editor:")), row, 0);
Chris@178 129
Chris@195 130 m_editPathLabel = new QLineEdit();
Chris@181 131 pathsLayout->addWidget(m_editPathLabel, row, 2);
Chris@178 132
Chris@178 133 browse = new QPushButton(tr("Browse..."));
Chris@181 134 pathsLayout->addWidget(browse, row++, 1);
Chris@178 135 connect(browse, SIGNAL(clicked()), this, SLOT(editPathBrowse()));
Chris@178 136
Chris@176 137 pathsLayout->addWidget(new QLabel(tr("EasyHg Mercurial extension:")), row, 0);
Chris@176 138
Chris@195 139 m_extensionPathLabel = new QLineEdit();
Chris@181 140 pathsLayout->addWidget(m_extensionPathLabel, row, 2);
Chris@176 141
Chris@176 142 browse = new QPushButton(tr("Browse..."));
Chris@181 143 pathsLayout->addWidget(browse, row++, 1);
Chris@176 144 connect(browse, SIGNAL(clicked()), this, SLOT(extensionPathBrowse()));
Chris@176 145
Chris@176 146 //!!! more info plz
Chris@176 147 m_useExtension = new QCheckBox(tr("Use EasyHg Mercurial extension"));
Chris@181 148 pathsLayout->addWidget(m_useExtension, row++, 2);
Chris@176 149
Chris@176 150
Chris@239 151 reset(); // loads current defaults from settings
Chris@175 152
Chris@230 153
Chris@175 154 QDialogButtonBox *bbox = new QDialogButtonBox(QDialogButtonBox::Ok);
Chris@239 155 connect(bbox->addButton(tr("Restore defaults"), QDialogButtonBox::ResetRole),
Chris@239 156 SIGNAL(clicked()), this, SLOT(restoreDefaults()));
Chris@175 157 connect(bbox, SIGNAL(accepted()), this, SLOT(accept()));
Chris@230 158 mainLayout->addWidget(bbox, 3, 0);
Chris@175 159 m_ok = bbox->button(QDialogButtonBox::Ok);
Chris@175 160 }
Chris@175 161
Chris@175 162 void
Chris@175 163 SettingsDialog::hgPathBrowse()
Chris@175 164 {
Chris@181 165 browseFor(tr("Mercurial program"), m_hgPathLabel);
Chris@175 166 }
Chris@175 167
Chris@175 168 void
Chris@175 169 SettingsDialog::diffPathBrowse()
Chris@175 170 {
Chris@181 171 browseFor(tr("External diff program"), m_diffPathLabel);
Chris@175 172 }
Chris@175 173
Chris@175 174 void
Chris@175 175 SettingsDialog::mergePathBrowse()
Chris@175 176 {
Chris@181 177 browseFor(tr("External file-merge program"), m_mergePathLabel);
Chris@175 178 }
Chris@175 179
Chris@175 180 void
Chris@178 181 SettingsDialog::editPathBrowse()
Chris@175 182 {
Chris@181 183 browseFor(tr("External text editor"), m_editPathLabel);
Chris@176 184 }
Chris@176 185
Chris@176 186 void
Chris@176 187 SettingsDialog::extensionPathBrowse()
Chris@176 188 {
Chris@181 189 browseFor(tr("EasyHg Mercurial extension"), m_extensionPathLabel);
Chris@181 190 }
Chris@181 191
Chris@181 192 void
Chris@195 193 SettingsDialog::browseFor(QString title, QLineEdit *edit)
Chris@181 194 {
Chris@181 195 QString origin = edit->text();
Chris@181 196
Chris@181 197 if (origin == "") {
Chris@181 198 #ifdef Q_OS_WIN32
Chris@181 199 origin = "c:";
Chris@181 200 #else
Chris@181 201 origin = QDir::homePath();
Chris@181 202 #endif
Chris@181 203 }
Chris@181 204
Chris@181 205 QString path = QFileDialog::getOpenFileName(this, title, origin);
Chris@181 206 if (path != QString()) {
Chris@181 207 edit->setText(path);
Chris@181 208 }
Chris@176 209 }
Chris@176 210
Chris@176 211 void
Chris@239 212 SettingsDialog::restoreDefaults()
Chris@239 213 {
Chris@273 214 if (QMessageBox::question
Chris@273 215 (this, tr("Restore default settings?"),
Chris@273 216 tr("<qt><b>Restore default settings?</b><br><br>Are you sure you want to reset all settings to their default values?"),
Chris@273 217 QMessageBox::Ok | QMessageBox::Cancel,
Chris@273 218 QMessageBox::Cancel) == QMessageBox::Ok) {
Chris@273 219 clear();
Chris@273 220 findDefaultLocations();
Chris@273 221 reset();
Chris@273 222 }
Chris@239 223 }
Chris@239 224
Chris@239 225 void
Chris@239 226 SettingsDialog::findDefaultLocations(QString installPath)
Chris@239 227 {
Chris@239 228 m_installPath = installPath;
Chris@239 229 findHgBinaryName();
Chris@239 230 findExtension();
Chris@239 231 findDiffBinaryName();
Chris@239 232 findMergeBinaryName();
Chris@239 233 findEditorBinaryName();
Chris@239 234 }
Chris@239 235
Chris@239 236 void
Chris@239 237 SettingsDialog::findHgBinaryName()
Chris@239 238 {
Chris@239 239 QSettings settings;
Chris@239 240 settings.beginGroup("Locations");
Chris@239 241 QString hg = settings.value("hgbinary", "").toString();
Chris@239 242 if (hg == "") {
Chris@239 243 hg = findInPath("hg", m_installPath, true);
Chris@239 244 }
Chris@239 245 if (hg != "") {
Chris@239 246 settings.setValue("hgbinary", hg);
Chris@239 247 }
Chris@239 248 }
Chris@239 249
Chris@240 250 QString
Chris@240 251 SettingsDialog::getUnbundledExtensionFileName()
Chris@240 252 {
Chris@240 253 QString home = QDir::homePath();
Chris@240 254 QString target = QString("%1/.easyhg").arg(home);
Chris@240 255 QString extpath = QString("%1/easyhg.py").arg(target);
Chris@240 256 return extpath;
Chris@240 257 }
Chris@240 258
Chris@239 259 void
Chris@239 260 SettingsDialog::findExtension()
Chris@239 261 {
Chris@239 262 QSettings settings;
Chris@239 263 settings.beginGroup("Locations");
Chris@239 264
Chris@239 265 QString extpath = settings.value("extensionpath", "").toString();
Chris@239 266 if (extpath != "" || !QFile(extpath).exists()) {
Chris@239 267
Chris@240 268 extpath = getUnbundledExtensionFileName();
Chris@239 269
Chris@239 270 if (!QFile(extpath).exists()) {
Chris@239 271 extpath = findInPath("easyhg.py", m_installPath, false);
Chris@239 272 }
Chris@239 273 }
Chris@239 274
Chris@239 275 settings.setValue("extensionpath", extpath);
Chris@239 276 }
Chris@239 277
Chris@239 278 void
Chris@239 279 SettingsDialog::findDiffBinaryName()
Chris@239 280 {
Chris@239 281 QSettings settings;
Chris@239 282 settings.beginGroup("Locations");
Chris@239 283 QString diff = settings.value("extdiffbinary", "").toString();
Chris@239 284 if (diff == "") {
Chris@239 285 QStringList bases;
Chris@272 286 #ifdef Q_OS_WIN32
Chris@272 287 bases << "easyhg-extdiff.bat";
Chris@272 288 #else
Chris@269 289 bases << "easyhg-extdiff.sh";
Chris@272 290 #endif
Chris@239 291 bases << "kompare" << "kdiff3" << "meld";
Chris@239 292 bool found = false;
Chris@239 293 foreach (QString base, bases) {
Chris@239 294 diff = findInPath(base, m_installPath, true);
Chris@239 295 if (diff != "") {
Chris@239 296 found = true;
Chris@239 297 break;
Chris@239 298 }
Chris@239 299 }
Chris@239 300 if (found) {
Chris@239 301 settings.setValue("extdiffbinary", diff);
Chris@239 302 }
Chris@239 303 }
Chris@239 304 }
Chris@239 305
Chris@239 306 void
Chris@239 307 SettingsDialog::findMergeBinaryName()
Chris@239 308 {
Chris@239 309 QSettings settings;
Chris@239 310 settings.beginGroup("Locations");
Chris@239 311 if (settings.contains("mergebinary")) {
Chris@239 312 return;
Chris@239 313 }
Chris@239 314 QString merge;
Chris@239 315 QStringList bases;
Chris@272 316 #ifdef Q_OS_WIN32
Chris@272 317 bases << "easyhg-merge.bat";
Chris@272 318 #else
Chris@269 319 bases << "easyhg-merge.sh";
Chris@272 320 #endif
Chris@269 321 // NB it's not a good idea to add other tools here, as command
Chris@269 322 // line argument ordering varies. Configure them through hgrc
Chris@269 323 // instead
Chris@239 324 bool found = false;
Chris@239 325 foreach (QString base, bases) {
Chris@239 326 merge = findInPath(base, m_installPath, true);
Chris@239 327 if (merge != "") {
Chris@239 328 found = true;
Chris@239 329 break;
Chris@239 330 }
Chris@239 331 }
Chris@239 332 if (found) {
Chris@239 333 settings.setValue("mergebinary", merge);
Chris@239 334 }
Chris@239 335 }
Chris@239 336
Chris@239 337 void
Chris@239 338 SettingsDialog::findEditorBinaryName()
Chris@239 339 {
Chris@239 340 QSettings settings;
Chris@239 341 settings.beginGroup("Locations");
Chris@239 342 QString editor = settings.value("editorbinary", "").toString();
Chris@239 343 if (editor == "") {
Chris@239 344 QStringList bases;
Chris@239 345 bases
Chris@239 346 #if defined Q_OS_WIN32
Chris@239 347 << "wordpad.exe"
Chris@239 348 << "C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe"
Chris@239 349 << "notepad.exe"
Chris@239 350 #elif defined Q_OS_MAC
Chris@239 351 << "/Applications/TextEdit.app/Contents/MacOS/TextEdit"
Chris@239 352 #else
Chris@239 353 << "gedit" << "kate"
Chris@239 354 #endif
Chris@239 355 ;
Chris@239 356 bool found = false;
Chris@239 357 foreach (QString base, bases) {
Chris@239 358 editor = findInPath(base, m_installPath, true);
Chris@239 359 if (editor != "") {
Chris@239 360 found = true;
Chris@239 361 break;
Chris@239 362 }
Chris@239 363 }
Chris@239 364 if (found) {
Chris@239 365 settings.setValue("editorbinary", editor);
Chris@239 366 }
Chris@239 367 }
Chris@239 368 }
Chris@239 369
Chris@239 370 void
Chris@239 371 SettingsDialog::clear()
Chris@239 372 {
Chris@239 373 // Clear everything that has a default setting
Chris@239 374 DEBUG << "SettingsDialog::clear" << endl;
Chris@239 375 QSettings settings;
Chris@239 376 settings.beginGroup("Presentation");
Chris@239 377 settings.remove("showiconlabels");
Chris@239 378 settings.remove("showhelpfultext");
Chris@239 379 settings.endGroup();
Chris@239 380 settings.beginGroup("Locations");
Chris@239 381 settings.remove("hgbinary");
Chris@239 382 settings.remove("extdiffbinary");
Chris@239 383 settings.remove("mergebinary");
Chris@239 384 settings.remove("editorbinary");
Chris@239 385 settings.remove("extensionpath");
Chris@239 386 settings.endGroup();
Chris@239 387 settings.beginGroup("General");
Chris@239 388 settings.remove("useextension");
Chris@239 389 settings.endGroup();
Chris@239 390 }
Chris@239 391
Chris@239 392 void
Chris@239 393 SettingsDialog::reset()
Chris@239 394 {
Chris@239 395 DEBUG << "SettingsDialog::reset" << endl;
Chris@239 396 QSettings settings;
Chris@239 397 settings.beginGroup("User Information");
Chris@239 398 m_nameEdit->setText(settings.value("name", getUserRealName()).toString());
Chris@239 399 m_emailEdit->setText(settings.value("email").toString());
Chris@239 400 settings.endGroup();
Chris@239 401 settings.beginGroup("Presentation");
Chris@239 402 m_showIconLabels->setChecked(settings.value("showiconlabels", true).toBool());
Chris@239 403 m_showExtraText->setChecked(settings.value("showhelpfultext", true).toBool());
Chris@273 404 #ifdef NOT_IMPLEMENTED_YET
Chris@273 405 m_workHistoryArrangement->setCurrentIndex(settings.value("workhistoryarrangement", 0).toInt());
Chris@273 406 #endif
Chris@273 407 m_dateFormat->setCurrentIndex(settings.value("dateformat", 0).toInt());
Chris@239 408 settings.endGroup();
Chris@239 409 settings.beginGroup("Locations");
Chris@239 410 m_hgPathLabel->setText(settings.value("hgbinary").toString());
Chris@239 411 m_diffPathLabel->setText(settings.value("extdiffbinary").toString());
Chris@239 412 m_mergePathLabel->setText(settings.value("mergebinary").toString());
Chris@239 413 m_editPathLabel->setText(settings.value("editorbinary").toString());
Chris@239 414 m_extensionPathLabel->setText(settings.value("extensionpath").toString());
Chris@239 415 settings.endGroup();
Chris@239 416 settings.beginGroup("General");
Chris@239 417 m_useExtension->setChecked(settings.value("useextension", true).toBool());
Chris@239 418 settings.endGroup();
Chris@239 419 }
Chris@239 420
Chris@239 421 void
Chris@175 422 SettingsDialog::accept()
Chris@175 423 {
Chris@177 424 DEBUG << "SettingsDialog::accept" << endl;
Chris@175 425 QSettings settings;
Chris@175 426 settings.beginGroup("User Information");
Chris@175 427 settings.setValue("name", m_nameEdit->text());
Chris@175 428 settings.setValue("email", m_emailEdit->text());
Chris@175 429 settings.endGroup();
Chris@230 430 settings.beginGroup("Presentation");
Chris@230 431 bool b;
Chris@230 432 b = m_showIconLabels->isChecked();
Chris@230 433 if (b != settings.value("showiconlabels", true)) {
Chris@230 434 settings.setValue("showiconlabels", b);
Chris@230 435 m_presentationChanged = true;
Chris@230 436 }
Chris@230 437 b = m_showExtraText->isChecked();
Chris@230 438 if (b != settings.value("showhelpfultext", true)) {
Chris@230 439 settings.setValue("showhelpfultext", b);
Chris@230 440 m_presentationChanged = true;
Chris@230 441 }
Chris@273 442 int i;
Chris@273 443 #ifdef NOT_IMPLEMENTED_YET
Chris@273 444 i = m_workHistoryArrangement->currentIndex();
Chris@273 445 if (i != settings.value("workhistoryarrangement", 0)) {
Chris@273 446 settings.setValue("workhistoryarrangement", i);
Chris@273 447 m_presentationChanged = true;
Chris@273 448 }
Chris@273 449 #endif
Chris@273 450 i = m_dateFormat->currentIndex();
Chris@273 451 if (i != settings.value("dateformat", 0)) {
Chris@273 452 settings.setValue("dateformat", i);
Chris@273 453 m_presentationChanged = true;
Chris@273 454 }
Chris@230 455 settings.endGroup();
Chris@175 456 settings.beginGroup("Locations");
Chris@181 457 settings.setValue("hgbinary", m_hgPathLabel->text());
Chris@181 458 settings.setValue("extdiffbinary", m_diffPathLabel->text());
Chris@181 459 settings.setValue("mergebinary", m_mergePathLabel->text());
Chris@221 460 settings.setValue("editorbinary", m_editPathLabel->text());
Chris@181 461 settings.setValue("extensionpath", m_extensionPathLabel->text());
Chris@176 462 settings.endGroup();
Chris@176 463 settings.beginGroup("General");
Chris@176 464 settings.setValue("useextension", m_useExtension->isChecked());
Chris@175 465 settings.endGroup();
Chris@175 466 QDialog::accept();
Chris@175 467 }
Chris@175 468
Chris@175 469