annotate src/filestatuswidget.cpp @ 571:012ba1b83328

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