annotate mainwindow.cpp @ 164:de39da2f9f4d

* (Re)implement tagging
author Chris Cannam
date Fri, 03 Dec 2010 20:37:40 +0000
parents 5c262ac73948
children 4bad3c5c053a
rev   line source
Chris@57 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
jtkorhonen@0 2
Chris@57 3 /*
Chris@57 4 EasyMercurial
Chris@57 5
Chris@98 6 Based on hgExplorer by Jari Korhonen
Chris@57 7 Copyright (c) 2010 Jari Korhonen
Chris@57 8 Copyright (c) 2010 Chris Cannam
Chris@57 9 Copyright (c) 2010 Queen Mary, University of London
Chris@57 10
Chris@57 11 This program is free software; you can redistribute it and/or
Chris@57 12 modify it under the terms of the GNU General Public License as
Chris@57 13 published by the Free Software Foundation; either version 2 of the
Chris@57 14 License, or (at your option) any later version. See the file
Chris@57 15 COPYING included with this distribution for more information.
Chris@57 16 */
Chris@50 17
jtkorhonen@0 18 #include <QStringList>
jtkorhonen@0 19 #include <QDir>
jtkorhonen@24 20 #include <QNetworkInterface>
jtkorhonen@17 21 #include <QHostAddress>
jtkorhonen@17 22 #include <QHostInfo>
jtkorhonen@34 23 #include <QDesktopServices>
Chris@50 24 #include <QStatusBar>
Chris@50 25 #include <QMessageBox>
Chris@50 26 #include <QMenuBar>
Chris@50 27 #include <QApplication>
Chris@50 28 #include <QToolBar>
Chris@61 29 #include <QToolButton>
Chris@50 30 #include <QSettings>
Chris@90 31 #include <QInputDialog>
Chris@125 32 #include <QRegExp>
jtkorhonen@0 33
Chris@53 34 #include "mainwindow.h"
Chris@69 35 #include "multichoicedialog.h"
Chris@64 36 #include "startupdialog.h"
Chris@53 37 #include "colourset.h"
Chris@62 38 #include "debug.h"
Chris@74 39 #include "logparser.h"
Chris@103 40 #include "confirmcommentdialog.h"
Chris@125 41 #include "incomingdialog.h"
Chris@53 42
jtkorhonen@0 43
jtkorhonen@0 44 MainWindow::MainWindow()
jtkorhonen@0 45 {
jtkorhonen@0 46 QString wndTitle;
jtkorhonen@0 47
Chris@90 48 fsWatcher = 0;
Chris@133 49 commitsSincePush = 0;
Chris@163 50 shouldHgStat = true;
Chris@90 51
jtkorhonen@0 52 createActions();
jtkorhonen@0 53 createMenus();
jtkorhonen@0 54 createToolBars();
jtkorhonen@0 55 createStatusBar();
jtkorhonen@0 56
jtkorhonen@0 57 runner = new HgRunner(this);
Chris@109 58 connect(runner, SIGNAL(commandCompleted(HgAction, QString)),
Chris@109 59 this, SLOT(commandCompleted(HgAction, QString)));
Chris@109 60 connect(runner, SIGNAL(commandFailed(HgAction, QString)),
Chris@109 61 this, SLOT(commandFailed(HgAction, QString)));
jtkorhonen@0 62 statusBar()->addPermanentWidget(runner);
jtkorhonen@0 63
Chris@61 64 setWindowTitle(tr("EasyMercurial"));
jtkorhonen@0 65
jtkorhonen@0 66 remoteRepoPath = "";
jtkorhonen@0 67 workFolderPath = "";
jtkorhonen@0 68
jtkorhonen@0 69 readSettings();
jtkorhonen@0 70
jtkorhonen@33 71 justMerged = false;
Chris@98 72 hgTabs = new HgTabWidget((QWidget *) this, remoteRepoPath, workFolderPath);
Chris@141 73 connectTabsSignals();
Chris@98 74 setCentralWidget(hgTabs);
jtkorhonen@0 75
Chris@98 76 connect(hgTabs, SIGNAL(selectionChanged()),
Chris@95 77 this, SLOT(enableDisableActions()));
Chris@95 78
jtkorhonen@0 79 setUnifiedTitleAndToolBarOnMac(true);
jtkorhonen@0 80 connectActions();
Chris@120 81 clearState();
jtkorhonen@0 82 enableDisableActions();
jtkorhonen@0 83
Chris@64 84 if (firstStart) {
Chris@64 85 startupDialog();
jtkorhonen@0 86 }
jtkorhonen@0 87
Chris@112 88 findDiffBinaryName();
Chris@163 89 findMergeBinaryName();
Chris@112 90
Chris@64 91 ColourSet *cs = ColourSet::instance();
Chris@64 92 cs->clearDefaultNames();
Chris@64 93 cs->addDefaultName("");
Chris@153 94 cs->addDefaultName("default");
Chris@64 95 cs->addDefaultName(getUserInfo());
Chris@62 96
Chris@72 97 if (workFolderPath == "") {
Chris@72 98 open();
Chris@72 99 }
Chris@72 100
Chris@109 101 hgQueryPaths();
jtkorhonen@0 102 }
jtkorhonen@0 103
jtkorhonen@0 104
jtkorhonen@0 105 void MainWindow::closeEvent(QCloseEvent *)
jtkorhonen@0 106 {
jtkorhonen@0 107 writeSettings();
Chris@90 108 delete fsWatcher;
jtkorhonen@0 109 }
jtkorhonen@0 110
jtkorhonen@0 111
Chris@64 112 QString MainWindow::getUserInfo() const
Chris@64 113 {
Chris@64 114 QSettings settings;
Chris@64 115 settings.beginGroup("User Information");
Chris@64 116 QString name = settings.value("name", getUserRealName()).toString();
Chris@64 117 QString email = settings.value("email", "").toString();
Chris@64 118
Chris@64 119 QString identifier;
Chris@64 120
Chris@64 121 if (email != "") {
Chris@64 122 identifier = QString("%1 <%2>").arg(name).arg(email);
Chris@64 123 } else {
Chris@64 124 identifier = name;
Chris@64 125 }
Chris@64 126
Chris@64 127 return identifier;
Chris@64 128 }
Chris@64 129
jtkorhonen@0 130 void MainWindow::about()
jtkorhonen@0 131 {
Chris@97 132 QMessageBox::about(this, tr("About EasyMercurial"),
Chris@97 133 tr("<qt><h2>About EasyMercurial</h2>"
Chris@97 134 "<p>EasyMercurial is a simple user interface for the "
Chris@97 135 "Mercurial version control system.</p>"
Chris@98 136 "<p>EasyMercurial is based on hgExplorer by "
Chris@97 137 "Jari Korhonen, with thanks.<br>EasyMercurial development carried out by "
Chris@97 138 "Chris Cannam for soundsoftware.ac.uk at the Centre for Digital Music, Queen Mary, University of London."
Chris@97 139 "<ul><li>Copyright &copy; 2010 Jari Korhonen</li>"
Chris@97 140 "<li>Copyright &copy; 2010 Chris Cannam</li>"
Chris@97 141 "<li>Copyright &copy; 2010 Queen Mary, University of London</li>"
Chris@97 142 "</ul>"
Chris@97 143 "<p> This program is free software; you can redistribute it and/or "
Chris@97 144 "modify it under the terms of the GNU General Public License as "
Chris@97 145 "published by the Free Software Foundation; either version 2 of the "
Chris@97 146 "License, or (at your option) any later version. See the file "
Chris@97 147 "COPYING included with this distribution for more information."));
jtkorhonen@0 148 }
jtkorhonen@0 149
Chris@94 150 void MainWindow::clearSelections()
Chris@94 151 {
Chris@98 152 hgTabs->clearSelections();
Chris@94 153 }
jtkorhonen@0 154
Chris@120 155 void MainWindow::hgRefresh()
Chris@120 156 {
Chris@120 157 clearState();
Chris@120 158 hgQueryPaths();
Chris@120 159 }
Chris@120 160
jtkorhonen@0 161 void MainWindow::hgStat()
jtkorhonen@0 162 {
Chris@109 163 QStringList params;
Chris@109 164 params << "stat" << "-ardum";
Chris@153 165
Chris@163 166 lastStatOutput = "";
Chris@163 167
Chris@153 168 // annoyingly, hg stat actually modifies the working directory --
Chris@153 169 // it creates files called hg-checklink and hg-checkexec to test
Chris@153 170 // properties of the filesystem
Chris@153 171 if (fsWatcher) fsWatcher->blockSignals(true);
Chris@153 172
Chris@109 173 runner->requestAction(HgAction(ACT_STAT, workFolderPath, params));
jtkorhonen@0 174 }
jtkorhonen@0 175
Chris@109 176 void MainWindow::hgQueryPaths()
Chris@74 177 {
Chris@109 178 QStringList params;
Chris@109 179 params << "paths";
Chris@109 180 runner->requestAction(HgAction(ACT_QUERY_PATHS, workFolderPath, params));
Chris@74 181 }
Chris@74 182
Chris@109 183 void MainWindow::hgQueryBranch()
Chris@106 184 {
Chris@109 185 QStringList params;
Chris@109 186 params << "branch";
Chris@109 187 runner->requestAction(HgAction(ACT_QUERY_BRANCH, workFolderPath, params));
Chris@106 188 }
Chris@106 189
Chris@109 190 void MainWindow::hgQueryHeads()
jtkorhonen@0 191 {
Chris@109 192 QStringList params;
Chris@137 193 // On empty repos, "hg heads" will fail -- we don't care about
Chris@137 194 // that. Use --closed option so as to include closed branches;
Chris@137 195 // otherwise we'll be stuck if the user updates into one, and our
Chris@137 196 // incremental log will end up with spurious stuff in it because
Chris@137 197 // we won't be pruning at the ends of closed branches
Chris@137 198 params << "heads" << "--closed";
Chris@109 199 runner->requestAction(HgAction(ACT_QUERY_HEADS, workFolderPath, params));
jtkorhonen@0 200 }
jtkorhonen@0 201
jtkorhonen@0 202 void MainWindow::hgLog()
jtkorhonen@0 203 {
Chris@109 204 QStringList params;
Chris@109 205 params << "log";
Chris@109 206 params << "--template";
Chris@125 207 params << Changeset::getLogTemplate();
Chris@109 208
Chris@109 209 runner->requestAction(HgAction(ACT_LOG, workFolderPath, params));
Chris@109 210 }
Chris@109 211
Chris@150 212 void MainWindow::hgLogIncremental(QStringList prune)
Chris@120 213 {
Chris@120 214 QStringList params;
Chris@120 215 params << "log";
Chris@120 216
Chris@150 217 foreach (QString p, prune) {
Chris@153 218 params << "--prune" << Changeset::hashOf(p);
Chris@120 219 }
Chris@120 220
Chris@120 221 params << "--template";
Chris@125 222 params << Changeset::getLogTemplate();
Chris@120 223
Chris@120 224 runner->requestAction(HgAction(ACT_LOG_INCREMENTAL, workFolderPath, params));
Chris@120 225 }
Chris@109 226
Chris@109 227 void MainWindow::hgQueryParents()
Chris@109 228 {
Chris@109 229 QStringList params;
Chris@109 230 params << "parents";
Chris@109 231 runner->requestAction(HgAction(ACT_QUERY_PARENTS, workFolderPath, params));
Chris@109 232 }
Chris@109 233
Chris@109 234 void MainWindow::hgAnnotate()
Chris@109 235 {
Chris@109 236 QStringList params;
Chris@109 237 QString currentFile;//!!! = hgTabs -> getCurrentFileListLine();
Chris@109 238
Chris@109 239 if (!currentFile.isEmpty())
jtkorhonen@0 240 {
Chris@109 241 params << "annotate" << "--" << currentFile.mid(2); //Jump over status marker characters (e.g "M ")
jtkorhonen@0 242
Chris@109 243 runner->requestAction(HgAction(ACT_ANNOTATE, workFolderPath, params));
jtkorhonen@0 244 }
jtkorhonen@0 245 }
jtkorhonen@0 246
Chris@109 247 void MainWindow::hgResolveList()
Chris@109 248 {
Chris@109 249 QStringList params;
jtkorhonen@0 250
Chris@109 251 params << "resolve" << "--list";
Chris@109 252 runner->requestAction(HgAction(ACT_RESOLVE_LIST, workFolderPath, params));
Chris@109 253 }
Chris@109 254
Chris@109 255 void MainWindow::hgAdd()
jtkorhonen@0 256 {
Chris@109 257 QStringList params;
jtkorhonen@0 258
Chris@109 259 // hgExplorer permitted adding "all" files -- I'm not sure
Chris@109 260 // that one is a good idea, let's require the user to select
jtkorhonen@0 261
Chris@109 262 QStringList files = hgTabs->getSelectedAddableFiles();
Chris@109 263
Chris@109 264 if (!files.empty()) {
Chris@109 265 params << "add" << "--" << files;
Chris@109 266 runner->requestAction(HgAction(ACT_ADD, workFolderPath, params));
jtkorhonen@0 267 }
jtkorhonen@0 268 }
jtkorhonen@0 269
jtkorhonen@0 270
Chris@98 271 void MainWindow::hgRemove()
Chris@98 272 {
Chris@109 273 QStringList params;
Chris@98 274
Chris@109 275 QStringList files = hgTabs->getSelectedRemovableFiles();
Chris@98 276
Chris@109 277 //!!! todo: confirmation dialog (with file list in it) (or do we
Chris@109 278 // need that? all it does is move the files to the removed
Chris@109 279 // list... doesn't it?)
Chris@98 280
Chris@109 281 if (!files.empty()) {
Chris@109 282 params << "remove" << "--after" << "--force" << "--" << files;
Chris@109 283 runner->requestAction(HgAction(ACT_REMOVE, workFolderPath, params));
Chris@109 284 }
jtkorhonen@0 285 }
jtkorhonen@0 286
jtkorhonen@0 287 void MainWindow::hgCommit()
jtkorhonen@0 288 {
Chris@109 289 QStringList params;
Chris@109 290 QString comment;
Chris@94 291
Chris@157 292 if (justMerged) {
Chris@157 293 comment = mergeCommitComment;
Chris@157 294 }
Chris@157 295
Chris@109 296 QStringList files = hgTabs->getSelectedCommittableFiles();
Chris@127 297 QStringList reportFiles = files;
Chris@127 298 if (reportFiles.empty()) reportFiles = hgTabs->getAllCommittableFiles();
Chris@103 299
Chris@155 300 QString cf(tr("Commit files"));
Chris@155 301
Chris@109 302 if (ConfirmCommentDialog::confirmAndGetLongComment
Chris@109 303 (this,
Chris@155 304 cf,
Chris@155 305 tr("<h3>%1</h3><p>%2").arg(cf)
Chris@155 306 .arg(tr("You are about to commit the following files:")),
Chris@155 307 tr("<h3>%1</h3><p>%2").arg(cf)
Chris@155 308 .arg(tr("You are about to commit %n file(s):", "", reportFiles.size())),
Chris@127 309 reportFiles,
Chris@109 310 comment)) {
Chris@103 311
Chris@157 312 if (!justMerged && !files.empty()) {
Chris@157 313 // User wants to commit selected file(s) (and this is not
Chris@157 314 // merge commit, which would fail if we selected files)
Chris@157 315 params << "commit" << "--message" << comment
Chris@157 316 << "--user" << getUserInfo() << "--" << files;
Chris@109 317 } else {
Chris@109 318 // Commit all changes
Chris@157 319 params << "commit" << "--message" << comment
Chris@157 320 << "--user" << getUserInfo();
jtkorhonen@0 321 }
Chris@109 322
Chris@109 323 runner->requestAction(HgAction(ACT_COMMIT, workFolderPath, params));
jtkorhonen@0 324 }
jtkorhonen@0 325 }
jtkorhonen@0 326
jtkorhonen@34 327 QString MainWindow::filterTag(QString tag)
jtkorhonen@34 328 {
jtkorhonen@34 329 for(int i = 0; i < tag.size(); i++)
jtkorhonen@34 330 {
jtkorhonen@34 331 if (tag[i].isLower() || tag[i].isUpper() || tag[i].isDigit() || (tag[i] == QChar('.')))
jtkorhonen@34 332 {
jtkorhonen@34 333 //ok
jtkorhonen@34 334 }
jtkorhonen@34 335 else
jtkorhonen@34 336 {
jtkorhonen@34 337 tag[i] = QChar('_');
jtkorhonen@34 338 }
jtkorhonen@34 339 }
jtkorhonen@34 340 return tag;
jtkorhonen@34 341 }
jtkorhonen@34 342
jtkorhonen@34 343
Chris@164 344 void MainWindow::hgTag(QString id)
jtkorhonen@34 345 {
Chris@109 346 QStringList params;
Chris@109 347 QString tag;
jtkorhonen@34 348
Chris@109 349 if (ConfirmCommentDialog::confirmAndGetShortComment
Chris@109 350 (this,
Chris@109 351 tr("Tag"),
Chris@109 352 tr("Enter tag:"),
Chris@109 353 tag)) {
Chris@164 354 if (!tag.isEmpty()) {//!!! do something better if it is empty
Chris@164 355
Chris@164 356 params << "tag" << "--user" << getUserInfo();
Chris@164 357 params << "--rev" << Changeset::hashOf(id) << filterTag(tag);
Chris@109 358
Chris@109 359 runner->requestAction(HgAction(ACT_TAG, workFolderPath, params));
jtkorhonen@34 360 }
jtkorhonen@34 361 }
jtkorhonen@34 362 }
jtkorhonen@34 363
jtkorhonen@34 364
jtkorhonen@34 365 void MainWindow::hgIgnore()
jtkorhonen@34 366 {
Chris@109 367 QString hgIgnorePath;
Chris@109 368 QStringList params;
Chris@109 369 QString editorName;
Chris@109 370
Chris@109 371 hgIgnorePath = workFolderPath;
Chris@109 372 hgIgnorePath += ".hgignore";
Chris@109 373
Chris@109 374 params << hgIgnorePath;
Chris@112 375
Chris@112 376 //!!!
Chris@112 377 #ifdef Q_OS_LINUX
Chris@112 378
Chris@109 379 editorName = "gedit";
Chris@112 380
Chris@112 381 #else
Chris@112 382
Chris@109 383 editorName = """C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe""";
Chris@112 384
Chris@112 385 #endif
jtkorhonen@34 386
Chris@109 387 HgAction action(ACT_HG_IGNORE, workFolderPath, params);
Chris@109 388 action.executable = editorName;
jtkorhonen@34 389
Chris@109 390 runner->requestAction(action);
jtkorhonen@34 391 }
jtkorhonen@34 392
Chris@112 393 void MainWindow::findDiffBinaryName()
Chris@112 394 {
Chris@112 395 QSettings settings;
Chris@112 396 QString diff = settings.value("extdiffbinary", "").toString();
Chris@112 397 if (diff == "") {
Chris@112 398 QStringList bases;
Chris@112 399 bases << "opendiff" << "kompare" << "kdiff3" << "meld";
Chris@112 400 bool found = false;
Chris@112 401 foreach (QString base, bases) {
Chris@112 402 diff = findExecutable(base);
Chris@112 403 if (diff != base) {
Chris@112 404 found = true;
Chris@112 405 break;
Chris@112 406 }
Chris@112 407 }
Chris@112 408 if (found) {
Chris@112 409 settings.setValue("extdiffbinary", diff);
Chris@112 410 } else {
Chris@112 411 diff = "";
Chris@112 412 }
Chris@112 413 }
Chris@112 414 diffBinaryName = diff;
Chris@112 415 }
jtkorhonen@34 416
Chris@163 417 void MainWindow::findMergeBinaryName()
Chris@163 418 {
Chris@163 419 QSettings settings;
Chris@163 420 QString merge = settings.value("mergebinary", "").toString();
Chris@163 421 if (merge == "") {
Chris@163 422 QStringList bases;
Chris@164 423 bases << "fmdiff3" << "meld" << "diffuse" << "kdiff3";
Chris@163 424 bool found = false;
Chris@163 425 foreach (QString base, bases) {
Chris@163 426 merge = findExecutable(base);
Chris@163 427 if (merge != base) {
Chris@163 428 found = true;
Chris@163 429 break;
Chris@163 430 }
Chris@163 431 }
Chris@163 432 if (found) {
Chris@163 433 settings.setValue("mergebinary", merge);
Chris@163 434 } else {
Chris@163 435 merge = "";
Chris@163 436 }
Chris@163 437 }
Chris@163 438 mergeBinaryName = merge;
Chris@163 439 }
Chris@163 440
jtkorhonen@0 441 void MainWindow::hgFolderDiff()
jtkorhonen@0 442 {
Chris@112 443 if (diffBinaryName == "") return;
Chris@112 444
Chris@109 445 QStringList params;
jtkorhonen@0 446
Chris@112 447 // Diff parent against working folder (folder diff)
Chris@112 448
Chris@148 449 params << "--config" << "extensions.extdiff=" << "extdiff";
Chris@148 450 params << "--program" << diffBinaryName;
Chris@109 451
Chris@153 452 params << hgTabs->getSelectedCommittableFiles(); // may be none: whole dir
Chris@153 453
Chris@109 454 runner->requestAction(HgAction(ACT_FOLDERDIFF, workFolderPath, params));
jtkorhonen@0 455 }
jtkorhonen@0 456
jtkorhonen@0 457
Chris@148 458 void MainWindow::hgDiffToCurrent(QString id)
jtkorhonen@0 459 {
Chris@163 460 if (diffBinaryName == "") return;
Chris@163 461
Chris@148 462 QStringList params;
jtkorhonen@0 463
Chris@148 464 // Diff given revision against working folder
jtkorhonen@0 465
Chris@148 466 params << "--config" << "extensions.extdiff=" << "extdiff";
Chris@148 467 params << "--program" << diffBinaryName;
Chris@153 468 params << "--rev" << Changeset::hashOf(id);
Chris@148 469
Chris@148 470 runner->requestAction(HgAction(ACT_FOLDERDIFF, workFolderPath, params));
jtkorhonen@0 471 }
jtkorhonen@0 472
jtkorhonen@0 473
Chris@148 474 void MainWindow::hgDiffToParent(QString child, QString parent)
Chris@148 475 {
Chris@163 476 if (diffBinaryName == "") return;
Chris@163 477
Chris@148 478 QStringList params;
Chris@148 479
Chris@148 480 // Diff given revision against working folder
Chris@148 481
Chris@148 482 params << "--config" << "extensions.extdiff=" << "extdiff";
Chris@148 483 params << "--program" << diffBinaryName;
Chris@153 484 params << "--rev" << Changeset::hashOf(parent)
Chris@153 485 << "--rev" << Changeset::hashOf(child);
Chris@148 486
Chris@148 487 runner->requestAction(HgAction(ACT_CHGSETDIFF, workFolderPath, params));
Chris@148 488 }
Chris@148 489
jtkorhonen@0 490
jtkorhonen@0 491 void MainWindow::hgUpdate()
jtkorhonen@0 492 {
Chris@109 493 QStringList params;
jtkorhonen@0 494
Chris@109 495 params << "update";
Chris@109 496
Chris@109 497 runner->requestAction(HgAction(ACT_UPDATE, workFolderPath, params));
jtkorhonen@0 498 }
jtkorhonen@0 499
jtkorhonen@0 500
Chris@148 501 void MainWindow::hgUpdateToRev(QString id)
jtkorhonen@0 502 {
Chris@148 503 QStringList params;
jtkorhonen@0 504
Chris@153 505 params << "update" << "--rev" << Changeset::hashOf(id) << "--check";
jtkorhonen@0 506
Chris@148 507 runner->requestAction(HgAction(ACT_UPDATE, workFolderPath, params));
jtkorhonen@0 508 }
jtkorhonen@0 509
jtkorhonen@0 510
jtkorhonen@0 511 void MainWindow::hgRevert()
jtkorhonen@0 512 {
Chris@109 513 QStringList params;
Chris@109 514 QString comment;
Chris@98 515
Chris@109 516 QStringList files = hgTabs->getSelectedRevertableFiles();
Chris@109 517 if (files.empty()) files = hgTabs->getAllRevertableFiles();
Chris@155 518
Chris@155 519 QString rf(tr("Revert files"));
Chris@109 520
Chris@109 521 if (ConfirmCommentDialog::confirmDangerousFilesAction
Chris@109 522 (this,
Chris@155 523 rf,
Chris@155 524 tr("<h3>%1</h3><p>%2").arg(rf)
Chris@155 525 .arg(tr("You are about to <b>revert</b> the following files to their previous committed state.<br><br>This will <b>throw away any changes</b> that you have made to these files but have not committed:")),
Chris@155 526 tr("<h3>%1</h3><p>%2").arg(rf)
Chris@155 527 .arg(tr("You are about to <b>revert</b> %n file(s).<br><br>This will <b>throw away any changes</b> that you have made to these files but have not committed.", "", files.size())),
Chris@109 528 files)) {
Chris@163 529
Chris@163 530 lastRevertedFiles = files;
Chris@109 531
Chris@98 532 if (files.empty()) {
Chris@98 533 params << "revert" << "--no-backup";
Chris@98 534 } else {
Chris@164 535 params << "revert" << "--" << files;
Chris@98 536 }
Chris@163 537
Chris@163 538 //!!! This is problematic. If you've got an uncommitted
Chris@163 539 //!!! merge, you can't revert it without declaring which
Chris@163 540 //!!! parent of the merge you want to revert to (reasonably
Chris@163 541 //!!! enough). We're OK if we just did the merge in easyhg a
Chris@163 542 //!!! moment ago, because we have a record of which parent was
Chris@163 543 //!!! the target -- but if you exit and restart, we've lost
Chris@163 544 //!!! that record and it doesn't appear to be possible to get
Chris@163 545 //!!! it back from Hg. Even if you just switched from one
Chris@163 546 //!!! repo to another, the record is lost. What to do?
Chris@163 547
Chris@163 548 if (justMerged && mergeTargetRevision != "") {
Chris@163 549 params << "--rev" << mergeTargetRevision;
Chris@163 550 }
Chris@109 551
Chris@109 552 runner->requestAction(HgAction(ACT_REVERT, workFolderPath, params));
jtkorhonen@0 553 }
jtkorhonen@0 554 }
jtkorhonen@0 555
Chris@163 556
Chris@163 557 void MainWindow::hgMarkResolved(QStringList files)
Chris@163 558 {
Chris@163 559 QStringList params;
Chris@163 560
Chris@163 561 params << "resolve" << "--mark";
Chris@163 562
Chris@163 563 if (files.empty()) {
Chris@163 564 params << "--all";
Chris@163 565 } else {
Chris@164 566 params << "--" << files;
Chris@163 567 }
Chris@163 568
Chris@163 569 runner->requestAction(HgAction(ACT_RESOLVE_MARK, workFolderPath, params));
Chris@163 570 }
Chris@163 571
Chris@163 572
jtkorhonen@33 573 void MainWindow::hgRetryMerge()
jtkorhonen@33 574 {
Chris@109 575 QStringList params;
jtkorhonen@33 576
Chris@163 577 params << "resolve";
Chris@163 578
Chris@163 579 if (mergeBinaryName != "") {
Chris@163 580 params << "--tool" << mergeBinaryName;
Chris@163 581 }
Chris@163 582
Chris@163 583 QStringList files = hgTabs->getSelectedUnresolvedFiles();
Chris@163 584 if (files.empty()) {
Chris@163 585 params << "--all";
Chris@163 586 } else {
Chris@164 587 params << "--" << files;
Chris@163 588 }
Chris@163 589
Chris@109 590 runner->requestAction(HgAction(ACT_RETRY_MERGE, workFolderPath, params));
Chris@163 591
Chris@163 592 mergeCommitComment = tr("Merge");
jtkorhonen@33 593 }
jtkorhonen@33 594
jtkorhonen@33 595
jtkorhonen@0 596 void MainWindow::hgMerge()
jtkorhonen@0 597 {
Chris@163 598 if (hgTabs->canResolve()) {
Chris@163 599 hgRetryMerge();
Chris@163 600 return;
Chris@163 601 }
Chris@163 602
Chris@109 603 QStringList params;
jtkorhonen@0 604
Chris@109 605 params << "merge";
Chris@163 606
Chris@163 607 if (mergeBinaryName != "") {
Chris@163 608 params << "--tool" << mergeBinaryName;
Chris@163 609 }
Chris@163 610
Chris@163 611 if (currentParents.size() == 1) {
Chris@163 612 mergeTargetRevision = currentParents[0]->id();
Chris@163 613 }
Chris@163 614
Chris@109 615 runner->requestAction(HgAction(ACT_MERGE, workFolderPath, params));
Chris@157 616
Chris@157 617 mergeCommitComment = tr("Merge");
jtkorhonen@0 618 }
jtkorhonen@0 619
jtkorhonen@0 620
Chris@148 621 void MainWindow::hgMergeFrom(QString id)
Chris@148 622 {
Chris@148 623 QStringList params;
Chris@148 624
Chris@148 625 params << "merge";
Chris@153 626 params << "--rev" << Changeset::hashOf(id);
Chris@163 627
Chris@163 628 if (mergeBinaryName != "") {
Chris@163 629 params << "--tool" << mergeBinaryName;
Chris@163 630 }
Chris@148 631
Chris@148 632 runner->requestAction(HgAction(ACT_MERGE, workFolderPath, params));
Chris@157 633
Chris@157 634 mergeCommitComment = "";
Chris@157 635
Chris@157 636 foreach (Changeset *cs, currentHeads) {
Chris@157 637 if (cs->id() == id && !cs->isOnBranch(currentBranch)) {
Chris@157 638 if (cs->branch() == "" || cs->branch() == "default") {
Chris@157 639 mergeCommitComment = tr("Merge from the default branch");
Chris@157 640 } else {
Chris@157 641 mergeCommitComment = tr("Merge from branch \"%1\"").arg(cs->branch());
Chris@157 642 }
Chris@157 643 }
Chris@157 644 }
Chris@157 645
Chris@157 646 if (mergeCommitComment == "") {
Chris@157 647 mergeCommitComment = tr("Merge from %1").arg(id);
Chris@157 648 }
Chris@148 649 }
Chris@148 650
Chris@148 651
jtkorhonen@0 652 void MainWindow::hgCloneFromRemote()
jtkorhonen@0 653 {
Chris@109 654 QStringList params;
jtkorhonen@0 655
Chris@109 656 if (!QDir(workFolderPath).exists()) {
Chris@109 657 if (!QDir().mkpath(workFolderPath)) {
Chris@109 658 DEBUG << "hgCloneFromRemote: Failed to create target path "
Chris@109 659 << workFolderPath << endl;
Chris@109 660 //!!! report error
Chris@109 661 return;
Chris@104 662 }
Chris@109 663 }
Chris@104 664
Chris@109 665 params << "clone" << remoteRepoPath << workFolderPath;
Chris@109 666
Chris@109 667 hgTabs->setWorkFolderAndRepoNames(workFolderPath, remoteRepoPath);
Chris@113 668 hgTabs->updateWorkFolderFileList("");
jtkorhonen@0 669
Chris@109 670 runner->requestAction(HgAction(ACT_CLONEFROMREMOTE, workFolderPath, params));
jtkorhonen@0 671 }
jtkorhonen@0 672
jtkorhonen@0 673 void MainWindow::hgInit()
jtkorhonen@0 674 {
Chris@109 675 QStringList params;
jtkorhonen@0 676
Chris@109 677 params << "init";
Chris@109 678 params << workFolderPath;
jtkorhonen@0 679
Chris@109 680 runner->requestAction(HgAction(ACT_INIT, workFolderPath, params));
jtkorhonen@0 681 }
jtkorhonen@0 682
jtkorhonen@0 683 void MainWindow::hgIncoming()
jtkorhonen@0 684 {
Chris@109 685 QStringList params;
jtkorhonen@0 686
Chris@109 687 params << "incoming" << "--newest-first" << remoteRepoPath;
Chris@125 688 params << "--template" << Changeset::getLogTemplate();
jtkorhonen@0 689
Chris@109 690 runner->requestAction(HgAction(ACT_INCOMING, workFolderPath, params));
jtkorhonen@0 691 }
jtkorhonen@0 692
jtkorhonen@0 693 void MainWindow::hgPull()
jtkorhonen@0 694 {
Chris@126 695 if (QMessageBox::question
Chris@126 696 (this, tr("Confirm pull"),
Chris@126 697 format3(tr("Confirm pull from remote repository"),
Chris@126 698 tr("You are about to pull from the following remote repository:"),
Chris@126 699 remoteRepoPath),
Chris@126 700 QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
jtkorhonen@0 701
Chris@126 702 QStringList params;
Chris@126 703 params << "pull" << remoteRepoPath;
Chris@126 704 runner->requestAction(HgAction(ACT_PULL, workFolderPath, params));
Chris@126 705 }
jtkorhonen@0 706 }
jtkorhonen@0 707
jtkorhonen@0 708 void MainWindow::hgPush()
jtkorhonen@0 709 {
Chris@126 710 if (QMessageBox::question
Chris@126 711 (this, tr("Confirm push"),
Chris@126 712 format3(tr("Confirm push to remote repository"),
Chris@126 713 tr("You are about to push to the following remote repository:"),
Chris@126 714 remoteRepoPath),
Chris@126 715 QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
jtkorhonen@0 716
Chris@126 717 QStringList params;
Chris@154 718 params << "push" << "--new-branch" << remoteRepoPath;
Chris@126 719 runner->requestAction(HgAction(ACT_PUSH, workFolderPath, params));
Chris@126 720 }
jtkorhonen@0 721 }
jtkorhonen@0 722
jtkorhonen@28 723 QString MainWindow::listAllUpIpV4Addresses()
jtkorhonen@26 724 {
jtkorhonen@28 725 QString ret;
jtkorhonen@26 726 QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
jtkorhonen@26 727
jtkorhonen@26 728 for (int i = 0; i < ifaces.count(); i++)
jtkorhonen@26 729 {
jtkorhonen@26 730 QNetworkInterface iface = ifaces.at(i);
jtkorhonen@26 731
jtkorhonen@26 732 if (iface.flags().testFlag(QNetworkInterface::IsUp) && !iface.flags().testFlag(QNetworkInterface::IsLoopBack))
jtkorhonen@26 733 {
jtkorhonen@26 734 for (int j=0; j<iface.addressEntries().count(); j++)
jtkorhonen@26 735 {
jtkorhonen@28 736 QHostAddress tmp = iface.addressEntries().at(j).ip();
jtkorhonen@28 737 if (QAbstractSocket::IPv4Protocol == tmp.protocol())
jtkorhonen@24 738 {
jtkorhonen@28 739 if (!ret.isEmpty())
jtkorhonen@28 740 {
jtkorhonen@28 741 ret += " ";
jtkorhonen@28 742 }
jtkorhonen@28 743 ret += tmp.toString();
jtkorhonen@24 744 }
jtkorhonen@24 745 }
jtkorhonen@22 746 }
jtkorhonen@17 747 }
jtkorhonen@28 748 return ret;
jtkorhonen@28 749 }
jtkorhonen@17 750
Chris@120 751 void MainWindow::clearState()
Chris@120 752 {
Chris@120 753 foreach (Changeset *cs, currentParents) delete cs;
Chris@120 754 currentParents.clear();
Chris@120 755 foreach (Changeset *cs, currentHeads) delete cs;
Chris@120 756 currentHeads.clear();
Chris@120 757 currentBranch = "";
Chris@163 758 lastStatOutput = "";
Chris@163 759 lastRevertedFiles.clear();
Chris@163 760 mergeTargetRevision = "";
Chris@163 761 mergeCommitComment = "";
Chris@120 762 needNewLog = true;
Chris@120 763 }
jtkorhonen@17 764
jtkorhonen@11 765 void MainWindow::hgServe()
jtkorhonen@11 766 {
Chris@109 767 QStringList params;
Chris@109 768 QString msg;
jtkorhonen@11 769
Chris@109 770 QString addrs = listAllUpIpV4Addresses();
Chris@109 771 QTextStream(&msg) << "Server running on address(es) (" << addrs << "), port 8000";
Chris@109 772 params << "serve";
jtkorhonen@11 773
Chris@109 774 runner->requestAction(HgAction(ACT_SERVE, workFolderPath, params));
Chris@109 775
Chris@109 776 QMessageBox::information(this, "Serve", msg, QMessageBox::Close);
Chris@109 777 //!!! runner -> killCurrentCommand();
jtkorhonen@11 778 }
jtkorhonen@11 779
Chris@64 780 void MainWindow::startupDialog()
Chris@64 781 {
Chris@64 782 StartupDialog *dlg = new StartupDialog(this);
Chris@65 783 if (dlg->exec()) firstStart = false;
Chris@64 784 }
jtkorhonen@11 785
Chris@69 786 void MainWindow::open()
Chris@69 787 {
Chris@86 788 bool done = false;
Chris@69 789
Chris@86 790 while (!done) {
Chris@69 791
Chris@86 792 MultiChoiceDialog *d = new MultiChoiceDialog
Chris@86 793 (tr("Open Repository"),
Chris@86 794 tr("<qt><big>What would you like to open?</big></qt>"),
Chris@86 795 this);
Chris@69 796
Chris@86 797 d->addChoice("remote",
Chris@86 798 tr("<qt><center><img src=\":images/browser-64.png\"><br>Remote repository</center></qt>"),
Chris@86 799 tr("Open a remote Mercurial repository, by cloning from its URL into a local folder."),
Chris@86 800 MultiChoiceDialog::UrlToDirectoryArg);
Chris@69 801
Chris@86 802 d->addChoice("local",
Chris@86 803 tr("<qt><center><img src=\":images/hglogo-64.png\"><br>Local repository</center></qt>"),
Chris@86 804 tr("Open an existing local Mercurial repository."),
Chris@86 805 MultiChoiceDialog::DirectoryArg);
Chris@69 806
Chris@86 807 d->addChoice("init",
Chris@86 808 tr("<qt><center><img src=\":images/hdd_unmount-64.png\"><br>File folder</center></qt>"),
Chris@86 809 tr("Open a local folder, by creating a Mercurial repository in it."),
Chris@86 810 MultiChoiceDialog::DirectoryArg);
Chris@79 811
Chris@86 812 d->setCurrentChoice("local");
Chris@86 813
Chris@86 814 if (d->exec() == QDialog::Accepted) {
Chris@86 815
Chris@86 816 QString choice = d->getCurrentChoice();
Chris@86 817 QString arg = d->getArgument().trimmed();
Chris@86 818
Chris@86 819 bool result = false;
Chris@86 820
Chris@86 821 if (choice == "local") {
Chris@86 822 result = openLocal(arg);
Chris@86 823 } else if (choice == "remote") {
Chris@86 824 result = openRemote(arg, d->getAdditionalArgument().trimmed());
Chris@86 825 } else if (choice == "init") {
Chris@86 826 result = openInit(arg);
Chris@86 827 }
Chris@86 828
Chris@86 829 if (result) {
Chris@86 830 enableDisableActions();
Chris@120 831 clearState();
Chris@109 832 hgQueryPaths();
Chris@91 833 done = true;
Chris@91 834 }
Chris@86 835
Chris@86 836 } else {
Chris@86 837
Chris@86 838 // cancelled
Chris@86 839 done = true;
Chris@69 840 }
Chris@79 841
Chris@86 842 delete d;
Chris@69 843 }
Chris@69 844 }
Chris@69 845
Chris@145 846 void MainWindow::open(QString local)
Chris@145 847 {
Chris@145 848 if (openLocal(local)) {
Chris@145 849 enableDisableActions();
Chris@145 850 clearState();
Chris@145 851 hgQueryPaths();
Chris@145 852 }
Chris@145 853 }
Chris@145 854
Chris@79 855 bool MainWindow::complainAboutFilePath(QString arg)
Chris@79 856 {
Chris@79 857 QMessageBox::critical
Chris@79 858 (this, tr("File chosen"),
Chris@84 859 tr("<qt><b>Folder required</b><br><br>You asked to open \"%1\".<br>This is a file; to open a repository, you need to choose a folder.</qt>").arg(xmlEncode(arg)));
Chris@79 860 return false;
Chris@79 861 }
Chris@79 862
Chris@79 863 bool MainWindow::complainAboutUnknownFolder(QString arg)
Chris@79 864 {
Chris@79 865 QMessageBox::critical
Chris@79 866 (this, tr("Folder does not exist"),
Chris@84 867 tr("<qt><b>Folder does not exist</b><br><br>You asked to open \"%1\".<br>This folder does not exist, and it cannot be created because its parent does not exist either.</qt>").arg(xmlEncode(arg)));
Chris@84 868 return false;
Chris@84 869 }
Chris@84 870
Chris@84 871 bool MainWindow::complainAboutInitInRepo(QString arg)
Chris@84 872 {
Chris@84 873 QMessageBox::critical
Chris@84 874 (this, tr("Path is in existing repository"),
Chris@84 875 tr("<qt><b>Path is in an existing repository</b><br><br>You asked to initialise a repository at \"%1\".<br>This path is already inside an existing repository.</qt>").arg(xmlEncode(arg)));
Chris@84 876 return false;
Chris@84 877 }
Chris@84 878
Chris@84 879 bool MainWindow::complainAboutInitFile(QString arg)
Chris@84 880 {
Chris@84 881 QMessageBox::critical
Chris@84 882 (this, tr("Path is a file"),
Chris@84 883 tr("<qt><b>Path is a file</b><br><br>You asked to initialise a repository at \"%1\".<br>This is an existing file; it is only possible to initialise in folders.</qt>").arg(xmlEncode(arg)));
Chris@84 884 return false;
Chris@84 885 }
Chris@84 886
Chris@84 887 bool MainWindow::complainAboutCloneToExisting(QString arg)
Chris@84 888 {
Chris@84 889 QMessageBox::critical
Chris@84 890 (this, tr("Path is in existing repository"),
Chris@84 891 tr("<qt><b>Local path is in an existing repository</b><br><br>You asked to open a remote repository by cloning it to the local path \"%1\".<br>This path is already inside an existing repository.<br>Please provide a new folder name for the local repository.</qt>").arg(xmlEncode(arg)));
Chris@84 892 return false;
Chris@84 893 }
Chris@84 894
Chris@84 895 bool MainWindow::complainAboutCloneToFile(QString arg)
Chris@84 896 {
Chris@84 897 QMessageBox::critical
Chris@84 898 (this, tr("Path is a file"),
Chris@84 899 tr("<qt><b>Local path is a file</b><br><br>You asked to open a remote repository by cloning it to the local path \"%1\".<br>This path is an existing file.<br>Please provide a new folder name for the local repository.</qt>").arg(xmlEncode(arg)));
Chris@84 900 return false;
Chris@84 901 }
Chris@84 902
Chris@84 903 bool MainWindow::complainAboutCloneToExistingFolder(QString arg)
Chris@84 904 {
Chris@84 905 QMessageBox::critical
Chris@84 906 (this, tr("Folder exists"),
Chris@84 907 tr("<qt><b>Local folder already exists</b><br><br>You asked to open a remote repository by cloning it to the local path \"%1\".<br>This is the path of an existing folder.<br>Please provide a new folder name for the local repository.</qt>").arg(xmlEncode(arg)));
Chris@79 908 return false;
Chris@79 909 }
Chris@79 910
Chris@79 911 bool MainWindow::askToOpenParentRepo(QString arg, QString parent)
Chris@79 912 {
Chris@79 913 return (QMessageBox::question
Chris@84 914 (this, tr("Path is inside a repository"),
Chris@86 915 tr("<qt><b>Open the repository that contains this path?</b><br><br>You asked to open \"%1\".<br>This is not the root folder of a repository.<br>But it is inside a repository, whose root is at \"%2\". <br><br>Would you like to open that repository instead?</qt>")
Chris@79 916 .arg(xmlEncode(arg)).arg(xmlEncode(parent)),
Chris@79 917 QMessageBox::Ok | QMessageBox::Cancel,
Chris@79 918 QMessageBox::Ok)
Chris@79 919 == QMessageBox::Ok);
Chris@79 920 }
Chris@79 921
Chris@79 922 bool MainWindow::askToInitExisting(QString arg)
Chris@79 923 {
Chris@79 924 return (QMessageBox::question
Chris@84 925 (this, tr("Folder has no repository"),
Chris@84 926 tr("<qt><b>Initialise a repository here?</b><br><br>You asked to open \"%1\".<br>This folder does not contain a Mercurial repository.<br><br>Would you like to initialise a repository here?</qt>")
Chris@79 927 .arg(xmlEncode(arg)),
Chris@79 928 QMessageBox::Ok | QMessageBox::Cancel,
Chris@79 929 QMessageBox::Ok)
Chris@79 930 == QMessageBox::Ok);
Chris@79 931 }
Chris@79 932
Chris@79 933 bool MainWindow::askToInitNew(QString arg)
Chris@79 934 {
Chris@79 935 return (QMessageBox::question
Chris@84 936 (this, tr("Folder does not exist"),
Chris@84 937 tr("<qt><b>Initialise a new repository?</b><br><br>You asked to open \"%1\".<br>This folder does not yet exist.<br><br>Would you like to create the folder and initialise a new empty repository in it?</qt>")
Chris@84 938 .arg(xmlEncode(arg)),
Chris@84 939 QMessageBox::Ok | QMessageBox::Cancel,
Chris@84 940 QMessageBox::Ok)
Chris@84 941 == QMessageBox::Ok);
Chris@84 942 }
Chris@84 943
Chris@84 944 bool MainWindow::askToOpenInsteadOfInit(QString arg)
Chris@84 945 {
Chris@84 946 return (QMessageBox::question
Chris@84 947 (this, tr("Repository exists"),
Chris@84 948 tr("<qt><b>Open existing repository?</b><br><br>You asked to initialise a new repository at \"%1\".<br>This folder already contains a repository. Would you like to open it?</qt>")
Chris@79 949 .arg(xmlEncode(arg)),
Chris@79 950 QMessageBox::Ok | QMessageBox::Cancel,
Chris@79 951 QMessageBox::Ok)
Chris@79 952 == QMessageBox::Ok);
Chris@79 953 }
Chris@79 954
Chris@79 955 bool MainWindow::openLocal(QString local)
Chris@79 956 {
Chris@79 957 DEBUG << "open " << local << endl;
Chris@79 958
Chris@79 959 FolderStatus status = getFolderStatus(local);
Chris@79 960 QString containing = getContainingRepoFolder(local);
Chris@79 961
Chris@79 962 switch (status) {
Chris@79 963
Chris@79 964 case FolderHasRepo:
Chris@79 965 // fine
Chris@79 966 break;
Chris@79 967
Chris@79 968 case FolderExists:
Chris@79 969 if (containing != "") {
Chris@79 970 if (!askToOpenParentRepo(local, containing)) return false;
Chris@84 971 local = containing;
Chris@79 972 } else {
Chris@86 973 //!!! No -- this is likely to happen far more by accident
Chris@86 974 // than because the user actually wanted to init something.
Chris@86 975 // Don't ask, just politely reject.
Chris@79 976 if (!askToInitExisting(local)) return false;
Chris@79 977 return openInit(local);
Chris@79 978 }
Chris@79 979 break;
Chris@79 980
Chris@79 981 case FolderParentExists:
Chris@79 982 if (containing != "") {
Chris@79 983 if (!askToOpenParentRepo(local, containing)) return false;
Chris@84 984 local = containing;
Chris@79 985 } else {
Chris@79 986 if (!askToInitNew(local)) return false;
Chris@79 987 return openInit(local);
Chris@79 988 }
Chris@79 989 break;
Chris@79 990
Chris@79 991 case FolderUnknown:
Chris@84 992 if (containing != "") {
Chris@84 993 if (!askToOpenParentRepo(local, containing)) return false;
Chris@84 994 local = containing;
Chris@84 995 } else {
Chris@84 996 return complainAboutUnknownFolder(local);
Chris@84 997 }
Chris@84 998 break;
Chris@79 999
Chris@79 1000 case FolderIsFile:
Chris@79 1001 return complainAboutFilePath(local);
Chris@79 1002 }
Chris@79 1003
Chris@79 1004 workFolderPath = local;
Chris@79 1005 remoteRepoPath = "";
Chris@79 1006 return true;
Chris@79 1007 }
Chris@79 1008
Chris@79 1009 bool MainWindow::openRemote(QString remote, QString local)
Chris@79 1010 {
Chris@79 1011 DEBUG << "clone " << remote << " to " << local << endl;
Chris@84 1012
Chris@84 1013 FolderStatus status = getFolderStatus(local);
Chris@84 1014 QString containing = getContainingRepoFolder(local);
Chris@84 1015
Chris@84 1016 DEBUG << "status = " << status << ", containing = " << containing << endl;
Chris@84 1017
Chris@84 1018 if (status == FolderHasRepo || containing != "") {
Chris@84 1019 return complainAboutCloneToExisting(local);
Chris@84 1020 }
Chris@84 1021
Chris@84 1022 if (status == FolderIsFile) {
Chris@84 1023 return complainAboutCloneToFile(local);
Chris@84 1024 }
Chris@84 1025
Chris@84 1026 if (status == FolderUnknown) {
Chris@84 1027 return complainAboutUnknownFolder(local);
Chris@84 1028 }
Chris@84 1029
Chris@84 1030 if (status == FolderExists) {
Chris@84 1031 //!!! we can do better than this surely?
Chris@84 1032 return complainAboutCloneToExistingFolder(local);
Chris@84 1033 }
Chris@84 1034
Chris@84 1035 workFolderPath = local;
Chris@84 1036 remoteRepoPath = remote;
Chris@84 1037 hgCloneFromRemote();
Chris@84 1038
Chris@79 1039 return true;
Chris@79 1040 }
Chris@79 1041
Chris@84 1042 bool MainWindow::openInit(QString local)
Chris@79 1043 {
Chris@84 1044 DEBUG << "openInit " << local << endl;
Chris@84 1045
Chris@84 1046 FolderStatus status = getFolderStatus(local);
Chris@84 1047 QString containing = getContainingRepoFolder(local);
Chris@84 1048
Chris@84 1049 DEBUG << "status = " << status << ", containing = " << containing << endl;
Chris@84 1050
Chris@84 1051 if (status == FolderHasRepo) {
Chris@84 1052 if (!askToOpenInsteadOfInit(local)) return false;
Chris@84 1053 }
Chris@84 1054
Chris@84 1055 if (containing != "") {
Chris@84 1056 return complainAboutInitInRepo(local);
Chris@84 1057 }
Chris@84 1058
Chris@84 1059 if (status == FolderIsFile) {
Chris@84 1060 return complainAboutInitFile(local);
Chris@84 1061 }
Chris@84 1062
Chris@84 1063 if (status == FolderUnknown) {
Chris@84 1064 return complainAboutUnknownFolder(local);
Chris@84 1065 }
Chris@84 1066
Chris@84 1067 workFolderPath = local;
Chris@84 1068 remoteRepoPath = "";
Chris@84 1069 hgInit();
Chris@79 1070 return true;
Chris@79 1071 }
Chris@79 1072
jtkorhonen@0 1073 void MainWindow::settings()
jtkorhonen@0 1074 {
Chris@69 1075 /*!!!
jtkorhonen@0 1076 SettingsDialog *settingsDlg = new SettingsDialog(this);
jtkorhonen@0 1077 settingsDlg->setModal(true);
jtkorhonen@0 1078 settingsDlg->exec();
Chris@98 1079 hgTabs -> clearLists();
jtkorhonen@0 1080 enableDisableActions();
jtkorhonen@0 1081 hgStat();
Chris@69 1082 */
jtkorhonen@0 1083 }
jtkorhonen@0 1084
jtkorhonen@2 1085 #define STDOUT_NEEDS_BIG_WINDOW 512
jtkorhonen@2 1086 #define SMALL_WND_W 500
jtkorhonen@2 1087 #define SMALL_WND_H 300
jtkorhonen@2 1088
jtkorhonen@2 1089 #define BIG_WND_W 1024
jtkorhonen@2 1090 #define BIG_WND_H 768
jtkorhonen@2 1091
jtkorhonen@2 1092
jtkorhonen@2 1093 void MainWindow::presentLongStdoutToUser(QString stdo)
jtkorhonen@0 1094 {
jtkorhonen@2 1095 if (!stdo.isEmpty())
jtkorhonen@2 1096 {
jtkorhonen@2 1097 QDialog dlg;
jtkorhonen@0 1098
jtkorhonen@2 1099 if (stdo.length() > STDOUT_NEEDS_BIG_WINDOW)
jtkorhonen@2 1100 {
jtkorhonen@2 1101 dlg.setMinimumWidth(BIG_WND_W);
jtkorhonen@2 1102 dlg.setMinimumHeight(BIG_WND_H);
jtkorhonen@2 1103 }
jtkorhonen@2 1104 else
jtkorhonen@2 1105 {
jtkorhonen@2 1106 dlg.setMinimumWidth(SMALL_WND_W);
jtkorhonen@2 1107 dlg.setMinimumHeight(SMALL_WND_H);
jtkorhonen@2 1108 }
jtkorhonen@0 1109
jtkorhonen@2 1110 QVBoxLayout *box = new QVBoxLayout;
jtkorhonen@2 1111 QListWidget *list = new QListWidget;
jtkorhonen@2 1112 list-> addItems(stdo.split("\n"));
jtkorhonen@2 1113 QPushButton *btn = new QPushButton(tr("Ok"));
jtkorhonen@2 1114 connect(btn, SIGNAL(clicked()), &dlg, SLOT(accept()));
jtkorhonen@0 1115
jtkorhonen@2 1116 box -> addWidget(list);
jtkorhonen@2 1117 box -> addWidget(btn);
jtkorhonen@2 1118 dlg.setLayout(box);
jtkorhonen@2 1119
jtkorhonen@2 1120 dlg.exec();
jtkorhonen@2 1121 }
jtkorhonen@2 1122 else
jtkorhonen@2 1123 {
Chris@98 1124 QMessageBox::information(this, tr("EasyMercurial"), tr("Mercurial command did not return any output."));
jtkorhonen@2 1125 }
jtkorhonen@0 1126 }
jtkorhonen@0 1127
Chris@90 1128 void MainWindow::updateFileSystemWatcher()
Chris@90 1129 {
Chris@90 1130 delete fsWatcher;
Chris@90 1131 fsWatcher = new QFileSystemWatcher();
Chris@90 1132 std::deque<QString> pending;
Chris@90 1133 pending.push_back(workFolderPath);
Chris@90 1134 while (!pending.empty()) {
Chris@90 1135 QString path = pending.front();
Chris@90 1136 pending.pop_front();
Chris@90 1137 fsWatcher->addPath(path);
Chris@90 1138 DEBUG << "Added to file system watcher: " << path << endl;
Chris@90 1139 QDir d(path);
Chris@90 1140 if (d.exists()) {
Chris@115 1141 d.setFilter(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Readable);
Chris@90 1142 foreach (QString entry, d.entryList()) {
Chris@90 1143 if (entry == ".hg") continue;
Chris@90 1144 QString entryPath = d.absoluteFilePath(entry);
Chris@90 1145 pending.push_back(entryPath);
Chris@90 1146 }
Chris@90 1147 }
Chris@90 1148 }
Chris@90 1149 connect(fsWatcher, SIGNAL(directoryChanged(QString)),
Chris@90 1150 this, SLOT(fsDirectoryChanged(QString)));
Chris@90 1151 connect(fsWatcher, SIGNAL(fileChanged(QString)),
Chris@90 1152 this, SLOT(fsFileChanged(QString)));
Chris@90 1153 }
Chris@90 1154
Chris@122 1155 void MainWindow::fsDirectoryChanged(QString d)
Chris@90 1156 {
Chris@122 1157 DEBUG << "MainWindow::fsDirectoryChanged " << d << endl;
Chris@90 1158 hgStat();
Chris@90 1159 }
Chris@90 1160
Chris@122 1161 void MainWindow::fsFileChanged(QString f)
Chris@90 1162 {
Chris@122 1163 DEBUG << "MainWindow::fsFileChanged " << f << endl;
Chris@90 1164 hgStat();
Chris@90 1165 }
Chris@90 1166
Chris@125 1167 QString MainWindow::format3(QString head, QString intro, QString code)
Chris@125 1168 {
Chris@125 1169 if (intro == "") {
Chris@125 1170 return QString("<qt><h3>%1</h3><code>%2</code>")
Chris@125 1171 .arg(head).arg(xmlEncode(code).replace("\n", "<br>"));
Chris@126 1172 } else if (code == "") {
Chris@126 1173 return QString("<qt><h3>%1</h3><p>%2</p>")
Chris@126 1174 .arg(head).arg(intro);
Chris@125 1175 } else {
Chris@125 1176 return QString("<qt><h3>%1</h3><p>%2</p><code>%3</code>")
Chris@125 1177 .arg(head).arg(intro).arg(xmlEncode(code).replace("\n", "<br>"));
Chris@125 1178 }
Chris@125 1179 }
Chris@125 1180
Chris@120 1181 void MainWindow::showIncoming(QString output)
Chris@120 1182 {
Chris@120 1183 runner->hide();
Chris@125 1184 IncomingDialog *d = new IncomingDialog(this, output);
Chris@125 1185 d->exec();
Chris@125 1186 delete d;
Chris@125 1187 }
Chris@125 1188
Chris@125 1189 int MainWindow::extractChangeCount(QString text)
Chris@125 1190 {
Chris@125 1191 QRegExp re("added (\\d+) ch\\w+ with (\\d+) ch\\w+ to (\\d+) f\\w+");
Chris@125 1192 if (re.indexIn(text) >= 0) {
Chris@125 1193 return re.cap(1).toInt();
Chris@125 1194 } else if (text.contains("no changes")) {
Chris@125 1195 return 0;
Chris@125 1196 } else {
Chris@125 1197 return -1; // unknown
Chris@125 1198 }
Chris@120 1199 }
Chris@120 1200
Chris@120 1201 void MainWindow::showPushResult(QString output)
Chris@120 1202 {
Chris@125 1203 QString report;
Chris@125 1204 int n = extractChangeCount(output);
Chris@125 1205 if (n > 0) {
Chris@125 1206 report = tr("Pushed %n changeset(s)", "", n);
Chris@125 1207 } else if (n == 0) {
Chris@125 1208 report = tr("No changes to push");
Chris@125 1209 } else {
Chris@125 1210 report = tr("Push complete");
Chris@125 1211 }
Chris@125 1212 report = format3(report, tr("The push command output was:"), output);
Chris@120 1213 runner->hide();
Chris@125 1214 QMessageBox::information(this, "Push complete", report);
Chris@120 1215 }
Chris@120 1216
Chris@120 1217 void MainWindow::showPullResult(QString output)
Chris@120 1218 {
Chris@125 1219 QString report;
Chris@125 1220 int n = extractChangeCount(output);
Chris@125 1221 if (n > 0) {
Chris@125 1222 report = tr("Pulled %n changeset(s)", "", n);
Chris@125 1223 } else if (n == 0) {
Chris@125 1224 report = tr("No changes to pull");
Chris@125 1225 } else {
Chris@125 1226 report = tr("Pull complete");
Chris@125 1227 }
Chris@125 1228 report = format3(report, tr("The pull command output was:"), output);
Chris@120 1229 runner->hide();
Chris@125 1230
Chris@125 1231 //!!! and something about updating
Chris@125 1232
Chris@125 1233 QMessageBox::information(this, "Pull complete", report);
Chris@120 1234 }
Chris@120 1235
Chris@143 1236 void MainWindow::commandFailed(HgAction action, QString output)
Chris@62 1237 {
Chris@62 1238 DEBUG << "MainWindow::commandFailed" << endl;
Chris@74 1239
Chris@113 1240 // Some commands we just have to ignore bad return values from:
Chris@113 1241
Chris@113 1242 switch(action.action) {
Chris@113 1243 case ACT_NONE:
Chris@113 1244 // uh huh
Chris@113 1245 return;
Chris@113 1246 case ACT_INCOMING:
Chris@113 1247 // returns non-zero code if the check was successful but there
Chris@113 1248 // are no changes pending
Chris@143 1249 if (output.trimmed() == "") showIncoming("");
Chris@113 1250 return;
Chris@162 1251 case ACT_QUERY_HEADS:
Chris@162 1252 // fails if repo is empty; we don't care (if there's a genuine
Chris@162 1253 // problem, something else will fail too). Need to do this,
Chris@162 1254 // otherwise empty repo state will not be reflected properly
Chris@162 1255 // (since heads/log procedure never completes for empty repo)
Chris@162 1256 enableDisableActions();
Chris@162 1257 return;
Chris@113 1258 case ACT_FOLDERDIFF:
Chris@113 1259 case ACT_CHGSETDIFF:
Chris@113 1260 // external program, unlikely to be anything useful in stderr
Chris@113 1261 // and some return with failure codes when something as basic
Chris@113 1262 // as the user closing the window via the wm happens
Chris@113 1263 return;
Chris@113 1264
Chris@113 1265 default:
Chris@114 1266 break;
Chris@113 1267 }
Chris@113 1268
Chris@113 1269 QString command = action.executable;
Chris@113 1270 if (command == "") command = "hg";
Chris@113 1271 foreach (QString arg, action.params) {
Chris@113 1272 command += " " + arg;
Chris@113 1273 }
Chris@113 1274
Chris@113 1275 QString message = tr("<qt><h3>Command failed</h3>"
Chris@113 1276 "<p>The following command failed:</p>"
Chris@113 1277 "<code>%1</code>"
Chris@113 1278 "%2</qt>")
Chris@113 1279 .arg(command)
Chris@143 1280 .arg((output.trimmed() != "") ?
Chris@113 1281 tr("<p>Its output said:</p><code>%1</code>")
Chris@143 1282 .arg(xmlEncode(output.left(800))
Chris@113 1283 .replace("\n", "<br>"))
Chris@113 1284 : "");
Chris@113 1285
Chris@113 1286 QMessageBox::warning(this, tr("Command failed"), message);
Chris@62 1287 }
Chris@62 1288
Chris@109 1289 void MainWindow::commandCompleted(HgAction completedAction, QString output)
jtkorhonen@0 1290 {
Chris@109 1291 HGACTIONS action = completedAction.action;
Chris@109 1292
Chris@109 1293 if (action == ACT_NONE) return;
Chris@109 1294
Chris@150 1295 bool headsChanged = false;
Chris@150 1296 QStringList oldHeadIds;
Chris@150 1297
Chris@150 1298 switch (action) {
Chris@109 1299
Chris@109 1300 case ACT_QUERY_PATHS:
jtkorhonen@0 1301 {
Chris@109 1302 DEBUG << "stdout is " << output << endl;
Chris@109 1303 LogParser lp(output, "=");
Chris@109 1304 LogList ll = lp.parse();
Chris@109 1305 DEBUG << ll.size() << " results" << endl;
Chris@109 1306 if (!ll.empty()) {
Chris@109 1307 remoteRepoPath = lp.parse()[0]["default"].trimmed();
Chris@109 1308 DEBUG << "Set remote path to " << remoteRepoPath << endl;
Chris@109 1309 }
Chris@109 1310 MultiChoiceDialog::addRecentArgument("local", workFolderPath);
Chris@109 1311 MultiChoiceDialog::addRecentArgument("remote", remoteRepoPath);
Chris@109 1312 hgTabs->setWorkFolderAndRepoNames(workFolderPath, remoteRepoPath);
Chris@109 1313 break;
Chris@109 1314 }
jtkorhonen@0 1315
Chris@109 1316 case ACT_QUERY_BRANCH:
Chris@109 1317 currentBranch = output.trimmed();
Chris@109 1318 break;
jtkorhonen@0 1319
Chris@109 1320 case ACT_STAT:
Chris@153 1321 if (fsWatcher) fsWatcher->blockSignals(false);
Chris@163 1322 lastStatOutput = output;
Chris@109 1323 updateFileSystemWatcher();
Chris@109 1324 break;
Chris@163 1325
Chris@163 1326 case ACT_RESOLVE_LIST:
Chris@163 1327 if (output != "") {
Chris@163 1328 // Remove lines beginning with R (they are resolved,
Chris@163 1329 // and the file stat parser treats R as removed)
Chris@163 1330 QStringList outList = output.split('\n');
Chris@163 1331 QStringList winnowed;
Chris@163 1332 foreach (QString line, outList) {
Chris@163 1333 if (!line.startsWith("R ")) winnowed.push_back(line);
Chris@163 1334 }
Chris@163 1335 output = winnowed.join("\n");
Chris@163 1336 }
Chris@163 1337 DEBUG << "lastStatOutput = " << lastStatOutput << endl;
Chris@163 1338 DEBUG << "output = " << output << endl;
Chris@163 1339 hgTabs->updateWorkFolderFileList(lastStatOutput + output);
Chris@163 1340 break;
Chris@163 1341
Chris@163 1342 case ACT_RESOLVE_MARK:
Chris@163 1343 shouldHgStat = true;
Chris@163 1344 break;
Chris@109 1345
Chris@109 1346 case ACT_INCOMING:
Chris@120 1347 showIncoming(output);
Chris@120 1348 break;
Chris@120 1349
Chris@109 1350 case ACT_ANNOTATE:
Chris@109 1351 presentLongStdoutToUser(output);
Chris@109 1352 shouldHgStat = true;
Chris@109 1353 break;
Chris@109 1354
Chris@109 1355 case ACT_PULL:
Chris@120 1356 showPullResult(output);
Chris@109 1357 shouldHgStat = true;
Chris@109 1358 break;
Chris@109 1359
Chris@109 1360 case ACT_PUSH:
Chris@120 1361 showPushResult(output);
Chris@109 1362 break;
Chris@109 1363
Chris@109 1364 case ACT_INIT:
Chris@109 1365 MultiChoiceDialog::addRecentArgument("init", workFolderPath);
Chris@109 1366 MultiChoiceDialog::addRecentArgument("local", workFolderPath);
Chris@109 1367 enableDisableActions();
Chris@109 1368 shouldHgStat = true;
Chris@109 1369 break;
Chris@109 1370
Chris@109 1371 case ACT_CLONEFROMREMOTE:
Chris@109 1372 MultiChoiceDialog::addRecentArgument("local", workFolderPath);
Chris@109 1373 MultiChoiceDialog::addRecentArgument("remote", remoteRepoPath);
Chris@109 1374 MultiChoiceDialog::addRecentArgument("remote", workFolderPath, true);
Chris@109 1375 QMessageBox::information(this, "Clone", output);
Chris@109 1376 enableDisableActions();
Chris@109 1377 shouldHgStat = true;
Chris@109 1378 break;
Chris@109 1379
Chris@109 1380 case ACT_LOG:
Chris@120 1381 hgTabs->setNewLog(output);
Chris@120 1382 needNewLog = false;
Chris@120 1383 break;
Chris@120 1384
Chris@120 1385 case ACT_LOG_INCREMENTAL:
Chris@120 1386 hgTabs->addIncrementalLog(output);
Chris@109 1387 break;
Chris@109 1388
Chris@109 1389 case ACT_QUERY_PARENTS:
Chris@152 1390 {
Chris@109 1391 foreach (Changeset *cs, currentParents) delete cs;
Chris@109 1392 currentParents = Changeset::parseChangesets(output);
Chris@152 1393 QStringList parentIds = Changeset::getIds(currentParents);
Chris@153 1394 hgTabs->setCurrent(parentIds, currentBranch);
Chris@152 1395 }
Chris@109 1396 break;
Chris@109 1397
Chris@109 1398 case ACT_QUERY_HEADS:
Chris@150 1399 {
Chris@150 1400 oldHeadIds = Changeset::getIds(currentHeads);
Chris@150 1401 Changesets newHeads = Changeset::parseChangesets(output);
Chris@150 1402 QStringList newHeadIds = Changeset::getIds(newHeads);
Chris@150 1403 if (oldHeadIds != newHeadIds) {
Chris@150 1404 DEBUG << "Heads changed, will prompt an incremental log if appropriate" << endl;
Chris@150 1405 headsChanged = true;
Chris@150 1406 foreach (Changeset *cs, currentHeads) delete cs;
Chris@150 1407 currentHeads = newHeads;
Chris@150 1408 }
Chris@150 1409 }
Chris@109 1410 break;
Chris@130 1411
Chris@130 1412 case ACT_COMMIT:
Chris@130 1413 hgTabs->clearSelections();
Chris@163 1414 justMerged = false;
Chris@130 1415 shouldHgStat = true;
Chris@130 1416 break;
Chris@163 1417
Chris@163 1418 case ACT_REVERT:
Chris@163 1419 hgMarkResolved(lastRevertedFiles);
Chris@163 1420 justMerged = false;
Chris@163 1421 break;
Chris@109 1422
Chris@109 1423 case ACT_REMOVE:
Chris@109 1424 case ACT_ADD:
Chris@116 1425 hgTabs->clearSelections();
Chris@116 1426 shouldHgStat = true;
Chris@116 1427 break;
Chris@116 1428
Chris@164 1429 case ACT_TAG:
Chris@164 1430 needNewLog = true;
Chris@164 1431 shouldHgStat = true;
Chris@164 1432 break;
Chris@164 1433
Chris@109 1434 case ACT_FOLDERDIFF:
Chris@109 1435 case ACT_CHGSETDIFF:
Chris@109 1436 case ACT_SERVE:
Chris@109 1437 case ACT_HG_IGNORE:
Chris@109 1438 shouldHgStat = true;
Chris@109 1439 break;
Chris@109 1440
Chris@109 1441 case ACT_UPDATE:
Chris@162 1442 QMessageBox::information(this, tr("Update"), tr("<qt><h3>Update successful</h3><p>%1</p>").arg(xmlEncode(output)));
Chris@109 1443 shouldHgStat = true;
Chris@109 1444 break;
Chris@109 1445
Chris@109 1446 case ACT_MERGE:
Chris@162 1447 QMessageBox::information(this, tr("Update"), tr("<qt><h3>Merge successful</h3><p>%1</p>").arg(xmlEncode(output)));
Chris@109 1448 shouldHgStat = true;
Chris@109 1449 justMerged = true;
Chris@109 1450 break;
Chris@109 1451
Chris@109 1452 case ACT_RETRY_MERGE:
Chris@163 1453 QMessageBox::information(this, tr("Resolved"),
Chris@163 1454 tr("<qt><h3>Merge resolved</h3><p>Merge resolved successfully.</p>"));
Chris@109 1455 shouldHgStat = true;
Chris@109 1456 justMerged = true;
Chris@109 1457 break;
Chris@109 1458
Chris@109 1459 default:
Chris@109 1460 break;
Chris@109 1461 }
Chris@108 1462
Chris@121 1463 // Sequence when no full log required:
Chris@163 1464 // paths -> branch -> stat -> resolve-list -> heads ->
Chris@150 1465 // incremental-log (only if heads changed) -> parents
Chris@150 1466 //
Chris@121 1467 // Sequence when full log required:
Chris@163 1468 // paths -> branch -> stat -> resolve-list -> heads -> parents -> log
Chris@150 1469 //
Chris@150 1470 // Note we want to call enableDisableActions only once, at the end
Chris@150 1471 // of whichever sequence is in use.
Chris@150 1472
Chris@156 1473 bool noMore = false;
Chris@156 1474
Chris@150 1475 switch (action) {
Chris@150 1476
Chris@150 1477 case ACT_QUERY_PATHS:
Chris@109 1478 hgQueryBranch();
Chris@150 1479 break;
Chris@150 1480
Chris@150 1481 case ACT_QUERY_BRANCH:
Chris@109 1482 hgStat();
Chris@150 1483 break;
Chris@150 1484
Chris@150 1485 case ACT_STAT:
Chris@163 1486 hgResolveList();
Chris@163 1487 break;
Chris@163 1488
Chris@163 1489 case ACT_RESOLVE_LIST:
Chris@150 1490 hgQueryHeads();
Chris@150 1491 break;
Chris@150 1492
Chris@150 1493 case ACT_QUERY_HEADS:
Chris@150 1494 if (headsChanged && !needNewLog) {
Chris@150 1495 hgLogIncremental(oldHeadIds);
Chris@121 1496 } else {
Chris@150 1497 hgQueryParents();
Chris@121 1498 }
Chris@150 1499 break;
Chris@150 1500
Chris@150 1501 case ACT_LOG_INCREMENTAL:
Chris@109 1502 hgQueryParents();
Chris@150 1503 break;
Chris@150 1504
Chris@150 1505 case ACT_QUERY_PARENTS:
Chris@120 1506 if (needNewLog) {
Chris@120 1507 hgLog();
Chris@150 1508 } else {
Chris@150 1509 // we're done
Chris@156 1510 noMore = true;
Chris@120 1511 }
Chris@150 1512 break;
Chris@150 1513
Chris@150 1514 case ACT_LOG:
Chris@150 1515 // we're done
Chris@156 1516 noMore = true;
Chris@150 1517
Chris@150 1518 default:
Chris@109 1519 if (shouldHgStat) {
Chris@163 1520 shouldHgStat = false;
Chris@109 1521 hgQueryPaths();
Chris@150 1522 } else {
Chris@156 1523 noMore = true;
jtkorhonen@0 1524 }
Chris@150 1525 break;
Chris@150 1526 }
Chris@156 1527
Chris@156 1528 if (noMore) {
Chris@156 1529 enableDisableActions();
Chris@156 1530 hgTabs->updateHistory();
Chris@156 1531 }
jtkorhonen@0 1532 }
jtkorhonen@0 1533
jtkorhonen@0 1534 void MainWindow::connectActions()
jtkorhonen@0 1535 {
jtkorhonen@0 1536 connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
jtkorhonen@0 1537 connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
jtkorhonen@0 1538 connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
jtkorhonen@0 1539
Chris@120 1540 connect(hgRefreshAct, SIGNAL(triggered()), this, SLOT(hgRefresh()));
jtkorhonen@0 1541 connect(hgRemoveAct, SIGNAL(triggered()), this, SLOT(hgRemove()));
jtkorhonen@0 1542 connect(hgAddAct, SIGNAL(triggered()), this, SLOT(hgAdd()));
jtkorhonen@0 1543 connect(hgCommitAct, SIGNAL(triggered()), this, SLOT(hgCommit()));
jtkorhonen@0 1544 connect(hgFolderDiffAct, SIGNAL(triggered()), this, SLOT(hgFolderDiff()));
Chris@149 1545 // connect(hgChgSetDiffAct, SIGNAL(triggered()), this, SLOT(hgChgSetDiff()));
jtkorhonen@0 1546 connect(hgUpdateAct, SIGNAL(triggered()), this, SLOT(hgUpdate()));
jtkorhonen@0 1547 connect(hgRevertAct, SIGNAL(triggered()), this, SLOT(hgRevert()));
jtkorhonen@0 1548 connect(hgMergeAct, SIGNAL(triggered()), this, SLOT(hgMerge()));
Chris@164 1549 // connect(hgTagAct, SIGNAL(triggered()), this, SLOT(hgTag()));
jtkorhonen@34 1550 connect(hgIgnoreAct, SIGNAL(triggered()), this, SLOT(hgIgnore()));
jtkorhonen@0 1551
jtkorhonen@0 1552 connect(settingsAct, SIGNAL(triggered()), this, SLOT(settings()));
Chris@69 1553 connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
jtkorhonen@0 1554
jtkorhonen@0 1555 connect(hgInitAct, SIGNAL(triggered()), this, SLOT(hgInit()));
jtkorhonen@0 1556 connect(hgCloneFromRemoteAct, SIGNAL(triggered()), this, SLOT(hgCloneFromRemote()));
jtkorhonen@0 1557 connect(hgIncomingAct, SIGNAL(triggered()), this, SLOT(hgIncoming()));
jtkorhonen@0 1558 connect(hgPullAct, SIGNAL(triggered()), this, SLOT(hgPull()));
jtkorhonen@0 1559 connect(hgPushAct, SIGNAL(triggered()), this, SLOT(hgPush()));
jtkorhonen@0 1560
Chris@109 1561 // connect(hgTabs, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int)));
jtkorhonen@0 1562
Chris@148 1563 // connect(hgUpdateToRevAct, SIGNAL(triggered()), this, SLOT(hgUpdateToRev()));
jtkorhonen@0 1564 connect(hgAnnotateAct, SIGNAL(triggered()), this, SLOT(hgAnnotate()));
jtkorhonen@11 1565 connect(hgServeAct, SIGNAL(triggered()), this, SLOT(hgServe()));
Chris@94 1566 connect(clearSelectionsAct, SIGNAL(triggered()), this, SLOT(clearSelections()));
jtkorhonen@0 1567 }
Chris@141 1568
Chris@141 1569 void MainWindow::connectTabsSignals()
Chris@141 1570 {
Chris@141 1571 connect(hgTabs, SIGNAL(commit()),
Chris@141 1572 this, SLOT(hgCommit()));
Chris@141 1573
Chris@141 1574 connect(hgTabs, SIGNAL(revert()),
Chris@141 1575 this, SLOT(hgRevert()));
Chris@141 1576
Chris@141 1577 connect(hgTabs, SIGNAL(diffWorkingFolder()),
Chris@141 1578 this, SLOT(hgFolderDiff()));
Chris@148 1579
Chris@141 1580 connect(hgTabs, SIGNAL(updateTo(QString)),
Chris@148 1581 this, SLOT(hgUpdateToRev(QString)));
Chris@141 1582
Chris@141 1583 connect(hgTabs, SIGNAL(diffToCurrent(QString)),
Chris@148 1584 this, SLOT(hgDiffToCurrent(QString)));
Chris@141 1585
Chris@148 1586 connect(hgTabs, SIGNAL(diffToParent(QString, QString)),
Chris@148 1587 this, SLOT(hgDiffToParent(QString, QString)));
Chris@141 1588
Chris@141 1589 connect(hgTabs, SIGNAL(mergeFrom(QString)),
Chris@148 1590 this, SLOT(hgMergeFrom(QString)));
Chris@164 1591
Chris@141 1592 connect(hgTabs, SIGNAL(tag(QString)),
Chris@148 1593 this, SLOT(hgTag(QString)));
Chris@141 1594 }
Chris@141 1595
Chris@109 1596 /*!!!
jtkorhonen@0 1597 void MainWindow::tabChanged(int currTab)
jtkorhonen@0 1598 {
jtkorhonen@0 1599 tabPage = currTab;
jtkorhonen@32 1600
jtkorhonen@0 1601 }
Chris@109 1602 */
jtkorhonen@0 1603 void MainWindow::enableDisableActions()
jtkorhonen@0 1604 {
Chris@90 1605 DEBUG << "MainWindow::enableDisableActions" << endl;
Chris@90 1606
Chris@115 1607 //!!! should also do things like set the status texts for the
Chris@115 1608 //!!! actions appropriately by context
Chris@115 1609
jtkorhonen@0 1610 QDir localRepoDir;
jtkorhonen@0 1611 QDir workFolderDir;
Chris@145 1612 bool workFolderExist = true;
Chris@145 1613 bool localRepoExist = true;
jtkorhonen@0 1614
jtkorhonen@0 1615 remoteRepoActionsEnabled = true;
Chris@90 1616 if (remoteRepoPath.isEmpty()) {
jtkorhonen@0 1617 remoteRepoActionsEnabled = false;
jtkorhonen@0 1618 }
jtkorhonen@0 1619
jtkorhonen@0 1620 localRepoActionsEnabled = true;
Chris@90 1621 if (workFolderPath.isEmpty()) {
jtkorhonen@0 1622 localRepoActionsEnabled = false;
jtkorhonen@0 1623 workFolderExist = false;
jtkorhonen@0 1624 }
jtkorhonen@0 1625
Chris@90 1626 if (!workFolderDir.exists(workFolderPath)) {
jtkorhonen@0 1627 localRepoActionsEnabled = false;
jtkorhonen@0 1628 workFolderExist = false;
Chris@90 1629 } else {
jtkorhonen@0 1630 workFolderExist = true;
jtkorhonen@0 1631 }
jtkorhonen@0 1632
Chris@112 1633 if (!localRepoDir.exists(workFolderPath + "/.hg")) {
jtkorhonen@0 1634 localRepoActionsEnabled = false;
jtkorhonen@0 1635 localRepoExist = false;
jtkorhonen@0 1636 }
jtkorhonen@0 1637
jtkorhonen@0 1638 hgCloneFromRemoteAct -> setEnabled(remoteRepoActionsEnabled);
jtkorhonen@0 1639 hgIncomingAct -> setEnabled(remoteRepoActionsEnabled && remoteRepoActionsEnabled);
jtkorhonen@0 1640 hgPullAct -> setEnabled(remoteRepoActionsEnabled && remoteRepoActionsEnabled);
jtkorhonen@0 1641 hgPushAct -> setEnabled(remoteRepoActionsEnabled && remoteRepoActionsEnabled);
Chris@73 1642 /*
jtkorhonen@0 1643 if (tabPage != WORKTAB)
jtkorhonen@0 1644 {
jtkorhonen@0 1645 localRepoActionsEnabled = false;
jtkorhonen@0 1646 }
Chris@73 1647 */
Chris@112 1648 bool haveDiff = (diffBinaryName != "");
Chris@112 1649
jtkorhonen@0 1650 hgInitAct -> setEnabled((localRepoExist == false) && (workFolderExist==true));
Chris@120 1651 hgRefreshAct -> setEnabled(localRepoActionsEnabled);
Chris@112 1652 hgFolderDiffAct -> setEnabled(localRepoActionsEnabled && haveDiff);
jtkorhonen@0 1653 hgRevertAct -> setEnabled(localRepoActionsEnabled);
jtkorhonen@0 1654 hgAddAct -> setEnabled(localRepoActionsEnabled);
jtkorhonen@0 1655 hgRemoveAct -> setEnabled(localRepoActionsEnabled);
jtkorhonen@0 1656 hgUpdateAct -> setEnabled(localRepoActionsEnabled);
jtkorhonen@0 1657 hgCommitAct -> setEnabled(localRepoActionsEnabled);
jtkorhonen@0 1658 hgMergeAct -> setEnabled(localRepoActionsEnabled);
jtkorhonen@2 1659 hgAnnotateAct -> setEnabled(localRepoActionsEnabled);
jtkorhonen@11 1660 hgServeAct -> setEnabled(localRepoActionsEnabled);
jtkorhonen@34 1661 hgTagAct -> setEnabled(localRepoActionsEnabled);
jtkorhonen@34 1662 hgIgnoreAct -> setEnabled(localRepoActionsEnabled);
jtkorhonen@0 1663
Chris@98 1664 //!!!hgTabs -> enableDisableOtherTabs(tabPage);
jtkorhonen@0 1665
Chris@90 1666 DEBUG << "localRepoActionsEnabled = " << localRepoActionsEnabled << endl;
Chris@98 1667 DEBUG << "canCommit = " << hgTabs->canCommit() << endl;
Chris@90 1668
Chris@90 1669 //!!! new stuff:
Chris@98 1670 hgAddAct->setEnabled(localRepoActionsEnabled && hgTabs->canAdd());
Chris@98 1671 hgRemoveAct->setEnabled(localRepoActionsEnabled && hgTabs->canRemove());
Chris@98 1672 hgCommitAct->setEnabled(localRepoActionsEnabled && hgTabs->canCommit());
Chris@163 1673 hgRevertAct->setEnabled(localRepoActionsEnabled && hgTabs->canRevert());
Chris@163 1674 hgFolderDiffAct->setEnabled(localRepoActionsEnabled && hgTabs->canDiff());
Chris@90 1675
Chris@108 1676 // A default merge makes sense if:
Chris@108 1677 // * there is only one parent (if there are two, we have an uncommitted merge) and
Chris@108 1678 // * there are exactly two heads that have the same branch as the current branch and
Chris@108 1679 // * our parent is one of those heads
Chris@108 1680 //
Chris@108 1681 // A default update makes sense if:
Chris@108 1682 // * there is only one parent and
Chris@108 1683 // * the parent is not one of the current heads
Chris@156 1684
Chris@108 1685 bool canMerge = false;
Chris@108 1686 bool canUpdate = false;
Chris@156 1687 bool haveMerge = false;
Chris@162 1688 bool emptyRepo = false;
Chris@156 1689 int currentBranchHeads = 0;
Chris@156 1690
Chris@108 1691 if (currentParents.size() == 1) {
Chris@156 1692 bool parentIsHead = false;
Chris@108 1693 Changeset *parent = currentParents[0];
Chris@108 1694 foreach (Changeset *head, currentHeads) {
Chris@108 1695 DEBUG << "head branch " << head->branch() << ", current branch " << currentBranch << endl;
Chris@108 1696 if (head->isOnBranch(currentBranch)) {
Chris@108 1697 ++currentBranchHeads;
Chris@108 1698 if (parent->id() == head->id()) {
Chris@108 1699 parentIsHead = true;
Chris@108 1700 }
Chris@108 1701 }
Chris@108 1702 }
Chris@108 1703 if (currentBranchHeads == 2 && parentIsHead) {
Chris@108 1704 canMerge = true;
Chris@108 1705 }
Chris@108 1706 if (!parentIsHead) {
Chris@108 1707 canUpdate = true;
Chris@108 1708 DEBUG << "parent id = " << parent->id() << endl;
Chris@108 1709 DEBUG << " head ids "<<endl;
Chris@108 1710 foreach (Changeset *h, currentHeads) {
Chris@108 1711 DEBUG << "head id = " << h->id() << endl;
Chris@108 1712 }
Chris@108 1713 }
Chris@162 1714 } else if (currentParents.size() == 0) {
Chris@162 1715 emptyRepo = true;
Chris@156 1716 } else {
Chris@156 1717 haveMerge = true;
Chris@163 1718 justMerged = true;
Chris@108 1719 }
Chris@156 1720
Chris@163 1721 hgMergeAct->setEnabled(localRepoActionsEnabled &&
Chris@163 1722 (canMerge || hgTabs->canResolve()));
Chris@163 1723 hgUpdateAct->setEnabled(localRepoActionsEnabled &&
Chris@163 1724 (canUpdate && !hgTabs->canRevert()));
Chris@115 1725
Chris@115 1726 // Set the state field on the file status widget
Chris@115 1727
Chris@115 1728 QString branchText;
Chris@115 1729 if (currentBranch == "" || currentBranch == "default") {
Chris@115 1730 branchText = tr("the default branch");
Chris@115 1731 } else {
Chris@115 1732 branchText = tr("branch \"%1\"").arg(currentBranch);
Chris@115 1733 }
Chris@156 1734
Chris@156 1735 //!!! Want "merge failed" report
Chris@156 1736
Chris@162 1737 if (emptyRepo) {
Chris@162 1738 hgTabs->setState(tr("Nothing committed to this repository yet"));
Chris@162 1739 } else if (canMerge) {
Chris@156 1740 hgTabs->setState(tr("<b>Awaiting merge</b> on %1").arg(branchText));
Chris@163 1741 } else if (!hgTabs->getAllUnresolvedFiles().empty()) {
Chris@163 1742 hgTabs->setState(tr("Have unresolved files following merge on %1").arg(branchText));
Chris@156 1743 } else if (haveMerge) {
Chris@157 1744 hgTabs->setState(tr("Have merged but not yet committed on %1").arg(branchText));
Chris@156 1745 } else if (canUpdate) {
Chris@163 1746 if (hgTabs->canRevert()) {
Chris@163 1747 // have uncommitted changes
Chris@163 1748 hgTabs->setState(tr("On %1. Not at the head of the branch").arg(branchText));
Chris@163 1749 } else {
Chris@163 1750 // no uncommitted changes
Chris@163 1751 hgTabs->setState(tr("On %1. Not at the head of the branch: consider updating").arg(branchText));
Chris@163 1752 }
Chris@156 1753 } else if (currentBranchHeads > 1) {
Chris@156 1754 hgTabs->setState(tr("At one of %n heads of %1", "", currentBranchHeads).arg(branchText));
Chris@115 1755 } else {
Chris@115 1756 hgTabs->setState(tr("At the head of %1").arg(branchText));
Chris@115 1757 }
jtkorhonen@0 1758 }
jtkorhonen@0 1759
jtkorhonen@0 1760 void MainWindow::createActions()
jtkorhonen@0 1761 {
jtkorhonen@0 1762 //File actions
jtkorhonen@0 1763 hgInitAct = new QAction(tr("Init local repository"), this);
jtkorhonen@0 1764 hgInitAct->setStatusTip(tr("Create an empty local repository in selected folder"));
jtkorhonen@0 1765
jtkorhonen@0 1766 hgCloneFromRemoteAct = new QAction(tr("Clone from remote"), this);
jtkorhonen@0 1767 hgCloneFromRemoteAct->setStatusTip(tr("Clone from remote repository into local repository in selected folder"));
jtkorhonen@0 1768
Chris@69 1769 openAct = new QAction(QIcon(":/images/fileopen.png"), tr("Open..."), this);
Chris@69 1770 openAct -> setStatusTip(tr("Open repository"));
Chris@69 1771 openAct -> setIconVisibleInMenu(true);
Chris@69 1772
jtkorhonen@0 1773 settingsAct = new QAction(QIcon(":/images/settings.png"), tr("Settings..."), this);
jtkorhonen@0 1774 settingsAct -> setStatusTip(tr("View and change application settings"));
jtkorhonen@0 1775 settingsAct -> setIconVisibleInMenu(true);
jtkorhonen@0 1776
jtkorhonen@0 1777 exitAct = new QAction(QIcon(":/images/exit.png"), tr("Exit"), this);
jtkorhonen@0 1778 exitAct->setShortcuts(QKeySequence::Quit);
jtkorhonen@0 1779 exitAct->setStatusTip(tr("Exit application"));
jtkorhonen@0 1780 exitAct -> setIconVisibleInMenu(true);
jtkorhonen@0 1781
jtkorhonen@0 1782 //Repository actions
Chris@120 1783 hgRefreshAct = new QAction(QIcon(":/images/status.png"), tr("Refresh"), this);
Chris@120 1784 hgRefreshAct->setStatusTip(tr("Refresh (info of) status of workfolder files"));
Chris@61 1785
Chris@61 1786 hgIncomingAct = new QAction(QIcon(":/images/incoming.png"), tr("Preview"), this);
jtkorhonen@0 1787 hgIncomingAct -> setStatusTip(tr("View info of changesets incoming to us from remote repository (on pull operation)"));
jtkorhonen@0 1788
Chris@61 1789 hgPullAct = new QAction(QIcon(":/images/pull.png"), tr("Pull"), this);
jtkorhonen@0 1790 hgPullAct -> setStatusTip(tr("Pull changesets from remote repository to local repository"));
jtkorhonen@0 1791
Chris@61 1792 hgPushAct = new QAction(QIcon(":/images/push.png"), tr("Push"), this);
jtkorhonen@0 1793 hgPushAct->setStatusTip(tr("Push local changesets to remote repository"));
jtkorhonen@0 1794
jtkorhonen@0 1795 //Workfolder actions
Chris@99 1796 hgFolderDiffAct = new QAction(QIcon(":/images/folderdiff.png"), tr("Diff"), this);
jtkorhonen@0 1797 hgFolderDiffAct->setStatusTip(tr("Folderdiff: View all differences between working folder files and local repository files"));
jtkorhonen@0 1798
jtkorhonen@0 1799 hgChgSetDiffAct = new QAction(QIcon(":/images/chgsetdiff.png"), tr("View changesetdiff"), this);
jtkorhonen@0 1800 hgChgSetDiffAct->setStatusTip(tr("Change set diff: View differences between all files of 2 repository changesets"));
jtkorhonen@0 1801
Chris@61 1802 hgRevertAct = new QAction(QIcon(":/images/undo.png"), tr("Revert"), this);
jtkorhonen@0 1803 hgRevertAct->setStatusTip(tr("Undo selected working folder file changes (return to local repository version)"));
jtkorhonen@0 1804
Chris@61 1805 hgAddAct = new QAction(QIcon(":/images/add.png"), tr("Add"), this);
jtkorhonen@17 1806 hgAddAct -> setStatusTip(tr("Add working folder file(s) (selected or all yet untracked) to local repository (on next commit)"));
jtkorhonen@0 1807
Chris@61 1808 hgRemoveAct = new QAction(QIcon(":/images/remove.png"), tr("Remove"), this);
jtkorhonen@0 1809 hgRemoveAct -> setStatusTip(tr("Remove selected working folder file from local repository (on next commit)"));
jtkorhonen@0 1810
Chris@61 1811 hgUpdateAct = new QAction(QIcon(":/images/update.png"), tr("Update"), this);
jtkorhonen@0 1812 hgUpdateAct->setStatusTip(tr("Update working folder from local repository"));
jtkorhonen@0 1813
Chris@61 1814 hgCommitAct = new QAction(QIcon(":/images/commit.png"), tr("Commit"), this);
jtkorhonen@20 1815 hgCommitAct->setStatusTip(tr("Save selected file(s) or all changed files in working folder (and all subfolders) to local repository"));
jtkorhonen@0 1816
jtkorhonen@0 1817 hgMergeAct = new QAction(QIcon(":/images/merge.png"), tr("Merge"), this);
jtkorhonen@0 1818 hgMergeAct->setStatusTip(tr("Merge two local repository changesets to working folder"));
jtkorhonen@0 1819
jtkorhonen@0 1820 //Advanced actions
Chris@148 1821 /* hgUpdateToRevAct = new QAction(tr("Update to revision"), this);
jtkorhonen@0 1822 hgUpdateToRevAct -> setStatusTip(tr("Update working folder to version selected from history list"));
Chris@148 1823 */
jtkorhonen@0 1824 hgAnnotateAct = new QAction(tr("Annotate"), this);
jtkorhonen@0 1825 hgAnnotateAct -> setStatusTip(tr("Show line-by-line version information for selected file"));
jtkorhonen@0 1826
jtkorhonen@34 1827 hgTagAct = new QAction(tr("Tag revision"), this);
jtkorhonen@34 1828 hgTagAct -> setStatusTip(tr("Give decsriptive name (tag) to current workfolder parent revision."));
jtkorhonen@34 1829
jtkorhonen@34 1830 hgIgnoreAct = new QAction(tr("Edit .hgignore"), this);
jtkorhonen@34 1831 hgIgnoreAct -> setStatusTip(tr("Edit .hgignore file (file contains names of files that should be ignored by mercurial)"));
jtkorhonen@34 1832
jtkorhonen@11 1833 hgServeAct = new QAction(tr("Serve (via http)"), this);
jtkorhonen@11 1834 hgServeAct -> setStatusTip(tr("Serve local repository via http for workgroup access"));
jtkorhonen@11 1835
jtkorhonen@0 1836 //Help actions
jtkorhonen@0 1837 aboutAct = new QAction(tr("About"), this);
jtkorhonen@0 1838 aboutAct->setStatusTip(tr("Show the application's About box"));
jtkorhonen@0 1839
jtkorhonen@0 1840 aboutQtAct = new QAction(tr("About Qt"), this);
jtkorhonen@0 1841 aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
Chris@94 1842
Chris@94 1843 // Miscellaneous
Chris@94 1844 clearSelectionsAct = new QAction(tr("Clear selections"), this);
Chris@94 1845 clearSelectionsAct->setShortcut(Qt::Key_Escape);
jtkorhonen@0 1846 }
jtkorhonen@0 1847
jtkorhonen@0 1848 void MainWindow::createMenus()
jtkorhonen@0 1849 {
jtkorhonen@0 1850 fileMenu = menuBar()->addMenu(tr("File"));
Chris@131 1851 /* fileMenu -> addAction(hgInitAct);
jtkorhonen@0 1852 fileMenu -> addAction(hgCloneFromRemoteAct);
Chris@94 1853 fileMenu->addAction(clearSelectionsAct); //!!! can't live here!
jtkorhonen@0 1854 fileMenu -> addSeparator();
Chris@131 1855 */
Chris@69 1856 fileMenu -> addAction(openAct);
jtkorhonen@0 1857 fileMenu -> addAction(settingsAct);
jtkorhonen@0 1858 fileMenu -> addSeparator();
jtkorhonen@0 1859 fileMenu -> addAction(exitAct);
jtkorhonen@0 1860
jtkorhonen@0 1861 advancedMenu = menuBar()->addMenu(tr("Advanced"));
Chris@131 1862 /*
jtkorhonen@0 1863 advancedMenu -> addAction(hgUpdateToRevAct);
jtkorhonen@0 1864 advancedMenu -> addSeparator();
jtkorhonen@0 1865 advancedMenu -> addAction(hgAnnotateAct);
jtkorhonen@0 1866 advancedMenu -> addSeparator();
jtkorhonen@33 1867 advancedMenu -> addAction(hgRetryMergeAct);
jtkorhonen@0 1868 advancedMenu -> addAction(hgResolveListAct);
jtkorhonen@0 1869 advancedMenu -> addAction(hgResolveMarkAct);
jtkorhonen@11 1870 advancedMenu -> addSeparator();
jtkorhonen@34 1871 advancedMenu -> addAction(hgTagAct);
jtkorhonen@34 1872 advancedMenu -> addSeparator();
Chris@131 1873 */
jtkorhonen@34 1874 advancedMenu -> addAction(hgIgnoreAct);
jtkorhonen@34 1875 advancedMenu -> addSeparator();
jtkorhonen@11 1876 advancedMenu -> addAction(hgServeAct);
jtkorhonen@0 1877
jtkorhonen@0 1878 helpMenu = menuBar()->addMenu(tr("Help"));
jtkorhonen@0 1879 helpMenu->addAction(aboutAct);
Chris@128 1880 //!!! helpMenu->addAction(aboutQtAct);
jtkorhonen@0 1881 }
jtkorhonen@0 1882
jtkorhonen@0 1883 void MainWindow::createToolBars()
jtkorhonen@0 1884 {
jtkorhonen@0 1885 fileToolBar = addToolBar(tr("File"));
jtkorhonen@0 1886 fileToolBar -> setIconSize(QSize(MY_ICON_SIZE, MY_ICON_SIZE));
Chris@69 1887 fileToolBar -> addAction(openAct);
Chris@120 1888 fileToolBar -> addAction(hgRefreshAct);
jtkorhonen@0 1889 fileToolBar -> addSeparator();
Chris@61 1890 // fileToolBar -> addAction(hgChgSetDiffAct);
jtkorhonen@0 1891 fileToolBar -> setMovable(false);
jtkorhonen@0 1892
jtkorhonen@0 1893 repoToolBar = addToolBar(tr(REPOMENU_TITLE));
jtkorhonen@0 1894 repoToolBar -> setIconSize(QSize(MY_ICON_SIZE, MY_ICON_SIZE));
jtkorhonen@0 1895 repoToolBar->addAction(hgIncomingAct);
jtkorhonen@0 1896 repoToolBar->addAction(hgPullAct);
jtkorhonen@0 1897 repoToolBar->addAction(hgPushAct);
jtkorhonen@0 1898 repoToolBar -> setMovable(false);
jtkorhonen@0 1899
jtkorhonen@0 1900 workFolderToolBar = addToolBar(tr(WORKFOLDERMENU_TITLE));
jtkorhonen@0 1901 addToolBar(Qt::LeftToolBarArea, workFolderToolBar);
jtkorhonen@0 1902 workFolderToolBar -> setIconSize(QSize(MY_ICON_SIZE, MY_ICON_SIZE));
Chris@95 1903 workFolderToolBar->addAction(hgFolderDiffAct);
jtkorhonen@0 1904 workFolderToolBar->addSeparator();
jtkorhonen@0 1905 workFolderToolBar->addAction(hgRevertAct);
jtkorhonen@0 1906 workFolderToolBar->addAction(hgUpdateAct);
jtkorhonen@0 1907 workFolderToolBar->addAction(hgCommitAct);
jtkorhonen@0 1908 workFolderToolBar->addAction(hgMergeAct);
jtkorhonen@0 1909 workFolderToolBar->addSeparator();
jtkorhonen@0 1910 workFolderToolBar->addAction(hgAddAct);
jtkorhonen@0 1911 workFolderToolBar->addAction(hgRemoveAct);
jtkorhonen@0 1912 workFolderToolBar -> setMovable(false);
Chris@61 1913
Chris@61 1914 foreach (QToolButton *tb, findChildren<QToolButton *>()) {
Chris@61 1915 tb->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
Chris@61 1916 }
jtkorhonen@0 1917 }
jtkorhonen@0 1918
jtkorhonen@0 1919
jtkorhonen@0 1920 void MainWindow::createStatusBar()
jtkorhonen@0 1921 {
jtkorhonen@0 1922 statusBar()->showMessage(tr("Ready"));
jtkorhonen@0 1923 }
jtkorhonen@0 1924
Chris@69 1925
Chris@69 1926 //!!! review these:
Chris@69 1927
jtkorhonen@0 1928 void MainWindow::readSettings()
jtkorhonen@0 1929 {
jtkorhonen@0 1930 QDir workFolder;
jtkorhonen@0 1931
Chris@61 1932 QSettings settings;
jtkorhonen@0 1933
jtkorhonen@30 1934 remoteRepoPath = settings.value("remoterepopath", "").toString();
jtkorhonen@0 1935 workFolderPath = settings.value("workfolderpath", "").toString();
jtkorhonen@0 1936 if (!workFolder.exists(workFolderPath))
jtkorhonen@0 1937 {
jtkorhonen@0 1938 workFolderPath = "";
jtkorhonen@0 1939 }
jtkorhonen@0 1940
jtkorhonen@0 1941 QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
jtkorhonen@0 1942 QSize size = settings.value("size", QSize(400, 400)).toSize();
jtkorhonen@0 1943 firstStart = settings.value("firststart", QVariant(true)).toBool();
jtkorhonen@0 1944
Chris@109 1945 //!!! initialFileTypesBits = (unsigned char) settings.value("viewFileTypes", QVariant(DEFAULT_HG_STAT_BITS)).toInt();
jtkorhonen@0 1946 resize(size);
jtkorhonen@0 1947 move(pos);
jtkorhonen@0 1948 }
jtkorhonen@0 1949
jtkorhonen@17 1950
jtkorhonen@0 1951 void MainWindow::writeSettings()
jtkorhonen@0 1952 {
Chris@61 1953 QSettings settings;
jtkorhonen@0 1954 settings.setValue("pos", pos());
jtkorhonen@0 1955 settings.setValue("size", size());
jtkorhonen@0 1956 settings.setValue("remoterepopath", remoteRepoPath);
jtkorhonen@0 1957 settings.setValue("workfolderpath", workFolderPath);
jtkorhonen@0 1958 settings.setValue("firststart", firstStart);
Chris@98 1959 //!!!settings.setValue("viewFileTypes", hgTabs -> getFileTypesBits());
jtkorhonen@0 1960 }
jtkorhonen@0 1961
jtkorhonen@0 1962
jtkorhonen@0 1963
jtkorhonen@0 1964