logic: Added indexing mode to reindex incomplete files (issue #493, #496)

* added radio buttons to start indexing dialog
* don't block task scheduler thread while start indexing dialog is visible
* don't force whole project refresh on settings change
* added help button to start indexing dialog explaining indexing modes
* disable unavailable modes when project needs full refresh
* improved label texts on indexing dialogs
* added --incomplete flag to index command of commandline API
* fixed deletion of window stack elements
This commit is contained in:
Eberhard Graether
2017-12-03 22:30:09 +01:00
parent faf9e7655f
commit f9e4afda77
33 changed files with 748 additions and 529 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ bool QtApplication::event(QEvent *event)
if (path.exists() && (path.extension() == ".srctrlprj" || path.extension() == ".coatiproject"))
{
MessageLoadProject(path, false).dispatch();
MessageLoadProject(path).dispatch();
return true;
}
}
+136 -62
View File
@@ -5,13 +5,16 @@
#include <thread>
#include <QMessageBox>
#include <QTimer>
#include "data/access/StorageAccess.h"
#include "qt/window/QtIndexingDialog.h"
#include "qt/window/QtMainWindow.h"
#include "qt/window/QtWindow.h"
#include "utility/messaging/type/MessageStatus.h"
#include "utility/scheduling/TaskLambda.h"
#include "utility/utility.h"
#include "project/Project.h"
QtDialogView::QtDialogView(QtMainWindow* mainWindow, StorageAccess* storageAccess)
: DialogView(storageAccess)
@@ -34,19 +37,7 @@ void QtDialogView::showUnknownProgressDialog(const std::string& title, const std
m_onQtThread2(
[=]()
{
QtIndexingDialog* window = dynamic_cast<QtIndexingDialog*>(m_windowStack.getTopWindow());
if (!window || window->getType() != QtIndexingDialog::DIALOG_UNKNOWN_PROGRESS)
{
m_windowStack.clearWindows();
window = createWindow<QtIndexingDialog>();
window->setupUnknownProgress();
}
window->updateTitle(title.c_str());
window->updateMessage(message.c_str());
setUIBlocked(true);
showUnknownProgress(title, message, false);
}
);
}
@@ -58,13 +49,7 @@ void QtDialogView::hideUnknownProgressDialog()
m_onQtThread2(
[=]()
{
QtIndexingDialog* window = dynamic_cast<QtIndexingDialog*>(m_windowStack.getTopWindow());
if (window && window->getType() == QtIndexingDialog::DIALOG_UNKNOWN_PROGRESS)
{
m_windowStack.popWindow();
}
setUIBlocked(false);
hideUnknownProgress();
}
);
@@ -117,43 +102,91 @@ void QtDialogView::hideProgressDialog()
}
DialogView::IndexingOptions QtDialogView::startIndexingDialog(
size_t cleanFileCount, size_t indexFileCount, size_t totalFileCount, DialogView::IndexingOptions options)
void QtDialogView::startIndexingDialog(
Project* project, const std::vector<RefreshMode>& enabledModes, const RefreshInfo& info)
{
DialogView::IndexingOptions result;
m_resultReady = false;
m_refreshInfos.clear();
m_onQtThread(
[=, &result]()
[=]()
{
QtIndexingDialog* window = createWindow<QtIndexingDialog>();
window->setupStart(cleanFileCount, indexFileCount, totalFileCount, options,
[&](DialogView::IndexingOptions o)
{
result = o;
m_resultReady = true;
m_windowStack.clearWindows();
setUIBlocked(o.startIndexing);
QtIndexingDialog* window = createWindow<QtIndexingDialog>();
window->setupStart(enabledModes);
m_refreshInfos.emplace(info.mode, info);
connect(window, &QtIndexingDialog::setMode,
[=](RefreshMode refreshMode)
{
auto it = m_refreshInfos.find(refreshMode);
if (it != m_refreshInfos.end())
{
window->updateRefreshInfo(it->second);
return;
}
std::shared_ptr<QTimer> timer = std::make_shared<QTimer>();
connect(timer.get(), &QTimer::timeout,
[=]()
{
showUnknownProgress("Preparing Index", "Processing Files", true);
}
);
timer->start(200);
Task::dispatch(std::make_shared<TaskLambda>(
[=]()
{
RefreshInfo info = project->getRefreshInfo(refreshMode);
m_onQtThread2(
[=]()
{
m_refreshInfos.emplace(info.mode, info);
window->updateRefreshInfo(info);
timer->stop();
hideUnknownProgress();
}
);
}
));
}
);
connect(window, &QtIndexingDialog::startIndexing,
[=](RefreshMode refreshMode)
{
RefreshInfo info = m_refreshInfos.find(refreshMode)->second;
Task::dispatch(std::make_shared<TaskLambda>(
[=]()
{
project->buildIndex(info);
}
));
m_windowStack.clearWindows();
}
);
connect(window, &QtWindow::canceled,
[=]()
{
setUIBlocked(false);
}
);
window->updateRefreshInfo(info);
setUIBlocked(true);
}
);
while (!m_resultReady)
{
const int SLEEP_TIME_MS = 25;
std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME_MS));
}
return result;
}
void QtDialogView::updateIndexingDialog(
size_t startedFileCount, size_t finishedFileCount, size_t totalFileCount, std::string sourcePath)
{
m_onQtThread(
[=]()
{
@@ -257,6 +290,68 @@ void QtDialogView::setParentWindow(QtWindow* window)
);
}
void QtDialogView::showUnknownProgress(const std::string& title, const std::string& message, bool stacked)
{
QtIndexingDialog* window = nullptr;
if (!stacked)
{
window = dynamic_cast<QtIndexingDialog*>(m_windowStack.getTopWindow());
if (window && window->getType() != QtIndexingDialog::DIALOG_UNKNOWN_PROGRESS)
{
m_windowStack.clearWindows();
window = nullptr;
}
}
if (!window)
{
window = createWindow<QtIndexingDialog>();
window->setupUnknownProgress();
}
window->updateTitle(title.c_str());
window->updateMessage(message.c_str());
setUIBlocked(true);
}
void QtDialogView::hideUnknownProgress()
{
QtIndexingDialog* window = dynamic_cast<QtIndexingDialog*>(m_windowStack.getTopWindow());
if (window && window->getType() == QtIndexingDialog::DIALOG_UNKNOWN_PROGRESS)
{
m_windowStack.popWindow();
}
if (!m_windowStack.getWindowCount())
{
setUIBlocked(false);
}
}
void QtDialogView::setUIBlocked(bool blocked)
{
if (m_parentWindow)
{
m_parentWindow->setEnabled(!blocked);
}
else
{
m_mainWindow->setContentEnabled(!blocked);
}
if (blocked)
{
QWidget* window = m_windowStack.getTopWindow();
if (window)
{
window->setEnabled(true);
}
}
}
void QtDialogView::handleMessage(MessageInterruptTasks* message)
{
m_onQtThread3(
@@ -337,24 +432,3 @@ template<typename T>
return window;
}
void QtDialogView::setUIBlocked(bool blocked)
{
if (m_parentWindow)
{
m_parentWindow->setEnabled(!blocked);
}
else
{
m_mainWindow->setContentEnabled(!blocked);
}
if (blocked)
{
QWidget* window = m_windowStack.getTopWindow();
if (window)
{
window->setEnabled(true);
}
}
}
+10 -4
View File
@@ -35,8 +35,8 @@ public:
virtual void showProgressDialog(const std::string& title, const std::string& message, int progress) override;
virtual void hideProgressDialog() override;
virtual DialogView::IndexingOptions startIndexingDialog(
size_t cleanFileCount, size_t indexFileCount, size_t totalFileCount, DialogView::IndexingOptions options) override;
virtual void startIndexingDialog(
Project* project, const std::vector<RefreshMode>& enabledModes, const RefreshInfo& info) override;
virtual void updateIndexingDialog(
size_t startedFileCount, size_t finishedFileCount, size_t totalFileCount, std::string sourcePath) override;
virtual void finishedIndexingDialog(
@@ -49,6 +49,12 @@ public:
void setParentWindow(QtWindow* window);
private slots:
void showUnknownProgress(const std::string& title, const std::string& message, bool stacked);
void hideUnknownProgress();
void setUIBlocked(bool blocked);
private:
void handleMessage(MessageInterruptTasks* message) override;
void handleMessage(MessageNewErrors* message) override;
@@ -60,8 +66,6 @@ private:
template<typename T>
T* createWindow();
void setUIBlocked(bool blocked);
QtMainWindow* m_mainWindow;
QtWindow* m_parentWindow;
@@ -71,6 +75,8 @@ private:
QtThreadedLambdaFunctor m_onQtThread2;
QtThreadedLambdaFunctor m_onQtThread3;
std::map<RefreshMode, RefreshInfo> m_refreshInfos;
bool m_resultReady;
};
+101 -54
View File
@@ -2,8 +2,7 @@
#include <QCheckBox>
#include <QLabel>
#include <QTimer>
#include <QPainter>
#include <QRadioButton>
#include <QPushButton>
#include "qt/utility/utilityQt.h"
@@ -24,9 +23,7 @@ QtIndexingDialog::QtIndexingDialog(QWidget* parent)
, m_messageLabel(nullptr)
, m_filePathLabel(nullptr)
, m_errorWidget(nullptr)
, m_fullRefreshCheckBox(nullptr)
, m_sizeHint(QSize(450, 450))
, m_callback([](DialogView::IndexingOptions){})
{
setSizeGripStyle(false);
}
@@ -41,69 +38,120 @@ QtIndexingDialog::DialogType QtIndexingDialog::getType() const
return m_type;
}
void QtIndexingDialog::setupStart(
size_t cleanFileCount, size_t indexFileCount, size_t totalFileCount,
DialogView::IndexingOptions options, std::function<void(DialogView::IndexingOptions)> callback)
void QtIndexingDialog::setupStart(const std::vector<RefreshMode>& enabledModes)
{
setType(DIALOG_START_INDEXING);
QBoxLayout* layout = createLayout();
addTitle("Start Indexing", layout);
layout->addSpacing(5);
QLabel* clearLabel = createMessageLabel(layout);
QLabel* indexLabel = createMessageLabel(layout);
QLabel* fullLabel = createMessageLabel(layout);
m_clearLabel = createMessageLabel(layout);
m_indexLabel = createMessageLabel(layout);
clearLabel->setText("Clear: " + QString::number(cleanFileCount) + " File" + (cleanFileCount != 1 ? "s" : ""));
indexLabel->setText("Index: " + QString::number(indexFileCount) + " File" + (indexFileCount != 1 ? "s" : ""));
fullLabel->setText("Index: " + QString::number(totalFileCount) + " File" + (totalFileCount != 1 ? "s" : ""));
m_clearLabel->setVisible(false);
m_indexLabel->setVisible(false);
layout->addStretch();
if (options.fullRefreshVisible)
{
m_fullRefreshCheckBox = new QCheckBox("full refresh", this);
m_fullRefreshCheckBox->setObjectName("message");
QHBoxLayout* subLayout = new QHBoxLayout();
subLayout->addStretch();
connect(m_fullRefreshCheckBox, &QCheckBox::toggled,
[=](bool checked = false)
QVBoxLayout* modeLayout = new QVBoxLayout();
modeLayout->setSpacing(7);
QHBoxLayout* modeTitleLayout = new QHBoxLayout();
modeTitleLayout->setSpacing(7);
QLabel* modeLabel = createMessageLabel(modeTitleLayout);
modeLabel->setText("Mode:");
modeLabel->setAlignment(Qt::AlignLeft);
QtHelpButton* helpButton = new QtHelpButton(
"Indexing Modes",
"<b>Updated files:</b> Reindexes all files that were modified since the last indexing, all files depending "
"on those and new files.<br /><br />"
"<b>Incomplete & updated files:</b> Reindexes all files that had errors during last indexing, all files "
"depending on those and all updated files.<br /><br />"
"<b>All files:</b> Deletes the previous index and reindexes all files.<br /><br />"
);
helpButton->setColor(Qt::white);
modeTitleLayout->addWidget(helpButton);
modeTitleLayout->addStretch();
modeLayout->addLayout(modeTitleLayout);
modeLayout->addSpacing(5);
m_refreshModeButtons.emplace(REFRESH_UPDATED_FILES, new QRadioButton("Updated files"));
m_refreshModeButtons.emplace(REFRESH_UPDATED_AND_INCOMPLETE_FILES, new QRadioButton("Incomplete && updated files"));
m_refreshModeButtons.emplace(REFRESH_ALL_FILES, new QRadioButton("All files"));
std::function<void(bool)> func =
[=](bool checked)
{
if (!checked)
{
clearLabel->setVisible(!checked);
indexLabel->setVisible(!checked);
fullLabel->setVisible(checked);
return;
}
);
m_fullRefreshCheckBox->setChecked(!options.fullRefresh);
m_fullRefreshCheckBox->setChecked(options.fullRefresh);
for (auto p : m_refreshModeButtons)
{
if (p.second->isChecked())
{
emit setMode(p.first);
return;
}
}
};
QHBoxLayout* subLayout = new QHBoxLayout();
subLayout->addStretch();
subLayout->addWidget(m_fullRefreshCheckBox);
layout->addLayout(subLayout);
}
else
for (auto p : m_refreshModeButtons)
{
clearLabel->hide();
indexLabel->hide();
QRadioButton* button = p.second;
button->setObjectName("option");
button->setEnabled(false);
modeLayout->addWidget(button);
connect(button, &QRadioButton::toggled, func);
}
if (m_fullRefreshCheckBox)
for (RefreshMode mode : enabledModes)
{
layout->addSpacing(20);
m_refreshModeButtons[mode]->setEnabled(true);
}
subLayout->addLayout(modeLayout);
layout->addLayout(subLayout);
layout->addSpacing(20);
addButtons(layout);
updateNextButton("Start");
updateCloseButton("Cancel");
m_sizeHint = QSize(350, 270);
m_callback = callback;
m_sizeHint = QSize(350, 310);
finishSetup();
}
void QtIndexingDialog::updateRefreshInfo(const RefreshInfo& info)
{
QRadioButton* button = m_refreshModeButtons.find(info.mode)->second;
if (!button->isChecked())
{
button->setChecked(true);
}
size_t clearCount = info.filesToClear.size();
size_t indexCount = info.filesToIndex.size();
m_clearLabel->setText("Files to clear: " + QString::number(clearCount));
m_indexLabel->setText("Source files to index: " + QString::number(indexCount));
m_clearLabel->setVisible(clearCount);
m_indexLabel->setVisible(true);
}
void QtIndexingDialog::setupIndexing()
{
setType(DIALOG_INDEXING);
@@ -143,15 +191,15 @@ void QtIndexingDialog::setupReport(
layout->addSpacing(5);
createMessageLabel(layout)->setText(
"Source Files indexed: " + QString::number(indexedFileCount) + "/" + QString::number(totalIndexedFileCount)
"Source files indexed: " + QString::number(indexedFileCount) + "/" + QString::number(totalIndexedFileCount)
);
createMessageLabel(layout)->setText(
"Files completed: " + QString::number(completedFileCount) + "/" + QString::number(totalFileCount)
"Total files completed: " + QString::number(completedFileCount) + "/" + QString::number(totalFileCount)
);
layout->addSpacing(12);
createMessageLabel(layout)->setText("Total Time: " + QString::fromStdString(utility::timeToString(time)));
createMessageLabel(layout)->setText("Time: " + QString::fromStdString(utility::timeToString(time)));
layout->addSpacing(12);
addErrorWidget(layout);
@@ -283,14 +331,19 @@ void QtIndexingDialog::resizeEvent(QResizeEvent* event)
void QtIndexingDialog::handleNext()
{
if (m_type == DIALOG_MESSAGE)
if (m_type == DIALOG_START_INDEXING)
{
DialogView::IndexingOptions options;
options.startIndexing = true;
options.fullRefresh = m_fullRefreshCheckBox && m_fullRefreshCheckBox->isChecked();
m_callback(options);
for (auto p : m_refreshModeButtons)
{
if (p.second->isChecked())
{
emit startIndexing(p.first);
return;
}
}
}
else if (m_type == DIALOG_REPORT)
if (m_type == DIALOG_REPORT)
{
MessageShowErrorHelpMessage().dispatch();
}
@@ -300,12 +353,6 @@ void QtIndexingDialog::handleNext()
void QtIndexingDialog::handleClose()
{
if (m_type == DIALOG_MESSAGE)
{
DialogView::IndexingOptions options;
m_callback(options);
}
if (m_type == DIALOG_INDEXING)
{
MessageInterruptTasks().dispatch();
@@ -368,7 +415,7 @@ void QtIndexingDialog::addTitle(QString title, QBoxLayout* layout)
{
m_title->show();
}
else
else if (layout)
{
layout->addWidget(m_title, 0, Qt::AlignRight);
}
+16 -9
View File
@@ -1,13 +1,14 @@
#ifndef QT_INDEXING_WIZARD_WINDOW_H
#define QT_INDEXING_WIZARD_WINDOW_H
#ifndef QT_INDEXING_DIALOG_H
#define QT_INDEXING_DIALOG_H
#include <functional>
#include "component/view/DialogView.h"
#include "project/RefreshInfo.h"
#include "qt/window/QtWindow.h"
class QCheckBox;
class QLabel;
class QRadioButton;
class QtProgressBar;
class QtIndexingDialog
@@ -15,12 +16,17 @@ class QtIndexingDialog
{
Q_OBJECT
signals:
void setMode(RefreshMode mode);
void startIndexing(RefreshMode mode);
public:
enum DialogType
{
DIALOG_MESSAGE,
DIALOG_UNKNOWN_PROGRESS,
DIALOG_PROGRESS,
DIALOG_START_INDEXING,
DIALOG_INDEXING,
DIALOG_REPORT
};
@@ -30,8 +36,9 @@ public:
DialogType getType() const;
void setupStart(size_t cleanFileCount, size_t indexFileCount, size_t totalFileCount,
DialogView::IndexingOptions options, std::function<void(DialogView::IndexingOptions)> callback);
void setupStart(const std::vector<RefreshMode>& enabledModes);
void updateRefreshInfo(const RefreshInfo& info);
void setupIndexing();
void setupReport(
size_t indexedFileCount, size_t totalIndexedFileCount, size_t completedFileCount, size_t totalFileCount,
@@ -82,12 +89,12 @@ private:
QWidget* m_errorWidget;
// start indexing
QCheckBox* m_fullRefreshCheckBox;
QLabel* m_clearLabel;
QLabel* m_indexLabel;
std::map<RefreshMode, QRadioButton*> m_refreshModeButtons;
QSize m_sizeHint;
std::function<void(DialogView::IndexingOptions)> m_callback;
QString m_sourcePath;
};
#endif // QT_INDEXING_WIZARD_WINDOW_H
#endif // QT_INDEXING_DIALOG_H
+2 -2
View File
@@ -582,7 +582,7 @@ void QtMainWindow::openProject()
if (!fileName.isEmpty())
{
MessageLoadProject(FilePath(fileName.toStdString()), false).dispatch();
MessageLoadProject(FilePath(fileName.toStdString())).dispatch();
m_windowStack.clearWindows();
}
}
@@ -687,7 +687,7 @@ void QtMainWindow::openRecentProject()
QAction *action = qobject_cast<QAction*>(sender());
if (action)
{
MessageLoadProject(FilePath(action->data().toString().toStdString()), false).dispatch();
MessageLoadProject(FilePath(action->data().toString().toStdString())).dispatch();
m_windowStack.clearWindows();
}
}
+1 -1
View File
@@ -49,7 +49,7 @@ void QtRecentProjectButton::handleButtonClick()
{
if (m_projectExists)
{
MessageLoadProject(m_projectFilePath, false).dispatch();
MessageLoadProject(m_projectFilePath).dispatch();
}
else
{
+2 -2
View File
@@ -57,7 +57,7 @@ void QtWindowStack::popWindow()
if (m_stack.size())
{
m_stack.back()->hideWindow();
delete m_stack.back();
m_stack.back()->deleteLater();
m_stack.pop_back();
emit pop();
@@ -93,7 +93,7 @@ void QtWindowStack::clearWindows()
for (QtWindowStackElement* window : m_stack)
{
window->hideWindow();
delete window;
window->deleteLater();
}
m_stack.clear();
@@ -919,30 +919,23 @@ void QtProjectWizzard::createProject()
m_projectSettings->setAllSourceGroupSettings(m_allSourceGroupSettings);
m_projectSettings->save(path);
bool forceRefreshProject = false;
bool settingsChanged = false;
if (m_editing)
{
bool settingsChanged = false;
Application* application = Application::getInstance().get();
if (application->getCurrentProject() != NULL)
{
settingsChanged = !(application->getCurrentProject()->settingsEqualExceptNameAndLocation(*(m_projectSettings.get())));
}
bool appSettingsChanged = !(m_appSettings == *ApplicationSettings::getInstance().get());
if (settingsChanged || appSettingsChanged)
{
forceRefreshProject = true;
}
settingsChanged |= !(m_appSettings == *ApplicationSettings::getInstance().get());
}
else
{
MessageStatus("Created project: " + path.str()).dispatch();
}
MessageLoadProject(path, forceRefreshProject).dispatch();
MessageLoadProject(path, settingsChanged).dispatch();
finishWizzard();
}