# HG changeset patch # User Chris Cannam # Date 1300096829 0 # Node ID 4229b6a8e9c6e084856c2eefc47510fac266d7bd # Parent aa852b477e4df228eec960f30029c0f884f2eec1# Parent cee2e8691eeb004b67e3b8f690a02f856bb23c5c Merge diff -r aa852b477e4d -r 4229b6a8e9c6 annotatedialog.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/annotatedialog.cpp Mon Mar 14 10:00:29 2011 +0000 @@ -0,0 +1,94 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + EasyMercurial + + Based on hgExplorer by Jari Korhonen + Copyright (c) 2010 Jari Korhonen + Copyright (c) 2011 Chris Cannam + Copyright (c) 2011 Queen Mary, University of London + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "annotatedialog.h" +#include "common.h" +#include "colourset.h" +#include "debug.h" + +#include +#include +#include +#include +#include + +AnnotateDialog::AnnotateDialog(QWidget *w, QString text) : + QDialog(w) +{ + setMinimumWidth(800); + setMinimumHeight(500); + + text.replace("\r\n", "\n"); + QStringList lines = text.split("\n"); + + QGridLayout *layout = new QGridLayout; + QTableWidget *table = new QTableWidget; + + QRegExp annotateLineRE = QRegExp("^([^:]+) ([a-z0-9]{12}) ([0-9-]+): (.*)$"); + + table->setRowCount(lines.size()); + table->setColumnCount(4); + table->horizontalHeader()->setStretchLastSection(true); + table->verticalHeader()->setDefaultSectionSize + (table->verticalHeader()->fontMetrics().height() + 2); + + QStringList labels; + labels << tr("User") << tr("Revision") << tr("Date") << tr("Content"); + table->setHorizontalHeaderLabels(labels); + + table->setShowGrid(false); + + QFont monofont("Monospace"); + monofont.setStyleHint(QFont::TypeWriter); + + int row = 0; + + foreach (QString line, lines) { + if (annotateLineRE.indexIn(line) == 0) { + QStringList items = annotateLineRE.capturedTexts(); + QString id = items[2]; + QColor colour = ColourSet::instance()->getColourFor(id); + QColor bg = QColor::fromHsv(colour.hue(), + 30, + 230); + // note items[0] is the whole match, so we want 1-4 + for (int col = 0; col+1 < items.size(); ++col) { + QString item = items[col+1]; + if (col == 0) item = item.trimmed(); + QTableWidgetItem *wi = new QTableWidgetItem(item); + wi->setFlags(Qt::ItemIsEnabled); + wi->setBackground(bg); + if (col == 3) { // id, content + wi->setFont(monofont); + } + table->setItem(row, col, wi); + } + } else { + DEBUG << "AnnotateDialog: Failed to match RE in line: " << line << " at row " << row << endl; + } + ++row; + } + + QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok); + connect(bb, SIGNAL(accepted()), this, SLOT(accept())); + + layout->addWidget(table, 0, 0); + layout->addWidget(bb, 1, 0); + + setLayout(layout); +} + diff -r aa852b477e4d -r 4229b6a8e9c6 annotatedialog.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/annotatedialog.h Mon Mar 14 10:00:29 2011 +0000 @@ -0,0 +1,31 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + EasyMercurial + + Based on hgExplorer by Jari Korhonen + Copyright (c) 2010 Jari Korhonen + Copyright (c) 2011 Chris Cannam + Copyright (c) 2011 Queen Mary, University of London + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef ANNOTATE_DIALOG_H +#define ANNOTATE_DIALOG_H + +#include + +class AnnotateDialog : public QDialog +{ + Q_OBJECT + +public: + AnnotateDialog(QWidget *parent, QString output); +}; + +#endif diff -r aa852b477e4d -r 4229b6a8e9c6 easyhg-extdiff.sh --- a/easyhg-extdiff.sh Wed Mar 02 15:58:34 2011 +0000 +++ b/easyhg-extdiff.sh Mon Mar 14 10:00:29 2011 +0000 @@ -7,24 +7,17 @@ while [ $# -gt 2 ]; do shift done -found="" for d in kdiff3 kdiff3.exe; do if [ -x "$p/$d" ]; then - found=true - "$p/$d" "$1" "$2" - break + exec "$p/$d" "$1" "$2" elif [ -x "$(type -path $d)" ]; then - found=true - "$d" "$1" "$2" - break; + exec "$d" "$1" "$2" fi done -if [ -z "$found" ]; then - od=/usr/bin/opendiff - if [ -x "$od" ]; then - found=true - "$od" "$1" "$2" | cat - fi +od=/usr/bin/opendiff +if [ -x "$od" ]; then + "$od" "$1" "$2" | cat + exit 0 fi -[ -n "$found" ] +exit 1 diff -r aa852b477e4d -r 4229b6a8e9c6 easyhg-merge.sh --- a/easyhg-merge.sh Wed Mar 02 15:58:34 2011 +0000 +++ b/easyhg-merge.sh Mon Mar 14 10:00:29 2011 +0000 @@ -12,23 +12,15 @@ left="$1" ancestor="$2" right="$3" -found="" for d in kdiff3 kdiff3.exe; do if [ -x "$p/$d" ]; then - found=true - "$p/$d" "$ancestor" "$left" "$right" -o "$out" - break + exec "$p/$d" "$ancestor" "$left" "$right" -o "$out" elif [ -x "$(type -path $d)" ]; then - found=true - "$d" "$ancestor" "$left" "$right" -o "$out" - break; + exec "$d" "$ancestor" "$left" "$right" -o "$out" fi done -if [ -z "$found" ]; then - fm=/Developer/Applications/Utilities/FileMerge.app/Contents/MacOS/FileMerge - if [ -x "$fm" ]; then - found=true - "$fm" -left "$left" -merge "$out" -ancestor "$ancestor" -right "$right" - fi +fm=/Developer/Applications/Utilities/FileMerge.app/Contents/MacOS/FileMerge +if [ -x "$fm" ]; then + exec "$fm" -left "$left" -merge "$out" -ancestor "$ancestor" -right "$right" fi -[ -n "$found" ] +exit 1 diff -r aa852b477e4d -r 4229b6a8e9c6 easyhg.pro --- a/easyhg.pro Wed Mar 02 15:58:34 2011 +0000 +++ b/easyhg.pro Mon Mar 14 10:00:29 2011 +0000 @@ -59,7 +59,8 @@ settingsdialog.h \ clickablelabel.h \ workstatuswidget.h \ - moreinformationdialog.h + moreinformationdialog.h \ + annotatedialog.h SOURCES = main.cpp \ mainwindow.cpp \ hgtabwidget.cpp \ @@ -91,7 +92,8 @@ uncommitteditem.cpp \ settingsdialog.cpp \ workstatuswidget.cpp \ - moreinformationdialog.cpp + moreinformationdialog.cpp \ + annotatedialog.cpp macx-* { SOURCES += common_osx.mm diff -r aa852b477e4d -r 4229b6a8e9c6 filestates.cpp --- a/filestates.cpp Wed Mar 02 15:58:34 2011 +0000 +++ b/filestates.cpp Mon Mar 14 10:00:29 2011 +0000 @@ -63,7 +63,7 @@ QStringList *FileStates::stateToBucket(State s) { switch (s) { - case Clean: return &m_clean; // not implemented yet + case Clean: return &m_clean; case Modified: return &m_modified; case Added: return &m_added; case Unknown: return &m_unknown; @@ -112,14 +112,19 @@ << m_unknown.size() << " unknown" << endl; } -QStringList FileStates::getFilesInState(State s) const +QStringList FileStates::filesInState(State s) const { QStringList *sl = const_cast(this)->stateToBucket(s); if (sl) return *sl; else return QStringList(); } -FileStates::State FileStates::getStateOfFile(QString file) const +bool FileStates::isInState(QString file, State s) const +{ + return filesInState(s).contains(file); +} + +FileStates::State FileStates::stateOf(QString file) const { if (m_stateMap.contains(file)) { return m_stateMap[file]; @@ -131,3 +136,85 @@ << endl; return Unknown; } + +FileStates::Activities FileStates::activitiesSupportedBy(State s) +{ + Activities a; + + switch (s) { + + case Modified: + a << Annotate << Diff << Commit << Revert << Remove; + break; + + case Added: + a << Commit << Revert << Remove; + break; + + case Removed: + a << Commit << Revert << Add; + break; + + case InConflict: + a << Annotate << Diff << RedoMerge << MarkResolved << Revert; + break; + + case Missing: + a << Revert << Remove; + break; + + case Unknown: + a << Add << Ignore; + break; + + case Clean: + a << Annotate << Remove; + break; + + case Ignored: + a << UnIgnore; + break; + } + + return a; +} + +bool FileStates::supportsActivity(State s, Activity a) +{ + return activitiesSupportedBy(s).contains(a); +} + +int FileStates::activityGroup(Activity a) +{ + switch (a) { + case Annotate: case Diff: return 0; + case Commit: case Revert: return 1; + case Add: case Remove: return 2; + case RedoMerge: case MarkResolved: return 3; + case Ignore: case UnIgnore: return 4; + } + return 0; +} + +bool FileStates::supportsActivity(QString file, Activity a) const +{ + return supportsActivity(stateOf(file), a); +} + +QStringList FileStates::filesSupportingActivity(Activity a) const +{ + QStringList f; + for (int i = int(FirstState); i <= int(LastState); ++i) { + State s = (State)i; + if (supportsActivity(s, a)) { + f << filesInState(s); + } + } + return f; +} + +FileStates::Activities FileStates::activitiesSupportedBy(QString file) const +{ + return activitiesSupportedBy(stateOf(file)); +} + diff -r aa852b477e4d -r 4229b6a8e9c6 filestates.h --- a/filestates.h Wed Mar 02 15:58:34 2011 +0000 +++ b/filestates.h Mon Mar 14 10:00:29 2011 +0000 @@ -47,10 +47,11 @@ void parseStates(QString text); - void clearBuckets(); + bool isInState(QString file, State s) const; + QStringList filesInState(State s) const; + State stateOf(QString file) const; - QStringList getFilesInState(State) const; - +/*!!! -- to remove: */ QStringList modified() const { return m_modified; } QStringList added() const { return m_added; } QStringList unknown() const { return m_unknown; } @@ -60,7 +61,39 @@ QStringList clean() const { return m_clean; } QStringList ignored() const { return m_ignored; } - State getStateOfFile(QString file) const; + enum Activity { + + // These are in the order in which they want to be listed in + // the context menu + + Diff, + Annotate, + + Commit, + Revert, + + Add, + Remove, + + RedoMerge, + MarkResolved, + + Ignore, + UnIgnore, + + FirstActivity = Diff, + LastActivity = UnIgnore + }; + + typedef QList Activities; + + static bool supportsActivity(State s, Activity a); + static Activities activitiesSupportedBy(State s); + static int activityGroup(Activity a); + + bool supportsActivity(QString file, Activity a) const; + QStringList filesSupportingActivity(Activity) const; + Activities activitiesSupportedBy(QString file) const; private: QStringList m_modified; @@ -73,6 +106,8 @@ QStringList m_ignored; QMap m_stateMap; + void clearBuckets(); + State charToState(QChar, bool * = 0); QStringList *stateToBucket(State); }; diff -r aa852b477e4d -r 4229b6a8e9c6 filestatuswidget.cpp --- a/filestatuswidget.cpp Wed Mar 02 15:58:34 2011 +0000 +++ b/filestatuswidget.cpp Mon Mar 14 10:00:29 2011 +0000 @@ -31,6 +31,7 @@ #include #include #include +#include FileStatusWidget::FileStatusWidget(QWidget *parent) : QWidget(parent), @@ -56,6 +57,17 @@ m_simpleLabels[FileStates::Unknown] = tr("Untracked:"); m_simpleLabels[FileStates::Ignored] = tr("Ignored:"); + m_actionLabels[FileStates::Annotate] = tr("Show annotated version"); + m_actionLabels[FileStates::Diff] = tr("Diff to parent"); + m_actionLabels[FileStates::Commit] = tr("Commit..."); + m_actionLabels[FileStates::Revert] = tr("Revert to last committed state"); + m_actionLabels[FileStates::Add] = tr("Add to version control"); + m_actionLabels[FileStates::Remove] = tr("Remove from version control"); + m_actionLabels[FileStates::RedoMerge] = tr("Redo merge"); + m_actionLabels[FileStates::MarkResolved] = tr("Mark conflict as resolved"); + m_actionLabels[FileStates::Ignore] = tr("Ignore"); + m_actionLabels[FileStates::UnIgnore] = tr("Stop ignoring"); + m_descriptions[FileStates::Clean] = tr("You have not changed these files."); m_descriptions[FileStates::Modified] = tr("You have changed these files since you last committed them."); m_descriptions[FileStates::Added] = tr("These files will be added to version control next time you commit them."); @@ -105,6 +117,31 @@ connect(w, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged())); + connect(w, SIGNAL(itemDoubleClicked(QListWidgetItem *)), + this, SLOT(itemDoubleClicked(QListWidgetItem *))); + + FileStates::Activities activities = m_fileStates.activitiesSupportedBy(s); + int prevGroup = -1; + foreach (FileStates::Activity a, activities) { + // Skip activities which are not yet implemented + if (a == FileStates::Ignore || + a == FileStates::UnIgnore) { + continue; + } + int group = FileStates::activityGroup(a); + if (group != prevGroup && prevGroup != -1) { + QAction *sep = new QAction("", w); + sep->setSeparator(true); + w->insertAction(0, sep); + } + prevGroup = group; + QAction *act = new QAction(m_actionLabels[a], w); + act->setProperty("state", s); + act->setProperty("activity", a); + connect(act, SIGNAL(triggered()), this, SLOT(menuActionActivated())); + w->insertAction(0, act); + } + w->setContextMenuPolicy(Qt::ActionsContextMenu); boxlayout->addItem(new QSpacerItem(2, 2), 3, 0); @@ -173,6 +210,50 @@ } } + +void FileStatusWidget::menuActionActivated() +{ + QAction *act = qobject_cast(sender()); + if (!act) return; + + FileStates::State state = (FileStates::State) + act->property("state").toUInt(); + FileStates::Activity activity = (FileStates::Activity) + act->property("activity").toUInt(); + + DEBUG << "menuActionActivated: state = " << state << ", activity = " + << activity << endl; + + if (!FileStates::supportsActivity(state, activity)) { + std::cerr << "WARNING: FileStatusWidget::menuActionActivated: " + << "Action state " << state << " does not support activity " + << activity << std::endl; + return; + } + + QStringList files = getSelectedFilesInState(state); + + switch (activity) { + case FileStates::Annotate: emit annotateFiles(files); break; + case FileStates::Diff: emit diffFiles(files); break; + case FileStates::Commit: emit commitFiles(files); break; + case FileStates::Revert: emit revertFiles(files); break; + case FileStates::Add: emit addFiles(files); break; + case FileStates::Remove: emit removeFiles(files); break; + case FileStates::RedoMerge: emit redoFileMerges(files); break; + case FileStates::MarkResolved: emit markFilesResolved(files); break; + case FileStates::Ignore: emit ignoreFiles(files); break; + case FileStates::UnIgnore: emit unIgnoreFiles(files); break; + } +} + +void FileStatusWidget::itemDoubleClicked(QListWidgetItem *item) +{ + QStringList files; + files << item->text(); + emit annotateFiles(files); +} + void FileStatusWidget::itemSelectionChanged() { DEBUG << "FileStatusWidget::itemSelectionChanged" << endl; @@ -212,9 +293,7 @@ bool FileStatusWidget::haveChangesToCommit() const { - return !m_fileStates.added().empty() || - !m_fileStates.removed().empty() || - !m_fileStates.modified().empty(); + return !getAllCommittableFiles().empty(); } bool FileStatusWidget::haveSelection() const @@ -222,136 +301,47 @@ return !m_selectedFiles.empty(); } -QStringList FileStatusWidget::getAllSelectedFiles() const -{ - return m_selectedFiles; -} - -QStringList FileStatusWidget::getSelectedCommittableFiles() const +QStringList FileStatusWidget::getSelectedFilesInState(FileStates::State s) const { QStringList files; foreach (QString f, m_selectedFiles) { - switch (m_fileStates.getStateOfFile(f)) { - case FileStates::Added: - case FileStates::Modified: - case FileStates::Removed: - files.push_back(f); - break; - default: break; - } + if (m_fileStates.stateOf(f) == s) files.push_back(f); } return files; -} +} + +QStringList FileStatusWidget::getSelectedFilesSupportingActivity(FileStates::Activity a) const +{ + QStringList files; + foreach (QString f, m_selectedFiles) { + if (m_fileStates.supportsActivity(f, a)) files.push_back(f); + } + return files; +} QStringList FileStatusWidget::getAllCommittableFiles() const { - QStringList files; - files << m_fileStates.getFilesInState(FileStates::Modified); - files << m_fileStates.getFilesInState(FileStates::Added); - files << m_fileStates.getFilesInState(FileStates::Removed); - return files; -} - -QStringList FileStatusWidget::getSelectedRevertableFiles() const -{ - QStringList files; - foreach (QString f, m_selectedFiles) { - switch (m_fileStates.getStateOfFile(f)) { - case FileStates::Added: - case FileStates::Modified: - case FileStates::Removed: - case FileStates::Missing: - case FileStates::InConflict: - files.push_back(f); - break; - default: break; - } - } - return files; + return m_fileStates.filesSupportingActivity(FileStates::Commit); } QStringList FileStatusWidget::getAllRevertableFiles() const { - QStringList files; - files << m_fileStates.getFilesInState(FileStates::Modified); - files << m_fileStates.getFilesInState(FileStates::Added); - files << m_fileStates.getFilesInState(FileStates::Removed); - files << m_fileStates.getFilesInState(FileStates::Missing); - files << m_fileStates.getFilesInState(FileStates::InConflict); - return files; -} - -QStringList FileStatusWidget::getSelectedUnresolvedFiles() const -{ - QStringList files; - foreach (QString f, m_selectedFiles) { - switch (m_fileStates.getStateOfFile(f)) { - case FileStates::InConflict: - files.push_back(f); - break; - default: break; - } - } - return files; + return m_fileStates.filesSupportingActivity(FileStates::Revert); } QStringList FileStatusWidget::getAllUnresolvedFiles() const { - QStringList files; - files << m_fileStates.getFilesInState(FileStates::InConflict); - return files; + return m_fileStates.filesInState(FileStates::InConflict); } QStringList FileStatusWidget::getSelectedAddableFiles() const { - QStringList files; - foreach (QString f, m_selectedFiles) { - switch (m_fileStates.getStateOfFile(f)) { - case FileStates::Unknown: - case FileStates::Removed: - files.push_back(f); - break; - default: break; - } - } - return files; -} - -QStringList FileStatusWidget::getAllAddableFiles() const -{ - QStringList files; - files << m_fileStates.getFilesInState(FileStates::Removed); - files << m_fileStates.getFilesInState(FileStates::Unknown); - return files; + return getSelectedFilesSupportingActivity(FileStates::Add); } QStringList FileStatusWidget::getSelectedRemovableFiles() const { - QStringList files; - foreach (QString f, m_selectedFiles) { - switch (m_fileStates.getStateOfFile(f)) { - case FileStates::Clean: - case FileStates::Added: - case FileStates::Modified: - case FileStates::Missing: - case FileStates::InConflict: - files.push_back(f); - break; - default: break; - } - } - return files; -} - -QStringList FileStatusWidget::getAllRemovableFiles() const -{ - QStringList files; - files << m_fileStates.getFilesInState(FileStates::Clean); - files << m_fileStates.getFilesInState(FileStates::Added); - files << m_fileStates.getFilesInState(FileStates::Modified); - files << m_fileStates.getFilesInState(FileStates::Missing); - files << m_fileStates.getFilesInState(FileStates::InConflict); - return files; + return getSelectedFilesSupportingActivity(FileStates::Remove); } QString @@ -403,7 +393,7 @@ QListWidget *w = m_stateListMap[s]; w->clear(); - QStringList files = m_fileStates.getFilesInState(s); + QStringList files = m_fileStates.filesInState(s); QStringList highPriority, lowPriority; @@ -434,7 +424,7 @@ foreach (QString file, highPriority) { QListWidgetItem *item = new QListWidgetItem(file); w->addItem(item); - item->setForeground(QColor("#d40000")); //!!! and a nice gold star + item->setForeground(QColor("#d40000")); item->setSelected(selectedFiles.contains(file)); } diff -r aa852b477e4d -r 4229b6a8e9c6 filestatuswidget.h --- a/filestatuswidget.h Wed Mar 02 15:58:34 2011 +0000 +++ b/filestatuswidget.h Mon Mar 14 10:00:29 2011 +0000 @@ -25,6 +25,7 @@ class QLabel; class QListWidget; +class QListWidgetItem; class QPushButton; class QFileInfo; class QCheckBox; @@ -46,33 +47,36 @@ bool haveChangesToCommit() const; bool haveSelection() const; - QStringList getAllSelectedFiles() const; - - QStringList getSelectedCommittableFiles() const; QStringList getAllCommittableFiles() const; - - QStringList getSelectedRevertableFiles() const; QStringList getAllRevertableFiles() const; + QStringList getAllUnresolvedFiles() const; QStringList getSelectedAddableFiles() const; - QStringList getAllAddableFiles() const; + QStringList getSelectedRemovableFiles() const; - QStringList getSelectedRemovableFiles() const; - QStringList getAllRemovableFiles() const; - - QStringList getSelectedUnresolvedFiles() const; - QStringList getAllUnresolvedFiles() const; - signals: void selectionChanged(); void showAllChanged(bool); + void annotateFiles(QStringList); + void diffFiles(QStringList); + void commitFiles(QStringList); + void revertFiles(QStringList); + void addFiles(QStringList); + void removeFiles(QStringList); + void redoFileMerges(QStringList); + void markFilesResolved(QStringList); + void ignoreFiles(QStringList); + void unIgnoreFiles(QStringList); + public slots: void clearSelections(); void updateWidgets(); private slots: + void menuActionActivated(); void itemSelectionChanged(); + void itemDoubleClicked(QListWidgetItem *); private: QString m_localPath; @@ -84,6 +88,7 @@ QMap m_simpleLabels; QMap m_descriptions; QMap m_stateListMap; + QMap m_actionLabels; QString m_highlightExplanation; QFileInfo *m_dateReference; @@ -99,6 +104,9 @@ void setNoModificationsLabelText(); QString labelFor(FileStates::State, bool addHighlightExplanation = false); void setLabelFor(QWidget *w, FileStates::State, bool addHighlightExplanation); + + QStringList getSelectedFilesInState(FileStates::State s) const; + QStringList getSelectedFilesSupportingActivity(FileStates::Activity) const; }; #endif diff -r aa852b477e4d -r 4229b6a8e9c6 hgrunner.cpp --- a/hgrunner.cpp Wed Mar 02 15:58:34 2011 +0000 +++ b/hgrunner.cpp Mon Mar 14 10:00:29 2011 +0000 @@ -423,9 +423,7 @@ #endif #ifdef Q_OS_MAC - // On OS/X 10.6, Python is 64-bit by default but our Hg extension - // is only available in 32-bit - if (settings.value("python32", true).toBool()) { + if (settings.value("python32", false).toBool()) { env.insert("VERSIONER_PYTHON_PREFER_32_BIT", "1"); } #endif diff -r aa852b477e4d -r 4229b6a8e9c6 hgtabwidget.cpp --- a/hgtabwidget.cpp Wed Mar 02 15:58:34 2011 +0000 +++ b/hgtabwidget.cpp Mon Mar 14 10:00:29 2011 +0000 @@ -30,16 +30,49 @@ QString workFolderPath) : QTabWidget(parent) { - // Work page + // Work tab m_fileStatusWidget = new FileStatusWidget; m_fileStatusWidget->setLocalPath(workFolderPath); + connect(m_fileStatusWidget, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged())); + connect(m_fileStatusWidget, SIGNAL(showAllChanged(bool)), this, SIGNAL(showAllChanged(bool))); + + connect(m_fileStatusWidget, SIGNAL(annotateFiles(QStringList)), + this, SIGNAL(annotateFiles(QStringList))); + + connect(m_fileStatusWidget, SIGNAL(diffFiles(QStringList)), + this, SIGNAL(diffFiles(QStringList))); + + connect(m_fileStatusWidget, SIGNAL(commitFiles(QStringList)), + this, SIGNAL(commitFiles(QStringList))); + + connect(m_fileStatusWidget, SIGNAL(revertFiles(QStringList)), + this, SIGNAL(revertFiles(QStringList))); + + connect(m_fileStatusWidget, SIGNAL(addFiles(QStringList)), + this, SIGNAL(addFiles(QStringList))); + + connect(m_fileStatusWidget, SIGNAL(removeFiles(QStringList)), + this, SIGNAL(removeFiles(QStringList))); + + connect(m_fileStatusWidget, SIGNAL(redoFileMerges(QStringList)), + this, SIGNAL(redoFileMerges(QStringList))); + + connect(m_fileStatusWidget, SIGNAL(markFilesResolved(QStringList)), + this, SIGNAL(markFilesResolved(QStringList))); + + connect(m_fileStatusWidget, SIGNAL(ignoreFiles(QStringList)), + this, SIGNAL(ignoreFiles(QStringList))); + + connect(m_fileStatusWidget, SIGNAL(unIgnoreFiles(QStringList)), + this, SIGNAL(unIgnoreFiles(QStringList))); + addTab(m_fileStatusWidget, tr("My work")); - // History graph page + // History graph tab m_historyWidget = new HistoryWidget; addTab(m_historyWidget, tr("History")); @@ -116,16 +149,7 @@ { if (!m_fileStatusWidget->haveChangesToCommit()) return false; if (!m_fileStatusWidget->getAllUnresolvedFiles().empty()) return false; - - QStringList addable = m_fileStatusWidget->getSelectedAddableFiles(); - if (addable.empty()) return true; - - QStringList committable = m_fileStatusWidget->getSelectedCommittableFiles(); - - // "Removed" files are both committable and addable; don't return - // a false negative if the selection only contains these - if (committable == addable) return true; - return false; + return true; } bool HgTabWidget::canRevert() const @@ -134,35 +158,28 @@ // unresolved files, but we can't commit them if (!m_fileStatusWidget->haveChangesToCommit() && m_fileStatusWidget->getAllUnresolvedFiles().empty()) return false; - - // The rest of this logic is as in canCommit though - - QStringList addable = m_fileStatusWidget->getSelectedAddableFiles(); - if (addable.empty()) return true; - - QStringList committable = m_fileStatusWidget->getSelectedCommittableFiles(); - if (committable == addable) return true; - return false; + return true; } bool HgTabWidget::canAdd() const { + // Permit this only when work tab is visible + if (currentIndex() != 0) return false; + QStringList addable = m_fileStatusWidget->getSelectedAddableFiles(); if (addable.empty()) return false; QStringList removable = m_fileStatusWidget->getSelectedRemovableFiles(); if (!removable.empty()) return false; - QStringList committable = m_fileStatusWidget->getSelectedCommittableFiles(); - - // "Removed" files are both committable and addable; don't return - // a false negative if the selection only contains these - if (committable == addable || committable.empty()) return true; - return false; + return true; } bool HgTabWidget::canRemove() const { + // Permit this only when work tab is visible + if (currentIndex() != 0) return false; + if (m_fileStatusWidget->getSelectedRemovableFiles().empty()) return false; if (!m_fileStatusWidget->getSelectedAddableFiles().empty()) return false; return true; @@ -170,7 +187,7 @@ bool HgTabWidget::canResolve() const { - return !m_fileStatusWidget->getSelectedUnresolvedFiles().empty(); + return !m_fileStatusWidget->getAllUnresolvedFiles().empty(); } bool HgTabWidget::haveChangesToCommit() const @@ -178,41 +195,21 @@ return m_fileStatusWidget->haveChangesToCommit(); } -QStringList HgTabWidget::getAllSelectedFiles() const -{ - return m_fileStatusWidget->getAllSelectedFiles(); -} - QStringList HgTabWidget::getAllCommittableFiles() const { return m_fileStatusWidget->getAllCommittableFiles(); } -QStringList HgTabWidget::getSelectedCommittableFiles() const -{ - return m_fileStatusWidget->getSelectedCommittableFiles(); -} - QStringList HgTabWidget::getAllRevertableFiles() const { return m_fileStatusWidget->getAllRevertableFiles(); } -QStringList HgTabWidget::getSelectedRevertableFiles() const -{ - return m_fileStatusWidget->getSelectedRevertableFiles(); -} - QStringList HgTabWidget::getSelectedAddableFiles() const { return m_fileStatusWidget->getSelectedAddableFiles(); } -QStringList HgTabWidget::getAllRemovableFiles() const -{ - return m_fileStatusWidget->getAllRemovableFiles(); -} - QStringList HgTabWidget::getSelectedRemovableFiles() const { return m_fileStatusWidget->getSelectedRemovableFiles(); @@ -223,11 +220,6 @@ return m_fileStatusWidget->getAllUnresolvedFiles(); } -QStringList HgTabWidget::getSelectedUnresolvedFiles() const -{ - return m_fileStatusWidget->getSelectedUnresolvedFiles(); -} - void HgTabWidget::updateWorkFolderFileList(QString fileList) { m_fileStates.parseStates(fileList); diff -r aa852b477e4d -r 4229b6a8e9c6 hgtabwidget.h --- a/hgtabwidget.h Wed Mar 02 15:58:34 2011 +0000 +++ b/hgtabwidget.h Mon Mar 14 10:00:29 2011 +0000 @@ -62,22 +62,12 @@ bool canResolve() const; bool haveChangesToCommit() const; - QStringList getAllSelectedFiles() const; - - QStringList getSelectedCommittableFiles() const; QStringList getAllCommittableFiles() const; - - QStringList getSelectedRevertableFiles() const; QStringList getAllRevertableFiles() const; + QStringList getAllUnresolvedFiles() const; QStringList getSelectedAddableFiles() const; - QStringList getAllAddableFiles() const; - QStringList getSelectedRemovableFiles() const; - QStringList getAllRemovableFiles() const; - - QStringList getSelectedUnresolvedFiles() const; - QStringList getAllUnresolvedFiles() const; signals: void selectionChanged(); @@ -98,6 +88,17 @@ void newBranch(QString id); void tag(QString id); + void annotateFiles(QStringList); + void diffFiles(QStringList); + void commitFiles(QStringList); + void revertFiles(QStringList); + void addFiles(QStringList); + void removeFiles(QStringList); + void redoFileMerges(QStringList); + void markFilesResolved(QStringList); + void ignoreFiles(QStringList); + void unIgnoreFiles(QStringList); + public slots: void clearSelections(); void showWorkTab(); diff -r aa852b477e4d -r 4229b6a8e9c6 mainwindow.cpp --- a/mainwindow.cpp Wed Mar 02 15:58:34 2011 +0000 +++ b/mainwindow.cpp Mon Mar 14 10:00:29 2011 +0000 @@ -44,6 +44,7 @@ #include "incomingdialog.h" #include "settingsdialog.h" #include "moreinformationdialog.h" +#include "annotatedialog.h" #include "version.h" #include "workstatuswidget.h" @@ -357,15 +358,12 @@ m_runner->requestAction(HgAction(ACT_QUERY_PARENTS, m_workFolderPath, params)); } -void MainWindow::hgAnnotate() +void MainWindow::hgAnnotateFiles(QStringList files) { QStringList params; - QString currentFile;//!!! = m_hgTabs -> getCurrentFileListLine(); - if (!currentFile.isEmpty()) - { - params << "annotate" << "--" << currentFile.mid(2); //Jump over status marker characters (e.g "M ") - + if (!files.isEmpty()) { + params << "annotate" << "-udqc" << "--" << files; m_runner->requestAction(HgAction(ACT_ANNOTATE, m_workFolderPath, params)); } } @@ -380,12 +378,15 @@ void MainWindow::hgAdd() { - QStringList params; - // hgExplorer permitted adding "all" files -- I'm not sure // that one is a good idea, let's require the user to select - QStringList files = m_hgTabs->getSelectedAddableFiles(); + hgAddFiles(m_hgTabs->getSelectedAddableFiles()); +} + +void MainWindow::hgAddFiles(QStringList files) +{ + QStringList params; if (!files.empty()) { params << "add" << "--" << files; @@ -393,13 +394,15 @@ } } - void MainWindow::hgRemove() { + hgRemoveFiles(m_hgTabs->getSelectedRemovableFiles()); +} + +void MainWindow::hgRemoveFiles(QStringList files) +{ QStringList params; - QStringList files = m_hgTabs->getSelectedRemovableFiles(); - if (!files.empty()) { params << "remove" << "--after" << "--force" << "--" << files; m_runner->requestAction(HgAction(ACT_REMOVE, m_workFolderPath, params)); @@ -408,6 +411,11 @@ void MainWindow::hgCommit() { + hgCommitFiles(QStringList()); +} + +void MainWindow::hgCommitFiles(QStringList files) +{ QStringList params; QString comment; @@ -415,7 +423,6 @@ comment = m_mergeCommitComment; } - QStringList files = m_hgTabs->getSelectedCommittableFiles(); QStringList allFiles = m_hgTabs->getAllCommittableFiles(); QStringList reportFiles = files; if (reportFiles.empty()) { @@ -498,7 +505,6 @@ } } - void MainWindow::hgNoBranch() { if (m_currentParents.empty()) return; @@ -511,7 +517,6 @@ m_runner->requestAction(HgAction(ACT_NEW_BRANCH, m_workFolderPath, params)); } - void MainWindow::hgTag(QString id) { QStringList params; @@ -533,7 +538,6 @@ } } - void MainWindow::hgIgnore() { QString hgIgnorePath; @@ -568,6 +572,18 @@ m_runner->requestAction(action); } +void MainWindow::hgIgnoreFiles(QStringList files) +{ + //!!! not implemented yet + DEBUG << "MainWindow::hgIgnoreFiles: Not implemented" << endl; +} + +void MainWindow::hgUnIgnoreFiles(QStringList files) +{ + //!!! not implemented yet + DEBUG << "MainWindow::hgUnIgnoreFiles: Not implemented" << endl; +} + QString MainWindow::getDiffBinaryName() { QSettings settings; @@ -600,6 +616,11 @@ void MainWindow::hgFolderDiff() { + hgDiffFiles(QStringList()); +} + +void MainWindow::hgDiffFiles(QStringList files) +{ QString diff = getDiffBinaryName(); if (diff == "") return; @@ -610,12 +631,11 @@ params << "--config" << "extensions.extdiff=" << "extdiff"; params << "--program" << diff; - params << m_hgTabs->getSelectedCommittableFiles(); // may be none: whole dir + params << "--" << files; // may be none: whole dir m_runner->requestAction(HgAction(ACT_FOLDERDIFF, m_workFolderPath, params)); } - void MainWindow::hgDiffToCurrent(QString id) { QString diff = getDiffBinaryName(); @@ -632,7 +652,6 @@ m_runner->requestAction(HgAction(ACT_FOLDERDIFF, m_workFolderPath, params)); } - void MainWindow::hgDiffToParent(QString child, QString parent) { QString diff = getDiffBinaryName(); @@ -649,7 +668,7 @@ m_runner->requestAction(HgAction(ACT_CHGSETDIFF, m_workFolderPath, params)); } - + void MainWindow::hgShowSummaryFor(Changeset *cs) { @@ -687,11 +706,15 @@ void MainWindow::hgRevert() { + hgRevertFiles(QStringList()); +} + +void MainWindow::hgRevertFiles(QStringList files) +{ QStringList params; QString comment; bool all = false; - QStringList files = m_hgTabs->getSelectedRevertableFiles(); QStringList allFiles = m_hgTabs->getAllRevertableFiles(); if (files.empty() || files == allFiles) { files = allFiles; @@ -758,7 +781,7 @@ } -void MainWindow::hgMarkResolved(QStringList files) +void MainWindow::hgMarkFilesResolved(QStringList files) { QStringList params; @@ -774,7 +797,13 @@ } -void MainWindow::hgRetryMerge() +void MainWindow::hgRedoMerge() +{ + hgRedoFileMerges(QStringList()); +} + + +void MainWindow::hgRedoFileMerges(QStringList files) { QStringList params; @@ -785,7 +814,6 @@ params << "--tool" << merge; } - QStringList files = m_hgTabs->getSelectedUnresolvedFiles(); if (files.empty()) { params << "--all"; } else { @@ -800,12 +828,12 @@ m_mergeCommitComment = tr("Merge"); } - + void MainWindow::hgMerge() { if (m_hgTabs->canResolve()) { - hgRetryMerge(); + hgRedoMerge(); return; } @@ -1427,49 +1455,6 @@ } } -#define STDOUT_NEEDS_BIG_WINDOW 512 -#define SMALL_WND_W 500 -#define SMALL_WND_H 300 - -#define BIG_WND_W 1024 -#define BIG_WND_H 768 - - -void MainWindow::presentLongStdoutToUser(QString stdo) -{ - if (!stdo.isEmpty()) - { - QDialog dlg; - - if (stdo.length() > STDOUT_NEEDS_BIG_WINDOW) - { - dlg.setMinimumWidth(BIG_WND_W); - dlg.setMinimumHeight(BIG_WND_H); - } - else - { - dlg.setMinimumWidth(SMALL_WND_W); - dlg.setMinimumHeight(SMALL_WND_H); - } - - QVBoxLayout *box = new QVBoxLayout; - QListWidget *list = new QListWidget; - list-> addItems(stdo.split("\n")); - QPushButton *btn = new QPushButton(tr("Ok")); - connect(btn, SIGNAL(clicked()), &dlg, SLOT(accept())); - - box -> addWidget(list); - box -> addWidget(btn); - dlg.setLayout(box); - - dlg.exec(); - } - else - { - QMessageBox::information(this, tr("EasyMercurial"), tr("Mercurial command did not return any output.")); - } -} - void MainWindow::updateFileSystemWatcher() { bool justCreated = false; @@ -1667,7 +1652,7 @@ int n = extractChangeCount(output); if (n > 0) { head = tr("Pulled %n changeset(s)", "", n); - report = tr("The new changes will be highlighted in the history.
Use Update to bring these changes into your working copy."); + report = tr("New changes will be highlighted in yellow in the history."); } else if (n == 0) { head = tr("No changes to pull"); report = tr("Your local repository already contains all changes found in the remote repository."); @@ -1778,7 +1763,7 @@ // if clone fails, we have no repo m_workFolderPath = ""; enableDisableActions(); - break; + break; // go on to default report case ACT_INCOMING: // returns non-zero code and no output if the check was // successful but there are no changes pending @@ -1786,7 +1771,7 @@ showIncoming(""); return; } - break; + break; // go on to default report case ACT_QUERY_HEADS: // fails if repo is empty; we don't care (if there's a genuine // problem, something else will fail too). Pretend it @@ -1805,8 +1790,16 @@ reportNewRemoteHeads(output); return; } + break; // go on to default report + case ACT_MERGE: + case ACT_RETRY_MERGE: + MoreInformationDialog::information + (this, tr("Merge"), tr("Merge failed"), + tr("Some files were not merged successfully.

You can Merge again to repeat the interactive merge; use Revert to abandon the merge entirely; or edit the files that are in conflict in an editor and, when you are happy with them, choose Mark Resolved in each file's right-button menu."), + output); + return; case ACT_STAT: - break; // go on and report + break; // go on to default report default: break; } @@ -1895,9 +1888,12 @@ break; case ACT_ANNOTATE: - presentLongStdoutToUser(output); + { + AnnotateDialog dialog(this, output); + dialog.exec(); m_shouldHgStat = true; break; + } case ACT_PULL: showPullResult(output); @@ -1970,7 +1966,7 @@ break; case ACT_REVERT: - hgMarkResolved(m_lastRevertedFiles); + hgMarkFilesResolved(m_lastRevertedFiles); m_justMerged = false; break; @@ -2175,12 +2171,14 @@ connect(m_hgPullAct, SIGNAL(triggered()), this, SLOT(hgPull())); connect(m_hgPushAct, SIGNAL(triggered()), this, SLOT(hgPush())); - connect(m_hgAnnotateAct, SIGNAL(triggered()), this, SLOT(hgAnnotate())); connect(m_hgServeAct, SIGNAL(triggered()), this, SLOT(hgServe())); } void MainWindow::connectTabsSignals() { + connect(m_hgTabs, SIGNAL(currentChanged(int)), + this, SLOT(enableDisableActions())); + connect(m_hgTabs, SIGNAL(commit()), this, SLOT(hgCommit())); @@ -2219,6 +2217,36 @@ connect(m_hgTabs, SIGNAL(tag(QString)), this, SLOT(hgTag(QString))); + + connect(m_hgTabs, SIGNAL(annotateFiles(QStringList)), + this, SLOT(hgAnnotateFiles(QStringList))); + + connect(m_hgTabs, SIGNAL(diffFiles(QStringList)), + this, SLOT(hgDiffFiles(QStringList))); + + connect(m_hgTabs, SIGNAL(commitFiles(QStringList)), + this, SLOT(hgCommitFiles(QStringList))); + + connect(m_hgTabs, SIGNAL(revertFiles(QStringList)), + this, SLOT(hgRevertFiles(QStringList))); + + connect(m_hgTabs, SIGNAL(addFiles(QStringList)), + this, SLOT(hgAddFiles(QStringList))); + + connect(m_hgTabs, SIGNAL(removeFiles(QStringList)), + this, SLOT(hgRemoveFiles(QStringList))); + + connect(m_hgTabs, SIGNAL(redoFileMerges(QStringList)), + this, SLOT(hgRedoFileMerges(QStringList))); + + connect(m_hgTabs, SIGNAL(markFilesResolved(QStringList)), + this, SLOT(hgMarkFilesResolved(QStringList))); + + connect(m_hgTabs, SIGNAL(ignoreFiles(QStringList)), + this, SLOT(hgIgnoreFiles(QStringList))); + + connect(m_hgTabs, SIGNAL(unIgnoreFiles(QStringList)), + this, SLOT(hgUnIgnoreFiles(QStringList))); } void MainWindow::enableDisableActions() @@ -2283,7 +2311,6 @@ m_hgUpdateAct -> setEnabled(m_localRepoActionsEnabled); m_hgCommitAct -> setEnabled(m_localRepoActionsEnabled); m_hgMergeAct -> setEnabled(m_localRepoActionsEnabled); - m_hgAnnotateAct -> setEnabled(m_localRepoActionsEnabled); m_hgServeAct -> setEnabled(m_localRepoActionsEnabled); m_hgIgnoreAct -> setEnabled(m_localRepoActionsEnabled); @@ -2459,9 +2486,6 @@ m_hgMergeAct->setStatusTip(tr("Merge the two independent sets of changes in the local repository into the working folder")); //Advanced actions - //!!! needs to be modified for number - m_hgAnnotateAct = new QAction(tr("Annotate"), this); - m_hgAnnotateAct -> setStatusTip(tr("Show line-by-line version information for selected file")); m_hgIgnoreAct = new QAction(tr("Edit .hgignore File"), this); m_hgIgnoreAct -> setStatusTip(tr("Edit the .hgignore file, containing the names of files that should be ignored by Mercurial")); diff -r aa852b477e4d -r 4229b6a8e9c6 mainwindow.h --- a/mainwindow.h Wed Mar 02 15:58:34 2011 +0000 +++ b/mainwindow.h Mon Mar 14 10:00:29 2011 +0000 @@ -78,8 +78,7 @@ void hgUpdate(); void hgRevert(); void hgMerge(); - void hgMarkResolved(QStringList); - void hgRetryMerge(); + void hgRedoMerge(); void hgCloneFromRemote(); void hgInit(); void hgIncoming(); @@ -87,7 +86,6 @@ void hgPull(); void hgUpdateToRev(QString); void hgMergeFrom(QString); - void hgAnnotate(); void hgResolveList(); void hgTag(QString); void hgNewBranch(); @@ -95,6 +93,17 @@ void hgServe(); void hgIgnore(); + void hgAnnotateFiles(QStringList); + void hgDiffFiles(QStringList); + void hgCommitFiles(QStringList); + void hgRevertFiles(QStringList); + void hgAddFiles(QStringList); + void hgRemoveFiles(QStringList); + void hgRedoFileMerges(QStringList); + void hgMarkFilesResolved(QStringList); + void hgIgnoreFiles(QStringList); + void hgUnIgnoreFiles(QStringList); + void fsDirectoryChanged(QString); void fsFileChanged(QString); void checkFilesystem(); @@ -116,7 +125,6 @@ void readSettings(); void splitChangeSets(QStringList *list, QString hgLogOutput); void reportNewRemoteHeads(QString); - void presentLongStdoutToUser(QString stdo); void writeSettings(); QStringList listAllUpIpV4Addresses(); diff -r aa852b477e4d -r 4229b6a8e9c6 version.h --- a/version.h Wed Mar 02 15:58:34 2011 +0000 +++ b/version.h Mon Mar 14 10:00:29 2011 +0000 @@ -1,1 +1,1 @@ -#define EASYHG_VERSION "0.4" +#define EASYHG_VERSION "0.9"