annotate src/filestatuswidget.cpp @ 672:88fa1544b407

Merge from branch qt5. There's much more to be done before we can make another release, but clearly it's going to be done using qt5
author Chris Cannam
date Wed, 05 Dec 2018 09:44:10 +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