changeset 94:44ed7766d55a

* Clear selections when Esc pressed; some refactoring
author Chris Cannam
date Wed, 24 Nov 2010 14:41:52 +0000
parents dfb7a274b90f
children d1be9712818a
files filestates.cpp filestates.h filestatuswidget.cpp filestatuswidget.h hgexpwidget.cpp hgexpwidget.h mainwindow.cpp mainwindow.h
diffstat 8 files changed, 159 insertions(+), 85 deletions(-) [+]
line wrap: on
line diff
--- a/filestates.cpp	Wed Nov 24 13:50:33 2010 +0000
+++ b/filestates.cpp	Wed Nov 24 14:41:52 2010 +0000
@@ -4,56 +4,85 @@
 
 #include <QMap>
 
-FileStates::FileStates(QString text)
+FileStates::FileStates()
+{
+}
+
+void FileStates::clearBuckets()
+{
+    m_modified.clear();
+    m_added.clear();
+    m_removed.clear();
+    m_missing.clear();
+    m_unknown.clear();
+}
+
+FileStates::State FileStates::charToState(QChar c, bool *ok)
+{
+    if (ok) *ok = true;
+    if (c == 'M') return Modified;
+    if (c == 'A') return Added;
+    if (c == 'R') return Removed;
+    if (c == '!') return Missing;
+    if (c == '?') return Unknown;
+    if (c == 'C') return Clean;
+    if (ok) *ok = false;
+    return Unknown;
+}
+
+QStringList *FileStates::stateToBucket(State s)
+{
+    switch (s) {
+    case Clean: default: return 0; // not implemented yet
+    case Modified: return &m_modified;
+    case Added: return &m_added;
+    case Unknown: return &m_unknown;
+    case Removed: return &m_removed;
+    case Missing: return &m_missing;
+    }
+}
+
+void FileStates::parseStates(QString text)
 {
     text.replace("\r\n", "\n");
 
-    QMap<QChar, QStringList *> buckets;
-    buckets['M'] = &modified;
-    buckets['A'] = &added;
-    buckets['R'] = &removed;
-    buckets['!'] = &missing;
-    buckets['?'] = &unknown;
+    clearBuckets();
 
     QStringList lines = text.split("\n", QString::SkipEmptyParts);
+
     foreach (QString line, lines) {
+
         if (line.length() < 3 || line[1] != ' ') {
             continue;
         }
-        QChar tag = line[0];
+
+        QChar c = line[0];
+        bool ok = false;
+        State s = charToState(c, &ok);
+        if (!ok) continue;
+
         QString file = line.right(line.length() - 2);
-        if (buckets.contains(tag)) {
-            buckets[tag]->push_back(file);
-        }
+        QStringList *bucket = stateToBucket(s);
+        bucket->push_back(file);
+        m_stateMap[file] = s;
     }
 
-    DEBUG << "FileStates: " << modified.size() << " modified, " << added.size()
-            << " added, " << removed.size() << " removed, " << missing.size()
-            << " missing, " << unknown.size() << " unknown" << endl;
+    DEBUG << "FileStates: " << m_modified.size() << " modified, " << m_added.size()
+            << " added, " << m_removed.size() << " removed, " << m_missing.size()
+            << " missing, " << m_unknown.size() << " unknown" << endl;
 }
 
-QStringList FileStates::getFilesInState(State s)
+QStringList FileStates::getFilesInState(State s) const
 {
-    switch (s) {
-
-    case Modified: return modified;
-    case Added: return added;
-    case Unknown: return unknown;
-    case Removed: return removed;
-    case Missing: return missing;
-
-    case UpToDate: // not supported yet
-    default:
-        return QStringList();
-    }
+    QStringList *sl = const_cast<FileStates *>(this)->stateToBucket(s);
+    if (sl) return *sl;
+    else return QStringList();
 }
 
-FileStates::State FileStates::getStateOfFile(QString file)
+FileStates::State FileStates::getStateOfFile(QString file) const
 {
-    // slow, but let's worry about that if it becomes a problem
-    for (int is = int(FirstState); is <= int(LastState); ++is) {
-        QStringList fl = getFilesInState(State(is));
-        foreach (QString f, fl) if (f == file) return State(is);
+    if (m_stateMap.contains(file)) {
+        return m_stateMap[file];
     }
     DEBUG << "FileStates: WARNING: getStateOfFile: file "
             << file << " is unknown to us: returning Unknown state, "
--- a/filestates.h	Wed Nov 24 13:50:33 2010 +0000
+++ b/filestates.h	Wed Nov 24 14:41:52 2010 +0000
@@ -19,34 +19,51 @@
 #define FILESTATES_H
 
 #include <QStringList>
+#include <QMap>
+#include <QString>
 
 class FileStates
 {
 public:
-    FileStates() { }
-    FileStates(QString text);
+    FileStates();
 
     enum State {
 
-        UpToDate,
+        Clean,
         Modified,
         Added,
         Unknown,
         Removed,
         Missing,
 
-        FirstState = UpToDate,
+        FirstState = Clean,
         LastState = Missing
     };
 
-    QStringList modified;
-    QStringList added;
-    QStringList unknown;
-    QStringList removed;
-    QStringList missing;
+    void parseStates(QString text);
 
-    QStringList getFilesInState(State);
-    State getStateOfFile(QString file);
+    void clearBuckets();
+
+    QStringList getFilesInState(State) const;
+
+    QStringList modified() const { return m_modified; }
+    QStringList added() const { return m_added; }
+    QStringList unknown() const { return m_unknown; }
+    QStringList removed() const { return m_removed; }
+    QStringList missing() const { return m_missing; }
+
+    State getStateOfFile(QString file) const;
+
+private:
+    QStringList m_modified;
+    QStringList m_added;
+    QStringList m_unknown;
+    QStringList m_removed;
+    QStringList m_missing;
+    QMap<QString, State> m_stateMap;
+
+    State charToState(QChar, bool * = 0);
+    QStringList *stateToBucket(State);
 };
 
 #endif // FILESTATES_H
--- a/filestatuswidget.cpp	Wed Nov 24 13:50:33 2010 +0000
+++ b/filestatuswidget.cpp	Wed Nov 24 14:41:52 2010 +0000
@@ -49,31 +49,29 @@
 
     layout->setColumnStretch(1, 20);
 
-    QStringList labels;
-    labels << tr("Modified files:")
-            << tr("Added files:")
-            << tr("Removed files:")
-            << tr("New untracked files:")
-            << tr("Missing files:");
+    QMap<FileStates::State, QString> labels;
+    labels[FileStates::Clean] = tr("Unmodified files:");
+    labels[FileStates::Modified] = tr("Modified files:");
+    labels[FileStates::Added] = tr("Added files:");
+    labels[FileStates::Removed] = tr("Removed files:");
+    labels[FileStates::Missing] = tr("Missing files:");
+    labels[FileStates::Unknown] = tr("Untracked files:");
 
-    QList<QListWidget **> lists;
-    lists << &m_modifiedList
-            << &m_addedList
-            << &m_removedList
-            << &m_unknownList
-            << &m_missingList;
+    for (int i = int(FileStates::FirstState);
+             i <= int(FileStates::LastState); ++i) {
 
-    for (int i = 0; i < labels.size(); ++i) {
+        FileStates::State s = FileStates::State(i);
 
         QWidget *box = new QWidget;
         QGridLayout *boxlayout = new QGridLayout;
         box->setLayout(boxlayout);
 
-        boxlayout->addWidget(new QLabel(labels[i]), 0, 0);
+        boxlayout->addWidget(new QLabel(labels[s]), 0, 0);
 
-        *lists[i] = new QListWidget;
-        (*lists[i])->setSelectionMode(QListWidget::ExtendedSelection);
-        boxlayout->addWidget(*lists[i], 1, 0);
+        QListWidget *w = new QListWidget;
+        m_stateListMap[s] = w;
+        w->setSelectionMode(QListWidget::ExtendedSelection);
+        boxlayout->addWidget(w, 1, 0);
 
         layout->addWidget(box, ++row, 0, 1, 2);
         box->hide();
@@ -87,6 +85,13 @@
     delete m_dateReference;
 }
 
+void FileStatusWidget::clearSelections()
+{
+    foreach (QListWidget *w, m_stateListMap) {
+        w->clearSelection();
+    }
+}
+
 void
 FileStatusWidget::setLocalPath(QString p)
 {
@@ -132,18 +137,12 @@
 void
 FileStatusWidget::updateWidgets()
 {
-    FileStates &sp = m_fileStates;
-    QMap<QStringList *, QListWidget *> listmap;
-    listmap[&sp.modified] = m_modifiedList;
-    listmap[&sp.added] = m_addedList;
-    listmap[&sp.removed] = m_removedList;
-    listmap[&sp.missing] = m_missingList;
-    listmap[&sp.unknown] = m_unknownList;
-
-    foreach (QStringList *sl, listmap.keys()) {
-        listmap[sl]->clear();
-        listmap[sl]->addItems(*sl);
-        listmap[sl]->parentWidget()->setVisible(!sl->empty());
+    foreach (FileStates::State s, m_stateListMap.keys()) {
+        QListWidget *w = m_stateListMap[s];
+        w->clear();
+        QStringList sl = m_fileStates.getFilesInState(s);
+        w->addItems(sl);
+        w->parentWidget()->setVisible(!sl.empty());
     }
 
     if (m_dateReference) {
@@ -151,14 +150,15 @@
         // last interaction with the repo
         QDateTime refTime = m_dateReference->lastModified();
         DEBUG << "reference time: " << refTime << endl;
-        for (int i = 0; i < m_unknownList->count(); ++i) {
-            QString fn(m_localPath + "/" + m_unknownList->item(i)->text());
+        QListWidget *ul = m_stateListMap[FileStates::Unknown];
+        for (int i = 0; i < ul->count(); ++i) {
+            QString fn(m_localPath + "/" + ul->item(i)->text());
             DEBUG << "comparing with " << fn << endl;
             QFileInfo fi(fn);
             if (fi.exists() && fi.lastModified() > refTime) {
                 DEBUG << "file " << fn << " is newer (" << fi.lastModified()
                         << ") than reference" << endl;
-                highlightFile(m_unknownList, i);
+                highlightFile(ul, i);
             }
         }
     }
--- a/filestatuswidget.h	Wed Nov 24 13:50:33 2010 +0000
+++ b/filestatuswidget.h	Wed Nov 24 14:41:52 2010 +0000
@@ -44,11 +44,18 @@
     void setFileStates(FileStates sp);
 
     bool haveChangesToCommit() const {
-        return !m_fileStates.added.empty() ||
-               !m_fileStates.removed.empty() ||
-               !m_fileStates.modified.empty();
+        return !m_fileStates.added().empty() ||
+               !m_fileStates.removed().empty() ||
+               !m_fileStates.modified().empty();
     }
 
+    QStringList getSelectedCommittableFiles();
+    QStringList getSelectedAddableFiles();
+    QStringList getSelectedRemoveableFiles();
+
+public slots:
+    void clearSelections();
+
 private:
     QString m_localPath;
     QLabel *m_localPathLabel;
@@ -57,12 +64,7 @@
     QLabel *m_remoteURLLabel;
     
     FileStates m_fileStates;
-
-    QListWidget *m_modifiedList;
-    QListWidget *m_addedList;
-    QListWidget *m_unknownList;
-    QListWidget *m_removedList;
-    QListWidget *m_missingList;
+    QMap<FileStates::State, QListWidget *> m_stateListMap;
 
     QFileInfo *m_dateReference;
 
--- a/hgexpwidget.cpp	Wed Nov 24 13:50:33 2010 +0000
+++ b/hgexpwidget.cpp	Wed Nov 24 14:41:52 2010 +0000
@@ -57,6 +57,11 @@
     addTab(historyGraphPageWidget, tr("History"));
 }
 
+void HgExpWidget::clearSelections()
+{
+    fileStatusWidget->clearSelections();
+}
+
 bool HgExpWidget::canCommit() const
 {
     return fileStatusWidget->haveChangesToCommit();
@@ -64,7 +69,7 @@
 
 void HgExpWidget::updateWorkFolderFileList(QString fileList)
 {
-    fileStates = FileStates(fileList);
+    fileStates.parseStates(fileList);
     fileStatusWidget->setFileStates(fileStates);
 }
 
--- a/hgexpwidget.h	Wed Nov 24 13:50:33 2010 +0000
+++ b/hgexpwidget.h	Wed Nov 24 14:41:52 2010 +0000
@@ -54,6 +54,9 @@
     bool canRemove() const;
     bool canDoFolderDiff() const;
 
+public slots:
+    void clearSelections();
+
 private:
     FileStatusWidget *fileStatusWidget;
 
--- a/mainwindow.cpp	Wed Nov 24 13:50:33 2010 +0000
+++ b/mainwindow.cpp	Wed Nov 24 14:41:52 2010 +0000
@@ -130,6 +130,10 @@
                         "-Windows standalone install uses InstallJammer setup tool (Thanks, great tool !)<br>"));
 }
 
+void MainWindow::clearSelections()
+{
+    hgExp->clearSelections();
+}
 
 void MainWindow::hgStat()
 {
@@ -349,6 +353,10 @@
 
 void MainWindow::hgCommit()
 {
+    //!!! Now that hg actions can be fired asynchronously (e.g. from
+    // the filesystem modified callback) we _really_ need to be able to
+    // queue important actions rather than just ignore them if busy!
+
     if (runningAction == ACT_NONE)
     {
         QStringList params;
@@ -1498,6 +1506,7 @@
     connect(hgResolveListAct, SIGNAL(triggered()), this, SLOT(hgResolveList()));
     connect(hgResolveMarkAct, SIGNAL(triggered()), this, SLOT(hgResolveMark()));
     connect(hgServeAct, SIGNAL(triggered()), this, SLOT(hgServe()));
+    connect(clearSelectionsAct, SIGNAL(triggered()), this, SLOT(clearSelections()));
 }
 
 void MainWindow::tabChanged(int currTab)
@@ -1776,6 +1785,10 @@
 
     aboutQtAct = new QAction(tr("About Qt"), this);
     aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
+
+    // Miscellaneous
+    clearSelectionsAct = new QAction(tr("Clear selections"), this);
+    clearSelectionsAct->setShortcut(Qt::Key_Escape);
 }
 
 void MainWindow::createMenus()
@@ -1783,6 +1796,7 @@
     fileMenu = menuBar()->addMenu(tr("File"));
     fileMenu -> addAction(hgInitAct);
     fileMenu -> addAction(hgCloneFromRemoteAct);
+    fileMenu->addAction(clearSelectionsAct); //!!! can't live here!
     fileMenu -> addSeparator();
     fileMenu -> addAction(openAct);
     fileMenu -> addAction(settingsAct);
--- a/mainwindow.h	Wed Nov 24 13:50:33 2010 +0000
+++ b/mainwindow.h	Wed Nov 24 14:41:52 2010 +0000
@@ -93,6 +93,7 @@
     void settings();
     void open();
     void startupDialog();
+    void clearSelections();
 
     void hgRemove();
     void hgAdd();
@@ -209,6 +210,9 @@
     QAction *aboutAct;
     QAction *aboutQtAct;
 
+    // Other actions
+    QAction *clearSelectionsAct;
+
     QToolBar *fileToolBar;
     QToolBar *repoToolBar;
     QToolBar *workFolderToolBar;