annotate src/filestatuswidget.cpp @ 676:cb4f7c3c01dd

Toward some CI bits
author Chris Cannam
date Thu, 06 Dec 2018 13:45:23 +0000
parents ae67ea0af696
children
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@644 8 Copyright (c) 2013 Chris Cannam
Chris@644 9 Copyright (c) 2013 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@115 19 #include "debug.h"
Chris@115 20 #include "multichoicedialog.h"
Chris@558 21 #include "findwidget.h"
Chris@88 22
Chris@88 23 #include <QLabel>
Chris@88 24 #include <QListWidget>
Chris@88 25 #include <QGridLayout>
Chris@93 26 #include <QFileInfo>
Chris@93 27 #include <QApplication>
Chris@93 28 #include <QDateTime>
Chris@115 29 #include <QPushButton>
Chris@186 30 #include <QToolButton>
Chris@186 31 #include <QDir>
Chris@186 32 #include <QProcess>
Chris@199 33 #include <QCheckBox>
Chris@230 34 #include <QSettings>
Chris@323 35 #include <QAction>
Chris@88 36
Chris@88 37 FileStatusWidget::FileStatusWidget(QWidget *parent) :
Chris@93 38 QWidget(parent),
Chris@93 39 m_dateReference(0)
Chris@88 40 {
Chris@88 41 QGridLayout *layout = new QGridLayout;
Chris@215 42 layout->setMargin(10);
Chris@88 43 setLayout(layout);
Chris@88 44
Chris@88 45 int row = 0;
Chris@211 46
Chris@230 47 m_noModificationsLabel = new QLabel;
Chris@230 48 setNoModificationsLabelText();
Chris@297 49 layout->addWidget(m_noModificationsLabel, row, 0);
Chris@202 50 m_noModificationsLabel->hide();
Chris@106 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@163 57 m_simpleLabels[FileStates::InConflict] = tr("In Conflict:");
Chris@100 58 m_simpleLabels[FileStates::Unknown] = tr("Untracked:");
Chris@199 59 m_simpleLabels[FileStates::Ignored] = tr("Ignored:");
Chris@99 60
Chris@326 61 m_actionLabels[FileStates::Annotate] = tr("Show annotated version");
Chris@326 62 m_actionLabels[FileStates::Diff] = tr("Diff to parent");
Chris@325 63 m_actionLabels[FileStates::Commit] = tr("Commit...");
Chris@328 64 m_actionLabels[FileStates::Revert] = tr("Revert to last committed state");
Chris@361 65 m_actionLabels[FileStates::Rename] = tr("Rename...");
Chris@361 66 m_actionLabels[FileStates::Copy] = tr("Copy...");
Chris@326 67 m_actionLabels[FileStates::Add] = tr("Add to version control");
Chris@326 68 m_actionLabels[FileStates::Remove] = tr("Remove from version control");
Chris@326 69 m_actionLabels[FileStates::RedoMerge] = tr("Redo merge");
Chris@328 70 m_actionLabels[FileStates::MarkResolved] = tr("Mark conflict as resolved");
Chris@413 71 m_actionLabels[FileStates::Ignore] = tr("Ignore...");
Chris@421 72 // Unignore is too difficult in fact, so we just offer to edit the hgignore
Chris@421 73 m_actionLabels[FileStates::UnIgnore] = tr("Edit .hgignore File");
Chris@325 74
sam@624 75 // No "show in" under Unix at the moment.
sam@624 76 #if defined Q_OS_MAC
sam@624 77 m_actionLabels[FileStates::ShowIn] = tr("Show in Finder");
sam@624 78 #elif defined Q_OS_WIN32
sam@624 79 m_actionLabels[FileStates::ShowIn] = tr("Show in Windows Explorer");
sam@624 80 #endif
sam@624 81
sam@624 82 m_shortcuts[FileStates::ShowIn] = tr("Ctrl+Shift+S");
sam@627 83 m_shortcuts[FileStates::Diff] = tr("Ctrl+Shift+D");
sam@629 84 m_shortcuts[FileStates::Commit] = tr("Ctrl+Shift+C");
sam@632 85 m_shortcuts[FileStates::Revert] = tr("Ctrl+Shift+R");
sam@624 86
Chris@100 87 m_descriptions[FileStates::Clean] = tr("You have not changed these files.");
Chris@100 88 m_descriptions[FileStates::Modified] = tr("You have changed these files since you last committed them.");
Chris@225 89 m_descriptions[FileStates::Added] = tr("These files will be added to version control next time you commit them.");
Chris@225 90 m_descriptions[FileStates::Removed] = tr("These files will be removed from version control next time you commit them.<br>"
Chris@100 91 "They will not be deleted from the local folder.");
Chris@109 92 m_descriptions[FileStates::Missing] = tr("These files are recorded in the version control, but absent from your working folder.<br>"
Chris@153 93 "If you intended to delete them, select them and use Remove to tell the version control system about it.<br>"
Chris@596 94 "If you deleted them by accident, right-click them and use Revert to restore their previous contents.");
Chris@482 95 m_descriptions[FileStates::InConflict] = tr("These files are unresolved following an incomplete merge.<br>Use Merge to try to resolve the merge again.");
Chris@100 96 m_descriptions[FileStates::Unknown] = tr("These files are in your working folder but are not under version control.<br>"
Chris@186 97 // "Select a file and use Add to place it under version control or Ignore to remove it from this list.");
Chris@186 98 "Select a file and use Add to place it under version control.");
Chris@199 99 m_descriptions[FileStates::Ignored] = tr("These files have names that match entries in the working folder's .hgignore file,<br>"
Chris@199 100 "and so will be ignored by the version control system.");
Chris@100 101
Chris@118 102 m_highlightExplanation = tr("Files highlighted <font color=#d40000>in red</font> "
Chris@100 103 "have appeared since your most recent commit or update.");
Chris@89 104
Chris@230 105 m_boxesParent = new QWidget(this);
Chris@297 106 layout->addWidget(m_boxesParent, ++row, 0);
Chris@230 107
Chris@230 108 QGridLayout *boxesLayout = new QGridLayout;
Chris@230 109 boxesLayout->setMargin(0);
Chris@230 110 m_boxesParent->setLayout(boxesLayout);
Chris@230 111 int boxRow = 0;
Chris@230 112
Chris@94 113 for (int i = int(FileStates::FirstState);
Chris@163 114 i <= int(FileStates::LastState); ++i) {
Chris@89 115
Chris@94 116 FileStates::State s = FileStates::State(i);
Chris@89 117
Chris@230 118 QWidget *box = new QWidget(m_boxesParent);
Chris@89 119 QGridLayout *boxlayout = new QGridLayout;
Chris@99 120 boxlayout->setMargin(0);
Chris@89 121 box->setLayout(boxlayout);
Chris@89 122
Chris@211 123 boxlayout->addItem(new QSpacerItem(3, 3), 0, 0);
Chris@101 124
Chris@230 125 QLabel *label = new QLabel(labelFor(s));
Chris@230 126 label->setWordWrap(true);
Chris@230 127 boxlayout->addWidget(label, 1, 0);
Chris@89 128
Chris@94 129 QListWidget *w = new QListWidget;
Chris@94 130 m_stateListMap[s] = w;
Chris@94 131 w->setSelectionMode(QListWidget::ExtendedSelection);
Chris@101 132 boxlayout->addWidget(w, 2, 0);
Chris@89 133
Chris@95 134 connect(w, SIGNAL(itemSelectionChanged()),
Chris@95 135 this, SLOT(itemSelectionChanged()));
Chris@331 136 connect(w, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
Chris@331 137 this, SLOT(itemDoubleClicked(QListWidgetItem *)));
Chris@95 138
Chris@325 139 FileStates::Activities activities = m_fileStates.activitiesSupportedBy(s);
Chris@325 140 int prevGroup = -1;
Chris@325 141 foreach (FileStates::Activity a, activities) {
sam@624 142 QString label = m_actionLabels[a];
sam@624 143 if (label.length() == 0) {
sam@624 144 // Skip empty labels.
sam@624 145 continue;
sam@624 146 }
Chris@325 147 int group = FileStates::activityGroup(a);
Chris@325 148 if (group != prevGroup && prevGroup != -1) {
Chris@325 149 QAction *sep = new QAction("", w);
Chris@325 150 sep->setSeparator(true);
Chris@325 151 w->insertAction(0, sep);
Chris@325 152 }
Chris@325 153 prevGroup = group;
sam@624 154 QAction *act = new QAction(label, w);
Chris@326 155 act->setProperty("state", s);
Chris@326 156 act->setProperty("activity", a);
sam@624 157 if (m_shortcuts.contains(a)) {
sam@624 158 QString shortcut = m_shortcuts[a];
sam@624 159 act->setShortcut(shortcut);
sam@630 160 act->setShortcutContext(Qt::WidgetShortcut);
sam@624 161 }
Chris@326 162 connect(act, SIGNAL(triggered()), this, SLOT(menuActionActivated()));
Chris@325 163 w->insertAction(0, act);
Chris@325 164 }
Chris@323 165 w->setContextMenuPolicy(Qt::ActionsContextMenu);
Chris@323 166
Chris@211 167 boxlayout->addItem(new QSpacerItem(2, 2), 3, 0);
Chris@211 168
Chris@230 169 boxesLayout->addWidget(box, ++boxRow, 0);
Chris@230 170 m_boxes.push_back(box);
Chris@89 171 box->hide();
Chris@89 172 }
Chris@89 173
Chris@230 174 m_gridlyLayout = false;
Chris@230 175
Chris@89 176 layout->setRowStretch(++row, 20);
Chris@186 177
Chris@211 178 layout->addItem(new QSpacerItem(8, 8), ++row, 0);
Chris@199 179
Chris@558 180 QWidget *opts = new QWidget;
Chris@558 181 QGridLayout *optLayout = new QGridLayout(opts);
Chris@558 182 optLayout->setMargin(0);
Chris@558 183 layout->addWidget(opts, ++row, 0);
Chris@558 184
Chris@558 185 m_findWidget = new FindWidget(this);
Chris@558 186 optLayout->addWidget(m_findWidget, 0, 0, Qt::AlignLeft);
Chris@558 187 connect(m_findWidget, SIGNAL(findTextChanged(QString)),
Chris@558 188 this, SLOT(setSearchText(QString)));
Chris@558 189
Chris@558 190 m_showAllFiles = new QCheckBox(tr("Show all file states"), this);
Chris@340 191 m_showAllFiles->setEnabled(false);
Chris@558 192 optLayout->addWidget(m_showAllFiles, 0, 1, Qt::AlignRight);
Chris@484 193
Chris@484 194 QSettings settings;
Chris@484 195 m_showAllFiles->setChecked(settings.value("showall", false).toBool());
Chris@484 196
Chris@199 197 connect(m_showAllFiles, SIGNAL(toggled(bool)),
Chris@484 198 this, SIGNAL(showAllChanged()));
Chris@88 199 }
Chris@88 200
Chris@93 201 FileStatusWidget::~FileStatusWidget()
Chris@93 202 {
Chris@484 203 QSettings settings;
Chris@484 204 settings.setValue("showall", m_showAllFiles->isChecked());
Chris@484 205
Chris@93 206 delete m_dateReference;
Chris@93 207 }
Chris@93 208
Chris@484 209 bool FileStatusWidget::shouldShowAll() const
Chris@484 210 {
Chris@484 211 return m_showAllFiles->isChecked();
Chris@484 212 }
Chris@484 213
Chris@542 214 bool FileStatusWidget::shouldShow(FileStates::State s) const
Chris@542 215 {
Chris@542 216 if (shouldShowAll()) return true;
Chris@542 217 else return (s != FileStates::Clean &&
Chris@542 218 s != FileStates::Ignored);
Chris@542 219 }
Chris@542 220
Chris@100 221 QString FileStatusWidget::labelFor(FileStates::State s, bool addHighlightExplanation)
Chris@100 222 {
Chris@230 223 QSettings settings;
Chris@230 224 settings.beginGroup("Presentation");
Chris@230 225 if (settings.value("showhelpfultext", true).toBool()) {
Chris@230 226 if (addHighlightExplanation) {
Chris@230 227 return QString("<qt><b>%1</b><br>%2<br>%3</qt>")
Chris@230 228 .arg(m_simpleLabels[s])
Chris@230 229 .arg(m_descriptions[s])
Chris@230 230 .arg(m_highlightExplanation);
Chris@230 231 } else {
Chris@230 232 return QString("<qt><b>%1</b><br>%2</qt>")
Chris@230 233 .arg(m_simpleLabels[s])
Chris@230 234 .arg(m_descriptions[s]);
Chris@230 235 }
Chris@230 236 }
Chris@542 237 return QString("<qt><b>%1</b></qt>")
Chris@542 238 .arg(m_simpleLabels[s]);
Chris@230 239 }
Chris@230 240
Chris@230 241 void FileStatusWidget::setNoModificationsLabelText()
Chris@230 242 {
Chris@230 243 QSettings settings;
Chris@230 244 settings.beginGroup("Presentation");
Chris@558 245
Chris@558 246 if (m_searchText != "") {
Chris@558 247 if (!m_showAllFiles->isChecked()) {
Chris@558 248 m_noModificationsLabel->setText
Chris@558 249 (tr("<qt><b>Nothing found</b><br>None of the modified files have matching filenames.<br>Select <b>Show all file states</b> to find matches among unmodified and untracked files as well.</qt>"));
Chris@558 250 } else {
Chris@558 251 m_noModificationsLabel->setText
Chris@558 252 (tr("<qt><b>Nothing found</b><br>No files have matching filenames.</qt>"));
Chris@558 253 }
Chris@558 254 } else if (settings.value("showhelpfultext", true).toBool()) {
Chris@230 255 m_noModificationsLabel->setText
Chris@230 256 (tr("<qt>This area will list files in your working folder that you have changed.<br><br>At the moment you have no uncommitted changes.<br><br>To see changes previously made to the repository,<br>switch to the History tab.<br><br>%1</qt>")
Chris@230 257 #if defined Q_OS_MAC
Chris@230 258 .arg(tr("To open the working folder in Finder,<br>click on the &ldquo;Local&rdquo; folder path shown above."))
Chris@230 259 #elif defined Q_OS_WIN32
Chris@230 260 .arg(tr("To open the working folder in Windows Explorer,<br>click on the &ldquo;Local&rdquo; folder path shown above."))
Chris@230 261 #else
Chris@230 262 .arg(tr("To open the working folder in your system file manager,<br>click the &ldquo;Local&rdquo; folder path shown above."))
Chris@230 263 #endif
Chris@230 264 );
Chris@230 265 } else {
Chris@230 266 m_noModificationsLabel->setText
Chris@230 267 (tr("<qt>You have no uncommitted changes.</qt>"));
Chris@100 268 }
Chris@100 269 }
Chris@100 270
Chris@319 271
Chris@326 272 void FileStatusWidget::menuActionActivated()
Chris@326 273 {
Chris@326 274 QAction *act = qobject_cast<QAction *>(sender());
Chris@326 275 if (!act) return;
Chris@326 276
Chris@326 277 FileStates::State state = (FileStates::State)
Chris@326 278 act->property("state").toUInt();
Chris@326 279 FileStates::Activity activity = (FileStates::Activity)
Chris@326 280 act->property("activity").toUInt();
Chris@319 281
Chris@326 282 DEBUG << "menuActionActivated: state = " << state << ", activity = "
Chris@326 283 << activity << endl;
Chris@319 284
Chris@326 285 if (!FileStates::supportsActivity(state, activity)) {
Chris@326 286 std::cerr << "WARNING: FileStatusWidget::menuActionActivated: "
Chris@326 287 << "Action state " << state << " does not support activity "
Chris@326 288 << activity << std::endl;
Chris@326 289 return;
Chris@326 290 }
Chris@326 291
Chris@326 292 QStringList files = getSelectedFilesInState(state);
Chris@326 293
Chris@326 294 switch (activity) {
Chris@326 295 case FileStates::Annotate: emit annotateFiles(files); break;
Chris@326 296 case FileStates::Diff: emit diffFiles(files); break;
Chris@326 297 case FileStates::Commit: emit commitFiles(files); break;
Chris@326 298 case FileStates::Revert: emit revertFiles(files); break;
Chris@361 299 case FileStates::Rename: emit renameFiles(files); break;
Chris@361 300 case FileStates::Copy: emit copyFiles(files); break;
Chris@326 301 case FileStates::Add: emit addFiles(files); break;
Chris@326 302 case FileStates::Remove: emit removeFiles(files); break;
Chris@326 303 case FileStates::RedoMerge: emit redoFileMerges(files); break;
Chris@326 304 case FileStates::MarkResolved: emit markFilesResolved(files); break;
Chris@326 305 case FileStates::Ignore: emit ignoreFiles(files); break;
Chris@326 306 case FileStates::UnIgnore: emit unIgnoreFiles(files); break;
sam@624 307 case FileStates::ShowIn: emit showIn(files); break;
Chris@326 308 }
Chris@326 309 }
Chris@319 310
Chris@331 311 void FileStatusWidget::itemDoubleClicked(QListWidgetItem *item)
Chris@331 312 {
Chris@331 313 QStringList files;
Chris@350 314 QString file = item->text();
Chris@350 315 files << file;
Chris@350 316
Chris@350 317 switch (m_fileStates.stateOf(file)) {
Chris@350 318
Chris@350 319 case FileStates::Modified:
Chris@350 320 case FileStates::InConflict:
Chris@350 321 emit diffFiles(files);
Chris@350 322 break;
Chris@350 323
Chris@350 324 case FileStates::Clean:
Chris@350 325 case FileStates::Missing:
Chris@350 326 emit annotateFiles(files);
Chris@350 327 break;
Chris@373 328
Chris@373 329 default:
Chris@373 330 break;
Chris@350 331 }
Chris@331 332 }
Chris@319 333
Chris@95 334 void FileStatusWidget::itemSelectionChanged()
Chris@95 335 {
Chris@135 336 DEBUG << "FileStatusWidget::itemSelectionChanged" << endl;
Chris@135 337
Chris@135 338 QListWidget *list = qobject_cast<QListWidget *>(sender());
Chris@135 339
Chris@135 340 if (list) {
Chris@135 341 foreach (QListWidget *w, m_stateListMap) {
Chris@135 342 if (w != list) {
Chris@135 343 w->blockSignals(true);
Chris@135 344 w->clearSelection();
Chris@135 345 w->blockSignals(false);
Chris@135 346 }
Chris@135 347 }
Chris@135 348 }
Chris@135 349
Chris@95 350 m_selectedFiles.clear();
Chris@95 351
Chris@95 352 foreach (QListWidget *w, m_stateListMap) {
Chris@95 353 QList<QListWidgetItem *> sel = w->selectedItems();
Chris@95 354 foreach (QListWidgetItem *i, sel) {
Chris@95 355 m_selectedFiles.push_back(i->text());
Chris@95 356 DEBUG << "file " << i->text() << " is selected" << endl;
Chris@95 357 }
Chris@95 358 }
Chris@95 359
Chris@95 360 emit selectionChanged();
Chris@95 361 }
Chris@95 362
Chris@94 363 void FileStatusWidget::clearSelections()
Chris@94 364 {
Chris@95 365 m_selectedFiles.clear();
Chris@94 366 foreach (QListWidget *w, m_stateListMap) {
Chris@94 367 w->clearSelection();
Chris@94 368 }
Chris@94 369 }
Chris@94 370
Chris@95 371 bool FileStatusWidget::haveChangesToCommit() const
Chris@95 372 {
Chris@326 373 return !getAllCommittableFiles().empty();
Chris@95 374 }
Chris@95 375
Chris@95 376 bool FileStatusWidget::haveSelection() const
Chris@95 377 {
Chris@95 378 return !m_selectedFiles.empty();
Chris@95 379 }
Chris@95 380
Chris@326 381 QStringList FileStatusWidget::getSelectedFilesInState(FileStates::State s) const
Chris@95 382 {
Chris@95 383 QStringList files;
Chris@95 384 foreach (QString f, m_selectedFiles) {
Chris@326 385 if (m_fileStates.stateOf(f) == s) files.push_back(f);
Chris@95 386 }
Chris@95 387 return files;
Chris@326 388 }
Chris@326 389
Chris@326 390 QStringList FileStatusWidget::getSelectedFilesSupportingActivity(FileStates::Activity a) const
Chris@326 391 {
Chris@326 392 QStringList files;
Chris@326 393 foreach (QString f, m_selectedFiles) {
Chris@326 394 if (m_fileStates.supportsActivity(f, a)) files.push_back(f);
Chris@326 395 }
Chris@326 396 return files;
Chris@326 397 }
Chris@95 398
Chris@103 399 QStringList FileStatusWidget::getAllCommittableFiles() const
Chris@103 400 {
Chris@326 401 return m_fileStates.filesSupportingActivity(FileStates::Commit);
Chris@109 402 }
Chris@109 403
Chris@109 404 QStringList FileStatusWidget::getAllRevertableFiles() const
Chris@109 405 {
Chris@326 406 return m_fileStates.filesSupportingActivity(FileStates::Revert);
Chris@163 407 }
Chris@163 408
Chris@163 409 QStringList FileStatusWidget::getAllUnresolvedFiles() const
Chris@163 410 {
Chris@326 411 return m_fileStates.filesInState(FileStates::InConflict);
Chris@109 412 }
Chris@109 413
Chris@95 414 QStringList FileStatusWidget::getSelectedAddableFiles() const
Chris@95 415 {
Chris@326 416 return getSelectedFilesSupportingActivity(FileStates::Add);
Chris@103 417 }
Chris@103 418
Chris@95 419 QStringList FileStatusWidget::getSelectedRemovableFiles() const
Chris@95 420 {
Chris@326 421 return getSelectedFilesSupportingActivity(FileStates::Remove);
Chris@103 422 }
Chris@103 423
Chris@283 424 QString
Chris@283 425 FileStatusWidget::localPath() const
Chris@283 426 {
Chris@287 427 return m_localPath;
Chris@283 428 }
Chris@283 429
Chris@88 430 void
Chris@88 431 FileStatusWidget::setLocalPath(QString p)
Chris@88 432 {
Chris@287 433 m_localPath = p;
Chris@93 434 delete m_dateReference;
Chris@93 435 m_dateReference = new QFileInfo(p + "/.hg/dirstate");
Chris@93 436 if (!m_dateReference->exists() ||
Chris@93 437 !m_dateReference->isFile() ||
Chris@93 438 !m_dateReference->isReadable()) {
Chris@93 439 DEBUG << "FileStatusWidget::setLocalPath: date reference file "
Chris@93 440 << m_dateReference->absoluteFilePath()
Chris@93 441 << " does not exist, is not a file, or cannot be read"
Chris@93 442 << endl;
Chris@93 443 delete m_dateReference;
Chris@93 444 m_dateReference = 0;
Chris@340 445 m_showAllFiles->setEnabled(false);
Chris@340 446 } else {
Chris@340 447 m_showAllFiles->setEnabled(true);
Chris@93 448 }
Chris@283 449 }
Chris@283 450
Chris@88 451 void
Chris@92 452 FileStatusWidget::setFileStates(FileStates p)
Chris@88 453 {
Chris@92 454 m_fileStates = p;
Chris@88 455 updateWidgets();
Chris@88 456 }
Chris@88 457
Chris@88 458 void
Chris@555 459 FileStatusWidget::setSearchText(QString text)
Chris@555 460 {
Chris@555 461 if (m_searchText == text) return;
Chris@555 462 m_searchText = text;
Chris@555 463 updateWidgets();
Chris@555 464 }
Chris@555 465
Chris@555 466 void
Chris@608 467 FileStatusWidget::clearWidgets()
Chris@608 468 {
Chris@608 469 foreach (FileStates::State s, m_stateListMap.keys()) {
Chris@608 470 QListWidget *w = m_stateListMap[s];
Chris@608 471 w->clear();
Chris@608 472 w->parentWidget()->hide();
Chris@608 473 }
Chris@608 474 }
Chris@608 475
Chris@608 476 void
Chris@88 477 FileStatusWidget::updateWidgets()
Chris@88 478 {
Chris@95 479 QDateTime lastInteractionTime;
Chris@95 480 if (m_dateReference) {
Chris@95 481 lastInteractionTime = m_dateReference->lastModified();
Chris@95 482 DEBUG << "reference time: " << lastInteractionTime << endl;
Chris@95 483 }
Chris@95 484
Chris@95 485 QSet<QString> selectedFiles;
Chris@95 486 foreach (QString f, m_selectedFiles) selectedFiles.insert(f);
Chris@95 487
Chris@230 488 int visibleCount = 0;
Chris@555 489 bool finding = (m_searchText != "");
Chris@115 490
Chris@94 491 foreach (FileStates::State s, m_stateListMap.keys()) {
Chris@95 492
Chris@94 493 QListWidget *w = m_stateListMap[s];
Chris@94 494 w->clear();
Chris@542 495
Chris@542 496 if (!shouldShow(s)) {
Chris@542 497 w->parentWidget()->hide();
Chris@542 498 continue;
Chris@542 499 }
Chris@542 500
Chris@324 501 QStringList files = m_fileStates.filesInState(s);
Chris@557 502 bool foundSomething = false;
Chris@93 503
Chris@95 504 QStringList highPriority, lowPriority;
Chris@95 505
Chris@95 506 foreach (QString file, files) {
Chris@95 507
Chris@555 508 if (finding) {
Chris@555 509 if (file.contains(m_searchText, Qt::CaseInsensitive)) {
Chris@555 510 highPriority.push_back(file);
Chris@557 511 foundSomething = true;
Chris@555 512 }
Chris@555 513 continue;
Chris@557 514 } else {
Chris@557 515 foundSomething = true;
Chris@555 516 }
Chris@555 517
Chris@95 518 bool highlighted = false;
Chris@95 519
Chris@95 520 if (s == FileStates::Unknown) {
Chris@95 521 // We want to highlight untracked files that have appeared
Chris@95 522 // since the last interaction with the repo
Chris@287 523 QString fn(m_localPath + "/" + file);
Chris@95 524 DEBUG << "comparing with " << fn << endl;
Chris@95 525 QFileInfo fi(fn);
Chris@100 526 if (fi.exists() && fi.created() > lastInteractionTime) {
Chris@95 527 DEBUG << "file " << fn << " is newer (" << fi.lastModified()
Chris@95 528 << ") than reference" << endl;
Chris@95 529 highlighted = true;
Chris@95 530 }
Chris@95 531 }
Chris@95 532
Chris@95 533 if (highlighted) {
Chris@95 534 highPriority.push_back(file);
Chris@95 535 } else {
Chris@95 536 lowPriority.push_back(file);
Chris@93 537 }
Chris@93 538 }
Chris@95 539
Chris@95 540 foreach (QString file, highPriority) {
Chris@95 541 QListWidgetItem *item = new QListWidgetItem(file);
Chris@95 542 w->addItem(item);
Chris@555 543 if (finding) {
Chris@555 544 item->setForeground(QColor("#008400"));
Chris@555 545 } else {
Chris@555 546 item->setForeground(QColor("#d40000"));
Chris@555 547 }
Chris@95 548 item->setSelected(selectedFiles.contains(file));
Chris@95 549 }
Chris@95 550
Chris@95 551 foreach (QString file, lowPriority) {
Chris@95 552 QListWidgetItem *item = new QListWidgetItem(file);
Chris@95 553 w->addItem(item);
Chris@95 554 item->setSelected(selectedFiles.contains(file));
Chris@95 555 }
Chris@95 556
Chris@592 557 setLabelFor(w, s, !finding && !highPriority.empty());
Chris@100 558
Chris@557 559 if (!foundSomething) {
Chris@115 560 w->parentWidget()->hide();
Chris@115 561 } else {
Chris@115 562 w->parentWidget()->show();
Chris@230 563 ++visibleCount;
Chris@115 564 }
Chris@93 565 }
Chris@115 566
Chris@230 567 m_noModificationsLabel->setVisible(visibleCount == 0);
Chris@230 568
Chris@230 569 if (visibleCount > 3) {
Chris@230 570 layoutBoxesGridly(visibleCount);
Chris@230 571 } else {
Chris@230 572 layoutBoxesLinearly();
Chris@230 573 }
Chris@115 574
Chris@230 575 setNoModificationsLabelText();
Chris@230 576 }
Chris@230 577
Chris@230 578 void FileStatusWidget::layoutBoxesGridly(int visibleCount)
Chris@230 579 {
Chris@230 580 if (m_gridlyLayout && m_lastGridlyCount == visibleCount) return;
Chris@230 581
Chris@230 582 delete m_boxesParent->layout();
Chris@230 583
Chris@230 584 QGridLayout *layout = new QGridLayout;
Chris@230 585 layout->setMargin(0);
Chris@230 586 m_boxesParent->setLayout(layout);
Chris@230 587
Chris@230 588 int row = 0;
Chris@230 589 int col = 0;
Chris@230 590
Chris@230 591 DEBUG << "FileStatusWidget::layoutBoxesGridly: visibleCount = "
Chris@230 592 << visibleCount << endl;
Chris@230 593
Chris@230 594 for (int i = 0; i < m_boxes.size(); ++i) {
Chris@230 595
Chris@230 596 if (!m_boxes[i]->isVisible()) continue;
Chris@230 597
Chris@230 598 if (col == 0 && row >= (visibleCount+1)/2) {
Chris@230 599 layout->addItem(new QSpacerItem(10, 5), 0, 1);
Chris@230 600 col = 2;
Chris@230 601 row = 0;
Chris@230 602 }
Chris@230 603
Chris@230 604 layout->addWidget(m_boxes[i], row, col);
Chris@230 605
Chris@230 606 ++row;
Chris@230 607 }
Chris@230 608
Chris@230 609 m_gridlyLayout = true;
Chris@230 610 m_lastGridlyCount = visibleCount;
Chris@230 611 }
Chris@230 612
Chris@230 613 void FileStatusWidget::layoutBoxesLinearly()
Chris@230 614 {
Chris@230 615 if (!m_gridlyLayout) return;
Chris@230 616
Chris@230 617 delete m_boxesParent->layout();
Chris@230 618
Chris@230 619 QGridLayout *layout = new QGridLayout;
Chris@230 620 layout->setMargin(0);
Chris@230 621 m_boxesParent->setLayout(layout);
Chris@230 622
Chris@230 623 for (int i = 0; i < m_boxes.size(); ++i) {
Chris@230 624 layout->addWidget(m_boxes[i], i, 0);
Chris@230 625 }
Chris@230 626
Chris@230 627 m_gridlyLayout = false;
Chris@88 628 }
Chris@88 629
Chris@100 630 void FileStatusWidget::setLabelFor(QWidget *w, FileStates::State s, bool addHighlight)
Chris@100 631 {
Chris@100 632 QString text = labelFor(s, addHighlight);
Chris@100 633 QWidget *p = w->parentWidget();
Chris@100 634 QList<QLabel *> ql = p->findChildren<QLabel *>();
Chris@100 635 if (!ql.empty()) ql[0]->setText(text);
Chris@100 636 }
Chris@115 637