annotate filestatuswidget.cpp @ 103:0bd32aedc6f6

* Start to use the confirm-comment dialog for commits; much work still needed
author Chris Cannam
date Wed, 24 Nov 2010 22:44:40 +0000
parents f70ccc15c9d0
children 729438d70af8
rev   line source
Chris@88 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@88 2
Chris@88 3 /*
Chris@88 4 EasyMercurial
Chris@88 5
Chris@88 6 Based on HgExplorer by Jari Korhonen
Chris@88 7 Copyright (c) 2010 Jari Korhonen
Chris@88 8 Copyright (c) 2010 Chris Cannam
Chris@88 9 Copyright (c) 2010 Queen Mary, University of London
Chris@88 10
Chris@88 11 This program is free software; you can redistribute it and/or
Chris@88 12 modify it under the terms of the GNU General Public License as
Chris@88 13 published by the Free Software Foundation; either version 2 of the
Chris@88 14 License, or (at your option) any later version. See the file
Chris@88 15 COPYING included with this distribution for more information.
Chris@88 16 */
Chris@88 17
Chris@88 18 #include "filestatuswidget.h"
Chris@88 19
Chris@88 20 #include <QLabel>
Chris@88 21 #include <QListWidget>
Chris@88 22 #include <QGridLayout>
Chris@93 23 #include <QFileInfo>
Chris@93 24 #include <QApplication>
Chris@93 25 #include <QDateTime>
Chris@93 26
Chris@93 27 #include "debug.h"
Chris@88 28
Chris@88 29 FileStatusWidget::FileStatusWidget(QWidget *parent) :
Chris@93 30 QWidget(parent),
Chris@93 31 m_dateReference(0)
Chris@88 32 {
Chris@88 33 QGridLayout *layout = new QGridLayout;
Chris@88 34 setLayout(layout);
Chris@88 35
Chris@88 36 int row = 0;
Chris@88 37
Chris@88 38 layout->addWidget(new QLabel(tr("Local:")), row, 0);
Chris@88 39 m_localPathLabel = new QLabel;
Chris@89 40 QFont f(m_localPathLabel->font());
Chris@89 41 f.setBold(true);
Chris@89 42 m_localPathLabel->setFont(f);
Chris@88 43 layout->addWidget(m_localPathLabel, row, 1);
Chris@88 44
Chris@88 45 ++row;
Chris@88 46 layout->addWidget(new QLabel(tr("Remote:")), row, 0);
Chris@88 47 m_remoteURLLabel = new QLabel;
Chris@88 48 layout->addWidget(m_remoteURLLabel, row, 1);
Chris@88 49
Chris@89 50 layout->setColumnStretch(1, 20);
Chris@88 51
Chris@100 52 m_simpleLabels[FileStates::Clean] = tr("Unmodified:");
Chris@100 53 m_simpleLabels[FileStates::Modified] = tr("Modified:");
Chris@100 54 m_simpleLabels[FileStates::Added] = tr("Added:");
Chris@100 55 m_simpleLabels[FileStates::Removed] = tr("Removed:");
Chris@100 56 m_simpleLabels[FileStates::Missing] = tr("Missing:");
Chris@100 57 m_simpleLabels[FileStates::Unknown] = tr("Untracked:");
Chris@99 58
Chris@100 59 m_descriptions[FileStates::Clean] = tr("You have not changed these files.");
Chris@100 60 m_descriptions[FileStates::Modified] = tr("You have changed these files since you last committed them.");
Chris@100 61 m_descriptions[FileStates::Added] = tr("These files will be added to version control next time you commit.");
Chris@100 62 m_descriptions[FileStates::Removed] = tr("These files will be removed from version control next time you commit.<br>"
Chris@100 63 "They will not be deleted from the local folder.");
Chris@100 64 m_descriptions[FileStates::Missing] = tr("These files are recorded in the version control but absent from your working folder.<br>"
Chris@100 65 "If you deleted them intentionally, select them here and use <b>Remove</b> to tell the version control system about it.");
Chris@100 66 m_descriptions[FileStates::Unknown] = tr("These files are in your working folder but are not under version control.<br>"
Chris@100 67 "Select a file and use Add to place it under version control or Ignore to remove it from this list.");
Chris@100 68
Chris@102 69 m_highlightExplanation = tr("Files highlighted <font color=red>in red</font> "
Chris@100 70 "have appeared since your most recent commit or update.");
Chris@89 71
Chris@94 72 for (int i = int(FileStates::FirstState);
Chris@94 73 i <= int(FileStates::LastState); ++i) {
Chris@89 74
Chris@94 75 FileStates::State s = FileStates::State(i);
Chris@89 76
Chris@89 77 QWidget *box = new QWidget;
Chris@89 78 QGridLayout *boxlayout = new QGridLayout;
Chris@99 79 boxlayout->setMargin(0);
Chris@89 80 box->setLayout(boxlayout);
Chris@89 81
Chris@101 82 boxlayout->addItem(new QSpacerItem(5, 8), 0, 0);
Chris@101 83
Chris@101 84 boxlayout->addWidget(new QLabel(labelFor(s)), 1, 0);
Chris@89 85
Chris@94 86 QListWidget *w = new QListWidget;
Chris@94 87 m_stateListMap[s] = w;
Chris@94 88 w->setSelectionMode(QListWidget::ExtendedSelection);
Chris@101 89 boxlayout->addWidget(w, 2, 0);
Chris@89 90
Chris@95 91 connect(w, SIGNAL(itemSelectionChanged()),
Chris@95 92 this, SLOT(itemSelectionChanged()));
Chris@95 93
Chris@89 94 layout->addWidget(box, ++row, 0, 1, 2);
Chris@89 95 box->hide();
Chris@89 96 }
Chris@89 97
Chris@89 98 layout->setRowStretch(++row, 20);
Chris@88 99 }
Chris@88 100
Chris@93 101 FileStatusWidget::~FileStatusWidget()
Chris@93 102 {
Chris@93 103 delete m_dateReference;
Chris@93 104 }
Chris@93 105
Chris@100 106 QString FileStatusWidget::labelFor(FileStates::State s, bool addHighlightExplanation)
Chris@100 107 {
Chris@100 108 if (addHighlightExplanation) {
Chris@100 109 return QString("<qt><b>%1</b><br>%2<br>%3</qt>")
Chris@100 110 .arg(m_simpleLabels[s])
Chris@100 111 .arg(m_descriptions[s])
Chris@100 112 .arg(m_highlightExplanation);
Chris@100 113 } else {
Chris@100 114 return QString("<qt><b>%1</b><br>%2</qt>")
Chris@100 115 .arg(m_simpleLabels[s])
Chris@100 116 .arg(m_descriptions[s]);
Chris@100 117 }
Chris@100 118 }
Chris@100 119
Chris@95 120 void FileStatusWidget::itemSelectionChanged()
Chris@95 121 {
Chris@95 122 m_selectedFiles.clear();
Chris@95 123
Chris@95 124 DEBUG << "FileStatusWidget::itemSelectionChanged" << endl;
Chris@95 125
Chris@95 126 foreach (QListWidget *w, m_stateListMap) {
Chris@95 127 QList<QListWidgetItem *> sel = w->selectedItems();
Chris@95 128 foreach (QListWidgetItem *i, sel) {
Chris@95 129 m_selectedFiles.push_back(i->text());
Chris@95 130 DEBUG << "file " << i->text() << " is selected" << endl;
Chris@95 131 }
Chris@95 132 }
Chris@95 133
Chris@95 134 emit selectionChanged();
Chris@95 135 }
Chris@95 136
Chris@94 137 void FileStatusWidget::clearSelections()
Chris@94 138 {
Chris@95 139 m_selectedFiles.clear();
Chris@94 140 foreach (QListWidget *w, m_stateListMap) {
Chris@94 141 w->clearSelection();
Chris@94 142 }
Chris@94 143 }
Chris@94 144
Chris@95 145 bool FileStatusWidget::haveChangesToCommit() const
Chris@95 146 {
Chris@95 147 return !m_fileStates.added().empty() ||
Chris@95 148 !m_fileStates.removed().empty() ||
Chris@95 149 !m_fileStates.modified().empty();
Chris@95 150 }
Chris@95 151
Chris@95 152 bool FileStatusWidget::haveSelection() const
Chris@95 153 {
Chris@95 154 return !m_selectedFiles.empty();
Chris@95 155 }
Chris@95 156
Chris@95 157 QStringList FileStatusWidget::getAllSelectedFiles() const
Chris@95 158 {
Chris@95 159 return m_selectedFiles;
Chris@95 160 }
Chris@95 161
Chris@95 162 QStringList FileStatusWidget::getSelectedCommittableFiles() const
Chris@95 163 {
Chris@95 164 QStringList files;
Chris@95 165 foreach (QString f, m_selectedFiles) {
Chris@95 166 switch (m_fileStates.getStateOfFile(f)) {
Chris@95 167 case FileStates::Added:
Chris@95 168 case FileStates::Modified:
Chris@95 169 case FileStates::Removed:
Chris@95 170 files.push_back(f);
Chris@95 171 break;
Chris@95 172 default: break;
Chris@95 173 }
Chris@95 174 }
Chris@95 175 return files;
Chris@95 176 }
Chris@95 177
Chris@103 178 QStringList FileStatusWidget::getAllCommittableFiles() const
Chris@103 179 {
Chris@103 180 QStringList files;
Chris@103 181 files << m_fileStates.getFilesInState(FileStates::Modified);
Chris@103 182 files << m_fileStates.getFilesInState(FileStates::Added);
Chris@103 183 files << m_fileStates.getFilesInState(FileStates::Removed);
Chris@103 184 return files;
Chris@103 185 }
Chris@103 186
Chris@95 187 QStringList FileStatusWidget::getSelectedAddableFiles() const
Chris@95 188 {
Chris@95 189 QStringList files;
Chris@95 190 foreach (QString f, m_selectedFiles) {
Chris@95 191 switch (m_fileStates.getStateOfFile(f)) {
Chris@95 192 case FileStates::Unknown:
Chris@95 193 case FileStates::Removed:
Chris@95 194 files.push_back(f);
Chris@95 195 break;
Chris@95 196 default: break;
Chris@95 197 }
Chris@95 198 }
Chris@95 199 return files;
Chris@95 200 }
Chris@95 201
Chris@103 202 QStringList FileStatusWidget::getAllAddableFiles() const
Chris@103 203 {
Chris@103 204 QStringList files;
Chris@103 205 files << m_fileStates.getFilesInState(FileStates::Removed);
Chris@103 206 files << m_fileStates.getFilesInState(FileStates::Unknown);
Chris@103 207 return files;
Chris@103 208 }
Chris@103 209
Chris@95 210 QStringList FileStatusWidget::getSelectedRemovableFiles() const
Chris@95 211 {
Chris@95 212 QStringList files;
Chris@95 213 foreach (QString f, m_selectedFiles) {
Chris@95 214 switch (m_fileStates.getStateOfFile(f)) {
Chris@95 215 case FileStates::Clean:
Chris@95 216 case FileStates::Added:
Chris@95 217 case FileStates::Modified:
Chris@95 218 case FileStates::Missing:
Chris@95 219 files.push_back(f);
Chris@95 220 break;
Chris@95 221 default: break;
Chris@95 222 }
Chris@95 223 }
Chris@95 224 return files;
Chris@95 225 }
Chris@95 226
Chris@103 227 QStringList FileStatusWidget::getAllRemovableFiles() const
Chris@103 228 {
Chris@103 229 QStringList files;
Chris@103 230 files << m_fileStates.getFilesInState(FileStates::Clean);
Chris@103 231 files << m_fileStates.getFilesInState(FileStates::Added);
Chris@103 232 files << m_fileStates.getFilesInState(FileStates::Modified);
Chris@103 233 files << m_fileStates.getFilesInState(FileStates::Missing);
Chris@103 234 return files;
Chris@103 235 }
Chris@103 236
Chris@88 237 void
Chris@88 238 FileStatusWidget::setLocalPath(QString p)
Chris@88 239 {
Chris@88 240 m_localPath = p;
Chris@88 241 m_localPathLabel->setText(p);
Chris@93 242 delete m_dateReference;
Chris@93 243 m_dateReference = new QFileInfo(p + "/.hg/dirstate");
Chris@93 244 if (!m_dateReference->exists() ||
Chris@93 245 !m_dateReference->isFile() ||
Chris@93 246 !m_dateReference->isReadable()) {
Chris@93 247 DEBUG << "FileStatusWidget::setLocalPath: date reference file "
Chris@93 248 << m_dateReference->absoluteFilePath()
Chris@93 249 << " does not exist, is not a file, or cannot be read"
Chris@93 250 << endl;
Chris@93 251 delete m_dateReference;
Chris@93 252 m_dateReference = 0;
Chris@93 253 }
Chris@88 254 }
Chris@88 255
Chris@88 256 void
Chris@88 257 FileStatusWidget::setRemoteURL(QString r)
Chris@88 258 {
Chris@88 259 m_remoteURL = r;
Chris@88 260 m_remoteURLLabel->setText(r);
Chris@88 261 }
Chris@88 262
Chris@88 263 void
Chris@92 264 FileStatusWidget::setFileStates(FileStates p)
Chris@88 265 {
Chris@92 266 m_fileStates = p;
Chris@88 267 updateWidgets();
Chris@88 268 }
Chris@88 269
Chris@88 270 void
Chris@88 271 FileStatusWidget::updateWidgets()
Chris@88 272 {
Chris@95 273 QDateTime lastInteractionTime;
Chris@95 274 if (m_dateReference) {
Chris@95 275 lastInteractionTime = m_dateReference->lastModified();
Chris@95 276 DEBUG << "reference time: " << lastInteractionTime << endl;
Chris@95 277 }
Chris@95 278
Chris@95 279 QSet<QString> selectedFiles;
Chris@95 280 foreach (QString f, m_selectedFiles) selectedFiles.insert(f);
Chris@95 281
Chris@94 282 foreach (FileStates::State s, m_stateListMap.keys()) {
Chris@95 283
Chris@94 284 QListWidget *w = m_stateListMap[s];
Chris@94 285 w->clear();
Chris@95 286 QStringList files = m_fileStates.getFilesInState(s);
Chris@93 287
Chris@95 288 QStringList highPriority, lowPriority;
Chris@95 289
Chris@95 290 foreach (QString file, files) {
Chris@95 291
Chris@95 292 bool highlighted = false;
Chris@95 293
Chris@95 294 if (s == FileStates::Unknown) {
Chris@95 295 // We want to highlight untracked files that have appeared
Chris@95 296 // since the last interaction with the repo
Chris@95 297 QString fn(m_localPath + "/" + file);
Chris@95 298 DEBUG << "comparing with " << fn << endl;
Chris@95 299 QFileInfo fi(fn);
Chris@100 300 if (fi.exists() && fi.created() > lastInteractionTime) {
Chris@95 301 DEBUG << "file " << fn << " is newer (" << fi.lastModified()
Chris@95 302 << ") than reference" << endl;
Chris@95 303 highlighted = true;
Chris@95 304 }
Chris@95 305 }
Chris@95 306
Chris@95 307 if (highlighted) {
Chris@95 308 highPriority.push_back(file);
Chris@95 309 } else {
Chris@95 310 lowPriority.push_back(file);
Chris@93 311 }
Chris@93 312 }
Chris@95 313
Chris@95 314 foreach (QString file, highPriority) {
Chris@95 315 QListWidgetItem *item = new QListWidgetItem(file);
Chris@95 316 w->addItem(item);
Chris@95 317 item->setForeground(Qt::red); //!!! and a nice gold star
Chris@95 318 item->setSelected(selectedFiles.contains(file));
Chris@95 319 }
Chris@95 320
Chris@95 321 foreach (QString file, lowPriority) {
Chris@95 322 QListWidgetItem *item = new QListWidgetItem(file);
Chris@95 323 w->addItem(item);
Chris@95 324 item->setSelected(selectedFiles.contains(file));
Chris@95 325 }
Chris@95 326
Chris@100 327 setLabelFor(w, s, !highPriority.empty());
Chris@100 328
Chris@95 329 w->parentWidget()->setVisible(!files.empty());
Chris@93 330 }
Chris@88 331 }
Chris@88 332
Chris@100 333 void FileStatusWidget::setLabelFor(QWidget *w, FileStates::State s, bool addHighlight)
Chris@100 334 {
Chris@100 335 QString text = labelFor(s, addHighlight);
Chris@100 336 QWidget *p = w->parentWidget();
Chris@100 337 QList<QLabel *> ql = p->findChildren<QLabel *>();
Chris@100 338 if (!ql.empty()) ql[0]->setText(text);
Chris@100 339 }