Mercurial > hg > easyhg
comparison src/mainwindow.cpp @ 422:2af4b5b0bf83
Merge from branch "ignore"
author | Chris Cannam <chris.cannam@eecs.qmul.ac.uk> |
---|---|
date | Wed, 22 Jun 2011 13:01:50 +0100 |
parents | 653e9694a694 |
children | 06e5c4f3dd7c |
comparison
equal
deleted
inserted
replaced
412:498c2ca0b367 | 422:2af4b5b0bf83 |
---|---|
46 #include "settingsdialog.h" | 46 #include "settingsdialog.h" |
47 #include "moreinformationdialog.h" | 47 #include "moreinformationdialog.h" |
48 #include "annotatedialog.h" | 48 #include "annotatedialog.h" |
49 #include "version.h" | 49 #include "version.h" |
50 #include "workstatuswidget.h" | 50 #include "workstatuswidget.h" |
51 #include "hgignoredialog.h" | |
51 | 52 |
52 | 53 |
53 MainWindow::MainWindow(QString myDirPath) : | 54 MainWindow::MainWindow(QString myDirPath) : |
54 m_myDirPath(myDirPath), | 55 m_myDirPath(myDirPath), |
55 m_fsWatcherGeneralTimer(0), | 56 m_fsWatcherGeneralTimer(0), |
544 m_runner->requestAction(HgAction(ACT_TAG, m_workFolderPath, params)); | 545 m_runner->requestAction(HgAction(ACT_TAG, m_workFolderPath, params)); |
545 } | 546 } |
546 } | 547 } |
547 } | 548 } |
548 | 549 |
549 void MainWindow::hgIgnore() | 550 void MainWindow::initHgIgnore() |
550 { | 551 { |
551 QString hgIgnorePath; | |
552 QStringList params; | |
553 | |
554 hgIgnorePath = m_workFolderPath; | |
555 hgIgnorePath += "/.hgignore"; | |
556 | |
557 if (!QDir(m_workFolderPath).exists()) return; | 552 if (!QDir(m_workFolderPath).exists()) return; |
553 QString hgIgnorePath = m_workFolderPath + "/.hgignore"; | |
554 | |
558 QFile f(hgIgnorePath); | 555 QFile f(hgIgnorePath); |
559 if (!f.exists()) { | 556 if (!f.exists()) { |
560 f.open(QFile::WriteOnly); | 557 f.open(QFile::WriteOnly); |
561 QTextStream *ts = new QTextStream(&f); | 558 QTextStream *ts = new QTextStream(&f); |
562 *ts << "syntax: glob\n"; | 559 *ts << "syntax: glob\n"; |
563 delete ts; | 560 delete ts; |
564 f.close(); | 561 f.close(); |
565 } | 562 } |
566 | 563 } |
564 | |
565 void MainWindow::hgEditIgnore() | |
566 { | |
567 if (!QDir(m_workFolderPath).exists()) return; | |
568 | |
569 initHgIgnore(); | |
570 | |
571 QString hgIgnorePath = m_workFolderPath + "/.hgignore"; | |
572 QStringList params; | |
573 | |
567 params << hgIgnorePath; | 574 params << hgIgnorePath; |
568 | 575 |
569 QString editor = getEditorBinaryName(); | 576 QString editor = getEditorBinaryName(); |
570 | 577 |
571 if (editor == "") { | 578 if (editor == "") { |
572 DEBUG << "Failed to find a text editor" << endl; | 579 QMessageBox::critical |
573 //!!! visible error! | 580 (this, tr("Edit .hgignore"), |
581 tr("Failed to locate a system text editor program!")); | |
574 return; | 582 return; |
575 } | 583 } |
576 | 584 |
577 HgAction action(ACT_HG_IGNORE, m_workFolderPath, params); | 585 HgAction action(ACT_HG_IGNORE, m_workFolderPath, params); |
578 action.executable = editor; | 586 action.executable = editor; |
579 | 587 |
580 m_runner->requestAction(action); | 588 m_runner->requestAction(action); |
581 } | 589 } |
582 | 590 |
591 static QString regexEscape(QString filename) | |
592 { | |
593 return filename | |
594 .replace(".", "\\.") | |
595 .replace("[", "\\[") | |
596 .replace("]", "\\]") | |
597 .replace("(", "\\(") | |
598 .replace(")", "\\)") | |
599 .replace("?", "\\?"); | |
600 } | |
601 | |
583 void MainWindow::hgIgnoreFiles(QStringList files) | 602 void MainWindow::hgIgnoreFiles(QStringList files) |
584 { | 603 { |
585 //!!! not implemented yet | 604 if (!QDir(m_workFolderPath).exists() || files.empty()) return; |
586 DEBUG << "MainWindow::hgIgnoreFiles: Not implemented" << endl; | 605 |
606 // we should: | |
607 // | |
608 // * show the user the list of file names selected | |
609 // | |
610 // * offer a choice (depending on the files selected?) | |
611 // | |
612 // - ignore only these files | |
613 // | |
614 // - ignore files with these names, in any subdirectories? | |
615 // | |
616 // - ignore all files with this extension (if they have a common | |
617 // extension)? | |
618 // | |
619 // - ignore all files with these extensions (if they have any | |
620 // extensions?) | |
621 | |
622 DEBUG << "MainWindow::hgIgnoreFiles: File names are:" << endl; | |
623 foreach (QString file, files) DEBUG << file << endl; | |
624 | |
625 QSet<QString> suffixes; | |
626 foreach (QString file, files) { | |
627 QString s = QFileInfo(file).suffix(); | |
628 if (s != "") suffixes.insert(s); | |
629 } | |
630 | |
631 QString directory; | |
632 bool dirCount = 0; | |
633 foreach (QString file, files) { | |
634 QString d = QFileInfo(file).path(); | |
635 if (d != directory) { | |
636 ++dirCount; | |
637 directory = d; | |
638 } | |
639 } | |
640 if (dirCount != 1 || directory == ".") directory = ""; | |
641 | |
642 HgIgnoreDialog::IgnoreType itype = | |
643 HgIgnoreDialog::confirmIgnore | |
644 (this, files, QStringList::fromSet(suffixes), directory); | |
645 | |
646 DEBUG << "hgIgnoreFiles: Ignore type is " << itype << endl; | |
647 | |
648 if (itype == HgIgnoreDialog::IgnoreNothing) return; | |
649 | |
650 // Now, .hgignore can be switched from regex to glob syntax | |
651 // part-way through -- and glob is much simpler for us, so we | |
652 // should do that if it's in regex mode at the end of the file. | |
653 | |
654 initHgIgnore(); | |
655 | |
656 QString hgIgnorePath = m_workFolderPath + "/.hgignore"; | |
657 | |
658 // hgignore file should now exist (initHgIgnore should have | |
659 // created it if it didn't). Check for glob status first | |
660 | |
661 QFile f(hgIgnorePath); | |
662 if (!f.exists()) { | |
663 std::cerr << "MainWindow::ignoreFiles: Internal error: .hgignore file not found (even though we were supposed to have created it)" << std::endl; | |
664 return; | |
665 } | |
666 | |
667 f.open(QFile::ReadOnly); | |
668 bool glob = false; | |
669 while (!f.atEnd()) { | |
670 QByteArray ba = f.readLine(); | |
671 QString s = QString::fromLocal8Bit(ba).trimmed(); | |
672 if (s.startsWith("syntax:")) { | |
673 if (s.endsWith("glob")) { | |
674 glob = true; | |
675 } else { | |
676 glob = false; | |
677 } | |
678 } | |
679 } | |
680 f.close(); | |
681 | |
682 f.open(QFile::Append); | |
683 QTextStream out(&f); | |
684 | |
685 if (!glob) { | |
686 out << "syntax: glob" << endl; | |
687 } | |
688 | |
689 QString info = "<qt><h3>" + tr("Ignored files") + "</h3><p>"; | |
690 info += tr("The following lines have been added to the .hgignore file for this working copy:"); | |
691 info += "</p><code>"; | |
692 | |
693 QStringList args; | |
694 if (itype == HgIgnoreDialog::IgnoreAllFilesOfGivenSuffixes) { | |
695 args = QStringList::fromSet(suffixes); | |
696 } else if (itype == HgIgnoreDialog::IgnoreGivenFilesOnly) { | |
697 args = files; | |
698 } else if (itype == HgIgnoreDialog::IgnoreAllFilesOfGivenNames) { | |
699 QSet<QString> names; | |
700 foreach (QString f, files) { | |
701 names << QFileInfo(f).fileName(); | |
702 } | |
703 args = QStringList::fromSet(names); | |
704 } else if (itype == HgIgnoreDialog::IgnoreWholeDirectory) { | |
705 args << directory; | |
706 } | |
707 | |
708 bool first = true; | |
709 | |
710 foreach (QString a, args) { | |
711 QString line; | |
712 if (itype == HgIgnoreDialog::IgnoreAllFilesOfGivenSuffixes) { | |
713 line = "*." + a; | |
714 } else if (itype == HgIgnoreDialog::IgnoreGivenFilesOnly) { | |
715 // Doesn't seem to be possible to do this with a glob, | |
716 // because the glob is always unanchored and there is no | |
717 // equivalent of ^ to anchor it | |
718 line = "re:^" + regexEscape(a); | |
719 } else if (itype == HgIgnoreDialog::IgnoreAllFilesOfGivenNames) { | |
720 line = a; | |
721 } else if (itype == HgIgnoreDialog::IgnoreWholeDirectory) { | |
722 line = "re:^" + regexEscape(a) + "/"; | |
723 } | |
724 if (line != "") { | |
725 out << line << endl; | |
726 if (!first) info += "<br>"; | |
727 first = false; | |
728 info += xmlEncode(line); | |
729 } | |
730 } | |
731 | |
732 f.close(); | |
733 | |
734 info += "</code></qt>"; | |
735 | |
736 QMessageBox::information(this, tr("Ignored files"), | |
737 info); | |
738 | |
739 hgRefresh(); | |
587 } | 740 } |
588 | 741 |
589 void MainWindow::hgUnIgnoreFiles(QStringList files) | 742 void MainWindow::hgUnIgnoreFiles(QStringList files) |
590 { | 743 { |
591 //!!! not implemented yet | 744 // Not implemented: edit the .hgignore instead |
592 DEBUG << "MainWindow::hgUnIgnoreFiles: Not implemented" << endl; | 745 hgEditIgnore(); |
593 } | 746 } |
594 | 747 |
595 QString MainWindow::getDiffBinaryName() | 748 QString MainWindow::getDiffBinaryName() |
596 { | 749 { |
597 QSettings settings; | 750 QSettings settings; |
2337 connect(m_hgCommitAct, SIGNAL(triggered()), this, SLOT(hgCommit())); | 2490 connect(m_hgCommitAct, SIGNAL(triggered()), this, SLOT(hgCommit())); |
2338 connect(m_hgFolderDiffAct, SIGNAL(triggered()), this, SLOT(hgFolderDiff())); | 2491 connect(m_hgFolderDiffAct, SIGNAL(triggered()), this, SLOT(hgFolderDiff())); |
2339 connect(m_hgUpdateAct, SIGNAL(triggered()), this, SLOT(hgUpdate())); | 2492 connect(m_hgUpdateAct, SIGNAL(triggered()), this, SLOT(hgUpdate())); |
2340 connect(m_hgRevertAct, SIGNAL(triggered()), this, SLOT(hgRevert())); | 2493 connect(m_hgRevertAct, SIGNAL(triggered()), this, SLOT(hgRevert())); |
2341 connect(m_hgMergeAct, SIGNAL(triggered()), this, SLOT(hgMerge())); | 2494 connect(m_hgMergeAct, SIGNAL(triggered()), this, SLOT(hgMerge())); |
2342 connect(m_hgIgnoreAct, SIGNAL(triggered()), this, SLOT(hgIgnore())); | 2495 connect(m_hgEditIgnoreAct, SIGNAL(triggered()), this, SLOT(hgEditIgnore())); |
2343 | 2496 |
2344 connect(m_settingsAct, SIGNAL(triggered()), this, SLOT(settings())); | 2497 connect(m_settingsAct, SIGNAL(triggered()), this, SLOT(settings())); |
2345 connect(m_openAct, SIGNAL(triggered()), this, SLOT(open())); | 2498 connect(m_openAct, SIGNAL(triggered()), this, SLOT(open())); |
2346 connect(m_changeRemoteRepoAct, SIGNAL(triggered()), this, SLOT(changeRemoteRepo())); | 2499 connect(m_changeRemoteRepoAct, SIGNAL(triggered()), this, SLOT(changeRemoteRepo())); |
2347 | 2500 |
2491 m_hgRemoveAct->setEnabled(m_localRepoActionsEnabled); | 2644 m_hgRemoveAct->setEnabled(m_localRepoActionsEnabled); |
2492 m_hgUpdateAct->setEnabled(m_localRepoActionsEnabled); | 2645 m_hgUpdateAct->setEnabled(m_localRepoActionsEnabled); |
2493 m_hgCommitAct->setEnabled(m_localRepoActionsEnabled); | 2646 m_hgCommitAct->setEnabled(m_localRepoActionsEnabled); |
2494 m_hgMergeAct->setEnabled(m_localRepoActionsEnabled); | 2647 m_hgMergeAct->setEnabled(m_localRepoActionsEnabled); |
2495 m_hgServeAct->setEnabled(m_localRepoActionsEnabled); | 2648 m_hgServeAct->setEnabled(m_localRepoActionsEnabled); |
2496 m_hgIgnoreAct->setEnabled(m_localRepoActionsEnabled); | 2649 m_hgEditIgnoreAct->setEnabled(m_localRepoActionsEnabled); |
2497 | 2650 |
2498 DEBUG << "m_localRepoActionsEnabled = " << m_localRepoActionsEnabled << endl; | 2651 DEBUG << "m_localRepoActionsEnabled = " << m_localRepoActionsEnabled << endl; |
2499 DEBUG << "canCommit = " << m_hgTabs->canCommit() << endl; | 2652 DEBUG << "canCommit = " << m_hgTabs->canCommit() << endl; |
2500 | 2653 |
2501 m_hgAddAct->setEnabled(m_localRepoActionsEnabled && m_hgTabs->canAdd()); | 2654 m_hgAddAct->setEnabled(m_localRepoActionsEnabled && m_hgTabs->canAdd()); |
2708 m_hgMergeAct->setShortcut(tr("Ctrl+M")); | 2861 m_hgMergeAct->setShortcut(tr("Ctrl+M")); |
2709 m_hgMergeAct->setStatusTip(tr("Merge the two independent sets of changes in the local repository into the working folder")); | 2862 m_hgMergeAct->setStatusTip(tr("Merge the two independent sets of changes in the local repository into the working folder")); |
2710 | 2863 |
2711 //Advanced actions | 2864 //Advanced actions |
2712 | 2865 |
2713 m_hgIgnoreAct = new QAction(tr("Edit .hgignore File"), this); | 2866 m_hgEditIgnoreAct = new QAction(tr("Edit .hgignore File"), this); |
2714 m_hgIgnoreAct->setStatusTip(tr("Edit the .hgignore file, containing the names of files that should be ignored by Mercurial")); | 2867 m_hgEditIgnoreAct->setStatusTip(tr("Edit the .hgignore file, containing the names of files that should be ignored by Mercurial")); |
2715 | 2868 |
2716 m_hgServeAct = new QAction(tr("Serve via HTTP"), this); | 2869 m_hgServeAct = new QAction(tr("Serve via HTTP"), this); |
2717 m_hgServeAct->setStatusTip(tr("Serve local repository via http for workgroup access")); | 2870 m_hgServeAct->setStatusTip(tr("Serve local repository via http for workgroup access")); |
2718 | 2871 |
2719 //Help actions | 2872 //Help actions |
2758 remoteMenu->addAction(m_hgPushAct); | 2911 remoteMenu->addAction(m_hgPushAct); |
2759 remoteMenu->addSeparator(); | 2912 remoteMenu->addSeparator(); |
2760 remoteMenu->addAction(m_changeRemoteRepoAct); | 2913 remoteMenu->addAction(m_changeRemoteRepoAct); |
2761 | 2914 |
2762 m_advancedMenu = menuBar()->addMenu(tr("&Advanced")); | 2915 m_advancedMenu = menuBar()->addMenu(tr("&Advanced")); |
2763 m_advancedMenu->addAction(m_hgIgnoreAct); | 2916 m_advancedMenu->addAction(m_hgEditIgnoreAct); |
2764 m_advancedMenu->addSeparator(); | 2917 m_advancedMenu->addSeparator(); |
2765 m_advancedMenu->addAction(m_hgServeAct); | 2918 m_advancedMenu->addAction(m_hgServeAct); |
2766 | 2919 |
2767 m_helpMenu = menuBar()->addMenu(tr("&Help")); | 2920 m_helpMenu = menuBar()->addMenu(tr("&Help")); |
2768 m_helpMenu->addAction(m_aboutAct); | 2921 m_helpMenu->addAction(m_aboutAct); |