annotate filestatuswidget.cpp @ 111:151209bc5bd6

* Fixes to terminal lifecycle (only the first of a series of interactive commands was working before). Also switch from openpty to POSIX/Unix98 openpt
author Chris Cannam
date Fri, 26 Nov 2010 16:28:18 +0000
parents 1721c580c10e
children 78374cefa10f
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@106 50 ++row;
Chris@106 51 layout->addWidget(new QLabel(tr("Branch:")), row, 0);
Chris@106 52 m_branchLabel = new QLabel;
Chris@106 53 layout->addWidget(m_branchLabel, row, 1);
Chris@106 54
Chris@89 55 layout->setColumnStretch(1, 20);
Chris@88 56
Chris@106 57 layout->addWidget(new QLabel("<qt><hr></qt>"), ++row, 0, 1, 2);
Chris@106 58
Chris@100 59 m_simpleLabels[FileStates::Clean] = tr("Unmodified:");
Chris@100 60 m_simpleLabels[FileStates::Modified] = tr("Modified:");
Chris@100 61 m_simpleLabels[FileStates::Added] = tr("Added:");
Chris@100 62 m_simpleLabels[FileStates::Removed] = tr("Removed:");
Chris@100 63 m_simpleLabels[FileStates::Missing] = tr("Missing:");
Chris@100 64 m_simpleLabels[FileStates::Unknown] = tr("Untracked:");
Chris@99 65
Chris@100 66 m_descriptions[FileStates::Clean] = tr("You have not changed these files.");
Chris@100 67 m_descriptions[FileStates::Modified] = tr("You have changed these files since you last committed them.");
Chris@100 68 m_descriptions[FileStates::Added] = tr("These files will be added to version control next time you commit.");
Chris@100 69 m_descriptions[FileStates::Removed] = tr("These files will be removed from version control next time you commit.<br>"
Chris@100 70 "They will not be deleted from the local folder.");
Chris@109 71 m_descriptions[FileStates::Missing] = tr("These files are recorded in the version control, but absent from your working folder.<br>"
Chris@109 72 "If you deleted them by accident, select them here and use Revert to restore their previous contents.<br>"
Chris@109 73 "If you deleted them intentionally, select them here and use Remove to tell the version control system about it.");
Chris@100 74 m_descriptions[FileStates::Unknown] = tr("These files are in your working folder but are not under version control.<br>"
Chris@100 75 "Select a file and use Add to place it under version control or Ignore to remove it from this list.");
Chris@100 76
Chris@102 77 m_highlightExplanation = tr("Files highlighted <font color=red>in red</font> "
Chris@100 78 "have appeared since your most recent commit or update.");
Chris@89 79
Chris@94 80 for (int i = int(FileStates::FirstState);
Chris@94 81 i <= int(FileStates::LastState); ++i) {
Chris@89 82
Chris@94 83 FileStates::State s = FileStates::State(i);
Chris@89 84
Chris@89 85 QWidget *box = new QWidget;
Chris@89 86 QGridLayout *boxlayout = new QGridLayout;
Chris@99 87 boxlayout->setMargin(0);
Chris@89 88 box->setLayout(boxlayout);
Chris@89 89
Chris@106 90 boxlayout->addItem(new QSpacerItem(5, 5), 0, 0);
Chris@101 91
Chris@101 92 boxlayout->addWidget(new QLabel(labelFor(s)), 1, 0);
Chris@89 93
Chris@94 94 QListWidget *w = new QListWidget;
Chris@94 95 m_stateListMap[s] = w;
Chris@94 96 w->setSelectionMode(QListWidget::ExtendedSelection);
Chris@101 97 boxlayout->addWidget(w, 2, 0);
Chris@89 98
Chris@95 99 connect(w, SIGNAL(itemSelectionChanged()),
Chris@95 100 this, SLOT(itemSelectionChanged()));
Chris@95 101
Chris@89 102 layout->addWidget(box, ++row, 0, 1, 2);
Chris@89 103 box->hide();
Chris@89 104 }
Chris@89 105
Chris@89 106 layout->setRowStretch(++row, 20);
Chris@88 107 }
Chris@88 108
Chris@93 109 FileStatusWidget::~FileStatusWidget()
Chris@93 110 {
Chris@93 111 delete m_dateReference;
Chris@93 112 }
Chris@93 113
Chris@100 114 QString FileStatusWidget::labelFor(FileStates::State s, bool addHighlightExplanation)
Chris@100 115 {
Chris@100 116 if (addHighlightExplanation) {
Chris@100 117 return QString("<qt><b>%1</b><br>%2<br>%3</qt>")
Chris@100 118 .arg(m_simpleLabels[s])
Chris@100 119 .arg(m_descriptions[s])
Chris@100 120 .arg(m_highlightExplanation);
Chris@100 121 } else {
Chris@100 122 return QString("<qt><b>%1</b><br>%2</qt>")
Chris@100 123 .arg(m_simpleLabels[s])
Chris@100 124 .arg(m_descriptions[s]);
Chris@100 125 }
Chris@100 126 }
Chris@100 127
Chris@95 128 void FileStatusWidget::itemSelectionChanged()
Chris@95 129 {
Chris@95 130 m_selectedFiles.clear();
Chris@95 131
Chris@95 132 DEBUG << "FileStatusWidget::itemSelectionChanged" << endl;
Chris@95 133
Chris@95 134 foreach (QListWidget *w, m_stateListMap) {
Chris@95 135 QList<QListWidgetItem *> sel = w->selectedItems();
Chris@95 136 foreach (QListWidgetItem *i, sel) {
Chris@95 137 m_selectedFiles.push_back(i->text());
Chris@95 138 DEBUG << "file " << i->text() << " is selected" << endl;
Chris@95 139 }
Chris@95 140 }
Chris@95 141
Chris@95 142 emit selectionChanged();
Chris@95 143 }
Chris@95 144
Chris@94 145 void FileStatusWidget::clearSelections()
Chris@94 146 {
Chris@95 147 m_selectedFiles.clear();
Chris@94 148 foreach (QListWidget *w, m_stateListMap) {
Chris@94 149 w->clearSelection();
Chris@94 150 }
Chris@94 151 }
Chris@94 152
Chris@95 153 bool FileStatusWidget::haveChangesToCommit() const
Chris@95 154 {
Chris@95 155 return !m_fileStates.added().empty() ||
Chris@95 156 !m_fileStates.removed().empty() ||
Chris@95 157 !m_fileStates.modified().empty();
Chris@95 158 }
Chris@95 159
Chris@95 160 bool FileStatusWidget::haveSelection() const
Chris@95 161 {
Chris@95 162 return !m_selectedFiles.empty();
Chris@95 163 }
Chris@95 164
Chris@95 165 QStringList FileStatusWidget::getAllSelectedFiles() const
Chris@95 166 {
Chris@95 167 return m_selectedFiles;
Chris@95 168 }
Chris@95 169
Chris@95 170 QStringList FileStatusWidget::getSelectedCommittableFiles() const
Chris@95 171 {
Chris@95 172 QStringList files;
Chris@95 173 foreach (QString f, m_selectedFiles) {
Chris@95 174 switch (m_fileStates.getStateOfFile(f)) {
Chris@95 175 case FileStates::Added:
Chris@95 176 case FileStates::Modified:
Chris@95 177 case FileStates::Removed:
Chris@95 178 files.push_back(f);
Chris@95 179 break;
Chris@95 180 default: break;
Chris@95 181 }
Chris@95 182 }
Chris@95 183 return files;
Chris@95 184 }
Chris@95 185
Chris@103 186 QStringList FileStatusWidget::getAllCommittableFiles() const
Chris@103 187 {
Chris@103 188 QStringList files;
Chris@103 189 files << m_fileStates.getFilesInState(FileStates::Modified);
Chris@103 190 files << m_fileStates.getFilesInState(FileStates::Added);
Chris@103 191 files << m_fileStates.getFilesInState(FileStates::Removed);
Chris@103 192 return files;
Chris@103 193 }
Chris@103 194
Chris@109 195 QStringList FileStatusWidget::getSelectedRevertableFiles() const
Chris@109 196 {
Chris@109 197 QStringList files;
Chris@109 198 foreach (QString f, m_selectedFiles) {
Chris@109 199 switch (m_fileStates.getStateOfFile(f)) {
Chris@109 200 case FileStates::Added:
Chris@109 201 case FileStates::Modified:
Chris@109 202 case FileStates::Removed:
Chris@109 203 case FileStates::Missing:
Chris@109 204 files.push_back(f);
Chris@109 205 break;
Chris@109 206 default: break;
Chris@109 207 }
Chris@109 208 }
Chris@109 209 return files;
Chris@109 210 }
Chris@109 211
Chris@109 212 QStringList FileStatusWidget::getAllRevertableFiles() const
Chris@109 213 {
Chris@109 214 QStringList files;
Chris@109 215 files << m_fileStates.getFilesInState(FileStates::Modified);
Chris@109 216 files << m_fileStates.getFilesInState(FileStates::Added);
Chris@109 217 files << m_fileStates.getFilesInState(FileStates::Removed);
Chris@109 218 files << m_fileStates.getFilesInState(FileStates::Missing);
Chris@109 219 return files;
Chris@109 220 }
Chris@109 221
Chris@95 222 QStringList FileStatusWidget::getSelectedAddableFiles() const
Chris@95 223 {
Chris@95 224 QStringList files;
Chris@95 225 foreach (QString f, m_selectedFiles) {
Chris@95 226 switch (m_fileStates.getStateOfFile(f)) {
Chris@95 227 case FileStates::Unknown:
Chris@95 228 case FileStates::Removed:
Chris@95 229 files.push_back(f);
Chris@95 230 break;
Chris@95 231 default: break;
Chris@95 232 }
Chris@95 233 }
Chris@95 234 return files;
Chris@95 235 }
Chris@95 236
Chris@103 237 QStringList FileStatusWidget::getAllAddableFiles() const
Chris@103 238 {
Chris@103 239 QStringList files;
Chris@103 240 files << m_fileStates.getFilesInState(FileStates::Removed);
Chris@103 241 files << m_fileStates.getFilesInState(FileStates::Unknown);
Chris@103 242 return files;
Chris@103 243 }
Chris@103 244
Chris@95 245 QStringList FileStatusWidget::getSelectedRemovableFiles() const
Chris@95 246 {
Chris@95 247 QStringList files;
Chris@95 248 foreach (QString f, m_selectedFiles) {
Chris@95 249 switch (m_fileStates.getStateOfFile(f)) {
Chris@95 250 case FileStates::Clean:
Chris@95 251 case FileStates::Added:
Chris@95 252 case FileStates::Modified:
Chris@95 253 case FileStates::Missing:
Chris@95 254 files.push_back(f);
Chris@95 255 break;
Chris@95 256 default: break;
Chris@95 257 }
Chris@95 258 }
Chris@95 259 return files;
Chris@95 260 }
Chris@95 261
Chris@103 262 QStringList FileStatusWidget::getAllRemovableFiles() const
Chris@103 263 {
Chris@103 264 QStringList files;
Chris@103 265 files << m_fileStates.getFilesInState(FileStates::Clean);
Chris@103 266 files << m_fileStates.getFilesInState(FileStates::Added);
Chris@103 267 files << m_fileStates.getFilesInState(FileStates::Modified);
Chris@103 268 files << m_fileStates.getFilesInState(FileStates::Missing);
Chris@103 269 return files;
Chris@103 270 }
Chris@103 271
Chris@88 272 void
Chris@88 273 FileStatusWidget::setLocalPath(QString p)
Chris@88 274 {
Chris@88 275 m_localPath = p;
Chris@88 276 m_localPathLabel->setText(p);
Chris@93 277 delete m_dateReference;
Chris@93 278 m_dateReference = new QFileInfo(p + "/.hg/dirstate");
Chris@93 279 if (!m_dateReference->exists() ||
Chris@93 280 !m_dateReference->isFile() ||
Chris@93 281 !m_dateReference->isReadable()) {
Chris@93 282 DEBUG << "FileStatusWidget::setLocalPath: date reference file "
Chris@93 283 << m_dateReference->absoluteFilePath()
Chris@93 284 << " does not exist, is not a file, or cannot be read"
Chris@93 285 << endl;
Chris@93 286 delete m_dateReference;
Chris@93 287 m_dateReference = 0;
Chris@93 288 }
Chris@88 289 }
Chris@88 290
Chris@88 291 void
Chris@88 292 FileStatusWidget::setRemoteURL(QString r)
Chris@88 293 {
Chris@88 294 m_remoteURL = r;
Chris@88 295 m_remoteURLLabel->setText(r);
Chris@88 296 }
Chris@88 297
Chris@88 298 void
Chris@92 299 FileStatusWidget::setFileStates(FileStates p)
Chris@88 300 {
Chris@92 301 m_fileStates = p;
Chris@88 302 updateWidgets();
Chris@88 303 }
Chris@88 304
Chris@88 305 void
Chris@106 306 FileStatusWidget::setBranch(QString b)
Chris@106 307 {
Chris@106 308 m_branch = b;
Chris@106 309 m_branchLabel->setText(b);
Chris@106 310 }
Chris@106 311
Chris@106 312 void
Chris@88 313 FileStatusWidget::updateWidgets()
Chris@88 314 {
Chris@95 315 QDateTime lastInteractionTime;
Chris@95 316 if (m_dateReference) {
Chris@95 317 lastInteractionTime = m_dateReference->lastModified();
Chris@95 318 DEBUG << "reference time: " << lastInteractionTime << endl;
Chris@95 319 }
Chris@95 320
Chris@95 321 QSet<QString> selectedFiles;
Chris@95 322 foreach (QString f, m_selectedFiles) selectedFiles.insert(f);
Chris@95 323
Chris@94 324 foreach (FileStates::State s, m_stateListMap.keys()) {
Chris@95 325
Chris@94 326 QListWidget *w = m_stateListMap[s];
Chris@94 327 w->clear();
Chris@95 328 QStringList files = m_fileStates.getFilesInState(s);
Chris@93 329
Chris@95 330 QStringList highPriority, lowPriority;
Chris@95 331
Chris@95 332 foreach (QString file, files) {
Chris@95 333
Chris@95 334 bool highlighted = false;
Chris@95 335
Chris@95 336 if (s == FileStates::Unknown) {
Chris@95 337 // We want to highlight untracked files that have appeared
Chris@95 338 // since the last interaction with the repo
Chris@95 339 QString fn(m_localPath + "/" + file);
Chris@95 340 DEBUG << "comparing with " << fn << endl;
Chris@95 341 QFileInfo fi(fn);
Chris@100 342 if (fi.exists() && fi.created() > lastInteractionTime) {
Chris@95 343 DEBUG << "file " << fn << " is newer (" << fi.lastModified()
Chris@95 344 << ") than reference" << endl;
Chris@95 345 highlighted = true;
Chris@95 346 }
Chris@95 347 }
Chris@95 348
Chris@95 349 if (highlighted) {
Chris@95 350 highPriority.push_back(file);
Chris@95 351 } else {
Chris@95 352 lowPriority.push_back(file);
Chris@93 353 }
Chris@93 354 }
Chris@95 355
Chris@95 356 foreach (QString file, highPriority) {
Chris@95 357 QListWidgetItem *item = new QListWidgetItem(file);
Chris@95 358 w->addItem(item);
Chris@95 359 item->setForeground(Qt::red); //!!! and a nice gold star
Chris@95 360 item->setSelected(selectedFiles.contains(file));
Chris@95 361 }
Chris@95 362
Chris@95 363 foreach (QString file, lowPriority) {
Chris@95 364 QListWidgetItem *item = new QListWidgetItem(file);
Chris@95 365 w->addItem(item);
Chris@95 366 item->setSelected(selectedFiles.contains(file));
Chris@95 367 }
Chris@95 368
Chris@100 369 setLabelFor(w, s, !highPriority.empty());
Chris@100 370
Chris@95 371 w->parentWidget()->setVisible(!files.empty());
Chris@93 372 }
Chris@88 373 }
Chris@88 374
Chris@100 375 void FileStatusWidget::setLabelFor(QWidget *w, FileStates::State s, bool addHighlight)
Chris@100 376 {
Chris@100 377 QString text = labelFor(s, addHighlight);
Chris@100 378 QWidget *p = w->parentWidget();
Chris@100 379 QList<QLabel *> ql = p->findChildren<QLabel *>();
Chris@100 380 if (!ql.empty()) ql[0]->setText(text);
Chris@100 381 }