comparison mainwindow.cpp @ 307:5b4aa1c24407 new-branches-with-status-outside-tabs

Merge branch status_outside_tabs into branch new-branches, and make a new branch
author Chris Cannam
date Mon, 28 Feb 2011 13:09:37 +0000
parents f7cdd5b31aed b280a2dc0512
children 7f50c040e13d
comparison
equal deleted inserted replaced
278:f7cdd5b31aed 307:5b4aa1c24407
41 #include "debug.h" 41 #include "debug.h"
42 #include "logparser.h" 42 #include "logparser.h"
43 #include "confirmcommentdialog.h" 43 #include "confirmcommentdialog.h"
44 #include "incomingdialog.h" 44 #include "incomingdialog.h"
45 #include "settingsdialog.h" 45 #include "settingsdialog.h"
46 #include "moreinformationdialog.h"
46 #include "version.h" 47 #include "version.h"
48 #include "workstatuswidget.h"
47 49
48 50
49 MainWindow::MainWindow(QString myDirPath) : 51 MainWindow::MainWindow(QString myDirPath) :
50 m_myDirPath(myDirPath), 52 m_myDirPath(myDirPath),
51 m_fsWatcherGeneralTimer(0), 53 m_fsWatcherGeneralTimer(0),
54 { 56 {
55 setWindowIcon(QIcon(":images/easyhg-icon.png")); 57 setWindowIcon(QIcon(":images/easyhg-icon.png"));
56 58
57 QString wndTitle; 59 QString wndTitle;
58 60
59 showAllFiles = false; 61 m_showAllFiles = false;
60 62
61 fsWatcher = 0; 63 m_fsWatcher = 0;
62 commitsSincePush = 0; 64 m_commitsSincePush = 0;
63 shouldHgStat = true; 65 m_shouldHgStat = true;
64 66
65 createActions(); 67 createActions();
66 createMenus(); 68 createMenus();
67 createToolBars(); 69 createToolBars();
68 createStatusBar(); 70 createStatusBar();
69 71
70 runner = new HgRunner(myDirPath, this); 72 m_runner = new HgRunner(m_myDirPath, this);
71 connect(runner, SIGNAL(commandStarting(HgAction)), 73 connect(m_runner, SIGNAL(commandStarting(HgAction)),
72 this, SLOT(commandStarting(HgAction))); 74 this, SLOT(commandStarting(HgAction)));
73 connect(runner, SIGNAL(commandCompleted(HgAction, QString)), 75 connect(m_runner, SIGNAL(commandCompleted(HgAction, QString)),
74 this, SLOT(commandCompleted(HgAction, QString))); 76 this, SLOT(commandCompleted(HgAction, QString)));
75 connect(runner, SIGNAL(commandFailed(HgAction, QString)), 77 connect(m_runner, SIGNAL(commandFailed(HgAction, QString)),
76 this, SLOT(commandFailed(HgAction, QString))); 78 this, SLOT(commandFailed(HgAction, QString)));
77 statusBar()->addPermanentWidget(runner); 79 statusBar()->addPermanentWidget(m_runner);
78 80
79 setWindowTitle(tr("EasyMercurial")); 81 setWindowTitle(tr("EasyMercurial"));
80 82
81 remoteRepoPath = ""; 83 m_remoteRepoPath = "";
82 workFolderPath = ""; 84 m_workFolderPath = "";
83 85
84 readSettings(); 86 readSettings();
85 87
86 justMerged = false; 88 m_justMerged = false;
87 89
88 QWidget *central = new QWidget(this); 90 QWidget *central = new QWidget(this);
89 setCentralWidget(central); 91 setCentralWidget(central);
90 92
91 hgTabs = new HgTabWidget(central, remoteRepoPath, workFolderPath);
92 connectTabsSignals();
93
94 // Instead of setting the tab widget as our central widget
95 // directly, put it in a layout, so that we can have some space
96 // around it on the Mac where it looks very strange without
97
98 QGridLayout *cl = new QGridLayout(central); 93 QGridLayout *cl = new QGridLayout(central);
99 cl->addWidget(hgTabs, 0, 0); 94 int row = 0;
100 95
101 #ifndef Q_OS_MAC 96 #ifndef Q_OS_MAC
102 cl->setMargin(0); 97 cl->setMargin(0);
103 #endif 98 #endif
104 99
105 connect(hgTabs, SIGNAL(selectionChanged()), 100 m_workStatus = new WorkStatusWidget(this);
101 cl->addWidget(m_workStatus, row++, 0);
102
103 m_hgTabs = new HgTabWidget(central, m_workFolderPath);
104 connectTabsSignals();
105
106 cl->addWidget(m_hgTabs, row++, 0);
107
108 connect(m_hgTabs, SIGNAL(selectionChanged()),
106 this, SLOT(enableDisableActions())); 109 this, SLOT(enableDisableActions()));
107 connect(hgTabs, SIGNAL(showAllChanged(bool)), 110 connect(m_hgTabs, SIGNAL(showAllChanged(bool)),
108 this, SLOT(showAllChanged(bool))); 111 this, SLOT(showAllChanged(bool)));
109 112
110 setUnifiedTitleAndToolBarOnMac(true); 113 setUnifiedTitleAndToolBarOnMac(true);
111 connectActions(); 114 connectActions();
112 clearState(); 115 clearState();
113 enableDisableActions(); 116 enableDisableActions();
114 117
115 if (firstStart) { 118 if (m_firstStart) {
116 startupDialog(); 119 startupDialog();
117 } 120 }
118 121
119 SettingsDialog::findDefaultLocations(m_myDirPath); 122 SettingsDialog::findDefaultLocations(m_myDirPath);
120 123
129 132
130 133
131 void MainWindow::closeEvent(QCloseEvent *) 134 void MainWindow::closeEvent(QCloseEvent *)
132 { 135 {
133 writeSettings(); 136 writeSettings();
134 delete fsWatcher; 137 delete m_fsWatcher;
135 } 138 }
136 139
137 140
138 QString MainWindow::getUserInfo() const 141 QString MainWindow::getUserInfo() const
139 { 142 {
193 ).arg(EASYHG_VERSION)); 196 ).arg(EASYHG_VERSION));
194 } 197 }
195 198
196 void MainWindow::clearSelections() 199 void MainWindow::clearSelections()
197 { 200 {
198 hgTabs->clearSelections(); 201 m_hgTabs->clearSelections();
199 } 202 }
200 203
201 void MainWindow::showAllChanged(bool s) 204 void MainWindow::showAllChanged(bool s)
202 { 205 {
203 showAllFiles = s; 206 m_showAllFiles = s;
204 hgQueryPaths(); 207 hgQueryPaths();
205 } 208 }
206 209
207 void MainWindow::hgRefresh() 210 void MainWindow::hgRefresh()
208 { 211 {
214 { 217 {
215 QStringList params; 218 QStringList params;
216 //!!! should we test version output? Really we want at least 1.7.x 219 //!!! should we test version output? Really we want at least 1.7.x
217 //!!! for options such as merge --tool 220 //!!! for options such as merge --tool
218 params << "--version"; 221 params << "--version";
219 runner->requestAction(HgAction(ACT_TEST_HG, m_myDirPath, params)); 222 m_runner->requestAction(HgAction(ACT_TEST_HG, m_myDirPath, params));
220 } 223 }
221 224
222 void MainWindow::hgTestExtension() 225 void MainWindow::hgTestExtension()
223 { 226 {
224 QStringList params; 227 QStringList params;
225 params << "--version"; 228 params << "--version";
226 runner->requestAction(HgAction(ACT_TEST_HG_EXT, m_myDirPath, params)); 229 m_runner->requestAction(HgAction(ACT_TEST_HG_EXT, m_myDirPath, params));
227 } 230 }
228 231
229 void MainWindow::hgStat() 232 void MainWindow::hgStat()
230 { 233 {
231 QStringList params; 234 QStringList params;
232 235
233 if (showAllFiles) { 236 if (m_showAllFiles) {
234 params << "stat" << "-A"; 237 params << "stat" << "-A";
235 } else { 238 } else {
236 params << "stat" << "-ardum"; 239 params << "stat" << "-ardum";
237 } 240 }
238 241
239 lastStatOutput = ""; 242 m_lastStatOutput = "";
240 243
241 runner->requestAction(HgAction(ACT_STAT, workFolderPath, params)); 244 m_runner->requestAction(HgAction(ACT_STAT, m_workFolderPath, params));
242 } 245 }
243 246
244 void MainWindow::hgQueryPaths() 247 void MainWindow::hgQueryPaths()
245 { 248 {
246 // Quickest is to just read the file 249 // Quickest is to just read the file
247 250
248 QFileInfo hgrc(workFolderPath + "/.hg/hgrc"); 251 QFileInfo hgrc(m_workFolderPath + "/.hg/hgrc");
249 252
250 QString path; 253 QString path;
251 254
252 if (hgrc.exists()) { 255 if (hgrc.exists()) {
253 QSettings s(hgrc.canonicalFilePath(), QSettings::IniFormat); 256 QSettings s(hgrc.canonicalFilePath(), QSettings::IniFormat);
254 s.beginGroup("paths"); 257 s.beginGroup("paths");
255 path = s.value("default").toString(); 258 path = s.value("default").toString();
256 } 259 }
257 260
258 remoteRepoPath = path; 261 m_remoteRepoPath = path;
259 262
260 // We have to do this here, because commandCompleted won't be called 263 // We have to do this here, because commandCompleted won't be called
261 MultiChoiceDialog::addRecentArgument("local", workFolderPath); 264 MultiChoiceDialog::addRecentArgument("local", m_workFolderPath);
262 MultiChoiceDialog::addRecentArgument("remote", remoteRepoPath); 265 MultiChoiceDialog::addRecentArgument("remote", m_remoteRepoPath);
263 hgTabs->setWorkFolderAndRepoNames(workFolderPath, remoteRepoPath); 266 updateWorkFolderAndRepoNames();
264 267
265 hgQueryBranch(); 268 hgQueryBranch();
266 return; 269 return;
267 270
268 /* The classic method! 271 /* The classic method!
269 272
270 QStringList params; 273 QStringList params;
271 params << "paths"; 274 params << "paths";
272 runner->requestAction(HgAction(ACT_QUERY_PATHS, workFolderPath, params)); 275 m_runner->requestAction(HgAction(ACT_QUERY_PATHS, m_workFolderPath, params));
273 */ 276 */
274 } 277 }
275 278
276 void MainWindow::hgQueryBranch() 279 void MainWindow::hgQueryBranch()
277 { 280 {
278 // Quickest is to just read the file 281 // Quickest is to just read the file
279 282
280 QFile hgbr(workFolderPath + "/.hg/branch"); 283 QFile hgbr(m_workFolderPath + "/.hg/branch");
281 284
282 QString br = "default"; 285 QString br = "default";
283 286
284 if (hgbr.exists() && hgbr.open(QFile::ReadOnly)) { 287 if (hgbr.exists() && hgbr.open(QFile::ReadOnly)) {
285 QByteArray ba = hgbr.readLine(); 288 QByteArray ba = hgbr.readLine();
286 br = QString::fromUtf8(ba).trimmed(); 289 br = QString::fromUtf8(ba).trimmed();
287 } 290 }
288 291
289 currentBranch = br; 292 m_currentBranch = br;
290 293
291 // We have to do this here, because commandCompleted won't be called 294 // We have to do this here, because commandCompleted won't be called
292 hgStat(); 295 hgStat();
293 return; 296 return;
294 297
295 /* The classic method! 298 /* The classic method!
296 299
297 QStringList params; 300 QStringList params;
298 params << "branch"; 301 params << "branch";
299 runner->requestAction(HgAction(ACT_QUERY_BRANCH, workFolderPath, params)); 302 m_runner->requestAction(HgAction(ACT_QUERY_BRANCH, m_workFolderPath, params));
300 */ 303 */
301 } 304 }
302 305
303 void MainWindow::hgQueryHeads() 306 void MainWindow::hgQueryHeads()
304 { 307 {
307 // that. Use --closed option so as to include closed branches; 310 // that. Use --closed option so as to include closed branches;
308 // otherwise we'll be stuck if the user updates into one, and our 311 // otherwise we'll be stuck if the user updates into one, and our
309 // incremental log will end up with spurious stuff in it because 312 // incremental log will end up with spurious stuff in it because
310 // we won't be pruning at the ends of closed branches 313 // we won't be pruning at the ends of closed branches
311 params << "heads" << "--closed"; 314 params << "heads" << "--closed";
312 runner->requestAction(HgAction(ACT_QUERY_HEADS, workFolderPath, params)); 315 m_runner->requestAction(HgAction(ACT_QUERY_HEADS, m_workFolderPath, params));
313 } 316 }
314 317
315 void MainWindow::hgLog() 318 void MainWindow::hgLog()
316 { 319 {
317 QStringList params; 320 QStringList params;
318 params << "log"; 321 params << "log";
319 params << "--template"; 322 params << "--template";
320 params << Changeset::getLogTemplate(); 323 params << Changeset::getLogTemplate();
321 324
322 runner->requestAction(HgAction(ACT_LOG, workFolderPath, params)); 325 m_runner->requestAction(HgAction(ACT_LOG, m_workFolderPath, params));
323 } 326 }
324 327
325 void MainWindow::hgLogIncremental(QStringList prune) 328 void MainWindow::hgLogIncremental(QStringList prune)
326 { 329 {
330 // Sometimes we can be called with prune empty -- it represents
331 // the current heads, but if we have none already and for some
332 // reason are being prompted for an incremental update, we may run
333 // into trouble. In that case, make this a full log instead
334
335 if (prune.empty()) {
336 hgLog();
337 return;
338 }
339
327 QStringList params; 340 QStringList params;
328 params << "log"; 341 params << "log";
329 342
330 foreach (QString p, prune) { 343 foreach (QString p, prune) {
331 params << "--prune" << Changeset::hashOf(p); 344 params << "--prune" << Changeset::hashOf(p);
332 } 345 }
333 346
334 params << "--template"; 347 params << "--template";
335 params << Changeset::getLogTemplate(); 348 params << Changeset::getLogTemplate();
336 349
337 runner->requestAction(HgAction(ACT_LOG_INCREMENTAL, workFolderPath, params)); 350 m_runner->requestAction(HgAction(ACT_LOG_INCREMENTAL, m_workFolderPath, params));
338 } 351 }
339 352
340 void MainWindow::hgQueryParents() 353 void MainWindow::hgQueryParents()
341 { 354 {
342 QStringList params; 355 QStringList params;
343 params << "parents"; 356 params << "parents";
344 runner->requestAction(HgAction(ACT_QUERY_PARENTS, workFolderPath, params)); 357 m_runner->requestAction(HgAction(ACT_QUERY_PARENTS, m_workFolderPath, params));
345 } 358 }
346 359
347 void MainWindow::hgAnnotate() 360 void MainWindow::hgAnnotate()
348 { 361 {
349 QStringList params; 362 QStringList params;
350 QString currentFile;//!!! = hgTabs -> getCurrentFileListLine(); 363 QString currentFile;//!!! = m_hgTabs -> getCurrentFileListLine();
351 364
352 if (!currentFile.isEmpty()) 365 if (!currentFile.isEmpty())
353 { 366 {
354 params << "annotate" << "--" << currentFile.mid(2); //Jump over status marker characters (e.g "M ") 367 params << "annotate" << "--" << currentFile.mid(2); //Jump over status marker characters (e.g "M ")
355 368
356 runner->requestAction(HgAction(ACT_ANNOTATE, workFolderPath, params)); 369 m_runner->requestAction(HgAction(ACT_ANNOTATE, m_workFolderPath, params));
357 } 370 }
358 } 371 }
359 372
360 void MainWindow::hgResolveList() 373 void MainWindow::hgResolveList()
361 { 374 {
362 QStringList params; 375 QStringList params;
363 376
364 params << "resolve" << "--list"; 377 params << "resolve" << "--list";
365 runner->requestAction(HgAction(ACT_RESOLVE_LIST, workFolderPath, params)); 378 m_runner->requestAction(HgAction(ACT_RESOLVE_LIST, m_workFolderPath, params));
366 } 379 }
367 380
368 void MainWindow::hgAdd() 381 void MainWindow::hgAdd()
369 { 382 {
370 QStringList params; 383 QStringList params;
371 384
372 // hgExplorer permitted adding "all" files -- I'm not sure 385 // hgExplorer permitted adding "all" files -- I'm not sure
373 // that one is a good idea, let's require the user to select 386 // that one is a good idea, let's require the user to select
374 387
375 QStringList files = hgTabs->getSelectedAddableFiles(); 388 QStringList files = m_hgTabs->getSelectedAddableFiles();
376 389
377 if (!files.empty()) { 390 if (!files.empty()) {
378 params << "add" << "--" << files; 391 params << "add" << "--" << files;
379 runner->requestAction(HgAction(ACT_ADD, workFolderPath, params)); 392 m_runner->requestAction(HgAction(ACT_ADD, m_workFolderPath, params));
380 } 393 }
381 } 394 }
382 395
383 396
384 void MainWindow::hgRemove() 397 void MainWindow::hgRemove()
385 { 398 {
386 QStringList params; 399 QStringList params;
387 400
388 QStringList files = hgTabs->getSelectedRemovableFiles(); 401 QStringList files = m_hgTabs->getSelectedRemovableFiles();
389 402
390 if (!files.empty()) { 403 if (!files.empty()) {
391 params << "remove" << "--after" << "--force" << "--" << files; 404 params << "remove" << "--after" << "--force" << "--" << files;
392 runner->requestAction(HgAction(ACT_REMOVE, workFolderPath, params)); 405 m_runner->requestAction(HgAction(ACT_REMOVE, m_workFolderPath, params));
393 } 406 }
394 } 407 }
395 408
396 void MainWindow::hgCommit() 409 void MainWindow::hgCommit()
397 { 410 {
398 QStringList params; 411 QStringList params;
399 QString comment; 412 QString comment;
400 413
401 if (justMerged) { 414 if (m_justMerged) {
402 comment = mergeCommitComment; 415 comment = m_mergeCommitComment;
403 } 416 }
404 417
405 QStringList files = hgTabs->getSelectedCommittableFiles(); 418 QStringList files = m_hgTabs->getSelectedCommittableFiles();
406 QStringList allFiles = hgTabs->getAllCommittableFiles(); 419 QStringList allFiles = m_hgTabs->getAllCommittableFiles();
407 QStringList reportFiles = files; 420 QStringList reportFiles = files;
408 if (reportFiles.empty()) { 421 if (reportFiles.empty()) {
409 reportFiles = allFiles; 422 reportFiles = allFiles;
410 } 423 }
411 424
427 .arg(subsetNote), 440 .arg(subsetNote),
428 reportFiles, 441 reportFiles,
429 comment, 442 comment,
430 tr("Commit"))) { 443 tr("Commit"))) {
431 444
432 if (!justMerged && !files.empty()) { 445 if (!m_justMerged && !files.empty()) {
433 // User wants to commit selected file(s) (and this is not 446 // User wants to commit selected file(s) (and this is not
434 // merge commit, which would fail if we selected files) 447 // merge commit, which would fail if we selected files)
435 params << "commit" << "--message" << comment 448 params << "commit" << "--message" << comment
436 << "--user" << getUserInfo() << "--" << files; 449 << "--user" << getUserInfo() << "--" << files;
437 } else { 450 } else {
438 // Commit all changes 451 // Commit all changes
439 params << "commit" << "--message" << comment 452 params << "commit" << "--message" << comment
440 << "--user" << getUserInfo(); 453 << "--user" << getUserInfo();
441 } 454 }
442 455
443 runner->requestAction(HgAction(ACT_COMMIT, workFolderPath, params)); 456 m_runner->requestAction(HgAction(ACT_COMMIT, m_workFolderPath, params));
444 mergeCommitComment = ""; 457 m_mergeCommitComment = "";
445 } 458 }
446 } 459 }
447 460
448 QString MainWindow::filterTag(QString tag) 461 QString MainWindow::filterTag(QString tag)
449 { 462 {
471 branch, 484 branch,
472 tr("Start Branch"))) { 485 tr("Start Branch"))) {
473 if (!branch.isEmpty()) {//!!! do something better if it is empty 486 if (!branch.isEmpty()) {//!!! do something better if it is empty
474 487
475 params << "branch" << filterTag(branch); 488 params << "branch" << filterTag(branch);
476 runner->requestAction(HgAction(ACT_NEW_BRANCH, workFolderPath, params)); 489 m_runner->requestAction(HgAction(ACT_NEW_BRANCH, m_workFolderPath, params));
477 } 490 }
478 } 491 }
479 } 492 }
480 493
481 494
493 if (!tag.isEmpty()) {//!!! do something better if it is empty 506 if (!tag.isEmpty()) {//!!! do something better if it is empty
494 507
495 params << "tag" << "--user" << getUserInfo(); 508 params << "tag" << "--user" << getUserInfo();
496 params << "--rev" << Changeset::hashOf(id) << filterTag(tag); 509 params << "--rev" << Changeset::hashOf(id) << filterTag(tag);
497 510
498 runner->requestAction(HgAction(ACT_TAG, workFolderPath, params)); 511 m_runner->requestAction(HgAction(ACT_TAG, m_workFolderPath, params));
499 } 512 }
500 } 513 }
501 } 514 }
502 515
503 516
504 void MainWindow::hgIgnore() 517 void MainWindow::hgIgnore()
505 { 518 {
506 QString hgIgnorePath; 519 QString hgIgnorePath;
507 QStringList params; 520 QStringList params;
508 521
509 hgIgnorePath = workFolderPath; 522 hgIgnorePath = m_workFolderPath;
510 hgIgnorePath += "/.hgignore"; 523 hgIgnorePath += "/.hgignore";
511 524
512 if (!QDir(workFolderPath).exists()) return; 525 if (!QDir(m_workFolderPath).exists()) return;
513 QFile f(hgIgnorePath); 526 QFile f(hgIgnorePath);
514 if (!f.exists()) { 527 if (!f.exists()) {
515 f.open(QFile::WriteOnly); 528 f.open(QFile::WriteOnly);
516 QTextStream *ts = new QTextStream(&f); 529 QTextStream *ts = new QTextStream(&f);
517 *ts << "syntax: glob\n"; 530 *ts << "syntax: glob\n";
527 DEBUG << "Failed to find a text editor" << endl; 540 DEBUG << "Failed to find a text editor" << endl;
528 //!!! visible error! 541 //!!! visible error!
529 return; 542 return;
530 } 543 }
531 544
532 HgAction action(ACT_HG_IGNORE, workFolderPath, params); 545 HgAction action(ACT_HG_IGNORE, m_workFolderPath, params);
533 action.executable = editor; 546 action.executable = editor;
534 547
535 runner->requestAction(action); 548 m_runner->requestAction(action);
536 } 549 }
537 550
538 QString MainWindow::getDiffBinaryName() 551 QString MainWindow::getDiffBinaryName()
539 { 552 {
540 QSettings settings; 553 QSettings settings;
560 { 573 {
561 QStringList params; 574 QStringList params;
562 575
563 params << "diff" << "--stat"; 576 params << "diff" << "--stat";
564 577
565 runner->requestAction(HgAction(ACT_DIFF_SUMMARY, workFolderPath, params)); 578 m_runner->requestAction(HgAction(ACT_UNCOMMITTED_SUMMARY, m_workFolderPath, params));
566 } 579 }
567 580
568 void MainWindow::hgFolderDiff() 581 void MainWindow::hgFolderDiff()
569 { 582 {
570 QString diff = getDiffBinaryName(); 583 QString diff = getDiffBinaryName();
575 // Diff parent against working folder (folder diff) 588 // Diff parent against working folder (folder diff)
576 589
577 params << "--config" << "extensions.extdiff=" << "extdiff"; 590 params << "--config" << "extensions.extdiff=" << "extdiff";
578 params << "--program" << diff; 591 params << "--program" << diff;
579 592
580 params << hgTabs->getSelectedCommittableFiles(); // may be none: whole dir 593 params << m_hgTabs->getSelectedCommittableFiles(); // may be none: whole dir
581 594
582 runner->requestAction(HgAction(ACT_FOLDERDIFF, workFolderPath, params)); 595 m_runner->requestAction(HgAction(ACT_FOLDERDIFF, m_workFolderPath, params));
583 } 596 }
584 597
585 598
586 void MainWindow::hgDiffToCurrent(QString id) 599 void MainWindow::hgDiffToCurrent(QString id)
587 { 600 {
594 607
595 params << "--config" << "extensions.extdiff=" << "extdiff"; 608 params << "--config" << "extensions.extdiff=" << "extdiff";
596 params << "--program" << diff; 609 params << "--program" << diff;
597 params << "--rev" << Changeset::hashOf(id); 610 params << "--rev" << Changeset::hashOf(id);
598 611
599 runner->requestAction(HgAction(ACT_FOLDERDIFF, workFolderPath, params)); 612 m_runner->requestAction(HgAction(ACT_FOLDERDIFF, m_workFolderPath, params));
600 } 613 }
601 614
602 615
603 void MainWindow::hgDiffToParent(QString child, QString parent) 616 void MainWindow::hgDiffToParent(QString child, QString parent)
604 { 617 {
605 QString diff = getDiffBinaryName(); 618 QString diff = getDiffBinaryName();
606 if (diff == "") return; 619 if (diff == "") return;
607 620
608 QStringList params; 621 QStringList params;
609 622
610 // Diff given revision against working folder 623 // Diff given revision against parent revision
611 624
612 params << "--config" << "extensions.extdiff=" << "extdiff"; 625 params << "--config" << "extensions.extdiff=" << "extdiff";
613 params << "--program" << diff; 626 params << "--program" << diff;
614 params << "--rev" << Changeset::hashOf(parent) 627 params << "--rev" << Changeset::hashOf(parent)
615 << "--rev" << Changeset::hashOf(child); 628 << "--rev" << Changeset::hashOf(child);
616 629
617 runner->requestAction(HgAction(ACT_CHGSETDIFF, workFolderPath, params)); 630 m_runner->requestAction(HgAction(ACT_CHGSETDIFF, m_workFolderPath, params));
631 }
632
633
634 void MainWindow::hgShowSummaryFor(Changeset *cs)
635 {
636 QStringList params;
637
638 // This will pick a default parent if there is more than one
639 // (whereas with diff we need to supply one). But it does need a
640 // bit more parsing
641 params << "log" << "--stat" << "--rev" << Changeset::hashOf(cs->id());
642
643 m_runner->requestAction(HgAction(ACT_DIFF_SUMMARY, m_workFolderPath,
644 params, cs));
618 } 645 }
619 646
620 647
621 void MainWindow::hgUpdate() 648 void MainWindow::hgUpdate()
622 { 649 {
623 QStringList params; 650 QStringList params;
624 651
625 params << "update"; 652 params << "update";
626 653
627 runner->requestAction(HgAction(ACT_UPDATE, workFolderPath, params)); 654 m_runner->requestAction(HgAction(ACT_UPDATE, m_workFolderPath, params));
628 } 655 }
629 656
630 657
631 void MainWindow::hgUpdateToRev(QString id) 658 void MainWindow::hgUpdateToRev(QString id)
632 { 659 {
633 QStringList params; 660 QStringList params;
634 661
635 params << "update" << "--rev" << Changeset::hashOf(id) << "--check"; 662 params << "update" << "--rev" << Changeset::hashOf(id) << "--check";
636 663
637 runner->requestAction(HgAction(ACT_UPDATE, workFolderPath, params)); 664 m_runner->requestAction(HgAction(ACT_UPDATE, m_workFolderPath, params));
638 } 665 }
639 666
640 667
641 void MainWindow::hgRevert() 668 void MainWindow::hgRevert()
642 { 669 {
643 QStringList params; 670 QStringList params;
644 QString comment; 671 QString comment;
645 bool all = false; 672 bool all = false;
646 673
647 QStringList files = hgTabs->getSelectedRevertableFiles(); 674 QStringList files = m_hgTabs->getSelectedRevertableFiles();
648 QStringList allFiles = hgTabs->getAllRevertableFiles(); 675 QStringList allFiles = m_hgTabs->getAllRevertableFiles();
649 if (files.empty() || files == allFiles) { 676 if (files.empty() || files == allFiles) {
650 files = allFiles; 677 files = allFiles;
651 all = true; 678 all = true;
652 } 679 }
653 680
659 QString rf(tr("Revert files")); 686 QString rf(tr("Revert files"));
660 687
661 // Set up params before asking for confirmation, because there is 688 // Set up params before asking for confirmation, because there is
662 // a failure case here that we would need to report on early 689 // a failure case here that we would need to report on early
663 690
664 DEBUG << "hgRevert: justMerged = " << justMerged << ", mergeTargetRevision = " << mergeTargetRevision << endl; 691 DEBUG << "hgRevert: m_justMerged = " << m_justMerged << ", m_mergeTargetRevision = " << m_mergeTargetRevision << endl;
665 692
666 if (justMerged) { 693 if (m_justMerged) {
667 694
668 // This is a little fiddly. The proper way to "revert" the 695 // This is a little fiddly. The proper way to "revert" the
669 // whole of an uncommitted merge is with "hg update --clean ." 696 // whole of an uncommitted merge is with "hg update --clean ."
670 // But if the user has selected only some files, we're sort of 697 // But if the user has selected only some files, we're sort of
671 // promising to revert only those, which means we need to 698 // promising to revert only those, which means we need to
675 // restarted, or changed repository, since then. Hmmm. 702 // restarted, or changed repository, since then. Hmmm.
676 703
677 if (all) { 704 if (all) {
678 params << "update" << "--clean" << "."; 705 params << "update" << "--clean" << ".";
679 } else { 706 } else {
680 if (mergeTargetRevision != "") { 707 if (m_mergeTargetRevision != "") {
681 params << "revert" << "--rev" 708 params << "revert" << "--rev"
682 << Changeset::hashOf(mergeTargetRevision) 709 << Changeset::hashOf(m_mergeTargetRevision)
683 << "--" << files; 710 << "--" << files;
684 } else { 711 } else {
685 QMessageBox::information 712 QMessageBox::information
686 (this, tr("Unable to revert"), 713 (this, tr("Unable to revert"),
687 tr("<qt><b>Sorry, unable to revert these files</b><br><br>EasyMercurial can only revert a subset of files during a merge if it still has a record of which parent was the original merge target; that information is no longer available.<br><br>This is a limitation of EasyMercurial. Consider reverting all files, or using hg revert with a specific revision at the command-line instead.</qt>")); 714 tr("<qt><b>Sorry, unable to revert these files</b><br><br>EasyMercurial can only revert a subset of files during a merge if it still has a record of which parent was the original merge target; that information is no longer available.<br><br>This is a limitation of EasyMercurial. Consider reverting all files, or using hg revert with a specific revision at the command-line instead.</qt>"));
702 .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())) 729 .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()))
703 .arg(subsetNote), 730 .arg(subsetNote),
704 files, 731 files,
705 tr("Revert"))) { 732 tr("Revert"))) {
706 733
707 lastRevertedFiles = files; 734 m_lastRevertedFiles = files;
708 735
709 runner->requestAction(HgAction(ACT_REVERT, workFolderPath, params)); 736 m_runner->requestAction(HgAction(ACT_REVERT, m_workFolderPath, params));
710 } 737 }
711 } 738 }
712 739
713 740
714 void MainWindow::hgMarkResolved(QStringList files) 741 void MainWindow::hgMarkResolved(QStringList files)
721 params << "--all"; 748 params << "--all";
722 } else { 749 } else {
723 params << "--" << files; 750 params << "--" << files;
724 } 751 }
725 752
726 runner->requestAction(HgAction(ACT_RESOLVE_MARK, workFolderPath, params)); 753 m_runner->requestAction(HgAction(ACT_RESOLVE_MARK, m_workFolderPath, params));
727 } 754 }
728 755
729 756
730 void MainWindow::hgRetryMerge() 757 void MainWindow::hgRetryMerge()
731 { 758 {
736 QString merge = getMergeBinaryName(); 763 QString merge = getMergeBinaryName();
737 if (merge != "") { 764 if (merge != "") {
738 params << "--tool" << merge; 765 params << "--tool" << merge;
739 } 766 }
740 767
741 QStringList files = hgTabs->getSelectedUnresolvedFiles(); 768 QStringList files = m_hgTabs->getSelectedUnresolvedFiles();
742 if (files.empty()) { 769 if (files.empty()) {
743 params << "--all"; 770 params << "--all";
744 } else { 771 } else {
745 params << "--" << files; 772 params << "--" << files;
746 } 773 }
747 774
748 if (currentParents.size() == 1) { 775 if (m_currentParents.size() == 1) {
749 mergeTargetRevision = currentParents[0]->id(); 776 m_mergeTargetRevision = m_currentParents[0]->id();
750 } 777 }
751 778
752 runner->requestAction(HgAction(ACT_RETRY_MERGE, workFolderPath, params)); 779 m_runner->requestAction(HgAction(ACT_RETRY_MERGE, m_workFolderPath, params));
753 780
754 mergeCommitComment = tr("Merge"); 781 m_mergeCommitComment = tr("Merge");
755 } 782 }
756 783
757 784
758 void MainWindow::hgMerge() 785 void MainWindow::hgMerge()
759 { 786 {
760 if (hgTabs->canResolve()) { 787 if (m_hgTabs->canResolve()) {
761 hgRetryMerge(); 788 hgRetryMerge();
762 return; 789 return;
763 } 790 }
764 791
765 QStringList params; 792 QStringList params;
769 QString merge = getMergeBinaryName(); 796 QString merge = getMergeBinaryName();
770 if (merge != "") { 797 if (merge != "") {
771 params << "--tool" << merge; 798 params << "--tool" << merge;
772 } 799 }
773 800
774 if (currentParents.size() == 1) { 801 if (m_currentParents.size() == 1) {
775 mergeTargetRevision = currentParents[0]->id(); 802 m_mergeTargetRevision = m_currentParents[0]->id();
776 } 803 }
777 804
778 runner->requestAction(HgAction(ACT_MERGE, workFolderPath, params)); 805 m_runner->requestAction(HgAction(ACT_MERGE, m_workFolderPath, params));
779 806
780 mergeCommitComment = tr("Merge"); 807 m_mergeCommitComment = tr("Merge");
781 } 808 }
782 809
783 810
784 void MainWindow::hgMergeFrom(QString id) 811 void MainWindow::hgMergeFrom(QString id)
785 { 812 {
791 QString merge = getMergeBinaryName(); 818 QString merge = getMergeBinaryName();
792 if (merge != "") { 819 if (merge != "") {
793 params << "--tool" << merge; 820 params << "--tool" << merge;
794 } 821 }
795 822
796 if (currentParents.size() == 1) { 823 if (m_currentParents.size() == 1) {
797 mergeTargetRevision = currentParents[0]->id(); 824 m_mergeTargetRevision = m_currentParents[0]->id();
798 } 825 }
799 826
800 runner->requestAction(HgAction(ACT_MERGE, workFolderPath, params)); 827 m_runner->requestAction(HgAction(ACT_MERGE, m_workFolderPath, params));
801 828
802 mergeCommitComment = ""; 829 m_mergeCommitComment = "";
803 830
804 foreach (Changeset *cs, currentHeads) { 831 foreach (Changeset *cs, m_currentHeads) {
805 if (cs->id() == id && !cs->isOnBranch(currentBranch)) { 832 if (cs->id() == id && !cs->isOnBranch(m_currentBranch)) {
806 if (cs->branch() == "" || cs->branch() == "default") { 833 if (cs->branch() == "" || cs->branch() == "default") {
807 mergeCommitComment = tr("Merge from the default branch"); 834 m_mergeCommitComment = tr("Merge from the default branch");
808 } else { 835 } else {
809 mergeCommitComment = tr("Merge from branch \"%1\"").arg(cs->branch()); 836 m_mergeCommitComment = tr("Merge from branch \"%1\"").arg(cs->branch());
810 } 837 }
811 } 838 }
812 } 839 }
813 840
814 if (mergeCommitComment == "") { 841 if (m_mergeCommitComment == "") {
815 mergeCommitComment = tr("Merge from %1").arg(id); 842 m_mergeCommitComment = tr("Merge from %1").arg(id);
816 } 843 }
817 } 844 }
818 845
819 846
820 void MainWindow::hgCloneFromRemote() 847 void MainWindow::hgCloneFromRemote()
821 { 848 {
822 QStringList params; 849 QStringList params;
823 850
824 if (!QDir(workFolderPath).exists()) { 851 if (!QDir(m_workFolderPath).exists()) {
825 if (!QDir().mkpath(workFolderPath)) { 852 if (!QDir().mkpath(m_workFolderPath)) {
826 DEBUG << "hgCloneFromRemote: Failed to create target path " 853 DEBUG << "hgCloneFromRemote: Failed to create target path "
827 << workFolderPath << endl; 854 << m_workFolderPath << endl;
828 //!!! report error 855 //!!! report error
829 return; 856 return;
830 } 857 }
831 } 858 }
832 859
833 params << "clone" << remoteRepoPath << workFolderPath; 860 params << "clone" << m_remoteRepoPath << m_workFolderPath;
834 861
835 hgTabs->setWorkFolderAndRepoNames(workFolderPath, remoteRepoPath); 862 updateWorkFolderAndRepoNames();
836 hgTabs->updateWorkFolderFileList(""); 863 m_hgTabs->updateWorkFolderFileList("");
837 864
838 runner->requestAction(HgAction(ACT_CLONEFROMREMOTE, workFolderPath, params)); 865 m_runner->requestAction(HgAction(ACT_CLONEFROMREMOTE, m_workFolderPath, params));
839 } 866 }
840 867
841 void MainWindow::hgInit() 868 void MainWindow::hgInit()
842 { 869 {
843 QStringList params; 870 QStringList params;
844 871
845 params << "init"; 872 params << "init";
846 params << workFolderPath; 873 params << m_workFolderPath;
847 874
848 runner->requestAction(HgAction(ACT_INIT, workFolderPath, params)); 875 m_runner->requestAction(HgAction(ACT_INIT, m_workFolderPath, params));
849 } 876 }
850 877
851 void MainWindow::hgIncoming() 878 void MainWindow::hgIncoming()
852 { 879 {
853 QStringList params; 880 QStringList params;
854 881
855 params << "incoming" << "--newest-first" << remoteRepoPath; 882 params << "incoming" << "--newest-first" << m_remoteRepoPath;
856 params << "--template" << Changeset::getLogTemplate(); 883 params << "--template" << Changeset::getLogTemplate();
857 884
858 runner->requestAction(HgAction(ACT_INCOMING, workFolderPath, params)); 885 m_runner->requestAction(HgAction(ACT_INCOMING, m_workFolderPath, params));
859 } 886 }
860 887
861 void MainWindow::hgPull() 888 void MainWindow::hgPull()
862 { 889 {
863 if (ConfirmCommentDialog::confirm 890 if (ConfirmCommentDialog::confirm
864 (this, tr("Confirm pull"), 891 (this, tr("Confirm pull"),
865 format3(tr("Confirm pull from remote repository"), 892 tr("<qt><h3>Pull from remote repository?</h3></qt>"),
866 tr("You are about to pull changes from the following remote repository:"), 893 tr("<qt><p>You are about to pull changes from the remote repository at <code>%1</code>.</p></qt>").arg(xmlEncode(m_remoteRepoPath)),
867 remoteRepoPath),
868 tr("Pull"))) { 894 tr("Pull"))) {
869 895
870 QStringList params; 896 QStringList params;
871 params << "pull" << remoteRepoPath; 897 params << "pull" << m_remoteRepoPath;
872 runner->requestAction(HgAction(ACT_PULL, workFolderPath, params)); 898 m_runner->requestAction(HgAction(ACT_PULL, m_workFolderPath, params));
873 } 899 }
874 } 900 }
875 901
876 void MainWindow::hgPush() 902 void MainWindow::hgPush()
877 { 903 {
878 if (ConfirmCommentDialog::confirm 904 if (ConfirmCommentDialog::confirm
879 (this, tr("Confirm push"), 905 (this, tr("Confirm push"),
880 format3(tr("Confirm push to remote repository"), 906 tr("<qt><h3>Push to remote repository?</h3></qt>"),
881 tr("You are about to push your changes to the following remote repository:"), 907 tr("<qt><p>You are about to push your changes to the remote repository at <code>%1</code>.</p></qt>").arg(xmlEncode(m_remoteRepoPath)),
882 remoteRepoPath),
883 tr("Push"))) { 908 tr("Push"))) {
884 909
885 QStringList params; 910 QStringList params;
886 params << "push" << "--new-branch" << remoteRepoPath; 911 params << "push" << "--new-branch" << m_remoteRepoPath;
887 runner->requestAction(HgAction(ACT_PUSH, workFolderPath, params)); 912 m_runner->requestAction(HgAction(ACT_PUSH, m_workFolderPath, params));
888 } 913 }
889 } 914 }
890 915
891 QStringList MainWindow::listAllUpIpV4Addresses() 916 QStringList MainWindow::listAllUpIpV4Addresses()
892 { 917 {
908 return ret; 933 return ret;
909 } 934 }
910 935
911 void MainWindow::clearState() 936 void MainWindow::clearState()
912 { 937 {
913 foreach (Changeset *cs, currentParents) delete cs; 938 DEBUG << "MainWindow::clearState" << endl;
914 currentParents.clear(); 939 foreach (Changeset *cs, m_currentParents) delete cs;
915 foreach (Changeset *cs, currentHeads) delete cs; 940 m_currentParents.clear();
916 currentHeads.clear(); 941 foreach (Changeset *cs, m_currentHeads) delete cs;
917 currentBranch = ""; 942 m_currentHeads.clear();
918 lastStatOutput = ""; 943 m_currentBranch = "";
919 lastRevertedFiles.clear(); 944 m_lastStatOutput = "";
920 mergeTargetRevision = ""; 945 m_lastRevertedFiles.clear();
921 mergeCommitComment = ""; 946 m_mergeTargetRevision = "";
922 stateUnknown = true; 947 m_mergeCommitComment = "";
923 needNewLog = true; 948 m_stateUnknown = true;
924 if (fsWatcher) { 949 m_needNewLog = true;
950 if (m_fsWatcher) {
925 delete m_fsWatcherGeneralTimer; 951 delete m_fsWatcherGeneralTimer;
926 m_fsWatcherGeneralTimer = 0; 952 m_fsWatcherGeneralTimer = 0;
927 delete m_fsWatcherRestoreTimer; 953 delete m_fsWatcherRestoreTimer;
928 m_fsWatcherRestoreTimer = 0; 954 m_fsWatcherRestoreTimer = 0;
929 delete fsWatcher; 955 delete m_fsWatcher;
930 fsWatcher = 0; 956 m_fsWatcher = 0;
931 } 957 }
932 } 958 }
933 959
934 void MainWindow::hgServe() 960 void MainWindow::hgServe()
935 { 961 {
955 ts << tr("<p>Press Close to stop the server and return.</p>"); 981 ts << tr("<p>Press Close to stop the server and return.</p>");
956 ts.flush(); 982 ts.flush();
957 983
958 params << "serve"; 984 params << "serve";
959 985
960 runner->requestAction(HgAction(ACT_SERVE, workFolderPath, params)); 986 m_runner->requestAction(HgAction(ACT_SERVE, m_workFolderPath, params));
961 987
962 QMessageBox::information(this, tr("Serve"), msg, QMessageBox::Close); 988 QMessageBox::information(this, tr("Serve"), msg, QMessageBox::Close);
963 989
964 runner->killCurrentActions(); 990 m_runner->killCurrentActions();
965 } 991 }
966 992
967 void MainWindow::startupDialog() 993 void MainWindow::startupDialog()
968 { 994 {
969 StartupDialog *dlg = new StartupDialog(this); 995 StartupDialog *dlg = new StartupDialog(this);
970 if (dlg->exec()) firstStart = false; 996 if (dlg->exec()) m_firstStart = false;
971 } 997 }
972 998
973 void MainWindow::open() 999 void MainWindow::open()
974 { 1000 {
975 bool done = false; 1001 bool done = false;
1043 1069
1044 void MainWindow::changeRemoteRepo() 1070 void MainWindow::changeRemoteRepo()
1045 { 1071 {
1046 // This will involve rewriting the local .hgrc 1072 // This will involve rewriting the local .hgrc
1047 1073
1048 QDir hgDir(workFolderPath + "/.hg"); 1074 QDir hgDir(m_workFolderPath + "/.hg");
1049 if (!hgDir.exists()) { 1075 if (!hgDir.exists()) {
1050 //!!! visible error! 1076 //!!! visible error!
1051 return; 1077 return;
1052 } 1078 }
1053 1079
1054 QFileInfo hgrc(workFolderPath + "/.hg/hgrc"); 1080 QFileInfo hgrc(m_workFolderPath + "/.hg/hgrc");
1055 if (hgrc.exists() && !hgrc.isWritable()) { 1081 if (hgrc.exists() && !hgrc.isWritable()) {
1056 //!!! visible error! 1082 //!!! visible error!
1057 return; 1083 return;
1058 } 1084 }
1059 1085
1078 QSettings s(hgrc.absoluteFilePath(), QSettings::IniFormat); 1104 QSettings s(hgrc.absoluteFilePath(), QSettings::IniFormat);
1079 s.beginGroup("paths"); 1105 s.beginGroup("paths");
1080 s.setValue("default", d->getArgument()); 1106 s.setValue("default", d->getArgument());
1081 } 1107 }
1082 1108
1083 stateUnknown = true; 1109 m_stateUnknown = true;
1084 hgQueryPaths(); 1110 hgQueryPaths();
1085 } 1111 }
1086 1112
1087 delete d; 1113 delete d;
1088 } 1114 }
1296 1322
1297 case FolderIsFile: 1323 case FolderIsFile:
1298 return complainAboutFilePath(local); 1324 return complainAboutFilePath(local);
1299 } 1325 }
1300 1326
1301 workFolderPath = local; 1327 m_workFolderPath = local;
1302 remoteRepoPath = ""; 1328 m_remoteRepoPath = "";
1303 return true; 1329 return true;
1304 } 1330 }
1305 1331
1306 bool MainWindow::openRemote(QString remote, QString local) 1332 bool MainWindow::openRemote(QString remote, QString local)
1307 { 1333 {
1329 if (status == FolderExists) { 1355 if (status == FolderExists) {
1330 local = complainAboutCloneToExistingFolder(local, remote); 1356 local = complainAboutCloneToExistingFolder(local, remote);
1331 if (local == "") return false; 1357 if (local == "") return false;
1332 } 1358 }
1333 1359
1334 workFolderPath = local; 1360 m_workFolderPath = local;
1335 remoteRepoPath = remote; 1361 m_remoteRepoPath = remote;
1336 hgCloneFromRemote(); 1362 hgCloneFromRemote();
1337 1363
1338 return true; 1364 return true;
1339 } 1365 }
1340 1366
1361 1387
1362 if (status == FolderUnknown) { 1388 if (status == FolderUnknown) {
1363 return complainAboutUnknownFolder(local); 1389 return complainAboutUnknownFolder(local);
1364 } 1390 }
1365 1391
1366 workFolderPath = local; 1392 m_workFolderPath = local;
1367 remoteRepoPath = ""; 1393 m_remoteRepoPath = "";
1368 hgInit(); 1394 hgInit();
1369 return true; 1395 return true;
1370 } 1396 }
1371 1397
1372 void MainWindow::settings() 1398 void MainWindow::settings()
1373 { 1399 {
1374 SettingsDialog *settingsDlg = new SettingsDialog(this); 1400 SettingsDialog *settingsDlg = new SettingsDialog(this);
1375 settingsDlg->exec(); 1401 settingsDlg->exec();
1376 1402
1377 if (settingsDlg->presentationChanged()) { 1403 if (settingsDlg->presentationChanged()) {
1378 hgTabs->updateFileStates(); 1404 m_hgTabs->updateFileStates();
1379 updateToolBarStyle(); 1405 updateToolBarStyle();
1380 hgRefresh(); 1406 hgRefresh();
1381 } 1407 }
1382 } 1408 }
1383 1409
1425 } 1451 }
1426 1452
1427 void MainWindow::updateFileSystemWatcher() 1453 void MainWindow::updateFileSystemWatcher()
1428 { 1454 {
1429 bool justCreated = false; 1455 bool justCreated = false;
1430 if (!fsWatcher) { 1456 if (!m_fsWatcher) {
1431 fsWatcher = new QFileSystemWatcher(); 1457 m_fsWatcher = new QFileSystemWatcher();
1432 justCreated = true; 1458 justCreated = true;
1433 } 1459 }
1434 1460
1435 // QFileSystemWatcher will refuse to add a file or directory to 1461 // QFileSystemWatcher will refuse to add a file or directory to
1436 // its watch list that it is already watching -- fine, that's what 1462 // its watch list that it is already watching -- fine, that's what
1437 // we want -- but it prints a warning when this happens, which is 1463 // we want -- but it prints a warning when this happens, which is
1438 // annoying because it would be the normal case for us. So we'll 1464 // annoying because it would be the normal case for us. So we'll
1439 // check for duplicates ourselves. 1465 // check for duplicates ourselves.
1440 QSet<QString> alreadyWatched; 1466 QSet<QString> alreadyWatched;
1441 QStringList dl(fsWatcher->directories()); 1467 QStringList dl(m_fsWatcher->directories());
1442 foreach (QString d, dl) alreadyWatched.insert(d); 1468 foreach (QString d, dl) alreadyWatched.insert(d);
1443 1469
1444 std::deque<QString> pending; 1470 std::deque<QString> pending;
1445 pending.push_back(workFolderPath); 1471 pending.push_back(m_workFolderPath);
1446 1472
1447 while (!pending.empty()) { 1473 while (!pending.empty()) {
1448 1474
1449 QString path = pending.front(); 1475 QString path = pending.front();
1450 pending.pop_front(); 1476 pending.pop_front();
1451 if (!alreadyWatched.contains(path)) { 1477 if (!alreadyWatched.contains(path)) {
1452 fsWatcher->addPath(path); 1478 m_fsWatcher->addPath(path);
1453 DEBUG << "Added to file system watcher: " << path << endl; 1479 DEBUG << "Added to file system watcher: " << path << endl;
1454 } 1480 }
1455 1481
1456 QDir d(path); 1482 QDir d(path);
1457 if (d.exists()) { 1483 if (d.exists()) {
1474 this, SLOT(checkFilesystem())); 1500 this, SLOT(checkFilesystem()));
1475 m_fsWatcherGeneralTimer->setInterval(30 * 60 * 1000); // half an hour 1501 m_fsWatcherGeneralTimer->setInterval(30 * 60 * 1000); // half an hour
1476 m_fsWatcherGeneralTimer->start(); 1502 m_fsWatcherGeneralTimer->start();
1477 1503
1478 if (justCreated) { 1504 if (justCreated) {
1479 connect(fsWatcher, SIGNAL(directoryChanged(QString)), 1505 connect(m_fsWatcher, SIGNAL(directoryChanged(QString)),
1480 this, SLOT(fsDirectoryChanged(QString))); 1506 this, SLOT(fsDirectoryChanged(QString)));
1481 connect(fsWatcher, SIGNAL(fileChanged(QString)), 1507 connect(m_fsWatcher, SIGNAL(fileChanged(QString)),
1482 this, SLOT(fsFileChanged(QString))); 1508 this, SLOT(fsFileChanged(QString)));
1483 } 1509 }
1484 } 1510 }
1485 1511
1486 void MainWindow::suspendFileSystemWatcher() 1512 void MainWindow::suspendFileSystemWatcher()
1487 { 1513 {
1488 DEBUG << "MainWindow::suspendFileSystemWatcher" << endl; 1514 DEBUG << "MainWindow::suspendFileSystemWatcher" << endl;
1489 if (fsWatcher) { 1515 if (m_fsWatcher) {
1490 m_fsWatcherSuspended = true; 1516 m_fsWatcherSuspended = true;
1491 if (m_fsWatcherRestoreTimer) { 1517 if (m_fsWatcherRestoreTimer) {
1492 delete m_fsWatcherRestoreTimer; 1518 delete m_fsWatcherRestoreTimer;
1493 m_fsWatcherRestoreTimer = 0; 1519 m_fsWatcherRestoreTimer = 0;
1494 } 1520 }
1516 } 1542 }
1517 1543
1518 void MainWindow::actuallyRestoreFileSystemWatcher() 1544 void MainWindow::actuallyRestoreFileSystemWatcher()
1519 { 1545 {
1520 DEBUG << "MainWindow::actuallyRestoreFileSystemWatcher" << endl; 1546 DEBUG << "MainWindow::actuallyRestoreFileSystemWatcher" << endl;
1521 if (fsWatcher) { 1547 if (m_fsWatcher) {
1522 m_fsWatcherSuspended = false; 1548 m_fsWatcherSuspended = false;
1523 m_fsWatcherGeneralTimer->start(); 1549 m_fsWatcherGeneralTimer->start();
1524 } 1550 }
1525 } 1551 }
1526 1552
1543 DEBUG << "MainWindow::fsFileChanged " << f << endl; 1569 DEBUG << "MainWindow::fsFileChanged " << f << endl;
1544 if (!m_fsWatcherSuspended) { 1570 if (!m_fsWatcherSuspended) {
1545 hgStat(); 1571 hgStat();
1546 } 1572 }
1547 } 1573 }
1574
1575 QString MainWindow::format1(QString head)
1576 {
1577 return QString("<qt><h3>%1</h3></qt>").arg(head);
1578 }
1548 1579
1549 QString MainWindow::format3(QString head, QString intro, QString code) 1580 QString MainWindow::format3(QString head, QString intro, QString code)
1550 { 1581 {
1551 code = xmlEncode(code).replace("\n", "<br>") 1582 code = xmlEncode(code).replace("\n", "<br>")
1552 #ifndef Q_OS_WIN32 1583 #ifndef Q_OS_WIN32
1566 } 1597 }
1567 } 1598 }
1568 1599
1569 void MainWindow::showIncoming(QString output) 1600 void MainWindow::showIncoming(QString output)
1570 { 1601 {
1571 runner->hide(); 1602 m_runner->hide();
1572 IncomingDialog *d = new IncomingDialog(this, output); 1603 IncomingDialog *d = new IncomingDialog(this, output);
1573 d->exec(); 1604 d->exec();
1574 delete d; 1605 delete d;
1575 } 1606 }
1576 1607
1586 } 1617 }
1587 } 1618 }
1588 1619
1589 void MainWindow::showPushResult(QString output) 1620 void MainWindow::showPushResult(QString output)
1590 { 1621 {
1622 QString head;
1591 QString report; 1623 QString report;
1592 int n = extractChangeCount(output); 1624 int n = extractChangeCount(output);
1593 if (n > 0) { 1625 if (n > 0) {
1594 report = tr("Pushed %n changeset(s)", "", n); 1626 head = tr("Pushed %n changeset(s)", "", n);
1627 report = tr("<qt>Successfully pushed to the remote repository at <code>%1</code>.</qt>").arg(xmlEncode(m_remoteRepoPath));
1595 } else if (n == 0) { 1628 } else if (n == 0) {
1596 report = tr("No changes to push"); 1629 head = tr("No changes to push");
1630 report = tr("The remote repository already contains all changes that have been committed locally.");
1631 if (m_hgTabs->canCommit()) {
1632 report = tr("%1<p>You do have some uncommitted changes. If you wish to push those to the remote repository, commit them locally first.").arg(report);
1633 }
1597 } else { 1634 } else {
1598 report = tr("Push complete"); 1635 head = tr("Push complete");
1599 } 1636 }
1600 report = format3(report, tr("The push command output was:"), output); 1637 m_runner->hide();
1601 runner->hide(); 1638
1602 QMessageBox::information(this, "Push complete", report); 1639 MoreInformationDialog::information(this, tr("Push complete"),
1640 head, report, output);
1603 } 1641 }
1604 1642
1605 void MainWindow::showPullResult(QString output) 1643 void MainWindow::showPullResult(QString output)
1606 { 1644 {
1645 QString head;
1607 QString report; 1646 QString report;
1608 int n = extractChangeCount(output); 1647 int n = extractChangeCount(output);
1609 if (n > 0) { 1648 if (n > 0) {
1610 report = tr("Pulled %n changeset(s)", "", n); 1649 head = tr("Pulled %n changeset(s)", "", n);
1650 report = tr("The new changes will be highlighted in the history.<br>Use Update to bring these changes into your working copy.");
1611 } else if (n == 0) { 1651 } else if (n == 0) {
1612 report = tr("No changes to pull"); 1652 head = tr("No changes to pull");
1653 report = tr("Your local repository already contains all changes found in the remote repository.");
1613 } else { 1654 } else {
1614 report = tr("Pull complete"); 1655 head = tr("Pull complete");
1615 } 1656 }
1616 report = format3(report, tr("The pull command output was:"), output); 1657 m_runner->hide();
1617 runner->hide(); 1658
1618 1659 MoreInformationDialog::information(this, tr("Pull complete"),
1619 //!!! and something about updating 1660 head, report, output);
1620
1621 QMessageBox::information(this, "Pull complete", report);
1622 } 1661 }
1623 1662
1624 void MainWindow::reportNewRemoteHeads(QString output) 1663 void MainWindow::reportNewRemoteHeads(QString output)
1625 { 1664 {
1626 bool headsAreLocal = false; 1665 bool headsAreLocal = false;
1627 1666
1628 if (currentParents.size() == 1) { 1667 if (m_currentParents.size() == 1) {
1629 int currentBranchHeads = 0; 1668 int m_currentBranchHeads = 0;
1630 bool parentIsHead = false; 1669 bool parentIsHead = false;
1631 Changeset *parent = currentParents[0]; 1670 Changeset *parent = m_currentParents[0];
1632 foreach (Changeset *head, currentHeads) { 1671 foreach (Changeset *head, m_currentHeads) {
1633 if (head->isOnBranch(currentBranch)) { 1672 if (head->isOnBranch(m_currentBranch)) {
1634 ++currentBranchHeads; 1673 ++m_currentBranchHeads;
1635 } 1674 }
1636 if (parent->id() == head->id()) { 1675 if (parent->id() == head->id()) {
1637 parentIsHead = true; 1676 parentIsHead = true;
1638 } 1677 }
1639 } 1678 }
1640 if (currentBranchHeads == 2 && parentIsHead) { 1679 if (m_currentBranchHeads == 2 && parentIsHead) {
1641 headsAreLocal = true; 1680 headsAreLocal = true;
1642 } 1681 }
1643 } 1682 }
1644 1683
1645 if (headsAreLocal) { 1684 if (headsAreLocal) {
1646 QMessageBox::warning 1685 MoreInformationDialog::warning
1647 (this, tr("Push failed"), 1686 (this,
1648 format3(tr("Push failed"), 1687 tr("Push failed"),
1649 tr("Your local repository could not be pushed to the remote repository.<br><br>You may need to merge the changes locally first.<br><br>The output of the push command was:"), 1688 tr("Push failed"),
1650 output)); 1689 tr("Your local repository could not be pushed to the remote repository.<br><br>You may need to merge the changes locally first."),
1690 output);
1651 } else { 1691 } else {
1652 QMessageBox::warning 1692 MoreInformationDialog::warning
1653 (this, tr("Push failed"), 1693 (this,
1654 format3(tr("Push failed"), 1694 tr("Push failed"),
1655 tr("Your local repository could not be pushed to the remote repository.<br><br>The remote repository may have been changed by someone else since you last pushed. Try pulling and merging their changes into your local repository first.<br><br>The output of the push command was:"), 1695 tr("Push failed"),
1656 output)); 1696 tr("Your local repository could not be pushed to the remote repository.<br><br>The remote repository may have been changed by someone else since you last pushed. Try pulling and merging their changes into your local repository first."),
1697 output);
1657 } 1698 }
1658 } 1699 }
1659 1700
1660 void MainWindow::commandStarting(HgAction action) 1701 void MainWindow::commandStarting(HgAction action)
1661 { 1702 {
1687 switch(action.action) { 1728 switch(action.action) {
1688 case ACT_NONE: 1729 case ACT_NONE:
1689 // uh huh 1730 // uh huh
1690 return; 1731 return;
1691 case ACT_TEST_HG: 1732 case ACT_TEST_HG:
1692 QMessageBox::warning 1733 MoreInformationDialog::warning
1693 (this, tr("Failed to run Mercurial"), 1734 (this,
1694 format3(tr("Failed to run Mercurial"), 1735 tr("Failed to run Mercurial"),
1695 tr("The Mercurial program either could not be found or failed to run.<br>Check that the Mercurial program path is correct in %1.<br><br>%2").arg(setstr).arg(output == "" ? QString("") : tr("The test command said:")), 1736 tr("Failed to run Mercurial"),
1696 output)); 1737 tr("The Mercurial program either could not be found or failed to run.<br>Check that the Mercurial program path is correct in %1.").arg(setstr),
1738 output);
1697 settings(); 1739 settings();
1698 return; 1740 return;
1699 case ACT_TEST_HG_EXT: 1741 case ACT_TEST_HG_EXT:
1700 QMessageBox::warning 1742 QMessageBox::warning
1701 (this, tr("Failed to run Mercurial"), 1743 (this,
1702 format3(tr("Failed to run Mercurial with extension enabled"), 1744 tr("Failed to run Mercurial"),
1703 tr("The Mercurial program failed to run with the EasyMercurial interaction extension enabled.<br>This may indicate an installation problem with EasyMercurial.<br><br>You may be able to continue working if you switch off &ldquo;Use EasyHg Mercurial Extension&rdquo; in %1. Note that remote repositories that require authentication may not work if you do this.<br><br>%2").arg(setstr).arg(output == "" ? QString("") : tr("The test command said:")), 1745 tr("Failed to run Mercurial with extension enabled"),
1704 output)); 1746 tr("The Mercurial program failed to run with the EasyMercurial interaction extension enabled.<br>This may indicate an installation problem with EasyMercurial.<br><br>You may be able to continue working if you switch off &ldquo;Use EasyHg Mercurial Extension&rdquo; in %1. Note that remote repositories that require authentication may not work if you do this.").arg(setstr),
1747 output);
1705 settings(); 1748 settings();
1706 return; 1749 return;
1707 case ACT_CLONEFROMREMOTE: 1750 case ACT_CLONEFROMREMOTE:
1708 // if clone fails, we have no repo 1751 // if clone fails, we have no repo
1709 workFolderPath = ""; 1752 m_workFolderPath = "";
1710 enableDisableActions(); 1753 enableDisableActions();
1711 break; 1754 break;
1712 case ACT_INCOMING: 1755 case ACT_INCOMING:
1713 // returns non-zero code and no output if the check was 1756 // returns non-zero code and no output if the check was
1714 // successful but there are no changes pending 1757 // successful but there are no changes pending
1715 1758 if (output.replace(QRegExp("(^|\\n)warning: [^\\n]*\\n"), "").trimmed() == "") {
1716 //!!! -- won't do, there may legitimately be warnings,
1717 //!!! -- e.g. certificate not verified
1718 if (output.trimmed() == "") {
1719 showIncoming(""); 1759 showIncoming("");
1720 return; 1760 return;
1721 } 1761 }
1722 break; 1762 break;
1723 case ACT_QUERY_HEADS: 1763 case ACT_QUERY_HEADS:
1748 if (command == "") command = "hg"; 1788 if (command == "") command = "hg";
1749 foreach (QString arg, action.params) { 1789 foreach (QString arg, action.params) {
1750 command += " " + arg; 1790 command += " " + arg;
1751 } 1791 }
1752 1792
1793 //!!!
1794
1753 QString message = tr("<qt><h3>Command failed</h3>" 1795 QString message = tr("<qt><h3>Command failed</h3>"
1754 "<p>The following command failed:</p>" 1796 "<p>The following command failed:</p>"
1755 "<code>%1</code>" 1797 "<code>%1</code>"
1756 "%2</qt>") 1798 "%2</qt>")
1757 .arg(command) 1799 .arg(command)
1787 DEBUG << "stdout is " << output << endl; 1829 DEBUG << "stdout is " << output << endl;
1788 LogParser lp(output, "="); 1830 LogParser lp(output, "=");
1789 LogList ll = lp.parse(); 1831 LogList ll = lp.parse();
1790 DEBUG << ll.size() << " results" << endl; 1832 DEBUG << ll.size() << " results" << endl;
1791 if (!ll.empty()) { 1833 if (!ll.empty()) {
1792 remoteRepoPath = lp.parse()[0]["default"].trimmed(); 1834 m_remoteRepoPath = lp.parse()[0]["default"].trimmed();
1793 DEBUG << "Set remote path to " << remoteRepoPath << endl; 1835 DEBUG << "Set remote path to " << m_remoteRepoPath << endl;
1794 } else { 1836 } else {
1795 remoteRepoPath = ""; 1837 m_remoteRepoPath = "";
1796 } 1838 }
1797 MultiChoiceDialog::addRecentArgument("local", workFolderPath); 1839 MultiChoiceDialog::addRecentArgument("local", m_workFolderPath);
1798 MultiChoiceDialog::addRecentArgument("remote", remoteRepoPath); 1840 MultiChoiceDialog::addRecentArgument("remote", m_remoteRepoPath);
1799 hgTabs->setWorkFolderAndRepoNames(workFolderPath, remoteRepoPath); 1841 updateWorkFolderAndRepoNames();
1800 break; 1842 break;
1801 } 1843 }
1802 1844
1803 case ACT_QUERY_BRANCH: 1845 case ACT_QUERY_BRANCH:
1804 currentBranch = output.trimmed(); 1846 m_currentBranch = output.trimmed();
1805 break; 1847 break;
1806 1848
1807 case ACT_STAT: 1849 case ACT_STAT:
1808 lastStatOutput = output; 1850 m_lastStatOutput = output;
1809 updateFileSystemWatcher(); 1851 updateFileSystemWatcher();
1810 break; 1852 break;
1811 1853
1812 case ACT_RESOLVE_LIST: 1854 case ACT_RESOLVE_LIST:
1813 if (output != "") { 1855 if (output != "") {
1818 foreach (QString line, outList) { 1860 foreach (QString line, outList) {
1819 if (!line.startsWith("R ")) winnowed.push_back(line); 1861 if (!line.startsWith("R ")) winnowed.push_back(line);
1820 } 1862 }
1821 output = winnowed.join("\n"); 1863 output = winnowed.join("\n");
1822 } 1864 }
1823 DEBUG << "lastStatOutput = " << lastStatOutput << endl; 1865 DEBUG << "m_lastStatOutput = " << m_lastStatOutput << endl;
1824 DEBUG << "resolve output = " << output << endl; 1866 DEBUG << "resolve output = " << output << endl;
1825 hgTabs->updateWorkFolderFileList(lastStatOutput + output); 1867 m_hgTabs->updateWorkFolderFileList(m_lastStatOutput + output);
1826 break; 1868 break;
1827 1869
1828 case ACT_RESOLVE_MARK: 1870 case ACT_RESOLVE_MARK:
1829 shouldHgStat = true; 1871 m_shouldHgStat = true;
1830 break; 1872 break;
1831 1873
1832 case ACT_INCOMING: 1874 case ACT_INCOMING:
1833 showIncoming(output); 1875 showIncoming(output);
1834 break; 1876 break;
1835 1877
1836 case ACT_ANNOTATE: 1878 case ACT_ANNOTATE:
1837 presentLongStdoutToUser(output); 1879 presentLongStdoutToUser(output);
1838 shouldHgStat = true; 1880 m_shouldHgStat = true;
1839 break; 1881 break;
1840 1882
1841 case ACT_PULL: 1883 case ACT_PULL:
1842 showPullResult(output); 1884 showPullResult(output);
1843 shouldHgStat = true; 1885 m_shouldHgStat = true;
1844 break; 1886 break;
1845 1887
1846 case ACT_PUSH: 1888 case ACT_PUSH:
1847 showPushResult(output); 1889 showPushResult(output);
1848 break; 1890 break;
1849 1891
1850 case ACT_INIT: 1892 case ACT_INIT:
1851 MultiChoiceDialog::addRecentArgument("init", workFolderPath); 1893 MultiChoiceDialog::addRecentArgument("init", m_workFolderPath);
1852 MultiChoiceDialog::addRecentArgument("local", workFolderPath); 1894 MultiChoiceDialog::addRecentArgument("local", m_workFolderPath);
1853 enableDisableActions(); 1895 enableDisableActions();
1854 shouldHgStat = true; 1896 m_shouldHgStat = true;
1855 break; 1897 break;
1856 1898
1857 case ACT_CLONEFROMREMOTE: 1899 case ACT_CLONEFROMREMOTE:
1858 MultiChoiceDialog::addRecentArgument("local", workFolderPath); 1900 MultiChoiceDialog::addRecentArgument("local", m_workFolderPath);
1859 MultiChoiceDialog::addRecentArgument("remote", remoteRepoPath); 1901 MultiChoiceDialog::addRecentArgument("remote", m_remoteRepoPath);
1860 MultiChoiceDialog::addRecentArgument("remote", workFolderPath, true); 1902 MultiChoiceDialog::addRecentArgument("remote", m_workFolderPath, true);
1861 QMessageBox::information(this, tr("Clone"), tr("<qt><h3>Clone successful</h3><pre>%1</pre>").arg(xmlEncode(output))); 1903 MoreInformationDialog::information
1904 (this,
1905 tr("Clone"),
1906 tr("Clone successful"),
1907 tr("The remote repository was successfully cloned to the local folder <code>%1</code>.").arg(xmlEncode(m_workFolderPath)),
1908 output);
1862 enableDisableActions(); 1909 enableDisableActions();
1863 shouldHgStat = true; 1910 m_shouldHgStat = true;
1864 break; 1911 break;
1865 1912
1866 case ACT_LOG: 1913 case ACT_LOG:
1867 hgTabs->setNewLog(output); 1914 m_hgTabs->setNewLog(output);
1868 needNewLog = false; 1915 m_needNewLog = false;
1869 break; 1916 break;
1870 1917
1871 case ACT_LOG_INCREMENTAL: 1918 case ACT_LOG_INCREMENTAL:
1872 hgTabs->addIncrementalLog(output); 1919 m_hgTabs->addIncrementalLog(output);
1873 break; 1920 break;
1874 1921
1875 case ACT_QUERY_PARENTS: 1922 case ACT_QUERY_PARENTS:
1876 { 1923 {
1877 foreach (Changeset *cs, currentParents) delete cs; 1924 foreach (Changeset *cs, m_currentParents) delete cs;
1878 currentParents = Changeset::parseChangesets(output); 1925 m_currentParents = Changeset::parseChangesets(output);
1879 QStringList parentIds = Changeset::getIds(currentParents); 1926 QStringList parentIds = Changeset::getIds(m_currentParents);
1880 hgTabs->setCurrent(parentIds, currentBranch); 1927 m_hgTabs->setCurrent(parentIds, m_currentBranch);
1881 } 1928 }
1882 break; 1929 break;
1883 1930
1884 case ACT_QUERY_HEADS: 1931 case ACT_QUERY_HEADS:
1885 { 1932 {
1886 oldHeadIds = Changeset::getIds(currentHeads); 1933 oldHeadIds = Changeset::getIds(m_currentHeads);
1887 Changesets newHeads = Changeset::parseChangesets(output); 1934 Changesets newHeads = Changeset::parseChangesets(output);
1888 QStringList newHeadIds = Changeset::getIds(newHeads); 1935 QStringList newHeadIds = Changeset::getIds(newHeads);
1889 if (oldHeadIds != newHeadIds) { 1936 if (oldHeadIds != newHeadIds) {
1890 DEBUG << "Heads changed, will prompt an incremental log if appropriate" << endl; 1937 DEBUG << "Heads changed, will prompt an incremental log if appropriate" << endl;
1938 DEBUG << "Old heads: " << oldHeadIds.join(",") << endl;
1939 DEBUG << "New heads: " << newHeadIds.join(",") << endl;
1891 headsChanged = true; 1940 headsChanged = true;
1892 foreach (Changeset *cs, currentHeads) delete cs; 1941 foreach (Changeset *cs, m_currentHeads) delete cs;
1893 currentHeads = newHeads; 1942 m_currentHeads = newHeads;
1894 } 1943 }
1895 } 1944 }
1896 break; 1945 break;
1897 1946
1898 case ACT_COMMIT: 1947 case ACT_COMMIT:
1899 hgTabs->clearSelections(); 1948 m_hgTabs->clearSelections();
1900 justMerged = false; 1949 m_justMerged = false;
1901 shouldHgStat = true; 1950 m_shouldHgStat = true;
1902 break; 1951 break;
1903 1952
1904 case ACT_REVERT: 1953 case ACT_REVERT:
1905 hgMarkResolved(lastRevertedFiles); 1954 hgMarkResolved(m_lastRevertedFiles);
1906 justMerged = false; 1955 m_justMerged = false;
1907 break; 1956 break;
1908 1957
1909 case ACT_REMOVE: 1958 case ACT_REMOVE:
1910 case ACT_ADD: 1959 case ACT_ADD:
1911 hgTabs->clearSelections(); 1960 m_hgTabs->clearSelections();
1912 shouldHgStat = true; 1961 m_shouldHgStat = true;
1913 break; 1962 break;
1914 1963
1915 case ACT_TAG: 1964 case ACT_TAG:
1916 needNewLog = true; 1965 m_needNewLog = true;
1917 shouldHgStat = true; 1966 m_shouldHgStat = true;
1918 break; 1967 break;
1919 1968
1920 case ACT_NEW_BRANCH: 1969 case ACT_NEW_BRANCH:
1921 shouldHgStat = true; 1970 m_shouldHgStat = true;
1922 hgTabs->showWorkTab(); 1971 m_hgTabs->showWorkTab();
1923 break; 1972 break;
1924 1973
1925 case ACT_DIFF_SUMMARY: 1974 case ACT_UNCOMMITTED_SUMMARY:
1926 QMessageBox::information(this, tr("Change summary"), 1975 QMessageBox::information(this, tr("Change summary"),
1927 format3(tr("Summary of uncommitted changes"), 1976 format3(tr("Summary of uncommitted changes"),
1928 "", 1977 "",
1929 output)); 1978 output));
1930 break; 1979 break;
1931 1980
1981 case ACT_DIFF_SUMMARY:
1982 {
1983 // Output has log info first, diff following after a blank line
1984 output.replace("\r\n", "\n");
1985 QStringList olist = output.split("\n\n", QString::SkipEmptyParts);
1986 if (olist.size() > 1) output = olist[1];
1987
1988 Changeset *cs = (Changeset *)completedAction.extraData;
1989 if (cs) {
1990 QMessageBox::information
1991 (this, tr("Change summary"),
1992 format3(tr("Summary of changes"),
1993 cs->formatHtml(),
1994 output));
1995 } else if (output == "") {
1996 // Can happen, for a merge commit (depending on parent)
1997 QMessageBox::information(this, tr("Change summary"),
1998 format3(tr("Summary of changes"),
1999 tr("No changes"),
2000 output));
2001 } else {
2002 QMessageBox::information(this, tr("Change summary"),
2003 format3(tr("Summary of changes"),
2004 "",
2005 output));
2006 }
2007 break;
2008 }
2009
1932 case ACT_FOLDERDIFF: 2010 case ACT_FOLDERDIFF:
1933 case ACT_CHGSETDIFF: 2011 case ACT_CHGSETDIFF:
1934 case ACT_SERVE: 2012 case ACT_SERVE:
1935 case ACT_HG_IGNORE: 2013 case ACT_HG_IGNORE:
1936 shouldHgStat = true; 2014 m_shouldHgStat = true;
1937 break; 2015 break;
1938 2016
1939 case ACT_UPDATE: 2017 case ACT_UPDATE:
1940 QMessageBox::information(this, tr("Update"), tr("<qt><h3>Update successful</h3><p>%1</p>").arg(xmlEncode(output))); 2018 QMessageBox::information(this, tr("Update"), tr("<qt><h3>Update successful</h3><p>%1</p>").arg(xmlEncode(output)));
1941 shouldHgStat = true; 2019 m_shouldHgStat = true;
1942 break; 2020 break;
1943 2021
1944 case ACT_MERGE: 2022 case ACT_MERGE:
1945 //!!! use format3? 2023 MoreInformationDialog::information
1946 QMessageBox::information(this, tr("Merge"), tr("<qt><h3>Merge successful</h3><pre>%1</pre>").arg(xmlEncode(output))); 2024 (this, tr("Merge"), tr("Merge successful"),
1947 shouldHgStat = true; 2025 tr("Remember to test and commit the result before making any further changes."),
1948 justMerged = true; 2026 output);
2027 m_shouldHgStat = true;
2028 m_justMerged = true;
1949 break; 2029 break;
1950 2030
1951 case ACT_RETRY_MERGE: 2031 case ACT_RETRY_MERGE:
1952 QMessageBox::information(this, tr("Resolved"), 2032 QMessageBox::information(this, tr("Resolved"),
1953 tr("<qt><h3>Merge resolved</h3><p>Merge resolved successfully.</p>")); 2033 tr("<qt><h3>Merge resolved</h3><p>Merge resolved successfully.<br>Remember to test and commit the result before making any further changes.</p>"));
1954 shouldHgStat = true; 2034 m_shouldHgStat = true;
1955 justMerged = true; 2035 m_justMerged = true;
1956 break; 2036 break;
1957 2037
1958 default: 2038 default:
1959 break; 2039 break;
1960 } 2040 }
1977 { 2057 {
1978 QSettings settings; 2058 QSettings settings;
1979 settings.beginGroup("General"); 2059 settings.beginGroup("General");
1980 if (settings.value("useextension", true).toBool()) { 2060 if (settings.value("useextension", true).toBool()) {
1981 hgTestExtension(); 2061 hgTestExtension();
1982 } else if (workFolderPath == "") { 2062 } else if (m_workFolderPath == "") {
1983 open(); 2063 open();
1984 } else { 2064 } else {
1985 hgQueryPaths(); 2065 hgQueryPaths();
1986 } 2066 }
1987 break; 2067 break;
1988 } 2068 }
1989 2069
1990 case ACT_TEST_HG_EXT: 2070 case ACT_TEST_HG_EXT:
1991 if (workFolderPath == "") { 2071 if (m_workFolderPath == "") {
1992 open(); 2072 open();
1993 } else{ 2073 } else{
1994 hgQueryPaths(); 2074 hgQueryPaths();
1995 } 2075 }
1996 break; 2076 break;
2010 case ACT_RESOLVE_LIST: 2090 case ACT_RESOLVE_LIST:
2011 hgQueryHeads(); 2091 hgQueryHeads();
2012 break; 2092 break;
2013 2093
2014 case ACT_QUERY_HEADS: 2094 case ACT_QUERY_HEADS:
2015 if (headsChanged && !needNewLog) { 2095 if (headsChanged && !m_needNewLog) {
2016 hgLogIncremental(oldHeadIds); 2096 hgLogIncremental(oldHeadIds);
2017 } else { 2097 } else {
2018 hgQueryParents(); 2098 hgQueryParents();
2019 } 2099 }
2020 break; 2100 break;
2022 case ACT_LOG_INCREMENTAL: 2102 case ACT_LOG_INCREMENTAL:
2023 hgQueryParents(); 2103 hgQueryParents();
2024 break; 2104 break;
2025 2105
2026 case ACT_QUERY_PARENTS: 2106 case ACT_QUERY_PARENTS:
2027 if (needNewLog) { 2107 if (m_needNewLog) {
2028 hgLog(); 2108 hgLog();
2029 } else { 2109 } else {
2030 // we're done 2110 // we're done
2031 noMore = true; 2111 noMore = true;
2032 } 2112 }
2036 // we're done 2116 // we're done
2037 noMore = true; 2117 noMore = true;
2038 break; 2118 break;
2039 2119
2040 default: 2120 default:
2041 if (shouldHgStat) { 2121 if (m_shouldHgStat) {
2042 shouldHgStat = false; 2122 m_shouldHgStat = false;
2043 hgQueryPaths(); 2123 hgQueryPaths();
2044 } else { 2124 } else {
2045 noMore = true; 2125 noMore = true;
2046 } 2126 }
2047 break; 2127 break;
2048 } 2128 }
2049 2129
2050 if (noMore) { 2130 if (noMore) {
2051 stateUnknown = false; 2131 m_stateUnknown = false;
2052 enableDisableActions(); 2132 enableDisableActions();
2053 hgTabs->updateHistory(); 2133 m_hgTabs->updateHistory();
2054 } 2134 }
2055 } 2135 }
2056 2136
2057 void MainWindow::connectActions() 2137 void MainWindow::connectActions()
2058 { 2138 {
2059 connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); 2139 connect(m_exitAct, SIGNAL(triggered()), this, SLOT(close()));
2060 connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); 2140 connect(m_aboutAct, SIGNAL(triggered()), this, SLOT(about()));
2061 2141
2062 connect(hgRefreshAct, SIGNAL(triggered()), this, SLOT(hgRefresh())); 2142 connect(m_hgRefreshAct, SIGNAL(triggered()), this, SLOT(hgRefresh()));
2063 connect(hgRemoveAct, SIGNAL(triggered()), this, SLOT(hgRemove())); 2143 connect(m_hgRemoveAct, SIGNAL(triggered()), this, SLOT(hgRemove()));
2064 connect(hgAddAct, SIGNAL(triggered()), this, SLOT(hgAdd())); 2144 connect(m_hgAddAct, SIGNAL(triggered()), this, SLOT(hgAdd()));
2065 connect(hgCommitAct, SIGNAL(triggered()), this, SLOT(hgCommit())); 2145 connect(m_hgCommitAct, SIGNAL(triggered()), this, SLOT(hgCommit()));
2066 connect(hgFolderDiffAct, SIGNAL(triggered()), this, SLOT(hgFolderDiff())); 2146 connect(m_hgFolderDiffAct, SIGNAL(triggered()), this, SLOT(hgFolderDiff()));
2067 connect(hgUpdateAct, SIGNAL(triggered()), this, SLOT(hgUpdate())); 2147 connect(m_hgUpdateAct, SIGNAL(triggered()), this, SLOT(hgUpdate()));
2068 connect(hgRevertAct, SIGNAL(triggered()), this, SLOT(hgRevert())); 2148 connect(m_hgRevertAct, SIGNAL(triggered()), this, SLOT(hgRevert()));
2069 connect(hgMergeAct, SIGNAL(triggered()), this, SLOT(hgMerge())); 2149 connect(m_hgMergeAct, SIGNAL(triggered()), this, SLOT(hgMerge()));
2070 connect(hgIgnoreAct, SIGNAL(triggered()), this, SLOT(hgIgnore())); 2150 connect(m_hgIgnoreAct, SIGNAL(triggered()), this, SLOT(hgIgnore()));
2071 2151
2072 connect(settingsAct, SIGNAL(triggered()), this, SLOT(settings())); 2152 connect(m_settingsAct, SIGNAL(triggered()), this, SLOT(settings()));
2073 connect(openAct, SIGNAL(triggered()), this, SLOT(open())); 2153 connect(m_openAct, SIGNAL(triggered()), this, SLOT(open()));
2074 connect(changeRemoteRepoAct, SIGNAL(triggered()), this, SLOT(changeRemoteRepo())); 2154 connect(m_changeRemoteRepoAct, SIGNAL(triggered()), this, SLOT(changeRemoteRepo()));
2075 2155
2076 connect(hgIncomingAct, SIGNAL(triggered()), this, SLOT(hgIncoming())); 2156 connect(m_hgIncomingAct, SIGNAL(triggered()), this, SLOT(hgIncoming()));
2077 connect(hgPullAct, SIGNAL(triggered()), this, SLOT(hgPull())); 2157 connect(m_hgPullAct, SIGNAL(triggered()), this, SLOT(hgPull()));
2078 connect(hgPushAct, SIGNAL(triggered()), this, SLOT(hgPush())); 2158 connect(m_hgPushAct, SIGNAL(triggered()), this, SLOT(hgPush()));
2079 2159
2080 connect(hgAnnotateAct, SIGNAL(triggered()), this, SLOT(hgAnnotate())); 2160 connect(m_hgAnnotateAct, SIGNAL(triggered()), this, SLOT(hgAnnotate()));
2081 connect(hgServeAct, SIGNAL(triggered()), this, SLOT(hgServe())); 2161 connect(m_hgServeAct, SIGNAL(triggered()), this, SLOT(hgServe()));
2082 } 2162 }
2083 2163
2084 void MainWindow::connectTabsSignals() 2164 void MainWindow::connectTabsSignals()
2085 { 2165 {
2086 connect(hgTabs, SIGNAL(commit()), 2166 connect(m_hgTabs, SIGNAL(commit()),
2087 this, SLOT(hgCommit())); 2167 this, SLOT(hgCommit()));
2088 2168
2089 connect(hgTabs, SIGNAL(revert()), 2169 connect(m_hgTabs, SIGNAL(revert()),
2090 this, SLOT(hgRevert())); 2170 this, SLOT(hgRevert()));
2091 2171
2092 connect(hgTabs, SIGNAL(diffWorkingFolder()), 2172 connect(m_hgTabs, SIGNAL(diffWorkingFolder()),
2093 this, SLOT(hgFolderDiff())); 2173 this, SLOT(hgFolderDiff()));
2094 2174
2095 connect(hgTabs, SIGNAL(showSummary()), 2175 connect(m_hgTabs, SIGNAL(showSummary()),
2096 this, SLOT(hgShowSummary())); 2176 this, SLOT(hgShowSummary()));
2097 2177
2098 connect(hgTabs, SIGNAL(updateTo(QString)), 2178 connect(m_hgTabs, SIGNAL(updateTo(QString)),
2099 this, SLOT(hgUpdateToRev(QString))); 2179 this, SLOT(hgUpdateToRev(QString)));
2100 2180
2101 connect(hgTabs, SIGNAL(diffToCurrent(QString)), 2181 connect(m_hgTabs, SIGNAL(diffToCurrent(QString)),
2102 this, SLOT(hgDiffToCurrent(QString))); 2182 this, SLOT(hgDiffToCurrent(QString)));
2103 2183
2104 connect(hgTabs, SIGNAL(diffToParent(QString, QString)), 2184 connect(m_hgTabs, SIGNAL(diffToParent(QString, QString)),
2105 this, SLOT(hgDiffToParent(QString, QString))); 2185 this, SLOT(hgDiffToParent(QString, QString)));
2106 2186
2107 connect(hgTabs, SIGNAL(mergeFrom(QString)), 2187 connect(m_hgTabs, SIGNAL(showSummary(Changeset *)),
2188 this, SLOT(hgShowSummaryFor(Changeset *)));
2189
2190 connect(m_hgTabs, SIGNAL(mergeFrom(QString)),
2108 this, SLOT(hgMergeFrom(QString))); 2191 this, SLOT(hgMergeFrom(QString)));
2109 2192
2110 connect(hgTabs, SIGNAL(newBranch(QString)), 2193 connect(m_hgTabs, SIGNAL(newBranch(QString)),
2111 this, SLOT(hgNewBranch(QString))); 2194 this, SLOT(hgNewBranch(QString)));
2112 2195
2113 connect(hgTabs, SIGNAL(tag(QString)), 2196 connect(m_hgTabs, SIGNAL(tag(QString)),
2114 this, SLOT(hgTag(QString))); 2197 this, SLOT(hgTag(QString)));
2115 } 2198 }
2116 2199
2117 void MainWindow::enableDisableActions() 2200 void MainWindow::enableDisableActions()
2118 { 2201 {
2119 DEBUG << "MainWindow::enableDisableActions" << endl; 2202 DEBUG << "MainWindow::enableDisableActions" << endl;
2120 2203
2121 QString dirname = QDir(workFolderPath).dirName(); 2204 QString dirname = QDir(m_workFolderPath).dirName();
2122 if (dirname != "") { 2205 if (dirname != "") {
2123 setWindowTitle(tr("EasyMercurial: %1").arg(dirname)); 2206 setWindowTitle(tr("EasyMercurial: %1").arg(dirname));
2124 } else { 2207 } else {
2125 setWindowTitle(tr("EasyMercurial")); 2208 setWindowTitle(tr("EasyMercurial"));
2126 } 2209 }
2131 QDir localRepoDir; 2214 QDir localRepoDir;
2132 QDir workFolderDir; 2215 QDir workFolderDir;
2133 bool workFolderExist = true; 2216 bool workFolderExist = true;
2134 bool localRepoExist = true; 2217 bool localRepoExist = true;
2135 2218
2136 remoteRepoActionsEnabled = true; 2219 m_remoteRepoActionsEnabled = true;
2137 if (remoteRepoPath.isEmpty()) { 2220 if (m_remoteRepoPath.isEmpty()) {
2138 remoteRepoActionsEnabled = false; 2221 m_remoteRepoActionsEnabled = false;
2139 } 2222 }
2140 2223
2141 localRepoActionsEnabled = true; 2224 m_localRepoActionsEnabled = true;
2142 if (workFolderPath.isEmpty()) { 2225 if (m_workFolderPath.isEmpty()) {
2143 localRepoActionsEnabled = false; 2226 m_localRepoActionsEnabled = false;
2144 workFolderExist = false; 2227 workFolderExist = false;
2145 } 2228 }
2146 2229
2147 if (workFolderPath == "" || !workFolderDir.exists(workFolderPath)) { 2230 if (m_workFolderPath == "" || !workFolderDir.exists(m_workFolderPath)) {
2148 localRepoActionsEnabled = false; 2231 m_localRepoActionsEnabled = false;
2149 workFolderExist = false; 2232 workFolderExist = false;
2150 } else { 2233 } else {
2151 workFolderExist = true; 2234 workFolderExist = true;
2152 } 2235 }
2153 2236
2154 if (!localRepoDir.exists(workFolderPath + "/.hg")) { 2237 if (!localRepoDir.exists(m_workFolderPath + "/.hg")) {
2155 localRepoActionsEnabled = false; 2238 m_localRepoActionsEnabled = false;
2156 localRepoExist = false; 2239 localRepoExist = false;
2157 } 2240 }
2158 2241
2159 hgIncomingAct -> setEnabled(remoteRepoActionsEnabled && remoteRepoActionsEnabled); 2242 m_hgIncomingAct -> setEnabled(m_remoteRepoActionsEnabled && m_remoteRepoActionsEnabled);
2160 hgPullAct -> setEnabled(remoteRepoActionsEnabled && remoteRepoActionsEnabled); 2243 m_hgPullAct -> setEnabled(m_remoteRepoActionsEnabled && m_remoteRepoActionsEnabled);
2161 hgPushAct -> setEnabled(remoteRepoActionsEnabled && remoteRepoActionsEnabled); 2244 m_hgPushAct -> setEnabled(m_remoteRepoActionsEnabled && m_remoteRepoActionsEnabled);
2162 2245
2163 bool haveDiff = false; 2246 bool haveDiff = false;
2164 QSettings settings; 2247 QSettings settings;
2165 settings.beginGroup("Locations"); 2248 settings.beginGroup("Locations");
2166 if (settings.value("extdiffbinary", "").toString() != "") { 2249 if (settings.value("extdiffbinary", "").toString() != "") {
2167 haveDiff = true; 2250 haveDiff = true;
2168 } 2251 }
2169 settings.endGroup(); 2252 settings.endGroup();
2170 2253
2171 hgRefreshAct -> setEnabled(localRepoActionsEnabled); 2254 m_hgRefreshAct -> setEnabled(m_localRepoActionsEnabled);
2172 hgFolderDiffAct -> setEnabled(localRepoActionsEnabled && haveDiff); 2255 m_hgFolderDiffAct -> setEnabled(m_localRepoActionsEnabled && haveDiff);
2173 hgRevertAct -> setEnabled(localRepoActionsEnabled); 2256 m_hgRevertAct -> setEnabled(m_localRepoActionsEnabled);
2174 hgAddAct -> setEnabled(localRepoActionsEnabled); 2257 m_hgAddAct -> setEnabled(m_localRepoActionsEnabled);
2175 hgRemoveAct -> setEnabled(localRepoActionsEnabled); 2258 m_hgRemoveAct -> setEnabled(m_localRepoActionsEnabled);
2176 hgUpdateAct -> setEnabled(localRepoActionsEnabled); 2259 m_hgUpdateAct -> setEnabled(m_localRepoActionsEnabled);
2177 hgCommitAct -> setEnabled(localRepoActionsEnabled); 2260 m_hgCommitAct -> setEnabled(m_localRepoActionsEnabled);
2178 hgMergeAct -> setEnabled(localRepoActionsEnabled); 2261 m_hgMergeAct -> setEnabled(m_localRepoActionsEnabled);
2179 hgAnnotateAct -> setEnabled(localRepoActionsEnabled); 2262 m_hgAnnotateAct -> setEnabled(m_localRepoActionsEnabled);
2180 hgServeAct -> setEnabled(localRepoActionsEnabled); 2263 m_hgServeAct -> setEnabled(m_localRepoActionsEnabled);
2181 hgIgnoreAct -> setEnabled(localRepoActionsEnabled); 2264 m_hgIgnoreAct -> setEnabled(m_localRepoActionsEnabled);
2182 2265
2183 DEBUG << "localRepoActionsEnabled = " << localRepoActionsEnabled << endl; 2266 DEBUG << "m_localRepoActionsEnabled = " << m_localRepoActionsEnabled << endl;
2184 DEBUG << "canCommit = " << hgTabs->canCommit() << endl; 2267 DEBUG << "canCommit = " << m_hgTabs->canCommit() << endl;
2185 2268
2186 hgAddAct->setEnabled(localRepoActionsEnabled && hgTabs->canAdd()); 2269 m_hgAddAct->setEnabled(m_localRepoActionsEnabled && m_hgTabs->canAdd());
2187 hgRemoveAct->setEnabled(localRepoActionsEnabled && hgTabs->canRemove()); 2270 m_hgRemoveAct->setEnabled(m_localRepoActionsEnabled && m_hgTabs->canRemove());
2188 hgCommitAct->setEnabled(localRepoActionsEnabled && hgTabs->canCommit()); 2271 m_hgCommitAct->setEnabled(m_localRepoActionsEnabled && m_hgTabs->canCommit());
2189 hgRevertAct->setEnabled(localRepoActionsEnabled && hgTabs->canRevert()); 2272 m_hgRevertAct->setEnabled(m_localRepoActionsEnabled && m_hgTabs->canRevert());
2190 hgFolderDiffAct->setEnabled(localRepoActionsEnabled && hgTabs->canDiff()); 2273 m_hgFolderDiffAct->setEnabled(m_localRepoActionsEnabled && m_hgTabs->canDiff());
2191 2274
2192 // A default merge makes sense if: 2275 // A default merge makes sense if:
2193 // * there is only one parent (if there are two, we have an uncommitted merge) and 2276 // * there is only one parent (if there are two, we have an uncommitted merge) and
2194 // * there are exactly two heads that have the same branch as the current branch and 2277 // * there are exactly two heads that have the same branch as the current branch and
2195 // * our parent is one of those heads 2278 // * our parent is one of those heads
2202 bool canUpdate = false; 2285 bool canUpdate = false;
2203 bool haveMerge = false; 2286 bool haveMerge = false;
2204 bool emptyRepo = false; 2287 bool emptyRepo = false;
2205 bool noWorkingCopy = false; 2288 bool noWorkingCopy = false;
2206 bool newBranch = false; 2289 bool newBranch = false;
2207 int currentBranchHeads = 0; 2290 int m_currentBranchHeads = 0;
2208 2291
2209 if (currentParents.size() == 1) { 2292 if (m_currentParents.size() == 1) {
2210 bool parentIsHead = false; 2293 bool parentIsHead = false;
2211 Changeset *parent = currentParents[0]; 2294 Changeset *parent = m_currentParents[0];
2212 foreach (Changeset *head, currentHeads) { 2295 foreach (Changeset *head, m_currentHeads) {
2213 DEBUG << "head branch " << head->branch() << ", current branch " << currentBranch << endl; 2296 DEBUG << "head branch " << head->branch() << ", current branch " << m_currentBranch << endl;
2214 if (head->isOnBranch(currentBranch)) { 2297 if (head->isOnBranch(m_currentBranch)) {
2215 ++currentBranchHeads; 2298 ++m_currentBranchHeads;
2216 } 2299 }
2217 if (parent->id() == head->id()) { 2300 if (parent->id() == head->id()) {
2218 parentIsHead = true; 2301 parentIsHead = true;
2219 } 2302 }
2220 } 2303 }
2221 if (currentBranchHeads == 2 && parentIsHead) { 2304 if (m_currentBranchHeads == 2 && parentIsHead) {
2222 canMerge = true; 2305 canMerge = true;
2223 } 2306 }
2224 if (currentBranchHeads == 0 && parentIsHead) { 2307 if (m_currentBranchHeads == 0 && parentIsHead) {
2225 // Just created a new branch 2308 // Just created a new branch
2226 newBranch = true; 2309 newBranch = true;
2227 } 2310 }
2228 if (!parentIsHead) { 2311 if (!parentIsHead) {
2229 canUpdate = true; 2312 canUpdate = true;
2230 DEBUG << "parent id = " << parent->id() << endl; 2313 DEBUG << "parent id = " << parent->id() << endl;
2231 DEBUG << " head ids "<<endl; 2314 DEBUG << " head ids "<<endl;
2232 foreach (Changeset *h, currentHeads) { 2315 foreach (Changeset *h, m_currentHeads) {
2233 DEBUG << "head id = " << h->id() << endl; 2316 DEBUG << "head id = " << h->id() << endl;
2234 } 2317 }
2235 } 2318 }
2236 justMerged = false; 2319 m_justMerged = false;
2237 } else if (currentParents.size() == 0) { 2320 } else if (m_currentParents.size() == 0) {
2238 if (currentHeads.size() == 0) { 2321 if (m_currentHeads.size() == 0) {
2239 // No heads -> empty repo 2322 // No heads -> empty repo
2240 emptyRepo = true; 2323 emptyRepo = true;
2241 } else { 2324 } else {
2242 // Heads, but no parents -> no working copy, e.g. we have 2325 // Heads, but no parents -> no working copy, e.g. we have
2243 // just converted this repo but haven't updated in it yet. 2326 // just converted this repo but haven't updated in it yet.
2244 // Uncommon but confusing; probably merits a special case 2327 // Uncommon but confusing; probably merits a special case
2245 noWorkingCopy = true; 2328 noWorkingCopy = true;
2246 canUpdate = true; 2329 canUpdate = true;
2247 } 2330 }
2248 justMerged = false; 2331 m_justMerged = false;
2249 } else { 2332 } else {
2250 haveMerge = true; 2333 haveMerge = true;
2251 justMerged = true; 2334 m_justMerged = true;
2252 } 2335 }
2253 2336
2254 hgMergeAct->setEnabled(localRepoActionsEnabled && 2337 m_hgMergeAct->setEnabled(m_localRepoActionsEnabled &&
2255 (canMerge || hgTabs->canResolve())); 2338 (canMerge || m_hgTabs->canResolve()));
2256 hgUpdateAct->setEnabled(localRepoActionsEnabled && 2339 m_hgUpdateAct->setEnabled(m_localRepoActionsEnabled &&
2257 (canUpdate && !hgTabs->haveChangesToCommit())); 2340 (canUpdate && !m_hgTabs->haveChangesToCommit()));
2258 2341
2259 // Set the state field on the file status widget 2342 // Set the state field on the file status widget
2260 2343
2261 QString branchText; 2344 QString branchText;
2262 if (currentBranch == "" || currentBranch == "default") { 2345 if (m_currentBranch == "" || m_currentBranch == "default") {
2263 branchText = tr("the default branch"); 2346 branchText = tr("the default branch");
2264 } else { 2347 } else {
2265 branchText = tr("branch \"%1\"").arg(currentBranch); 2348 branchText = tr("branch \"%1\"").arg(m_currentBranch);
2266 } 2349 }
2267 2350
2268 if (stateUnknown) { 2351 if (m_stateUnknown) {
2269 if (workFolderPath == "") { 2352 if (m_workFolderPath == "") {
2270 hgTabs->setState(tr("No repository open")); 2353 m_workStatus->setState(tr("No repository open"));
2271 } else { 2354 } else {
2272 hgTabs->setState(tr("(Examining repository)")); 2355 m_workStatus->setState(tr("(Examining repository)"));
2273 } 2356 }
2274 } else if (emptyRepo) { 2357 } else if (emptyRepo) {
2275 hgTabs->setState(tr("Nothing committed to this repository yet")); 2358 m_workStatus->setState(tr("Nothing committed to this repository yet"));
2276 } else if (noWorkingCopy) { 2359 } else if (noWorkingCopy) {
2277 hgTabs->setState(tr("No working copy yet: consider updating")); 2360 m_workStatus->setState(tr("No working copy yet: consider updating"));
2278 } else if (canMerge) { 2361 } else if (canMerge) {
2279 hgTabs->setState(tr("<b>Awaiting merge</b> on %1").arg(branchText)); 2362 m_workStatus->setState(tr("<b>Awaiting merge</b> on %1").arg(branchText));
2280 } else if (!hgTabs->getAllUnresolvedFiles().empty()) { 2363 } else if (!m_hgTabs->getAllUnresolvedFiles().empty()) {
2281 hgTabs->setState(tr("Have unresolved files following merge on %1").arg(branchText)); 2364 m_workStatus->setState(tr("Have unresolved files following merge on %1").arg(branchText));
2282 } else if (haveMerge) { 2365 } else if (haveMerge) {
2283 hgTabs->setState(tr("Have merged but not yet committed on %1").arg(branchText)); 2366 m_workStatus->setState(tr("Have merged but not yet committed on %1").arg(branchText));
2284 } else if (newBranch) { 2367 } else if (newBranch) {
2285 hgTabs->setState(tr("On %1. New branch: has not yet been committed").arg(branchText)); 2368 m_workStatus->setState(tr("On %1. New branch: has not yet been committed").arg(branchText));
2286 } else if (canUpdate) { 2369 } else if (canUpdate) {
2287 if (hgTabs->haveChangesToCommit()) { 2370 if (m_hgTabs->haveChangesToCommit()) {
2288 // have uncommitted changes 2371 // have uncommitted changes
2289 hgTabs->setState(tr("On %1. Not at the head of the branch").arg(branchText)); 2372 m_workStatus->setState(tr("On %1. Not at the head of the branch").arg(branchText));
2290 } else { 2373 } else {
2291 // no uncommitted changes 2374 // no uncommitted changes
2292 hgTabs->setState(tr("On %1. Not at the head of the branch: consider updating").arg(branchText)); 2375 m_workStatus->setState(tr("On %1. Not at the head of the branch: consider updating").arg(branchText));
2293 } 2376 }
2294 } else if (currentBranchHeads > 1) { 2377 } else if (m_currentBranchHeads > 1) {
2295 hgTabs->setState(tr("At one of %n heads of %1", "", currentBranchHeads).arg(branchText)); 2378 m_workStatus->setState(tr("At one of %n heads of %1", "", m_currentBranchHeads).arg(branchText));
2296 } else { 2379 } else {
2297 hgTabs->setState(tr("At the head of %1").arg(branchText)); 2380 m_workStatus->setState(tr("At the head of %1").arg(branchText));
2298 } 2381 }
2299 } 2382 }
2300 2383
2301 void MainWindow::createActions() 2384 void MainWindow::createActions()
2302 { 2385 {
2303 //File actions 2386 //File actions
2304 openAct = new QAction(QIcon(":/images/fileopen.png"), tr("Open..."), this); 2387 m_openAct = new QAction(QIcon(":/images/fileopen.png"), tr("Open..."), this);
2305 openAct -> setStatusTip(tr("Open an existing repository or working folder")); 2388 m_openAct -> setStatusTip(tr("Open an existing repository or working folder"));
2306 2389
2307 changeRemoteRepoAct = new QAction(tr("Change Remote Location..."), this); 2390 m_changeRemoteRepoAct = new QAction(tr("Change Remote Location..."), this);
2308 changeRemoteRepoAct->setStatusTip(tr("Change the default remote repository for pull and push actions")); 2391 m_changeRemoteRepoAct->setStatusTip(tr("Change the default remote repository for pull and push actions"));
2309 2392
2310 settingsAct = new QAction(QIcon(":/images/settings.png"), tr("Settings..."), this); 2393 m_settingsAct = new QAction(QIcon(":/images/settings.png"), tr("Settings..."), this);
2311 settingsAct -> setStatusTip(tr("View and change application settings")); 2394 m_settingsAct -> setStatusTip(tr("View and change application settings"));
2312 2395
2313 exitAct = new QAction(QIcon(":/images/exit.png"), tr("Quit"), this); 2396 m_exitAct = new QAction(QIcon(":/images/exit.png"), tr("Quit"), this);
2314 exitAct->setShortcuts(QKeySequence::Quit); 2397 m_exitAct->setShortcuts(QKeySequence::Quit);
2315 exitAct->setStatusTip(tr("Quit EasyMercurial")); 2398 m_exitAct->setStatusTip(tr("Quit EasyMercurial"));
2316 2399
2317 //Repository actions 2400 //Repository actions
2318 hgRefreshAct = new QAction(QIcon(":/images/status.png"), tr("Refresh"), this); 2401 m_hgRefreshAct = new QAction(QIcon(":/images/status.png"), tr("Refresh"), this);
2319 hgRefreshAct->setStatusTip(tr("Refresh the window to show the current state of the working folder")); 2402 m_hgRefreshAct->setStatusTip(tr("Refresh the window to show the current state of the working folder"));
2320 2403
2321 hgIncomingAct = new QAction(QIcon(":/images/incoming.png"), tr("Preview"), this); 2404 m_hgIncomingAct = new QAction(QIcon(":/images/incoming.png"), tr("Preview"), this);
2322 hgIncomingAct -> setStatusTip(tr("See what changes are available in the remote repository waiting to be pulled")); 2405 m_hgIncomingAct -> setStatusTip(tr("See what changes are available in the remote repository waiting to be pulled"));
2323 2406
2324 hgPullAct = new QAction(QIcon(":/images/pull.png"), tr("Pull"), this); 2407 m_hgPullAct = new QAction(QIcon(":/images/pull.png"), tr("Pull"), this);
2325 hgPullAct -> setStatusTip(tr("Pull changes from the remote repository to the local repository")); 2408 m_hgPullAct -> setStatusTip(tr("Pull changes from the remote repository to the local repository"));
2326 2409
2327 hgPushAct = new QAction(QIcon(":/images/push.png"), tr("Push"), this); 2410 m_hgPushAct = new QAction(QIcon(":/images/push.png"), tr("Push"), this);
2328 hgPushAct->setStatusTip(tr("Push changes from the local repository to the remote repository")); 2411 m_hgPushAct->setStatusTip(tr("Push changes from the local repository to the remote repository"));
2329 2412
2330 //Workfolder actions 2413 //Workfolder actions
2331 hgFolderDiffAct = new QAction(QIcon(":/images/folderdiff.png"), tr("Diff"), this); 2414 m_hgFolderDiffAct = new QAction(QIcon(":/images/folderdiff.png"), tr("Diff"), this);
2332 hgFolderDiffAct->setStatusTip(tr("See what has changed in the working folder compared with the last committed state")); 2415 m_hgFolderDiffAct->setStatusTip(tr("See what has changed in the working folder compared with the last committed state"));
2333 2416
2334 hgRevertAct = new QAction(QIcon(":/images/undo.png"), tr("Revert"), this); 2417 m_hgRevertAct = new QAction(QIcon(":/images/undo.png"), tr("Revert"), this);
2335 hgRevertAct->setStatusTip(tr("Throw away your changes and return to the last committed state")); 2418 m_hgRevertAct->setStatusTip(tr("Throw away your changes and return to the last committed state"));
2336 2419
2337 hgAddAct = new QAction(QIcon(":/images/add.png"), tr("Add"), this); 2420 m_hgAddAct = new QAction(QIcon(":/images/add.png"), tr("Add"), this);
2338 hgAddAct -> setStatusTip(tr("Mark the selected file(s) to be added on the next commit")); 2421 m_hgAddAct -> setStatusTip(tr("Mark the selected file(s) to be added on the next commit"));
2339 2422
2340 //!!! needs to be modified for number 2423 //!!! needs to be modified for number
2341 hgRemoveAct = new QAction(QIcon(":/images/remove.png"), tr("Remove"), this); 2424 m_hgRemoveAct = new QAction(QIcon(":/images/remove.png"), tr("Remove"), this);
2342 hgRemoveAct -> setStatusTip(tr("Mark the selected file(s) to be removed from version control on the next commit")); 2425 m_hgRemoveAct -> setStatusTip(tr("Mark the selected file(s) to be removed from version control on the next commit"));
2343 2426
2344 hgUpdateAct = new QAction(QIcon(":/images/update.png"), tr("Update"), this); 2427 m_hgUpdateAct = new QAction(QIcon(":/images/update.png"), tr("Update"), this);
2345 hgUpdateAct->setStatusTip(tr("Update the working folder to the head of the current repository branch")); 2428 m_hgUpdateAct->setStatusTip(tr("Update the working folder to the head of the current repository branch"));
2346 2429
2347 //!!! needs to be modified when files selected 2430 //!!! needs to be modified when files selected
2348 hgCommitAct = new QAction(QIcon(":/images/commit.png"), tr("Commit"), this); 2431 m_hgCommitAct = new QAction(QIcon(":/images/commit.png"), tr("Commit"), this);
2349 hgCommitAct->setStatusTip(tr("Commit your changes to the local repository")); 2432 m_hgCommitAct->setStatusTip(tr("Commit your changes to the local repository"));
2350 2433
2351 hgMergeAct = new QAction(QIcon(":/images/merge.png"), tr("Merge"), this); 2434 m_hgMergeAct = new QAction(QIcon(":/images/merge.png"), tr("Merge"), this);
2352 hgMergeAct->setStatusTip(tr("Merge the two independent sets of changes in the local repository into the working folder")); 2435 m_hgMergeAct->setStatusTip(tr("Merge the two independent sets of changes in the local repository into the working folder"));
2353 2436
2354 //Advanced actions 2437 //Advanced actions
2355 //!!! needs to be modified for number 2438 //!!! needs to be modified for number
2356 hgAnnotateAct = new QAction(tr("Annotate"), this); 2439 m_hgAnnotateAct = new QAction(tr("Annotate"), this);
2357 hgAnnotateAct -> setStatusTip(tr("Show line-by-line version information for selected file")); 2440 m_hgAnnotateAct -> setStatusTip(tr("Show line-by-line version information for selected file"));
2358 2441
2359 hgIgnoreAct = new QAction(tr("Edit .hgignore File"), this); 2442 m_hgIgnoreAct = new QAction(tr("Edit .hgignore File"), this);
2360 hgIgnoreAct -> setStatusTip(tr("Edit the .hgignore file, containing the names of files that should be ignored by Mercurial")); 2443 m_hgIgnoreAct -> setStatusTip(tr("Edit the .hgignore file, containing the names of files that should be ignored by Mercurial"));
2361 2444
2362 hgServeAct = new QAction(tr("Serve via HTTP"), this); 2445 m_hgServeAct = new QAction(tr("Serve via HTTP"), this);
2363 hgServeAct -> setStatusTip(tr("Serve local repository via http for workgroup access")); 2446 m_hgServeAct -> setStatusTip(tr("Serve local repository via http for workgroup access"));
2364 2447
2365 //Help actions 2448 //Help actions
2366 aboutAct = new QAction(tr("About EasyMercurial"), this); 2449 m_aboutAct = new QAction(tr("About EasyMercurial"), this);
2367 2450
2368 // Miscellaneous 2451 // Miscellaneous
2369 QShortcut *clearSelectionsShortcut = new QShortcut(Qt::Key_Escape, this); 2452 QShortcut *clearSelectionsShortcut = new QShortcut(Qt::Key_Escape, this);
2370 connect(clearSelectionsShortcut, SIGNAL(activated()), 2453 connect(clearSelectionsShortcut, SIGNAL(activated()),
2371 this, SLOT(clearSelections())); 2454 this, SLOT(clearSelections()));
2372 } 2455 }
2373 2456
2374 void MainWindow::createMenus() 2457 void MainWindow::createMenus()
2375 { 2458 {
2376 fileMenu = menuBar()->addMenu(tr("File")); 2459 m_fileMenu = menuBar()->addMenu(tr("File"));
2377 2460
2378 fileMenu -> addAction(openAct); 2461 m_fileMenu -> addAction(m_openAct);
2379 fileMenu -> addAction(changeRemoteRepoAct); 2462 m_fileMenu -> addAction(m_changeRemoteRepoAct);
2380 fileMenu -> addSeparator(); 2463 m_fileMenu -> addSeparator();
2381 2464
2382 advancedMenu = fileMenu->addMenu(tr("Advanced")); 2465 m_advancedMenu = m_fileMenu->addMenu(tr("Advanced"));
2383 2466
2384 fileMenu -> addAction(settingsAct); 2467 m_fileMenu -> addAction(m_settingsAct);
2385 2468
2386 fileMenu -> addSeparator(); 2469 m_fileMenu -> addSeparator();
2387 fileMenu -> addAction(exitAct); 2470 m_fileMenu -> addAction(m_exitAct);
2388 2471
2389 advancedMenu -> addAction(hgIgnoreAct); 2472 m_advancedMenu -> addAction(m_hgIgnoreAct);
2390 advancedMenu -> addSeparator(); 2473 m_advancedMenu -> addSeparator();
2391 advancedMenu -> addAction(hgServeAct); 2474 m_advancedMenu -> addAction(m_hgServeAct);
2392 2475
2393 helpMenu = menuBar()->addMenu(tr("Help")); 2476 m_helpMenu = menuBar()->addMenu(tr("Help"));
2394 helpMenu->addAction(aboutAct); 2477 m_helpMenu->addAction(m_aboutAct);
2395 } 2478 }
2396 2479
2397 void MainWindow::createToolBars() 2480 void MainWindow::createToolBars()
2398 { 2481 {
2399 fileToolBar = addToolBar(tr("File")); 2482 m_fileToolBar = addToolBar(tr("File"));
2400 fileToolBar -> setIconSize(QSize(MY_ICON_SIZE, MY_ICON_SIZE)); 2483 m_fileToolBar -> setIconSize(QSize(MY_ICON_SIZE, MY_ICON_SIZE));
2401 fileToolBar -> addAction(openAct); 2484 m_fileToolBar -> addAction(m_openAct);
2402 fileToolBar -> addAction(hgRefreshAct); 2485 m_fileToolBar -> addAction(m_hgRefreshAct);
2403 fileToolBar -> addSeparator(); 2486 m_fileToolBar -> addSeparator();
2404 fileToolBar -> setMovable(false); 2487 m_fileToolBar -> setMovable(false);
2405 2488
2406 repoToolBar = addToolBar(tr(REPOMENU_TITLE)); 2489 m_repoToolBar = addToolBar(tr(REPOMENU_TITLE));
2407 repoToolBar -> setIconSize(QSize(MY_ICON_SIZE, MY_ICON_SIZE)); 2490 m_repoToolBar -> setIconSize(QSize(MY_ICON_SIZE, MY_ICON_SIZE));
2408 repoToolBar->addAction(hgIncomingAct); 2491 m_repoToolBar->addAction(m_hgIncomingAct);
2409 repoToolBar->addAction(hgPullAct); 2492 m_repoToolBar->addAction(m_hgPullAct);
2410 repoToolBar->addAction(hgPushAct); 2493 m_repoToolBar->addAction(m_hgPushAct);
2411 repoToolBar -> setMovable(false); 2494 m_repoToolBar -> setMovable(false);
2412 2495
2413 workFolderToolBar = addToolBar(tr(WORKFOLDERMENU_TITLE)); 2496 m_workFolderToolBar = addToolBar(tr(WORKFOLDERMENU_TITLE));
2414 addToolBar(Qt::LeftToolBarArea, workFolderToolBar); 2497 addToolBar(Qt::LeftToolBarArea, m_workFolderToolBar);
2415 workFolderToolBar -> setIconSize(QSize(MY_ICON_SIZE, MY_ICON_SIZE)); 2498 m_workFolderToolBar -> setIconSize(QSize(MY_ICON_SIZE, MY_ICON_SIZE));
2416 workFolderToolBar->addAction(hgFolderDiffAct); 2499 m_workFolderToolBar->addAction(m_hgFolderDiffAct);
2417 workFolderToolBar->addSeparator(); 2500 m_workFolderToolBar->addSeparator();
2418 workFolderToolBar->addAction(hgRevertAct); 2501 m_workFolderToolBar->addAction(m_hgRevertAct);
2419 workFolderToolBar->addAction(hgUpdateAct); 2502 m_workFolderToolBar->addAction(m_hgUpdateAct);
2420 workFolderToolBar->addAction(hgCommitAct); 2503 m_workFolderToolBar->addAction(m_hgCommitAct);
2421 workFolderToolBar->addAction(hgMergeAct); 2504 m_workFolderToolBar->addAction(m_hgMergeAct);
2422 workFolderToolBar->addSeparator(); 2505 m_workFolderToolBar->addSeparator();
2423 workFolderToolBar->addAction(hgAddAct); 2506 m_workFolderToolBar->addAction(m_hgAddAct);
2424 workFolderToolBar->addAction(hgRemoveAct); 2507 m_workFolderToolBar->addAction(m_hgRemoveAct);
2425 workFolderToolBar -> setMovable(false); 2508 m_workFolderToolBar -> setMovable(false);
2426 2509
2427 updateToolBarStyle(); 2510 updateToolBarStyle();
2428 } 2511 }
2429 2512
2430 void MainWindow::updateToolBarStyle() 2513 void MainWindow::updateToolBarStyle()
2439 Qt::ToolButtonTextUnderIcon : 2522 Qt::ToolButtonTextUnderIcon :
2440 Qt::ToolButtonIconOnly); 2523 Qt::ToolButtonIconOnly);
2441 } 2524 }
2442 } 2525 }
2443 2526
2527 void MainWindow::updateWorkFolderAndRepoNames()
2528 {
2529 m_hgTabs->setLocalPath(m_workFolderPath);
2530
2531 m_workStatus->setLocalPath(m_workFolderPath);
2532 m_workStatus->setRemoteURL(m_remoteRepoPath);
2533 }
2534
2444 void MainWindow::createStatusBar() 2535 void MainWindow::createStatusBar()
2445 { 2536 {
2446 statusBar()->showMessage(tr("Ready")); 2537 statusBar()->showMessage(tr("Ready"));
2447 } 2538 }
2448 2539
2449
2450 //!!! review these:
2451
2452 void MainWindow::readSettings() 2540 void MainWindow::readSettings()
2453 { 2541 {
2454 QDir workFolder; 2542 QDir workFolder;
2455 2543
2456 QSettings settings; 2544 QSettings settings;
2457 2545
2458 remoteRepoPath = settings.value("remoterepopath", "").toString(); 2546 m_remoteRepoPath = settings.value("remoterepopath", "").toString();
2459 workFolderPath = settings.value("workfolderpath", "").toString(); 2547 m_workFolderPath = settings.value("workfolderpath", "").toString();
2460 if (!workFolder.exists(workFolderPath)) 2548 if (!workFolder.exists(m_workFolderPath))
2461 { 2549 {
2462 workFolderPath = ""; 2550 m_workFolderPath = "";
2463 } 2551 }
2464 2552
2465 QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); 2553 QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
2466 QSize size = settings.value("size", QSize(400, 400)).toSize(); 2554 QSize size = settings.value("size", QSize(400, 400)).toSize();
2467 firstStart = settings.value("firststart", QVariant(true)).toBool(); 2555 m_firstStart = settings.value("firststart", QVariant(true)).toBool();
2468 2556
2469 //!!! initialFileTypesBits = (unsigned char) settings.value("viewFileTypes", QVariant(DEFAULT_HG_STAT_BITS)).toInt();
2470 resize(size); 2557 resize(size);
2471 move(pos); 2558 move(pos);
2472 } 2559 }
2473
2474 2560
2475 void MainWindow::writeSettings() 2561 void MainWindow::writeSettings()
2476 { 2562 {
2477 QSettings settings; 2563 QSettings settings;
2478 settings.setValue("pos", pos()); 2564 settings.setValue("pos", pos());
2479 settings.setValue("size", size()); 2565 settings.setValue("size", size());
2480 settings.setValue("remoterepopath", remoteRepoPath); 2566 settings.setValue("remoterepopath", m_remoteRepoPath);
2481 settings.setValue("workfolderpath", workFolderPath); 2567 settings.setValue("workfolderpath", m_workFolderPath);
2482 settings.setValue("firststart", firstStart); 2568 settings.setValue("firststart", m_firstStart);
2483 //!!!settings.setValue("viewFileTypes", hgTabs -> getFileTypesBits()); 2569 }
2484 } 2570
2485 2571
2486 2572
2487 2573
2488