Chris@57: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ jtkorhonen@0: Chris@57: /* Chris@57: EasyMercurial Chris@57: Chris@57: Based on HgExplorer by Jari Korhonen Chris@57: Copyright (c) 2010 Jari Korhonen Chris@57: Copyright (c) 2010 Chris Cannam Chris@57: Copyright (c) 2010 Queen Mary, University of London Chris@57: Chris@57: This program is free software; you can redistribute it and/or Chris@57: modify it under the terms of the GNU General Public License as Chris@57: published by the Free Software Foundation; either version 2 of the Chris@57: License, or (at your option) any later version. See the file Chris@57: COPYING included with this distribution for more information. Chris@57: */ Chris@50: jtkorhonen@0: #include jtkorhonen@0: #include jtkorhonen@24: #include jtkorhonen@17: #include jtkorhonen@17: #include jtkorhonen@34: #include Chris@50: #include Chris@50: #include Chris@50: #include Chris@50: #include Chris@50: #include Chris@61: #include Chris@50: #include Chris@90: #include jtkorhonen@0: Chris@53: #include "mainwindow.h" Chris@53: #include "settingsdialog.h" Chris@69: #include "multichoicedialog.h" Chris@64: #include "startupdialog.h" Chris@53: #include "colourset.h" Chris@62: #include "debug.h" Chris@74: #include "logparser.h" Chris@53: jtkorhonen@0: jtkorhonen@0: MainWindow::MainWindow() jtkorhonen@0: { jtkorhonen@0: QString wndTitle; jtkorhonen@0: Chris@90: fsWatcher = 0; Chris@90: jtkorhonen@0: createActions(); jtkorhonen@0: createMenus(); jtkorhonen@0: createToolBars(); jtkorhonen@0: createStatusBar(); jtkorhonen@0: jtkorhonen@0: runner = new HgRunner(this); Chris@62: connect(runner, SIGNAL(commandCompleted()), Chris@62: this, SLOT(commandCompleted())); Chris@62: connect(runner, SIGNAL(commandFailed()), Chris@62: this, SLOT(commandFailed())); jtkorhonen@0: runningAction = ACT_NONE; jtkorhonen@0: statusBar()->addPermanentWidget(runner); jtkorhonen@0: Chris@61: setWindowTitle(tr("EasyMercurial")); jtkorhonen@0: jtkorhonen@0: remoteRepoPath = ""; jtkorhonen@0: workFolderPath = ""; jtkorhonen@0: jtkorhonen@0: readSettings(); jtkorhonen@0: jtkorhonen@0: tabPage = 0; jtkorhonen@33: justMerged = false; Chris@96: hgExp = new HgTabWidget((QWidget *) this, remoteRepoPath, workFolderPath); jtkorhonen@0: setCentralWidget(hgExp); jtkorhonen@0: Chris@95: connect(hgExp, SIGNAL(selectionChanged()), Chris@95: this, SLOT(enableDisableActions())); Chris@95: jtkorhonen@0: setUnifiedTitleAndToolBarOnMac(true); jtkorhonen@0: connectActions(); jtkorhonen@0: enableDisableActions(); jtkorhonen@0: Chris@64: if (firstStart) { Chris@64: startupDialog(); jtkorhonen@0: } jtkorhonen@0: Chris@64: ColourSet *cs = ColourSet::instance(); Chris@64: cs->clearDefaultNames(); Chris@64: cs->addDefaultName(""); Chris@64: cs->addDefaultName(getUserInfo()); Chris@62: Chris@72: if (workFolderPath == "") { Chris@72: open(); Chris@72: } Chris@72: Chris@74: hgPaths(); jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: void MainWindow::closeEvent(QCloseEvent *) jtkorhonen@0: { jtkorhonen@0: writeSettings(); Chris@90: delete fsWatcher; jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: Chris@64: QString MainWindow::getUserInfo() const Chris@64: { Chris@64: QSettings settings; Chris@64: settings.beginGroup("User Information"); Chris@64: QString name = settings.value("name", getUserRealName()).toString(); Chris@64: QString email = settings.value("email", "").toString(); Chris@64: Chris@64: QString identifier; Chris@64: Chris@64: if (email != "") { Chris@64: identifier = QString("%1 <%2>").arg(name).arg(email); Chris@64: } else { Chris@64: identifier = name; Chris@64: } Chris@64: Chris@64: return identifier; Chris@64: } Chris@64: jtkorhonen@0: void MainWindow::about() jtkorhonen@0: { Chris@97: QMessageBox::about(this, tr("About EasyMercurial"), Chris@97: tr("

About EasyMercurial

" Chris@97: "

EasyMercurial is a simple user interface for the " Chris@97: "Mercurial version control system.

" Chris@97: "

EasyMercurial is based on HgExplorer by " Chris@97: "Jari Korhonen, with thanks.
EasyMercurial development carried out by " Chris@97: "Chris Cannam for soundsoftware.ac.uk at the Centre for Digital Music, Queen Mary, University of London." Chris@97: "

  • Copyright © 2010 Jari Korhonen
  • " Chris@97: "
  • Copyright © 2010 Chris Cannam
  • " Chris@97: "
  • Copyright © 2010 Queen Mary, University of London
  • " Chris@97: "
" Chris@97: "

This program is free software; you can redistribute it and/or " Chris@97: "modify it under the terms of the GNU General Public License as " Chris@97: "published by the Free Software Foundation; either version 2 of the " Chris@97: "License, or (at your option) any later version. See the file " Chris@97: "COPYING included with this distribution for more information.")); jtkorhonen@0: } jtkorhonen@0: Chris@94: void MainWindow::clearSelections() Chris@94: { Chris@94: hgExp->clearSelections(); Chris@94: } jtkorhonen@0: jtkorhonen@0: void MainWindow::hgStat() jtkorhonen@0: { Chris@73: if (runningAction == ACT_NONE) jtkorhonen@0: { Chris@73: QStringList params; Chris@73: Chris@91: params << "stat" << "-ardum"; Chris@73: Chris@73: runner -> startHgCommand(workFolderPath, params); Chris@73: runningAction = ACT_STAT; jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: Chris@74: void MainWindow::hgPaths() Chris@74: { Chris@74: if (runningAction == ACT_NONE) Chris@74: { Chris@74: QStringList params; Chris@74: params << "paths"; Chris@74: runner -> startHgCommand(workFolderPath, params); Chris@74: runningAction = ACT_PATHS; Chris@74: } Chris@74: } Chris@74: jtkorhonen@0: void MainWindow::hgHeads() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; jtkorhonen@0: params << "heads"; jtkorhonen@0: jtkorhonen@0: //on empty repos, "hg heads" will fail, don't care of that. Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_HEADS; jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: void MainWindow::hgLog() jtkorhonen@0: { Chris@90: //!!! This needs to be incremental, except when we pull or set new repo jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; Chris@43: params << "log"; Chris@43: params << "--template"; Chris@52: params << "id: {rev}:{node|short}\\nauthor: {author}\\nbranch: {branches}\\ntag: {tag}\\ndatetime: {date|isodate}\\ntimestamp: {date|hgdate}\\nage: {date|age}\\nparents: {parents}\\ncomment: {desc|json}\\n\\n"; jtkorhonen@0: Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_LOG; jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: void MainWindow::hgParents() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; jtkorhonen@0: params << "parents"; jtkorhonen@0: Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_PARENTS; jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: void MainWindow::hgRemove() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; Chris@91: QString currentFile;//!!! = hgExp -> getCurrentFileListLine(); jtkorhonen@0: jtkorhonen@0: if (!currentFile.isEmpty()) jtkorhonen@0: { jtkorhonen@6: if (QMessageBox::Ok == QMessageBox::warning(this, "Remove file", "Really remove file " + currentFile.mid(2) + "?", jtkorhonen@6: QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel)) jtkorhonen@6: { mg@41: params << "remove" << "--after" << "--force" << "--" << currentFile.mid(2); //Jump over status marker characters (e.g "M ") jtkorhonen@0: Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@6: runningAction = ACT_REMOVE; jtkorhonen@6: } jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: void MainWindow::hgAnnotate() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; Chris@91: QString currentFile;//!!! = hgExp -> getCurrentFileListLine(); jtkorhonen@0: jtkorhonen@0: if (!currentFile.isEmpty()) jtkorhonen@0: { mg@41: params << "annotate" << "--" << currentFile.mid(2); //Jump over status marker characters (e.g "M ") jtkorhonen@0: Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_ANNOTATE; jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: void MainWindow::hgResolveMark() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; Chris@91: QString currentFile;//!!! = hgExp -> getCurrentFileListLine(); jtkorhonen@0: jtkorhonen@0: if (!currentFile.isEmpty()) jtkorhonen@0: { mg@41: params << "resolve" << "--mark" << "--" << currentFile.mid(2); //Jump over status marker characters (e.g "M ") jtkorhonen@0: Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_RESOLVE_MARK; jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: void MainWindow::hgResolveList() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; jtkorhonen@0: jtkorhonen@0: params << "resolve" << "--list"; Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_RESOLVE_LIST; jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: void MainWindow::hgAdd() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; jtkorhonen@0: Chris@91: QString currentFile;//!!! = hgExp -> getCurrentFileListLine(); Chris@91: /*!!! jtkorhonen@17: if (areAllSelectedUntracked(hgExp -> workFolderFileList)) jtkorhonen@5: { jtkorhonen@17: //User wants to add selected file(s) jtkorhonen@42: params << "add" << "--"; jtkorhonen@17: jtkorhonen@17: QList selList = hgExp -> workFolderFileList -> selectedItems(); jtkorhonen@17: jtkorhonen@17: for (int i = 0; i < selList.size(); ++i) jtkorhonen@17: { jtkorhonen@17: QString tmp = selList.at(i)->text(); jtkorhonen@17: params.append(tmp.mid(2)); jtkorhonen@17: } jtkorhonen@5: } jtkorhonen@5: else jtkorhonen@5: { jtkorhonen@5: //Add all untracked files jtkorhonen@5: params << "add"; jtkorhonen@5: } jtkorhonen@0: Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_ADD; Chris@91: */ jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: Chris@90: bool MainWindow::getCommentOrTag(QString& commentOrTag, Chris@90: QString question, Chris@90: QString dlgTitle) jtkorhonen@0: { Chris@90: bool ok = false; Chris@90: QString text = QInputDialog::getText(this, dlgTitle, question, QLineEdit::Normal, commentOrTag, &ok); Chris@90: commentOrTag = text; Chris@90: return ok; Chris@90: Chris@90: /*!!! jtkorhonen@0: int ret; jtkorhonen@0: jtkorhonen@0: QDialog dlg(this); jtkorhonen@0: jtkorhonen@34: QLabel *commentLabel = new QLabel(question); jtkorhonen@34: QLineEdit *commentOrTagEdit = new QLineEdit; jtkorhonen@34: commentOrTagEdit -> setFixedWidth(400); jtkorhonen@0: QHBoxLayout *commentLayout = new QHBoxLayout; jtkorhonen@0: commentLayout -> addWidget(commentLabel); jtkorhonen@34: commentLayout -> addWidget(commentOrTagEdit); jtkorhonen@0: jtkorhonen@0: QPushButton *btnOk = new QPushButton(tr("Ok")); jtkorhonen@0: QPushButton *btnCancel = new QPushButton(tr("Cancel")); jtkorhonen@0: QHBoxLayout *btnLayout = new QHBoxLayout; jtkorhonen@0: btnLayout -> addWidget(btnOk); jtkorhonen@0: btnLayout -> addWidget(btnCancel); jtkorhonen@0: jtkorhonen@0: QVBoxLayout *mainLayout = new QVBoxLayout; jtkorhonen@0: mainLayout -> addLayout(commentLayout); jtkorhonen@0: mainLayout -> addLayout(btnLayout); jtkorhonen@0: jtkorhonen@0: dlg.setLayout(mainLayout); jtkorhonen@0: jtkorhonen@34: dlg.setWindowTitle(dlgTitle); jtkorhonen@0: jtkorhonen@0: connect(btnOk, SIGNAL(clicked()), &dlg, SLOT(accept())); jtkorhonen@0: connect(btnCancel, SIGNAL(clicked()), &dlg, SLOT(reject())); jtkorhonen@0: jtkorhonen@0: ret = dlg.exec(); jtkorhonen@34: commentOrTag = commentOrTagEdit -> text(); jtkorhonen@0: return ret; Chris@90: */ jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: void MainWindow::hgCommit() jtkorhonen@0: { Chris@94: //!!! Now that hg actions can be fired asynchronously (e.g. from Chris@94: // the filesystem modified callback) we _really_ need to be able to Chris@94: // queue important actions rather than just ignore them if busy! Chris@94: jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; jtkorhonen@0: QString comment; jtkorhonen@0: Chris@90: if (getCommentOrTag(comment, tr("Comment:"), tr("Save (commit)"))) jtkorhonen@0: { jtkorhonen@0: if (!comment.isEmpty()) jtkorhonen@0: { Chris@91: /*!!! jtkorhonen@33: if ((justMerged == false) && (areAllSelectedCommitable(hgExp -> workFolderFileList))) jtkorhonen@11: { jtkorhonen@33: //User wants to commit selected file(s) (and this is not merge commit, which would fail if we selected files) Chris@64: params << "commit" << "--message" << comment << "--user" << getUserInfo() << "--"; jtkorhonen@17: jtkorhonen@17: QList selList = hgExp -> workFolderFileList -> selectedItems(); jtkorhonen@17: for (int i = 0; i < selList.size(); ++i) jtkorhonen@17: { jtkorhonen@17: QString tmp = selList.at(i)->text(); jtkorhonen@17: params.append(tmp.mid(2)); jtkorhonen@17: } jtkorhonen@11: } jtkorhonen@11: else jtkorhonen@11: { jtkorhonen@11: //Commit all changes Chris@64: params << "commit" << "--message" << comment << "--user" << getUserInfo(); jtkorhonen@11: } jtkorhonen@0: Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_COMMIT; Chris@91: */ jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@34: QString MainWindow::filterTag(QString tag) jtkorhonen@34: { jtkorhonen@34: for(int i = 0; i < tag.size(); i++) jtkorhonen@34: { jtkorhonen@34: if (tag[i].isLower() || tag[i].isUpper() || tag[i].isDigit() || (tag[i] == QChar('.'))) jtkorhonen@34: { jtkorhonen@34: //ok jtkorhonen@34: } jtkorhonen@34: else jtkorhonen@34: { jtkorhonen@34: tag[i] = QChar('_'); jtkorhonen@34: } jtkorhonen@34: } jtkorhonen@34: return tag; jtkorhonen@34: } jtkorhonen@34: jtkorhonen@34: jtkorhonen@34: void MainWindow::hgTag() jtkorhonen@34: { jtkorhonen@34: if (runningAction == ACT_NONE) jtkorhonen@34: { jtkorhonen@34: QStringList params; jtkorhonen@34: QString tag; jtkorhonen@34: Chris@90: if (getCommentOrTag(tag, tr("Tag:"), tr("Tag"))) jtkorhonen@34: { jtkorhonen@34: if (!tag.isEmpty()) jtkorhonen@34: { Chris@64: params << "tag" << "--user" << getUserInfo() << filterTag(tag); jtkorhonen@34: Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@34: runningAction = ACT_TAG; jtkorhonen@34: } jtkorhonen@34: } jtkorhonen@34: } jtkorhonen@34: } jtkorhonen@34: jtkorhonen@34: jtkorhonen@34: void MainWindow::hgIgnore() jtkorhonen@34: { jtkorhonen@34: if (runningAction == ACT_NONE) jtkorhonen@34: { jtkorhonen@34: QString hgIgnorePath; jtkorhonen@36: QStringList params; jtkorhonen@36: QString editorName; jtkorhonen@34: jtkorhonen@36: hgIgnorePath = workFolderPath; jtkorhonen@34: hgIgnorePath += ".hgignore"; jtkorhonen@34: jtkorhonen@36: params << hgIgnorePath; jtkorhonen@36: jtkorhonen@36: if ((getSystem() == "Linux")) jtkorhonen@36: { jtkorhonen@36: editorName = "gedit"; jtkorhonen@36: } jtkorhonen@36: else jtkorhonen@36: { jtkorhonen@36: editorName = """C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe"""; jtkorhonen@36: } jtkorhonen@36: Chris@62: runner -> startCommand(editorName, workFolderPath, params); jtkorhonen@36: runningAction = ACT_HG_IGNORE; jtkorhonen@34: } jtkorhonen@34: } jtkorhonen@34: jtkorhonen@34: jtkorhonen@34: jtkorhonen@0: void MainWindow::hgFileDiff() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; Chris@91: /*!!! jtkorhonen@0: QString currentFile = hgExp -> getCurrentFileListLine(); jtkorhonen@0: jtkorhonen@0: if (!currentFile.isEmpty()) jtkorhonen@0: { jtkorhonen@0: //Diff parent file against working folder file mg@41: params << "kdiff3" << "--" << currentFile.mid(2); Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_FILEDIFF; jtkorhonen@0: } Chris@91: */ jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: void MainWindow::hgFolderDiff() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; jtkorhonen@0: jtkorhonen@0: //Diff parent against working folder (folder diff) jtkorhonen@0: params << "kdiff3"; Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_FOLDERDIFF; jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: void MainWindow::hgChgSetDiff() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; jtkorhonen@0: jtkorhonen@0: //Diff 2 history log versions against each other jtkorhonen@0: QString revA; jtkorhonen@0: QString revB; Chris@91: /*!!! jtkorhonen@0: hgExp -> getHistoryDiffRevisions(revA, revB); jtkorhonen@0: jtkorhonen@0: if ((!revA.isEmpty()) && (!revB.isEmpty())) jtkorhonen@0: { jtkorhonen@0: params << "kdiff3" << "--rev" << revA << "--rev" << revB; Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_CHGSETDIFF; jtkorhonen@0: } jtkorhonen@0: else jtkorhonen@0: { jtkorhonen@0: QMessageBox::information(this, tr("Changeset diff"), tr("Please select two changesets from history list or heads list first.")); jtkorhonen@0: } Chris@91: */ jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: void MainWindow::hgUpdate() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: params << "update"; jtkorhonen@0: jtkorhonen@0: Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_UPDATE; jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: void MainWindow::hgUpdateToRev() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; jtkorhonen@0: QString rev; Chris@91: /*!!! jtkorhonen@0: hgExp -> getUpdateToRevRevision(rev); jtkorhonen@0: jtkorhonen@0: hgExp -> setCurrentIndex(WORKTAB); jtkorhonen@0: enableDisableActions(); jtkorhonen@0: jtkorhonen@0: params << "update" << "--rev" << rev << "--clean"; jtkorhonen@0: Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: jtkorhonen@0: runningAction = ACT_UPDATE; Chris@91: */ jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: void MainWindow::hgRevert() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { Chris@91: /*!!! jtkorhonen@0: QStringList params; jtkorhonen@0: QString currentFile = hgExp -> getCurrentFileListLine(); jtkorhonen@0: mg@41: params << "revert" << "--no-backup" << "--" << currentFile.mid(2); jtkorhonen@0: Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_REVERT; Chris@91: */ jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@33: void MainWindow::hgRetryMerge() jtkorhonen@33: { jtkorhonen@33: if (runningAction == ACT_NONE) jtkorhonen@33: { jtkorhonen@33: QStringList params; jtkorhonen@33: jtkorhonen@33: params << "resolve" << "--all"; Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@33: runningAction = ACT_RETRY_MERGE; jtkorhonen@33: } jtkorhonen@33: } jtkorhonen@33: jtkorhonen@33: jtkorhonen@0: void MainWindow::hgMerge() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; jtkorhonen@0: jtkorhonen@0: params << "merge"; jtkorhonen@0: Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_MERGE; jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: void MainWindow::hgCloneFromRemote() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; jtkorhonen@0: jtkorhonen@0: params << "clone" << remoteRepoPath << workFolderPath; jtkorhonen@0: Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_CLONEFROMREMOTE; jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: void MainWindow::hgInit() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; jtkorhonen@0: jtkorhonen@0: params << "init"; Chris@84: params << workFolderPath; jtkorhonen@0: Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_INIT; jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: void MainWindow::hgIncoming() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; jtkorhonen@0: jtkorhonen@0: params << "incoming" << "--newest-first" << remoteRepoPath; jtkorhonen@0: Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_INCOMING; jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: void MainWindow::hgPull() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; jtkorhonen@0: jtkorhonen@0: params << "pull" << remoteRepoPath; jtkorhonen@0: Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_PULL; jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: void MainWindow::hgPush() jtkorhonen@0: { jtkorhonen@0: if (runningAction == ACT_NONE) jtkorhonen@0: { jtkorhonen@0: QStringList params; jtkorhonen@0: jtkorhonen@0: params << "push" << remoteRepoPath; jtkorhonen@0: Chris@62: runner -> startHgCommand(workFolderPath, params); jtkorhonen@0: runningAction = ACT_PUSH; jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@28: QString MainWindow::listAllUpIpV4Addresses() jtkorhonen@26: { jtkorhonen@28: QString ret; jtkorhonen@26: QList ifaces = QNetworkInterface::allInterfaces(); jtkorhonen@26: jtkorhonen@26: for (int i = 0; i < ifaces.count(); i++) jtkorhonen@26: { jtkorhonen@26: QNetworkInterface iface = ifaces.at(i); jtkorhonen@26: jtkorhonen@26: if (iface.flags().testFlag(QNetworkInterface::IsUp) && !iface.flags().testFlag(QNetworkInterface::IsLoopBack)) jtkorhonen@26: { jtkorhonen@26: for (int j=0; j startHgCommand(workFolderPath, params); jtkorhonen@11: runningAction = ACT_SERVE; jtkorhonen@11: jtkorhonen@17: QMessageBox::information(this, "Serve", msg, QMessageBox::Close); Chris@62: runner -> killCurrentCommand(); jtkorhonen@11: } jtkorhonen@11: } jtkorhonen@11: jtkorhonen@11: Chris@64: void MainWindow::startupDialog() Chris@64: { Chris@64: StartupDialog *dlg = new StartupDialog(this); Chris@65: if (dlg->exec()) firstStart = false; Chris@64: } Chris@64: jtkorhonen@11: Chris@69: void MainWindow::open() Chris@69: { Chris@86: bool done = false; Chris@69: Chris@86: while (!done) { Chris@69: Chris@86: MultiChoiceDialog *d = new MultiChoiceDialog Chris@86: (tr("Open Repository"), Chris@86: tr("What would you like to open?"), Chris@86: this); Chris@69: Chris@86: d->addChoice("remote", Chris@86: tr("


Remote repository
"), Chris@86: tr("Open a remote Mercurial repository, by cloning from its URL into a local folder."), Chris@86: MultiChoiceDialog::UrlToDirectoryArg); Chris@69: Chris@86: d->addChoice("local", Chris@86: tr("

Local repository
"), Chris@86: tr("Open an existing local Mercurial repository."), Chris@86: MultiChoiceDialog::DirectoryArg); Chris@69: Chris@86: d->addChoice("init", Chris@86: tr("

File folder
"), Chris@86: tr("Open a local folder, by creating a Mercurial repository in it."), Chris@86: MultiChoiceDialog::DirectoryArg); Chris@79: Chris@86: d->setCurrentChoice("local"); Chris@86: Chris@86: if (d->exec() == QDialog::Accepted) { Chris@86: Chris@86: QString choice = d->getCurrentChoice(); Chris@86: QString arg = d->getArgument().trimmed(); Chris@86: Chris@86: bool result = false; Chris@86: Chris@86: if (choice == "local") { Chris@86: result = openLocal(arg); Chris@86: } else if (choice == "remote") { Chris@86: result = openRemote(arg, d->getAdditionalArgument().trimmed()); Chris@86: } else if (choice == "init") { Chris@86: result = openInit(arg); Chris@86: } Chris@86: Chris@86: if (result) { Chris@86: enableDisableActions(); Chris@86: hgPaths(); Chris@91: done = true; Chris@91: } Chris@86: Chris@86: } else { Chris@86: Chris@86: // cancelled Chris@86: done = true; Chris@69: } Chris@79: Chris@86: delete d; Chris@69: } Chris@69: } Chris@69: Chris@79: bool MainWindow::complainAboutFilePath(QString arg) Chris@79: { Chris@79: QMessageBox::critical Chris@79: (this, tr("File chosen"), Chris@84: tr("Folder required

You asked to open \"%1\".
This is a file; to open a repository, you need to choose a folder.
").arg(xmlEncode(arg))); Chris@79: return false; Chris@79: } Chris@79: Chris@79: bool MainWindow::complainAboutUnknownFolder(QString arg) Chris@79: { Chris@79: QMessageBox::critical Chris@79: (this, tr("Folder does not exist"), Chris@84: tr("Folder does not exist

You asked to open \"%1\".
This folder does not exist, and it cannot be created because its parent does not exist either.
").arg(xmlEncode(arg))); Chris@84: return false; Chris@84: } Chris@84: Chris@84: bool MainWindow::complainAboutInitInRepo(QString arg) Chris@84: { Chris@84: QMessageBox::critical Chris@84: (this, tr("Path is in existing repository"), Chris@84: tr("Path is in an existing repository

You asked to initialise a repository at \"%1\".
This path is already inside an existing repository.
").arg(xmlEncode(arg))); Chris@84: return false; Chris@84: } Chris@84: Chris@84: bool MainWindow::complainAboutInitFile(QString arg) Chris@84: { Chris@84: QMessageBox::critical Chris@84: (this, tr("Path is a file"), Chris@84: tr("Path is a file

You asked to initialise a repository at \"%1\".
This is an existing file; it is only possible to initialise in folders.
").arg(xmlEncode(arg))); Chris@84: return false; Chris@84: } Chris@84: Chris@84: bool MainWindow::complainAboutCloneToExisting(QString arg) Chris@84: { Chris@84: QMessageBox::critical Chris@84: (this, tr("Path is in existing repository"), Chris@84: tr("Local path is in an existing repository

You asked to open a remote repository by cloning it to the local path \"%1\".
This path is already inside an existing repository.
Please provide a new folder name for the local repository.
").arg(xmlEncode(arg))); Chris@84: return false; Chris@84: } Chris@84: Chris@84: bool MainWindow::complainAboutCloneToFile(QString arg) Chris@84: { Chris@84: QMessageBox::critical Chris@84: (this, tr("Path is a file"), Chris@84: tr("Local path is a file

You asked to open a remote repository by cloning it to the local path \"%1\".
This path is an existing file.
Please provide a new folder name for the local repository.
").arg(xmlEncode(arg))); Chris@84: return false; Chris@84: } Chris@84: Chris@84: bool MainWindow::complainAboutCloneToExistingFolder(QString arg) Chris@84: { Chris@84: QMessageBox::critical Chris@84: (this, tr("Folder exists"), Chris@84: tr("Local folder already exists

You asked to open a remote repository by cloning it to the local path \"%1\".
This is the path of an existing folder.
Please provide a new folder name for the local repository.
").arg(xmlEncode(arg))); Chris@79: return false; Chris@79: } Chris@79: Chris@79: bool MainWindow::askToOpenParentRepo(QString arg, QString parent) Chris@79: { Chris@79: return (QMessageBox::question Chris@84: (this, tr("Path is inside a repository"), Chris@86: tr("Open the repository that contains this path?

You asked to open \"%1\".
This is not the root folder of a repository.
But it is inside a repository, whose root is at \"%2\".

Would you like to open that repository instead?
") Chris@79: .arg(xmlEncode(arg)).arg(xmlEncode(parent)), Chris@79: QMessageBox::Ok | QMessageBox::Cancel, Chris@79: QMessageBox::Ok) Chris@79: == QMessageBox::Ok); Chris@79: } Chris@79: Chris@79: bool MainWindow::askToInitExisting(QString arg) Chris@79: { Chris@79: return (QMessageBox::question Chris@84: (this, tr("Folder has no repository"), Chris@84: tr("Initialise a repository here?

You asked to open \"%1\".
This folder does not contain a Mercurial repository.

Would you like to initialise a repository here?
") Chris@79: .arg(xmlEncode(arg)), Chris@79: QMessageBox::Ok | QMessageBox::Cancel, Chris@79: QMessageBox::Ok) Chris@79: == QMessageBox::Ok); Chris@79: } Chris@79: Chris@79: bool MainWindow::askToInitNew(QString arg) Chris@79: { Chris@79: return (QMessageBox::question Chris@84: (this, tr("Folder does not exist"), Chris@84: tr("Initialise a new repository?

You asked to open \"%1\".
This folder does not yet exist.

Would you like to create the folder and initialise a new empty repository in it?
") Chris@84: .arg(xmlEncode(arg)), Chris@84: QMessageBox::Ok | QMessageBox::Cancel, Chris@84: QMessageBox::Ok) Chris@84: == QMessageBox::Ok); Chris@84: } Chris@84: Chris@84: bool MainWindow::askToOpenInsteadOfInit(QString arg) Chris@84: { Chris@84: return (QMessageBox::question Chris@84: (this, tr("Repository exists"), Chris@84: tr("Open existing repository?

You asked to initialise a new repository at \"%1\".
This folder already contains a repository. Would you like to open it?
") Chris@79: .arg(xmlEncode(arg)), Chris@79: QMessageBox::Ok | QMessageBox::Cancel, Chris@79: QMessageBox::Ok) Chris@79: == QMessageBox::Ok); Chris@79: } Chris@79: Chris@79: bool MainWindow::openLocal(QString local) Chris@79: { Chris@79: DEBUG << "open " << local << endl; Chris@79: Chris@79: FolderStatus status = getFolderStatus(local); Chris@79: QString containing = getContainingRepoFolder(local); Chris@79: Chris@79: switch (status) { Chris@79: Chris@79: case FolderHasRepo: Chris@79: // fine Chris@79: break; Chris@79: Chris@79: case FolderExists: Chris@79: if (containing != "") { Chris@79: if (!askToOpenParentRepo(local, containing)) return false; Chris@84: local = containing; Chris@79: } else { Chris@86: //!!! No -- this is likely to happen far more by accident Chris@86: // than because the user actually wanted to init something. Chris@86: // Don't ask, just politely reject. Chris@79: if (!askToInitExisting(local)) return false; Chris@79: return openInit(local); Chris@79: } Chris@79: break; Chris@79: Chris@79: case FolderParentExists: Chris@79: if (containing != "") { Chris@79: if (!askToOpenParentRepo(local, containing)) return false; Chris@84: local = containing; Chris@79: } else { Chris@79: if (!askToInitNew(local)) return false; Chris@79: return openInit(local); Chris@79: } Chris@79: break; Chris@79: Chris@79: case FolderUnknown: Chris@84: if (containing != "") { Chris@84: if (!askToOpenParentRepo(local, containing)) return false; Chris@84: local = containing; Chris@84: } else { Chris@84: return complainAboutUnknownFolder(local); Chris@84: } Chris@84: break; Chris@79: Chris@79: case FolderIsFile: Chris@79: return complainAboutFilePath(local); Chris@79: } Chris@79: Chris@79: workFolderPath = local; Chris@79: remoteRepoPath = ""; Chris@79: return true; Chris@79: } Chris@79: Chris@79: bool MainWindow::openRemote(QString remote, QString local) Chris@79: { Chris@79: DEBUG << "clone " << remote << " to " << local << endl; Chris@84: Chris@84: FolderStatus status = getFolderStatus(local); Chris@84: QString containing = getContainingRepoFolder(local); Chris@84: Chris@84: DEBUG << "status = " << status << ", containing = " << containing << endl; Chris@84: Chris@84: if (status == FolderHasRepo || containing != "") { Chris@84: return complainAboutCloneToExisting(local); Chris@84: } Chris@84: Chris@84: if (status == FolderIsFile) { Chris@84: return complainAboutCloneToFile(local); Chris@84: } Chris@84: Chris@84: if (status == FolderUnknown) { Chris@84: return complainAboutUnknownFolder(local); Chris@84: } Chris@84: Chris@84: if (status == FolderExists) { Chris@84: //!!! we can do better than this surely? Chris@84: return complainAboutCloneToExistingFolder(local); Chris@84: } Chris@84: Chris@84: workFolderPath = local; Chris@84: remoteRepoPath = remote; Chris@84: hgCloneFromRemote(); Chris@84: Chris@79: return true; Chris@79: } Chris@79: Chris@84: bool MainWindow::openInit(QString local) Chris@79: { Chris@84: DEBUG << "openInit " << local << endl; Chris@84: Chris@84: FolderStatus status = getFolderStatus(local); Chris@84: QString containing = getContainingRepoFolder(local); Chris@84: Chris@84: DEBUG << "status = " << status << ", containing = " << containing << endl; Chris@84: Chris@84: if (status == FolderHasRepo) { Chris@84: if (!askToOpenInsteadOfInit(local)) return false; Chris@84: } Chris@84: Chris@84: if (containing != "") { Chris@84: return complainAboutInitInRepo(local); Chris@84: } Chris@84: Chris@84: if (status == FolderIsFile) { Chris@84: return complainAboutInitFile(local); Chris@84: } Chris@84: Chris@84: if (status == FolderUnknown) { Chris@84: return complainAboutUnknownFolder(local); Chris@84: } Chris@84: Chris@84: workFolderPath = local; Chris@84: remoteRepoPath = ""; Chris@84: hgInit(); Chris@79: return true; Chris@79: } Chris@79: jtkorhonen@0: void MainWindow::settings() jtkorhonen@0: { Chris@69: /*!!! jtkorhonen@0: SettingsDialog *settingsDlg = new SettingsDialog(this); jtkorhonen@0: settingsDlg->setModal(true); jtkorhonen@0: settingsDlg->exec(); jtkorhonen@0: hgExp -> clearLists(); jtkorhonen@0: enableDisableActions(); jtkorhonen@0: hgStat(); Chris@69: */ jtkorhonen@0: } jtkorhonen@0: jtkorhonen@2: #define STDOUT_NEEDS_BIG_WINDOW 512 jtkorhonen@2: #define SMALL_WND_W 500 jtkorhonen@2: #define SMALL_WND_H 300 jtkorhonen@2: jtkorhonen@2: #define BIG_WND_W 1024 jtkorhonen@2: #define BIG_WND_H 768 jtkorhonen@2: jtkorhonen@2: jtkorhonen@2: void MainWindow::presentLongStdoutToUser(QString stdo) jtkorhonen@0: { jtkorhonen@2: if (!stdo.isEmpty()) jtkorhonen@2: { jtkorhonen@2: QDialog dlg; jtkorhonen@0: jtkorhonen@2: if (stdo.length() > STDOUT_NEEDS_BIG_WINDOW) jtkorhonen@2: { jtkorhonen@2: dlg.setMinimumWidth(BIG_WND_W); jtkorhonen@2: dlg.setMinimumHeight(BIG_WND_H); jtkorhonen@2: } jtkorhonen@2: else jtkorhonen@2: { jtkorhonen@2: dlg.setMinimumWidth(SMALL_WND_W); jtkorhonen@2: dlg.setMinimumHeight(SMALL_WND_H); jtkorhonen@2: } jtkorhonen@0: jtkorhonen@2: QVBoxLayout *box = new QVBoxLayout; jtkorhonen@2: QListWidget *list = new QListWidget; jtkorhonen@2: list-> addItems(stdo.split("\n")); jtkorhonen@2: QPushButton *btn = new QPushButton(tr("Ok")); jtkorhonen@2: connect(btn, SIGNAL(clicked()), &dlg, SLOT(accept())); jtkorhonen@0: jtkorhonen@2: box -> addWidget(list); jtkorhonen@2: box -> addWidget(btn); jtkorhonen@2: dlg.setLayout(box); jtkorhonen@2: jtkorhonen@2: dlg.exec(); jtkorhonen@2: } jtkorhonen@2: else jtkorhonen@2: { jtkorhonen@2: QMessageBox::information(this, tr("HgExplorer"), tr("Mercurial command did not return any output.")); jtkorhonen@2: } jtkorhonen@0: } jtkorhonen@0: Chris@90: void MainWindow::updateFileSystemWatcher() Chris@90: { Chris@90: //!!! this needs to be incremental when something changes Chris@90: Chris@90: delete fsWatcher; Chris@90: fsWatcher = new QFileSystemWatcher(); Chris@90: std::deque pending; Chris@90: pending.push_back(workFolderPath); Chris@90: while (!pending.empty()) { Chris@90: QString path = pending.front(); Chris@90: pending.pop_front(); Chris@90: fsWatcher->addPath(path); Chris@90: DEBUG << "Added to file system watcher: " << path << endl; Chris@90: QDir d(path); Chris@90: if (d.exists()) { Chris@90: d.setFilter(QDir::Files | QDir::Dirs | Chris@90: QDir::NoDotAndDotDot | QDir::Readable); Chris@90: foreach (QString entry, d.entryList()) { Chris@90: if (entry == ".hg") continue; Chris@90: QString entryPath = d.absoluteFilePath(entry); Chris@90: pending.push_back(entryPath); Chris@90: } Chris@90: } Chris@90: } Chris@90: connect(fsWatcher, SIGNAL(directoryChanged(QString)), Chris@90: this, SLOT(fsDirectoryChanged(QString))); Chris@90: connect(fsWatcher, SIGNAL(fileChanged(QString)), Chris@90: this, SLOT(fsFileChanged(QString))); Chris@90: } Chris@90: Chris@90: void MainWindow::fsDirectoryChanged(QString) Chris@90: { Chris@90: //!!! should just queue one of these! Chris@90: hgStat(); Chris@90: } Chris@90: Chris@90: void MainWindow::fsFileChanged(QString) Chris@90: { Chris@90: //!!! should just queue one of these! Chris@90: hgStat(); Chris@90: } Chris@90: Chris@62: void MainWindow::commandFailed() Chris@62: { Chris@62: DEBUG << "MainWindow::commandFailed" << endl; Chris@74: runningAction = ACT_NONE; Chris@74: runner -> hideProgBar(); Chris@74: Chris@79: //!!! N.B hg incoming returns 1 even if successful, if there were no changes Chris@62: } Chris@62: Chris@62: void MainWindow::commandCompleted() jtkorhonen@0: { jtkorhonen@0: bool shouldHgStat = false; jtkorhonen@0: jtkorhonen@0: if (runningAction != ACT_NONE) jtkorhonen@0: { jtkorhonen@0: //We are running some hg command... Chris@62: if (runner -> isCommandRunning() == false) jtkorhonen@0: { jtkorhonen@0: //Running has just ended. jtkorhonen@0: int exitCode = runner -> getExitCode(); jtkorhonen@0: jtkorhonen@0: runner -> hideProgBar(); jtkorhonen@0: jtkorhonen@0: //Clumsy... jtkorhonen@0: if ((EXITOK(exitCode)) || ((exitCode == 1) && (runningAction == ACT_INCOMING))) jtkorhonen@0: { jtkorhonen@0: //Successful running. jtkorhonen@0: switch(runningAction) jtkorhonen@0: { Chris@74: case ACT_PATHS: Chris@74: { Chris@84: QString sout = runner->getOutput(); Chris@76: DEBUG << "stdout is " << sout << endl; Chris@76: LogParser lp(sout, "="); Chris@74: LogList ll = lp.parse(); Chris@74: DEBUG << ll.size() << " results" << endl; Chris@74: if (!ll.empty()) { Chris@74: remoteRepoPath = lp.parse()[0]["default"].trimmed(); Chris@74: DEBUG << "Set remote path to " << remoteRepoPath << endl; Chris@74: } Chris@74: MultiChoiceDialog::addRecentArgument("local", workFolderPath); Chris@74: MultiChoiceDialog::addRecentArgument("remote", remoteRepoPath); Chris@74: enableDisableActions(); Chris@74: break; Chris@74: } Chris@74: jtkorhonen@0: case ACT_STAT: Chris@84: hgExp -> updateWorkFolderFileList(runner -> getOutput()); Chris@90: updateFileSystemWatcher(); jtkorhonen@0: break; jtkorhonen@0: jtkorhonen@0: case ACT_INCOMING: jtkorhonen@0: case ACT_ANNOTATE: jtkorhonen@0: case ACT_RESOLVE_LIST: jtkorhonen@0: case ACT_RESOLVE_MARK: Chris@84: presentLongStdoutToUser(runner -> getOutput()); jtkorhonen@0: shouldHgStat = true; jtkorhonen@0: break; jtkorhonen@0: jtkorhonen@0: case ACT_PULL: Chris@84: QMessageBox::information(this, "Pull", runner -> getOutput()); jtkorhonen@0: shouldHgStat = true; jtkorhonen@0: break; jtkorhonen@0: jtkorhonen@0: case ACT_PUSH: Chris@84: QMessageBox::information(this, "Push", runner -> getOutput()); jtkorhonen@0: shouldHgStat = true; jtkorhonen@0: break; jtkorhonen@0: jtkorhonen@0: case ACT_INIT: Chris@69: MultiChoiceDialog::addRecentArgument("init", workFolderPath); Chris@69: MultiChoiceDialog::addRecentArgument("local", workFolderPath); jtkorhonen@0: enableDisableActions(); jtkorhonen@0: shouldHgStat = true; jtkorhonen@0: break; jtkorhonen@0: jtkorhonen@0: case ACT_CLONEFROMREMOTE: Chris@69: MultiChoiceDialog::addRecentArgument("local", workFolderPath); Chris@69: MultiChoiceDialog::addRecentArgument("remote", remoteRepoPath); Chris@72: MultiChoiceDialog::addRecentArgument("remote", workFolderPath, true); Chris@84: QMessageBox::information(this, "Clone", runner -> getOutput()); jtkorhonen@0: enableDisableActions(); jtkorhonen@0: shouldHgStat = true; jtkorhonen@0: break; jtkorhonen@0: jtkorhonen@0: case ACT_LOG: Chris@91: hgExp -> updateLocalRepoHgLogList(runner -> getOutput()); jtkorhonen@0: break; jtkorhonen@0: jtkorhonen@0: case ACT_PARENTS: jtkorhonen@0: { Chris@91: //!!! hgExp -> updateLocalRepoParentsList(runner -> getOutput()); jtkorhonen@0: } jtkorhonen@0: break; jtkorhonen@0: jtkorhonen@0: case ACT_HEADS: jtkorhonen@0: { Chris@84: QString stdOut = runner -> getOutput(); Chris@91: //!!! hgExp -> updateLocalRepoHeadsList(stdOut); jtkorhonen@0: } jtkorhonen@0: break; jtkorhonen@0: jtkorhonen@0: case ACT_REMOVE: jtkorhonen@0: case ACT_ADD: jtkorhonen@0: case ACT_COMMIT: jtkorhonen@0: case ACT_FILEDIFF: jtkorhonen@0: case ACT_FOLDERDIFF: jtkorhonen@0: case ACT_CHGSETDIFF: jtkorhonen@0: case ACT_REVERT: jtkorhonen@11: case ACT_SERVE: jtkorhonen@34: case ACT_TAG: jtkorhonen@36: case ACT_HG_IGNORE: jtkorhonen@0: shouldHgStat = true; jtkorhonen@0: break; jtkorhonen@0: jtkorhonen@0: case ACT_UPDATE: Chris@84: QMessageBox::information(this, tr("Update"), runner -> getOutput()); jtkorhonen@0: shouldHgStat = true; jtkorhonen@0: break; jtkorhonen@0: jtkorhonen@0: case ACT_MERGE: Chris@84: QMessageBox::information(this, tr("Merge"), runner -> getOutput()); jtkorhonen@0: shouldHgStat = true; jtkorhonen@33: justMerged = true; jtkorhonen@33: break; jtkorhonen@33: jtkorhonen@33: case ACT_RETRY_MERGE: jtkorhonen@38: QMessageBox::information(this, tr("Merge retry"), tr("Merge retry successful.")); jtkorhonen@33: shouldHgStat = true; jtkorhonen@33: justMerged = true; jtkorhonen@0: break; jtkorhonen@0: jtkorhonen@0: default: jtkorhonen@0: break; jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@37: Chris@74: //Typical sequence goes paths -> stat -> heads -> parents -> log Chris@74: if (runningAction == ACT_PATHS) Chris@74: { Chris@74: runningAction = ACT_NONE; Chris@74: hgStat(); Chris@74: } Chris@74: else if (runningAction == ACT_STAT) jtkorhonen@0: { jtkorhonen@0: runningAction = ACT_NONE; jtkorhonen@0: hgHeads(); jtkorhonen@0: } jtkorhonen@0: else if (runningAction == ACT_HEADS) jtkorhonen@0: { jtkorhonen@0: runningAction = ACT_NONE; jtkorhonen@0: hgParents(); jtkorhonen@0: } jtkorhonen@0: else if (runningAction == ACT_PARENTS) jtkorhonen@0: { jtkorhonen@0: runningAction = ACT_NONE; jtkorhonen@0: hgLog(); jtkorhonen@0: } jtkorhonen@37: else if ((runningAction == ACT_MERGE) && (exitCode != 0)) jtkorhonen@37: { jtkorhonen@37: //If we had a failed merge, offer to retry jtkorhonen@37: if (QMessageBox::Ok == QMessageBox::information(this, tr("Retry merge ?"), tr("Merge attempt failed. retry ?"), QMessageBox::Ok | QMessageBox::Cancel)) jtkorhonen@37: { jtkorhonen@37: runningAction = ACT_NONE; jtkorhonen@37: hgRetryMerge(); jtkorhonen@37: } jtkorhonen@37: else jtkorhonen@37: { jtkorhonen@37: runningAction = ACT_NONE; jtkorhonen@37: hgStat(); jtkorhonen@37: } jtkorhonen@37: } jtkorhonen@0: else jtkorhonen@0: { jtkorhonen@0: runningAction = ACT_NONE; jtkorhonen@0: if (shouldHgStat) jtkorhonen@0: { Chris@74: hgPaths(); jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: } Chris@90: Chris@90: enableDisableActions(); jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: void MainWindow::connectActions() jtkorhonen@0: { jtkorhonen@0: connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); jtkorhonen@0: connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); jtkorhonen@0: connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); jtkorhonen@0: Chris@74: connect(hgStatAct, SIGNAL(triggered()), this, SLOT(hgPaths())); Chris@74: connect(hgExp, SIGNAL(workFolderViewTypesChanged()), this, SLOT(hgPaths())); jtkorhonen@0: connect(hgRemoveAct, SIGNAL(triggered()), this, SLOT(hgRemove())); jtkorhonen@0: connect(hgAddAct, SIGNAL(triggered()), this, SLOT(hgAdd())); jtkorhonen@0: connect(hgCommitAct, SIGNAL(triggered()), this, SLOT(hgCommit())); jtkorhonen@0: connect(hgFileDiffAct, SIGNAL(triggered()), this, SLOT(hgFileDiff())); jtkorhonen@0: connect(hgFolderDiffAct, SIGNAL(triggered()), this, SLOT(hgFolderDiff())); jtkorhonen@0: connect(hgChgSetDiffAct, SIGNAL(triggered()), this, SLOT(hgChgSetDiff())); jtkorhonen@0: connect(hgUpdateAct, SIGNAL(triggered()), this, SLOT(hgUpdate())); jtkorhonen@0: connect(hgRevertAct, SIGNAL(triggered()), this, SLOT(hgRevert())); jtkorhonen@0: connect(hgMergeAct, SIGNAL(triggered()), this, SLOT(hgMerge())); jtkorhonen@33: connect(hgRetryMergeAct, SIGNAL(triggered()), this, SLOT(hgRetryMerge())); jtkorhonen@34: connect(hgTagAct, SIGNAL(triggered()), this, SLOT(hgTag())); jtkorhonen@34: connect(hgIgnoreAct, SIGNAL(triggered()), this, SLOT(hgIgnore())); jtkorhonen@0: jtkorhonen@0: connect(settingsAct, SIGNAL(triggered()), this, SLOT(settings())); Chris@69: connect(openAct, SIGNAL(triggered()), this, SLOT(open())); jtkorhonen@0: jtkorhonen@0: connect(hgInitAct, SIGNAL(triggered()), this, SLOT(hgInit())); jtkorhonen@0: connect(hgCloneFromRemoteAct, SIGNAL(triggered()), this, SLOT(hgCloneFromRemote())); jtkorhonen@0: connect(hgIncomingAct, SIGNAL(triggered()), this, SLOT(hgIncoming())); jtkorhonen@0: connect(hgPullAct, SIGNAL(triggered()), this, SLOT(hgPull())); jtkorhonen@0: connect(hgPushAct, SIGNAL(triggered()), this, SLOT(hgPush())); jtkorhonen@0: jtkorhonen@0: connect(hgExp, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); jtkorhonen@0: jtkorhonen@0: connect(hgUpdateToRevAct, SIGNAL(triggered()), this, SLOT(hgUpdateToRev())); jtkorhonen@0: connect(hgAnnotateAct, SIGNAL(triggered()), this, SLOT(hgAnnotate())); jtkorhonen@0: connect(hgResolveListAct, SIGNAL(triggered()), this, SLOT(hgResolveList())); jtkorhonen@0: connect(hgResolveMarkAct, SIGNAL(triggered()), this, SLOT(hgResolveMark())); jtkorhonen@11: connect(hgServeAct, SIGNAL(triggered()), this, SLOT(hgServe())); Chris@94: connect(clearSelectionsAct, SIGNAL(triggered()), this, SLOT(clearSelections())); jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: void MainWindow::tabChanged(int currTab) jtkorhonen@0: { jtkorhonen@0: tabPage = currTab; jtkorhonen@32: jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: void MainWindow::enableDisableActions() jtkorhonen@0: { Chris@90: DEBUG << "MainWindow::enableDisableActions" << endl; Chris@90: jtkorhonen@0: QDir localRepoDir; jtkorhonen@0: QDir workFolderDir; jtkorhonen@0: bool workFolderExist; jtkorhonen@0: bool localRepoExist; jtkorhonen@0: jtkorhonen@0: remoteRepoActionsEnabled = true; Chris@90: if (remoteRepoPath.isEmpty()) { jtkorhonen@0: remoteRepoActionsEnabled = false; jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: localRepoActionsEnabled = true; Chris@90: if (workFolderPath.isEmpty()) { jtkorhonen@0: localRepoActionsEnabled = false; jtkorhonen@0: workFolderExist = false; jtkorhonen@0: } jtkorhonen@0: Chris@90: if (!workFolderDir.exists(workFolderPath)) { jtkorhonen@0: localRepoActionsEnabled = false; jtkorhonen@0: workFolderExist = false; Chris@90: } else { jtkorhonen@0: workFolderExist = true; jtkorhonen@0: } jtkorhonen@0: Chris@90: if (!localRepoDir.exists(workFolderPath + "/" + getHgDirName())) { jtkorhonen@0: localRepoActionsEnabled = false; jtkorhonen@0: localRepoExist = false; jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: hgCloneFromRemoteAct -> setEnabled(remoteRepoActionsEnabled); jtkorhonen@0: hgIncomingAct -> setEnabled(remoteRepoActionsEnabled && remoteRepoActionsEnabled); jtkorhonen@0: hgPullAct -> setEnabled(remoteRepoActionsEnabled && remoteRepoActionsEnabled); jtkorhonen@0: hgPushAct -> setEnabled(remoteRepoActionsEnabled && remoteRepoActionsEnabled); Chris@73: /* jtkorhonen@0: if (tabPage != WORKTAB) jtkorhonen@0: { jtkorhonen@0: localRepoActionsEnabled = false; jtkorhonen@0: } Chris@73: */ jtkorhonen@0: hgInitAct -> setEnabled((localRepoExist == false) && (workFolderExist==true)); jtkorhonen@0: hgStatAct -> setEnabled(localRepoActionsEnabled); jtkorhonen@0: hgFileDiffAct -> setEnabled(localRepoActionsEnabled); jtkorhonen@0: hgFolderDiffAct -> setEnabled(localRepoActionsEnabled); jtkorhonen@0: hgRevertAct -> setEnabled(localRepoActionsEnabled); jtkorhonen@0: hgAddAct -> setEnabled(localRepoActionsEnabled); jtkorhonen@0: hgRemoveAct -> setEnabled(localRepoActionsEnabled); jtkorhonen@0: hgUpdateAct -> setEnabled(localRepoActionsEnabled); jtkorhonen@0: hgCommitAct -> setEnabled(localRepoActionsEnabled); jtkorhonen@0: hgMergeAct -> setEnabled(localRepoActionsEnabled); jtkorhonen@33: hgRetryMergeAct -> setEnabled(localRepoActionsEnabled); jtkorhonen@2: hgResolveListAct -> setEnabled(localRepoActionsEnabled); jtkorhonen@2: hgResolveMarkAct -> setEnabled(localRepoActionsEnabled); jtkorhonen@2: hgAnnotateAct -> setEnabled(localRepoActionsEnabled); jtkorhonen@11: hgServeAct -> setEnabled(localRepoActionsEnabled); jtkorhonen@34: hgTagAct -> setEnabled(localRepoActionsEnabled); jtkorhonen@34: hgIgnoreAct -> setEnabled(localRepoActionsEnabled); jtkorhonen@0: Chris@91: //!!!hgExp -> enableDisableOtherTabs(tabPage); jtkorhonen@0: Chris@90: DEBUG << "localRepoActionsEnabled = " << localRepoActionsEnabled << endl; Chris@90: DEBUG << "canCommit = " << hgExp->canCommit() << endl; Chris@90: Chris@90: //!!! new stuff: Chris@95: hgAddAct->setEnabled(localRepoActionsEnabled && hgExp->canAdd()); Chris@95: hgRemoveAct->setEnabled(localRepoActionsEnabled && hgExp->canRemove()); Chris@90: hgCommitAct->setEnabled(localRepoActionsEnabled && hgExp->canCommit()); Chris@90: hgRevertAct->setEnabled(localRepoActionsEnabled && hgExp->canCommit()); Chris@95: hgFolderDiffAct->setEnabled(localRepoActionsEnabled && hgExp->canDoDiff()); Chris@90: Chris@90: /*!!! jtkorhonen@17: int added, modified, removed, notTracked, selected, selectedAdded, selectedModified, selectedRemoved, selectedNotTracked; jtkorhonen@17: jtkorhonen@17: countModifications(hgExp -> workFolderFileList, jtkorhonen@17: added, modified, removed, notTracked, jtkorhonen@17: selected, jtkorhonen@17: selectedAdded, selectedModified, selectedRemoved, selectedNotTracked); jtkorhonen@0: jtkorhonen@0: if (tabPage == WORKTAB) jtkorhonen@0: { jtkorhonen@0: //Enable / disable actions according to workFolderFileList selections / currentSelection / count jtkorhonen@0: hgChgSetDiffAct -> setEnabled(false); jtkorhonen@0: hgUpdateToRevAct -> setEnabled(false); jtkorhonen@0: jtkorhonen@0: if (localRepoActionsEnabled) jtkorhonen@0: { jtkorhonen@17: if ((added == 0) && (modified == 0) && (removed == 0)) jtkorhonen@0: { jtkorhonen@0: hgCommitAct -> setEnabled(false); jtkorhonen@0: hgRevertAct -> setEnabled(false); jtkorhonen@0: } jtkorhonen@17: else if (selected != 0) jtkorhonen@17: { jtkorhonen@17: if (selectedNotTracked != 0) jtkorhonen@17: { jtkorhonen@17: hgCommitAct -> setEnabled(false); jtkorhonen@17: } jtkorhonen@17: else if ((selectedAdded == 0) && (selectedModified == 0) && (selectedRemoved == 0)) jtkorhonen@17: { jtkorhonen@17: hgCommitAct -> setEnabled(false); jtkorhonen@17: } jtkorhonen@17: } jtkorhonen@0: jtkorhonen@17: if (modified == 0) jtkorhonen@0: { jtkorhonen@0: hgFolderDiffAct -> setEnabled(false); jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: if (!isSelectedModified(hgExp -> workFolderFileList)) jtkorhonen@0: { jtkorhonen@0: hgFileDiffAct -> setEnabled(false); jtkorhonen@0: hgRevertAct -> setEnabled(false); jtkorhonen@0: } jtkorhonen@0: jtkorhonen@5: //JK 14.5.2010: Fixed confusing add button. Now this is simple: If we have something to add (any non-tracked files), add is enabled. jtkorhonen@17: if (notTracked == 0) jtkorhonen@0: { jtkorhonen@0: hgAddAct -> setEnabled(false); jtkorhonen@0: } jtkorhonen@0: jtkorhonen@6: if (!isSelectedDeletable(hgExp -> workFolderFileList)) jtkorhonen@0: { jtkorhonen@0: hgRemoveAct -> setEnabled(false); jtkorhonen@0: } jtkorhonen@0: jtkorhonen@2: hgResolveListAct -> setEnabled(true); jtkorhonen@2: jtkorhonen@5: if (hgExp -> localRepoHeadsList->count() < 2) jtkorhonen@0: { jtkorhonen@0: hgMergeAct -> setEnabled(false); jtkorhonen@33: hgRetryMergeAct -> setEnabled(false); jtkorhonen@0: } jtkorhonen@0: jtkorhonen@34: if (hgExp -> localRepoHeadsList->count() < 1) jtkorhonen@34: { jtkorhonen@34: hgTagAct -> setEnabled(false); jtkorhonen@34: } jtkorhonen@34: jtkorhonen@2: QString currentFile = hgExp -> getCurrentFileListLine(); jtkorhonen@2: if (!currentFile.isEmpty()) jtkorhonen@2: { jtkorhonen@2: hgAnnotateAct -> setEnabled(true); jtkorhonen@2: hgResolveMarkAct -> setEnabled(true); jtkorhonen@2: } jtkorhonen@2: else jtkorhonen@2: { jtkorhonen@2: hgAnnotateAct -> setEnabled(false); jtkorhonen@2: hgResolveMarkAct -> setEnabled(false); jtkorhonen@2: } jtkorhonen@0: } jtkorhonen@0: } jtkorhonen@0: else jtkorhonen@0: { jtkorhonen@0: QList headSelList = hgExp -> localRepoHeadsList->selectedItems(); jtkorhonen@0: QList historySelList = hgExp -> localRepoHgLogList->selectedItems(); jtkorhonen@0: jtkorhonen@0: if ((historySelList.count() == 2) || (headSelList.count() == 2)) jtkorhonen@0: { jtkorhonen@0: hgChgSetDiffAct -> setEnabled(true); jtkorhonen@0: } jtkorhonen@0: else jtkorhonen@0: { jtkorhonen@0: hgChgSetDiffAct -> setEnabled(false); jtkorhonen@0: } jtkorhonen@0: jtkorhonen@30: if (historySelList.count() == 1) jtkorhonen@0: { jtkorhonen@30: hgUpdateToRevAct -> setEnabled(true); jtkorhonen@0: } jtkorhonen@0: else jtkorhonen@0: { jtkorhonen@0: hgUpdateToRevAct -> setEnabled(false); jtkorhonen@0: } jtkorhonen@0: } Chris@90: */ jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: void MainWindow::createActions() jtkorhonen@0: { jtkorhonen@0: //File actions jtkorhonen@0: hgInitAct = new QAction(tr("Init local repository"), this); jtkorhonen@0: hgInitAct->setStatusTip(tr("Create an empty local repository in selected folder")); jtkorhonen@0: jtkorhonen@0: hgCloneFromRemoteAct = new QAction(tr("Clone from remote"), this); jtkorhonen@0: hgCloneFromRemoteAct->setStatusTip(tr("Clone from remote repository into local repository in selected folder")); jtkorhonen@0: Chris@69: openAct = new QAction(QIcon(":/images/fileopen.png"), tr("Open..."), this); Chris@69: openAct -> setStatusTip(tr("Open repository")); Chris@69: openAct -> setIconVisibleInMenu(true); Chris@69: jtkorhonen@0: settingsAct = new QAction(QIcon(":/images/settings.png"), tr("Settings..."), this); jtkorhonen@0: settingsAct -> setStatusTip(tr("View and change application settings")); jtkorhonen@0: settingsAct -> setIconVisibleInMenu(true); jtkorhonen@0: jtkorhonen@0: exitAct = new QAction(QIcon(":/images/exit.png"), tr("Exit"), this); jtkorhonen@0: exitAct->setShortcuts(QKeySequence::Quit); jtkorhonen@0: exitAct->setStatusTip(tr("Exit application")); jtkorhonen@0: exitAct -> setIconVisibleInMenu(true); jtkorhonen@0: jtkorhonen@0: //Repository actions Chris@61: hgStatAct = new QAction(QIcon(":/images/status.png"), tr("Refresh"), this); Chris@61: hgStatAct->setStatusTip(tr("Refresh (info of) status of workfolder files")); Chris@61: Chris@61: hgIncomingAct = new QAction(QIcon(":/images/incoming.png"), tr("Preview"), this); jtkorhonen@0: hgIncomingAct -> setStatusTip(tr("View info of changesets incoming to us from remote repository (on pull operation)")); jtkorhonen@0: Chris@61: hgPullAct = new QAction(QIcon(":/images/pull.png"), tr("Pull"), this); jtkorhonen@0: hgPullAct -> setStatusTip(tr("Pull changesets from remote repository to local repository")); jtkorhonen@0: Chris@61: hgPushAct = new QAction(QIcon(":/images/push.png"), tr("Push"), this); jtkorhonen@0: hgPushAct->setStatusTip(tr("Push local changesets to remote repository")); jtkorhonen@0: jtkorhonen@0: //Workfolder actions Chris@61: hgFileDiffAct = new QAction(QIcon(":/images/diff.png"), tr("Diff"), this); jtkorhonen@0: hgFileDiffAct->setStatusTip(tr("Filediff: View differences between selected working folder file and local repository file")); jtkorhonen@0: jtkorhonen@0: hgFolderDiffAct = new QAction(QIcon(":/images/folderdiff.png"), tr("View folderdiff"), this); jtkorhonen@0: hgFolderDiffAct->setStatusTip(tr("Folderdiff: View all differences between working folder files and local repository files")); jtkorhonen@0: jtkorhonen@0: hgChgSetDiffAct = new QAction(QIcon(":/images/chgsetdiff.png"), tr("View changesetdiff"), this); jtkorhonen@0: hgChgSetDiffAct->setStatusTip(tr("Change set diff: View differences between all files of 2 repository changesets")); jtkorhonen@0: Chris@61: hgRevertAct = new QAction(QIcon(":/images/undo.png"), tr("Revert"), this); jtkorhonen@0: hgRevertAct->setStatusTip(tr("Undo selected working folder file changes (return to local repository version)")); jtkorhonen@0: Chris@61: hgAddAct = new QAction(QIcon(":/images/add.png"), tr("Add"), this); jtkorhonen@17: hgAddAct -> setStatusTip(tr("Add working folder file(s) (selected or all yet untracked) to local repository (on next commit)")); jtkorhonen@0: Chris@61: hgRemoveAct = new QAction(QIcon(":/images/remove.png"), tr("Remove"), this); jtkorhonen@0: hgRemoveAct -> setStatusTip(tr("Remove selected working folder file from local repository (on next commit)")); jtkorhonen@0: Chris@61: hgUpdateAct = new QAction(QIcon(":/images/update.png"), tr("Update"), this); jtkorhonen@0: hgUpdateAct->setStatusTip(tr("Update working folder from local repository")); jtkorhonen@0: Chris@61: hgCommitAct = new QAction(QIcon(":/images/commit.png"), tr("Commit"), this); jtkorhonen@20: hgCommitAct->setStatusTip(tr("Save selected file(s) or all changed files in working folder (and all subfolders) to local repository")); jtkorhonen@0: jtkorhonen@0: hgMergeAct = new QAction(QIcon(":/images/merge.png"), tr("Merge"), this); jtkorhonen@0: hgMergeAct->setStatusTip(tr("Merge two local repository changesets to working folder")); jtkorhonen@0: jtkorhonen@0: //Advanced actions jtkorhonen@0: hgUpdateToRevAct = new QAction(tr("Update to revision"), this); jtkorhonen@0: hgUpdateToRevAct -> setStatusTip(tr("Update working folder to version selected from history list")); jtkorhonen@0: jtkorhonen@0: hgAnnotateAct = new QAction(tr("Annotate"), this); jtkorhonen@0: hgAnnotateAct -> setStatusTip(tr("Show line-by-line version information for selected file")); jtkorhonen@0: jtkorhonen@0: hgResolveListAct = new QAction(tr("Resolve (list)"), this); jtkorhonen@0: hgResolveListAct -> setStatusTip(tr("Resolve (list): Show list of files needing merge")); jtkorhonen@0: jtkorhonen@0: hgResolveMarkAct = new QAction(tr("Resolve (mark)"), this); jtkorhonen@0: hgResolveMarkAct -> setStatusTip(tr("Resolve (mark): Mark selected file status as resolved")); jtkorhonen@0: jtkorhonen@33: hgRetryMergeAct = new QAction(tr("Retry merge"), this); jtkorhonen@33: hgRetryMergeAct -> setStatusTip(tr("Retry merge after failed merge attempt.")); jtkorhonen@33: jtkorhonen@34: hgTagAct = new QAction(tr("Tag revision"), this); jtkorhonen@34: hgTagAct -> setStatusTip(tr("Give decsriptive name (tag) to current workfolder parent revision.")); jtkorhonen@34: jtkorhonen@34: hgIgnoreAct = new QAction(tr("Edit .hgignore"), this); jtkorhonen@34: hgIgnoreAct -> setStatusTip(tr("Edit .hgignore file (file contains names of files that should be ignored by mercurial)")); jtkorhonen@34: jtkorhonen@11: hgServeAct = new QAction(tr("Serve (via http)"), this); jtkorhonen@11: hgServeAct -> setStatusTip(tr("Serve local repository via http for workgroup access")); jtkorhonen@11: jtkorhonen@0: //Help actions jtkorhonen@0: aboutAct = new QAction(tr("About"), this); jtkorhonen@0: aboutAct->setStatusTip(tr("Show the application's About box")); jtkorhonen@0: jtkorhonen@0: aboutQtAct = new QAction(tr("About Qt"), this); jtkorhonen@0: aboutQtAct->setStatusTip(tr("Show the Qt library's About box")); Chris@94: Chris@94: // Miscellaneous Chris@94: clearSelectionsAct = new QAction(tr("Clear selections"), this); Chris@94: clearSelectionsAct->setShortcut(Qt::Key_Escape); jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: void MainWindow::createMenus() jtkorhonen@0: { jtkorhonen@0: fileMenu = menuBar()->addMenu(tr("File")); jtkorhonen@0: fileMenu -> addAction(hgInitAct); jtkorhonen@0: fileMenu -> addAction(hgCloneFromRemoteAct); Chris@94: fileMenu->addAction(clearSelectionsAct); //!!! can't live here! jtkorhonen@0: fileMenu -> addSeparator(); Chris@69: fileMenu -> addAction(openAct); jtkorhonen@0: fileMenu -> addAction(settingsAct); jtkorhonen@0: fileMenu -> addSeparator(); jtkorhonen@0: fileMenu -> addAction(exitAct); jtkorhonen@0: jtkorhonen@0: advancedMenu = menuBar()->addMenu(tr("Advanced")); jtkorhonen@0: advancedMenu -> addAction(hgUpdateToRevAct); jtkorhonen@0: advancedMenu -> addSeparator(); jtkorhonen@0: advancedMenu -> addAction(hgAnnotateAct); jtkorhonen@0: advancedMenu -> addSeparator(); jtkorhonen@33: advancedMenu -> addAction(hgRetryMergeAct); jtkorhonen@0: advancedMenu -> addAction(hgResolveListAct); jtkorhonen@0: advancedMenu -> addAction(hgResolveMarkAct); jtkorhonen@11: advancedMenu -> addSeparator(); jtkorhonen@34: advancedMenu -> addAction(hgTagAct); jtkorhonen@34: advancedMenu -> addSeparator(); jtkorhonen@34: advancedMenu -> addAction(hgIgnoreAct); jtkorhonen@34: advancedMenu -> addSeparator(); jtkorhonen@11: advancedMenu -> addAction(hgServeAct); jtkorhonen@0: jtkorhonen@0: helpMenu = menuBar()->addMenu(tr("Help")); jtkorhonen@0: helpMenu->addAction(aboutAct); jtkorhonen@0: helpMenu->addAction(aboutQtAct); jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: void MainWindow::createToolBars() jtkorhonen@0: { jtkorhonen@0: fileToolBar = addToolBar(tr("File")); jtkorhonen@0: fileToolBar -> setIconSize(QSize(MY_ICON_SIZE, MY_ICON_SIZE)); Chris@69: fileToolBar -> addAction(openAct); Chris@43: fileToolBar -> addAction(hgStatAct); jtkorhonen@0: fileToolBar -> addSeparator(); Chris@61: // fileToolBar -> addAction(hgChgSetDiffAct); jtkorhonen@0: fileToolBar -> setMovable(false); jtkorhonen@0: jtkorhonen@0: repoToolBar = addToolBar(tr(REPOMENU_TITLE)); jtkorhonen@0: repoToolBar -> setIconSize(QSize(MY_ICON_SIZE, MY_ICON_SIZE)); jtkorhonen@0: repoToolBar->addAction(hgIncomingAct); jtkorhonen@0: repoToolBar->addAction(hgPullAct); jtkorhonen@0: repoToolBar->addAction(hgPushAct); jtkorhonen@0: repoToolBar -> setMovable(false); jtkorhonen@0: jtkorhonen@0: workFolderToolBar = addToolBar(tr(WORKFOLDERMENU_TITLE)); jtkorhonen@0: addToolBar(Qt::LeftToolBarArea, workFolderToolBar); jtkorhonen@0: workFolderToolBar -> setIconSize(QSize(MY_ICON_SIZE, MY_ICON_SIZE)); Chris@61: // workFolderToolBar->addSeparator(); Chris@95: // workFolderToolBar->addAction(hgFileDiffAct); Chris@95: workFolderToolBar->addAction(hgFolderDiffAct); jtkorhonen@0: workFolderToolBar->addSeparator(); jtkorhonen@0: workFolderToolBar->addAction(hgRevertAct); jtkorhonen@0: workFolderToolBar->addAction(hgUpdateAct); jtkorhonen@0: workFolderToolBar->addAction(hgCommitAct); jtkorhonen@0: workFolderToolBar->addAction(hgMergeAct); jtkorhonen@0: workFolderToolBar->addSeparator(); jtkorhonen@0: workFolderToolBar->addAction(hgAddAct); jtkorhonen@0: workFolderToolBar->addAction(hgRemoveAct); jtkorhonen@0: workFolderToolBar -> setMovable(false); Chris@61: Chris@61: foreach (QToolButton *tb, findChildren()) { Chris@61: tb->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); Chris@61: } jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: void MainWindow::createStatusBar() jtkorhonen@0: { jtkorhonen@0: statusBar()->showMessage(tr("Ready")); jtkorhonen@0: } jtkorhonen@0: Chris@69: Chris@69: //!!! review these: Chris@69: jtkorhonen@0: void MainWindow::readSettings() jtkorhonen@0: { jtkorhonen@0: QDir workFolder; jtkorhonen@0: Chris@61: QSettings settings; jtkorhonen@0: jtkorhonen@30: remoteRepoPath = settings.value("remoterepopath", "").toString(); jtkorhonen@0: workFolderPath = settings.value("workfolderpath", "").toString(); jtkorhonen@0: if (!workFolder.exists(workFolderPath)) jtkorhonen@0: { jtkorhonen@0: workFolderPath = ""; jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); jtkorhonen@0: QSize size = settings.value("size", QSize(400, 400)).toSize(); jtkorhonen@0: firstStart = settings.value("firststart", QVariant(true)).toBool(); jtkorhonen@0: jtkorhonen@0: initialFileTypesBits = (unsigned char) settings.value("viewFileTypes", QVariant(DEFAULT_HG_STAT_BITS)).toInt(); jtkorhonen@0: resize(size); jtkorhonen@0: move(pos); jtkorhonen@0: } jtkorhonen@0: jtkorhonen@17: jtkorhonen@0: void MainWindow::writeSettings() jtkorhonen@0: { Chris@61: QSettings settings; jtkorhonen@0: settings.setValue("pos", pos()); jtkorhonen@0: settings.setValue("size", size()); jtkorhonen@0: settings.setValue("remoterepopath", remoteRepoPath); jtkorhonen@0: settings.setValue("workfolderpath", workFolderPath); jtkorhonen@0: settings.setValue("firststart", firstStart); Chris@91: //!!!settings.setValue("viewFileTypes", hgExp -> getFileTypesBits()); jtkorhonen@0: } jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: jtkorhonen@0: