diff --git a/bin/app/data/gui/window/listbox.css b/bin/app/data/gui/window/listbox.css index a26e37a8..ad388724 100644 --- a/bin/app/data/gui/window/listbox.css +++ b/bin/app/data/gui/window/listbox.css @@ -2,7 +2,7 @@ font-size: 12px; } -QtDirectoryListBox { +QtListBox { background-color: white; border: 1px solid lightgray; border-radius: 12px; @@ -23,7 +23,7 @@ QListWidget::item:selected { background-color: #EEE; } -QtListItemWidget #field { +QtListBoxItem #field { background-color: transparent; border: none; color: black; @@ -31,7 +31,7 @@ QtListItemWidget #field { margin-left: 5px; } -QtListItemWidget #field:disabled { +QtListBoxItem #field:disabled { color: grey; } diff --git a/src/lib_gui/CMakeLists.txt b/src/lib_gui/CMakeLists.txt index 60f78ffc..5fc198b0 100644 --- a/src/lib_gui/CMakeLists.txt +++ b/src/lib_gui/CMakeLists.txt @@ -31,8 +31,6 @@ add_files( qt/element/QtCodeNavigator.h qt/element/QtCodeSnippet.cpp qt/element/QtCodeSnippet.h - qt/element/QtDirectoryListBox.cpp - qt/element/QtDirectoryListBox.h qt/element/QtHelpButton.cpp qt/element/QtHelpButton.h qt/element/QtHistoryList.cpp @@ -41,8 +39,16 @@ add_files( qt/element/QtIconButton.h qt/element/QtLineEdit.cpp qt/element/QtLineEdit.h + qt/element/QtListBox.cpp + qt/element/QtListBox.h + qt/element/QtListBoxItem.cpp + qt/element/QtListBoxItem.h qt/element/QtLocationPicker.cpp qt/element/QtLocationPicker.h + qt/element/QtPathListBox.cpp + qt/element/QtPathListBox.h + qt/element/QtPathListBoxItem.cpp + qt/element/QtPathListBoxItem.h qt/element/QtProgressBar.cpp qt/element/QtProgressBar.h qt/element/QtScreenSearchBox.cpp @@ -53,6 +59,10 @@ add_files( qt/element/QtSearchBarButton.h qt/element/QtSmartSearchBox.cpp qt/element/QtSmartSearchBox.h + qt/element/QtStringListBox.cpp + qt/element/QtStringListBox.h + qt/element/QtStringListBoxItem.cpp + qt/element/QtStringListBoxItem.h qt/element/QtStatusBar.cpp qt/element/QtStatusBar.h qt/element/QtTable.cpp diff --git a/src/lib_gui/qt/element/QtDirectoryListBox.cpp b/src/lib_gui/qt/element/QtDirectoryListBox.cpp deleted file mode 100644 index 1370406f..00000000 --- a/src/lib_gui/qt/element/QtDirectoryListBox.cpp +++ /dev/null @@ -1,444 +0,0 @@ -#include "qt/element/QtDirectoryListBox.h" - -#include -#include -#include -#include - -#include "qt/element/QtIconButton.h" -#include "qt/utility/utilityQt.h" -#include "qt/utility/QtFileDialog.h" -#include "qt/window/QtTextEditDialog.h" -#include "utility/ResourcePaths.h" -#include "utility/utilityString.h" - -QtListItemWidget::QtListItemWidget(QtDirectoryListBox* list, QListWidgetItem* item, QWidget *parent) - : QWidget(parent) - , m_list(list) - , m_item(item) - , m_readOnly(false) -{ - QBoxLayout* layout = new QHBoxLayout(); - layout->setSpacing(3); - layout->setContentsMargins(0, 0, 0, 0); - layout->setAlignment(Qt::AlignTop); - - m_data = new QtLineEdit(this); - m_data->setAttribute(Qt::WA_MacShowFocusRect, 0); - m_data->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac - m_data->setObjectName("field"); - m_data->setAcceptDrops(false); - - m_button = new QtIconButton( - ResourcePaths::getGuiPath().concatenate(L"window/dots.png"), - ResourcePaths::getGuiPath().concatenate(L"window/dots_hover.png") - ); - m_button->setIconSize(QSize(16, 16)); - m_button->setObjectName("dotsButton"); - - layout->addWidget(m_data); - layout->addWidget(m_button); - - if (list->isForStrings()) - { - m_button->hide(); - } - - setLayout(layout); - - connect(m_button, &QPushButton::clicked, this, &QtListItemWidget::handleButtonPress); - connect(m_data, &QtLineEdit::focus, this, &QtListItemWidget::handleFocus); -} - -QString QtListItemWidget::getText() -{ - return m_data->text(); -} - -void QtListItemWidget::setText(QString text) -{ - FilePath relativeRoot = m_list->getRelativeRootDirectory(); - if (!relativeRoot.empty()) - { - const FilePath path(text.toStdWString()); - const FilePath relPath = path.getRelativeTo(relativeRoot); - if (relPath.wstr().size() < path.wstr().size()) - { - text = QString::fromStdWString(relPath.wstr()); - } - } - - m_data->setText(text); -} - -bool QtListItemWidget::readOnly() const -{ - return m_readOnly; -} - -void QtListItemWidget::setReadOnly(bool readOnly) -{ - m_readOnly = readOnly; - - if (readOnly) - { - m_item->setFlags(m_item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEnabled)); - } - else - { - m_item->setFlags(m_item->flags() | ~(Qt::ItemIsSelectable | Qt::ItemIsEnabled)); - } - - m_data->setReadOnly(readOnly); - m_data->setEnabled(!readOnly); - m_button->setEnabled(!readOnly); -} - -void QtListItemWidget::setFocus() -{ - m_data->setFocus(Qt::OtherFocusReason); -} - -void QtListItemWidget::handleButtonPress() -{ - FilePath path(m_data->text().toStdWString()); - const FilePath relativeRoot = m_list->getRelativeRootDirectory(); - if (!path.empty() && !path.isAbsolute() && !relativeRoot.empty()) - { - path = relativeRoot.getConcatenated(path); - } - - QStringList list = QtFileDialog::getFileNamesAndDirectories(this, path); - if (!list.isEmpty()) - { - setText(list.at(0)); - } - - for (int i = 1; i < list.size(); i++) - { - m_list->addListBoxItemWithText(list.at(i)); - } - - handleFocus(); -} - -void QtListItemWidget::handleFocus() -{ - m_list->selectItem(m_item); -} - - -QtDirectoryListBox::QtDirectoryListBox(QWidget *parent, const QString& listName, bool forStrings) - : QFrame(parent) - , m_listName(listName) - , m_forStrings(forStrings) -{ - QBoxLayout* layout = new QVBoxLayout(); - layout->setSpacing(0); - layout->setContentsMargins(0, 6, 0, 0); - layout->setAlignment(Qt::AlignTop); - - m_list = new QListWidget(this); - m_list->setObjectName("list"); - m_list->setAttribute(Qt::WA_MacShowFocusRect, 0); - - setStyleSheet(utility::getStyleSheet(ResourcePaths::getGuiPath().concatenate(L"window/listbox.css")).c_str()); - layout->addWidget(m_list, 5); - - QWidget* buttonContainer = new QWidget(this); - buttonContainer->setObjectName("bar"); - - QHBoxLayout* innerLayout = new QHBoxLayout(); - innerLayout->setContentsMargins(8, 4, 8, 2); - innerLayout->setSpacing(0); - - m_addButton = new QtIconButton( - ResourcePaths::getGuiPath().concatenate(L"window/plus.png"), - ResourcePaths::getGuiPath().concatenate(L"window/plus_hover.png") - ); - m_addButton->setIconSize(QSize(16, 16)); - m_addButton->setObjectName("plusButton"); - m_addButton->setToolTip("add line"); - innerLayout->addWidget(m_addButton); - - m_removeButton = new QtIconButton( - ResourcePaths::getGuiPath().concatenate(L"window/minus.png"), - ResourcePaths::getGuiPath().concatenate(L"window/minus_hover.png") - ); - m_removeButton->setIconSize(QSize(16, 16)); - m_removeButton->setObjectName("minusButton"); - m_removeButton->setToolTip("remove line"); - innerLayout->addWidget(m_removeButton); - - innerLayout->addStretch(); - - QLabel* dropInfoText = new QLabel("Drop Files & Folders"); - dropInfoText->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - dropInfoText->setObjectName("dropInfo"); - dropInfoText->setAlignment(Qt::AlignRight); - innerLayout->addWidget(dropInfoText); - - QPushButton* editButton = new QtIconButton( - ResourcePaths::getGuiPath().concatenate(L"code_view/images/edit.png"), - FilePath() - ); - editButton->setIconSize(QSize(16, 16)); - editButton->setObjectName("editButton"); - editButton->setToolTip("edit plain text"); - innerLayout->addWidget(editButton); - - if (isForStrings()) - { - dropInfoText->hide(); - } - - buttonContainer->setLayout(innerLayout); - layout->addWidget(buttonContainer, 0); - setLayout(layout); - - connect(m_addButton, &QPushButton::clicked, this, &QtDirectoryListBox::addListBoxItem); - connect(m_removeButton, &QPushButton::clicked, this, &QtDirectoryListBox::removeListBoxItem); - connect(editButton, &QPushButton::clicked, this, &QtDirectoryListBox::showEditDialog); - - setAcceptDrops(true); - setMaximumHeight(160); -} - -void QtDirectoryListBox::clear() -{ - m_list->clear(); -} - -bool QtDirectoryListBox::event(QEvent* event) -{ - // Prevent nested ScrollAreas to scroll at the same time; - if (event->type() == QEvent::Wheel) - { - QRect rect = m_list->viewport()->rect(); - QPoint pos = m_list->mapFromGlobal( dynamic_cast(event)->globalPos()); - QScrollBar* bar = m_list->verticalScrollBar(); - - if (bar->minimum() != bar->maximum() && rect.contains(pos)) - { - bool down = dynamic_cast(event)->angleDelta().y() < 0; - - if ((down && bar->value() != bar->maximum()) || (!down && bar->value() != bar->minimum())) - { - return true; - } - } - } - - return QFrame::event(event); -} - -void QtDirectoryListBox::dropEvent(QDropEvent *event) -{ - foreach(QUrl url, event->mimeData()->urls()) - { - QtListItemWidget* widget = addListBoxItem(); - widget->setText(url.toLocalFile()); - } -} - -std::vector QtDirectoryListBox::getList() -{ - std::vector list; - for (const std::wstring& s : getStringList()) - { - list.push_back(FilePath(s)); - } - return list; -} - -void QtDirectoryListBox::setList(const std::vector& list, bool readOnly) -{ - std::vector strList; - for (const FilePath& path : list) - { - strList.push_back(path.wstr()); - } - setStringList(strList, readOnly); -} - -std::vector QtDirectoryListBox::getStringList() -{ - std::vector list; - for (int i = 0; i < m_list->count(); ++i) - { - QtListItemWidget* widget = dynamic_cast(m_list->itemWidget(m_list->item(i))); - list.push_back(widget->getText().toStdWString()); - } - return list; -} - -void QtDirectoryListBox::setStringList(const std::vector& list, bool readOnly) -{ - clear(); - - FilePath root = m_relativeRootDirectory; - m_relativeRootDirectory = FilePath(); - - for (const std::wstring& str : list) - { - QtListItemWidget* itemWidget = addListBoxItemWithText(QString::fromStdWString(str)); - itemWidget->setReadOnly(readOnly); - } - - m_list->scrollToTop(); - m_relativeRootDirectory = root; -} - -QtListItemWidget* QtDirectoryListBox::addListBoxItemWithText(const QString& text) -{ - QtListItemWidget* widget = addListBoxItem(); - widget->setText(text); - return widget; -} - -void QtDirectoryListBox::selectItem(QListWidgetItem* item) -{ - for (int i = 0; i < m_list->count(); i++) - { - m_list->item(i)->setSelected(false); - } - - item->setSelected(true); -} - -bool QtDirectoryListBox::isForStrings() const -{ - return m_forStrings; -} - -const FilePath& QtDirectoryListBox::getRelativeRootDirectory() const -{ - return m_relativeRootDirectory; -} - -void QtDirectoryListBox::setRelativeRootDirectory(const FilePath& dir) -{ - m_relativeRootDirectory = dir; -} - -QtListItemWidget* QtDirectoryListBox::addListBoxItem() -{ - QListWidgetItem *item = new QListWidgetItem(m_list); - m_list->addItem(item); - - QtListItemWidget* widget = new QtListItemWidget(this, item); - m_list->setItemWidget(item, widget); - - m_list->scrollToItem(item); - widget->setFocus(); - - return widget; -} - -void QtDirectoryListBox::removeListBoxItem() -{ - if (!m_list->selectedItems().size()) - { - return; - } - - int rowIndex = m_list->row(m_list->selectedItems().first()); - - qDeleteAll(m_list->selectedItems()); - - if (rowIndex == m_list->count()) - { - rowIndex -= 1; - } - - if (rowIndex >= 0) - { - m_list->setCurrentRow(rowIndex); - } -} - -void QtDirectoryListBox::dragEnterEvent(QDragEnterEvent *event) -{ - event->accept(); -} - -void QtDirectoryListBox::showEditDialog() -{ - if (!m_editDialog) - { - m_editDialog = std::make_shared(m_listName, "Edit the list in plain text. Each line is one item."); - m_editDialog->setup(); - - std::vector list; - for (int i = 0; i < m_list->count(); ++i) - { - QtListItemWidget* widget = dynamic_cast(m_list->itemWidget(m_list->item(i))); - if (!widget->readOnly()) - { - list.push_back(widget->getText().toStdWString()); - } - } - - m_editDialog->setText(utility::join(list, L"\n")); - - connect(m_editDialog.get(), &QtTextEditDialog::canceled, this, &QtDirectoryListBox::canceledEditDialog); - connect(m_editDialog.get(), &QtTextEditDialog::finished, this, &QtDirectoryListBox::savedEditDialog); - } - - m_editDialog->showWindow(); - m_editDialog->raise(); -} - -void QtDirectoryListBox::canceledEditDialog() -{ - m_editDialog->hide(); - m_editDialog.reset(); - - window()->raise(); -} - -void QtDirectoryListBox::savedEditDialog() -{ - std::vector readOnlyLines; - for (int i = 0; i < m_list->count(); ++i) - { - QtListItemWidget* widget = dynamic_cast(m_list->itemWidget(m_list->item(i))); - if (widget->readOnly()) - { - readOnlyLines.push_back(widget->getText().toStdString()); - } - } - - std::vector lines = utility::splitToVector(m_editDialog->getText(), L"\n"); - for (size_t i = 0; i < lines.size(); i++) - { - lines[i] = utility::trim(lines[i]); - - if (lines[i].empty()) - { - lines.erase(lines.begin() + i); - i--; - } - } - - clear(); - - FilePath root = m_relativeRootDirectory; - m_relativeRootDirectory = FilePath(); - - for (const std::string& str : readOnlyLines) - { - QtListItemWidget* itemWidget = addListBoxItemWithText(QString::fromStdString(str)); - itemWidget->setReadOnly(true); - } - - for (const std::wstring& line : lines) - { - QtListItemWidget* itemWidget = addListBoxItemWithText(QString::fromStdWString(line)); - itemWidget->setReadOnly(false); - } - - m_relativeRootDirectory = root; - - canceledEditDialog(); -} diff --git a/src/lib_gui/qt/element/QtDirectoryListBox.h b/src/lib_gui/qt/element/QtDirectoryListBox.h deleted file mode 100644 index e0b90294..00000000 --- a/src/lib_gui/qt/element/QtDirectoryListBox.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef QT_DIRECTORY_LIST_BOX_H -#define QT_DIRECTORY_LIST_BOX_H - -#include -#include -#include -#include -#include - -#include "utility/file/FilePath.h" - -#include "qt/element/QtLineEdit.h" - -class QtDirectoryListBox; -class QtTextEditDialog; - -class QtListItemWidget - : public QWidget -{ - Q_OBJECT - -public: - QtListItemWidget(QtDirectoryListBox* list, QListWidgetItem* item, QWidget *parent = nullptr); - - QString getText(); - void setText(QString text); - - bool readOnly() const; - void setReadOnly(bool readOnly); - -public slots: - void setFocus(); - -private slots: - void handleButtonPress(); - void handleFocus(); - -private: - QPushButton* m_button; - QtLineEdit* m_data; - - QtDirectoryListBox* m_list; - QListWidgetItem* m_item; - - bool m_readOnly; -}; - - -class QtDirectoryListBox - : public QFrame -{ - Q_OBJECT - -public: - QtDirectoryListBox(QWidget *parent, const QString& listName, bool forStrings = false); - - void clear(); - - std::vector getList(); - void setList(const std::vector& list, bool readOnly = false); - - std::vector getStringList(); - void setStringList(const std::vector& list, bool readOnly = false); - - QtListItemWidget* addListBoxItemWithText(const QString& text); - - void selectItem(QListWidgetItem* item); - - bool isForStrings() const; - - const FilePath& getRelativeRootDirectory() const; - void setRelativeRootDirectory(const FilePath& dir); - -protected: - bool event(QEvent* event) override; - - void dropEvent(QDropEvent *event) override; - void dragEnterEvent(QDragEnterEvent* event) override; - -private slots: - QtListItemWidget* addListBoxItem(); - void removeListBoxItem(); - - void showEditDialog(); - void canceledEditDialog(); - void savedEditDialog(); - -private: - QPushButton* m_addButton; - QPushButton* m_removeButton; - QListWidget* m_list; - - QString m_listName; - bool m_forStrings; - - std::shared_ptr m_editDialog; - - FilePath m_relativeRootDirectory; -}; - -#endif // QT_DIRECTORY_LIST_BOX_H diff --git a/src/lib_gui/qt/element/QtListBox.cpp b/src/lib_gui/qt/element/QtListBox.cpp new file mode 100644 index 00000000..c4bbfe30 --- /dev/null +++ b/src/lib_gui/qt/element/QtListBox.cpp @@ -0,0 +1,246 @@ +#include "qt/element/QtListBox.h" + +#include +#include +#include +#include +#include + +#include "qt/element/QtIconButton.h" +#include "qt/element/QtStringListBoxItem.h" +#include "qt/utility/utilityQt.h" +#include "qt/window/QtTextEditDialog.h" +#include "utility/ResourcePaths.h" +#include "utility/utilityString.h" + +QtListBox::QtListBox(QWidget *parent, const QString& listName) + : QFrame(parent) + , m_listName(listName) +{ + QBoxLayout* layout = new QVBoxLayout(); + layout->setSpacing(0); + layout->setContentsMargins(0, 6, 0, 0); + layout->setAlignment(Qt::AlignTop); + + m_list = new QListWidget(this); + m_list->setObjectName("list"); + m_list->setAttribute(Qt::WA_MacShowFocusRect, 0); + + setStyleSheet(utility::getStyleSheet(ResourcePaths::getGuiPath().concatenate(L"window/listbox.css")).c_str()); + layout->addWidget(m_list, 5); + + QWidget* buttonContainer = new QWidget(this); + buttonContainer->setObjectName("bar"); + + QHBoxLayout* barLayout = new QHBoxLayout(); + barLayout->setContentsMargins(8, 4, 8, 2); + barLayout->setSpacing(0); + + m_addButton = new QtIconButton( + ResourcePaths::getGuiPath().concatenate(L"window/plus.png"), + ResourcePaths::getGuiPath().concatenate(L"window/plus_hover.png") + ); + m_addButton->setIconSize(QSize(16, 16)); + m_addButton->setObjectName("plusButton"); + m_addButton->setToolTip("add line"); + barLayout->addWidget(m_addButton); + + m_removeButton = new QtIconButton( + ResourcePaths::getGuiPath().concatenate(L"window/minus.png"), + ResourcePaths::getGuiPath().concatenate(L"window/minus_hover.png") + ); + m_removeButton->setIconSize(QSize(16, 16)); + m_removeButton->setObjectName("minusButton"); + m_removeButton->setToolTip("remove line"); + barLayout->addWidget(m_removeButton); + + barLayout->addStretch(); + + m_innerBarLayout = new QHBoxLayout(); + barLayout->addLayout(m_innerBarLayout); + + QPushButton* editButton = new QtIconButton( + ResourcePaths::getGuiPath().concatenate(L"code_view/images/edit.png"), + FilePath() + ); + editButton->setIconSize(QSize(16, 16)); + editButton->setObjectName("editButton"); + editButton->setToolTip("edit plain text"); + barLayout->addWidget(editButton); + + buttonContainer->setLayout(barLayout); + layout->addWidget(buttonContainer, 0); + setLayout(layout); + + connect(m_addButton, &QPushButton::clicked, this, &QtListBox::addListBoxItem); + connect(m_removeButton, &QPushButton::clicked, this, &QtListBox::removeListBoxItem); + connect(editButton, &QPushButton::clicked, this, &QtListBox::showEditDialog); + + setAcceptDrops(true); + setMaximumHeight(160); +} + +void QtListBox::clear() +{ + m_list->clear(); +} + +void QtListBox::addWidgetToBar(QWidget* widget) +{ + if (m_innerBarLayout) + { + m_innerBarLayout->addWidget(widget); + } +} + +bool QtListBox::event(QEvent* event) +{ + // Prevent nested ScrollAreas from scrolling at the same time; + if (event->type() == QEvent::Wheel) + { + QRect rect = m_list->viewport()->rect(); + QPoint pos = m_list->mapFromGlobal(dynamic_cast(event)->globalPos()); + QScrollBar* bar = m_list->verticalScrollBar(); + + if (bar->minimum() != bar->maximum() && rect.contains(pos)) + { + bool down = dynamic_cast(event)->angleDelta().y() < 0; + + if ((down && bar->value() != bar->maximum()) || (!down && bar->value() != bar->minimum())) + { + return true; + } + } + } + + return QFrame::event(event); +} + +QtListBoxItem* QtListBox::addListBoxItemWithText(const QString& text) +{ + QtListBoxItem* item = addListBoxItem(); + item->setText(text); + return item; +} + +void QtListBox::selectItem(QListWidgetItem* item) +{ + for (int i = 0; i < m_list->count(); i++) + { + m_list->item(i)->setSelected(false); + } + + item->setSelected(true); +} + +QtListBoxItem* QtListBox::addListBoxItem() +{ + QListWidgetItem* item = new QListWidgetItem(m_list); + m_list->addItem(item); + + QtListBoxItem* widget = createListBoxItem(item); + m_list->setItemWidget(item, widget); + + m_list->scrollToItem(item); + widget->setFocus(); + + return widget; +} + +void QtListBox::removeListBoxItem() +{ + if (m_list->selectedItems().empty()) + { + return; + } + + int rowIndex = m_list->row(m_list->selectedItems().first()); + + qDeleteAll(m_list->selectedItems()); + + if (rowIndex == m_list->count()) + { + rowIndex -= 1; + } + + if (rowIndex >= 0) + { + m_list->setCurrentRow(rowIndex); + } +} + +void QtListBox::showEditDialog() +{ + if (!m_editDialog) + { + m_editDialog = std::make_shared(m_listName, "Edit the list in plain text. Each line is one item."); + m_editDialog->setup(); + + std::vector list; + for (int i = 0; i < m_list->count(); ++i) + { + QtListBoxItem* item = dynamic_cast(m_list->itemWidget(m_list->item(i))); + if (!item->getReadOnly()) + { + list.push_back(item->getText().toStdWString()); + } + } + + m_editDialog->setText(utility::join(list, L"\n")); + + connect(m_editDialog.get(), &QtTextEditDialog::canceled, this, &QtListBox::canceledEditDialog); + connect(m_editDialog.get(), &QtTextEditDialog::finished, this, &QtListBox::savedEditDialog); + } + + m_editDialog->showWindow(); + m_editDialog->raise(); +} + +void QtListBox::canceledEditDialog() +{ + m_editDialog->hide(); + m_editDialog.reset(); + + window()->raise(); +} + +void QtListBox::savedEditDialog() +{ + std::vector readOnlyLines; + for (int i = 0; i < m_list->count(); ++i) + { + QtListBoxItem* item = dynamic_cast(m_list->itemWidget(m_list->item(i))); + if (item->getReadOnly()) + { + readOnlyLines.push_back(item->getText().toStdWString()); + } + } + + std::vector lines = utility::splitToVector(m_editDialog->getText(), L"\n"); + for (size_t i = 0; i < lines.size(); i++) + { + lines[i] = utility::trim(lines[i]); + + if (lines[i].empty()) + { + lines.erase(lines.begin() + i); + i--; + } + } + + clear(); + + for (const std::wstring& line : readOnlyLines) + { + QtListBoxItem* itemWidget = addListBoxItemWithText(QString::fromStdWString(line)); + itemWidget->setReadOnly(true); + } + + for (const std::wstring& line : lines) + { + QtListBoxItem* itemWidget = addListBoxItemWithText(QString::fromStdWString(line)); + itemWidget->setReadOnly(false); + } + + canceledEditDialog(); +} diff --git a/src/lib_gui/qt/element/QtListBox.h b/src/lib_gui/qt/element/QtListBox.h new file mode 100644 index 00000000..8130803c --- /dev/null +++ b/src/lib_gui/qt/element/QtListBox.h @@ -0,0 +1,58 @@ +#ifndef QT_LIST_BOX_H +#define QT_LIST_BOX_H + +#include + +#include "utility/file/FilePath.h" + +class QEvent; +class QHBoxLayout; +class QListWidget; +class QListWidgetItem; +class QPushButton; + +class QtTextEditDialog; +class QtListBoxItem; + +class QtListBox + : public QFrame +{ + Q_OBJECT + +public: + QtListBox(QWidget *parent, const QString& listName); + virtual ~QtListBox() = default; + + void clear(); + + QtListBoxItem* addListBoxItemWithText(const QString& text); + + void selectItem(QListWidgetItem* item); + +protected: + void addWidgetToBar(QWidget* widget); + bool event(QEvent* event) override; + + QListWidget* m_list; + +protected slots: + QtListBoxItem* addListBoxItem(); + void removeListBoxItem(); + + void showEditDialog(); + void canceledEditDialog(); + void savedEditDialog(); + +private: + virtual QtListBoxItem* createListBoxItem(QListWidgetItem* item) = 0; + + QHBoxLayout* m_innerBarLayout; + QPushButton* m_addButton; + QPushButton* m_removeButton; + + QString m_listName; + + std::shared_ptr m_editDialog; +}; + +#endif // QT_LIST_BOX_H diff --git a/src/lib_gui/qt/element/QtListBoxItem.cpp b/src/lib_gui/qt/element/QtListBoxItem.cpp new file mode 100644 index 00000000..31a7ce53 --- /dev/null +++ b/src/lib_gui/qt/element/QtListBoxItem.cpp @@ -0,0 +1,88 @@ +#include "qt/element/QtListBoxItem.h" + +#include +#include +#include + +#include "qt/element/QtLineEdit.h" +#include "qt/element/QtListBox.h" +#include "qt/element/QtIconButton.h" +#include "qt/utility/QtFileDialog.h" +#include "utility/ResourcePaths.h" + +QtListBoxItem::QtListBoxItem(QListWidgetItem* item, QWidget *parent) + : QWidget(parent) + , m_item(item) + , m_readOnly(false) +{ + QBoxLayout* layout = new QHBoxLayout(); + layout->setSpacing(3); + layout->setContentsMargins(0, 0, 0, 0); + layout->setAlignment(Qt::AlignTop); + setLayout(layout); + + m_data = new QtLineEdit(this); + m_data->setAttribute(Qt::WA_MacShowFocusRect, 0); + m_data->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac + m_data->setObjectName("field"); + m_data->setAcceptDrops(false); + layout->addWidget(m_data); + + connect(m_data, &QtLineEdit::focus, this, &QtListBoxItem::handleFocus); +} + +QString QtListBoxItem::getText() const +{ + return m_data->text(); +} + +void QtListBoxItem::setText(const QString& text) +{ + m_data->setText(text); +} + +bool QtListBoxItem::getReadOnly() const +{ + return m_readOnly; +} + +void QtListBoxItem::setReadOnly(bool readOnly) +{ + if (readOnly != m_readOnly) + { + m_readOnly = readOnly; + + if (readOnly) + { + m_item->setFlags(m_item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEnabled)); + } + else + { + m_item->setFlags(m_item->flags() | ~(Qt::ItemIsSelectable | Qt::ItemIsEnabled)); + } + + m_data->setReadOnly(readOnly); + m_data->setEnabled(!readOnly); + + onReadOnlyChanged(); + } +} + +void QtListBoxItem::setFocus() +{ + m_data->setFocus(Qt::OtherFocusReason); +} + +void QtListBoxItem::selectItem() +{ + getListBox()->selectItem(m_item); +} + +void QtListBoxItem::handleFocus() +{ + selectItem(); +} + +void QtListBoxItem::onReadOnlyChanged() +{ +} diff --git a/src/lib_gui/qt/element/QtListBoxItem.h b/src/lib_gui/qt/element/QtListBoxItem.h new file mode 100644 index 00000000..99abbd8c --- /dev/null +++ b/src/lib_gui/qt/element/QtListBoxItem.h @@ -0,0 +1,46 @@ +#ifndef QT_LIST_BOX_ITEM_H +#define QT_LIST_BOX_ITEM_H + +#include + +class QtLineEdit; +class QListWidget; +class QPushButton; +class QListWidgetItem; + +class QtListBox; + +class QtListBoxItem + : public QWidget +{ + Q_OBJECT + +public: + QtListBoxItem(QListWidgetItem* item, QWidget *parent = nullptr); + virtual ~QtListBoxItem() = default; + + virtual QString getText() const; + void setText(const QString& text); + + bool getReadOnly() const; + void setReadOnly(bool readOnly); + +public slots: + void setFocus(); + +protected: + virtual QtListBox* getListBox() = 0; + void selectItem(); + +private slots: + void handleFocus(); + +private: + virtual void onReadOnlyChanged(); + + QListWidgetItem* m_item; + QtLineEdit* m_data; + bool m_readOnly; +}; + +#endif // QT_LIST_BOX_ITEM_H diff --git a/src/lib_gui/qt/element/QtPathListBox.cpp b/src/lib_gui/qt/element/QtPathListBox.cpp new file mode 100644 index 00000000..b511a5d8 --- /dev/null +++ b/src/lib_gui/qt/element/QtPathListBox.cpp @@ -0,0 +1,108 @@ +#include "qt/element/QtPathListBox.h" + +#include +#include +#include +#include + +#include "qt/element/QtPathListBoxItem.h" + +QtPathListBox::QtPathListBox(QWidget *parent, const QString& listName, SelectionPolicyType selectionPolicy) + : QtListBox(parent, listName) + , m_selectionPolicy(selectionPolicy) +{ + QLabel* dropInfoText = new QLabel("Drop Files & Folders"); + dropInfoText->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + dropInfoText->setObjectName("dropInfo"); + dropInfoText->setAlignment(Qt::AlignRight); + + addWidgetToBar(dropInfoText); +} + +QtPathListBox::SelectionPolicyType QtPathListBox::getSelectionPolicy() const +{ + return m_selectionPolicy; +} + +const FilePath& QtPathListBox::getRelativeRootDirectory() const +{ + return m_relativeRootDirectory; +} + +void QtPathListBox::setRelativeRootDirectory(const FilePath& dir) +{ + m_relativeRootDirectory = dir; +} + +std::vector QtPathListBox::getPathsAsDisplayed() const +{ + std::vector paths; + for (int i = 0; i < m_list->count(); ++i) + { + QtListBoxItem* widget = dynamic_cast(m_list->itemWidget(m_list->item(i))); + paths.push_back(FilePath(widget->getText().toStdWString())); + } + return paths; +} + +std::vector QtPathListBox::getPathsAsAbsolute() const +{ + std::vector paths = getPathsAsDisplayed(); + for (FilePath& path: paths) + { + makeAbsolute(path); + } + return paths; +} + +void QtPathListBox::setPaths(const std::vector& list, bool readOnly) +{ + clear(); + + for (FilePath path : list) + { + makeRelative(path); + QtListBoxItem* item = addListBoxItemWithText(QString::fromStdWString(path.wstr())); + item->setReadOnly(readOnly); + } +} + +void QtPathListBox::makeAbsolute(FilePath& path) const +{ + if (!path.empty() && !path.isAbsolute() && !m_relativeRootDirectory.empty()) + { + path = m_relativeRootDirectory.getConcatenated(path); + } +} + +void QtPathListBox::makeRelative(FilePath& path) const +{ + if (!m_relativeRootDirectory.empty()) + { + const FilePath relPath = path.getRelativeTo(m_relativeRootDirectory); + if (relPath.wstr().size() < path.wstr().size()) + { + path = relPath; + } + } +} + +void QtPathListBox::dropEvent(QDropEvent *event) +{ + foreach(QUrl url, event->mimeData()->urls()) + { + FilePath path(url.toLocalFile().toStdWString()); + makeRelative(path); + QtListBoxItem* item = addListBoxItemWithText(QString::fromStdWString(path.wstr())); + } +} + +void QtPathListBox::dragEnterEvent(QDragEnterEvent *event) +{ + event->accept(); +} + +QtListBoxItem* QtPathListBox::createListBoxItem(QListWidgetItem* item) +{ + return new QtPathListBoxItem(this, item); +} diff --git a/src/lib_gui/qt/element/QtPathListBox.h b/src/lib_gui/qt/element/QtPathListBox.h new file mode 100644 index 00000000..db817970 --- /dev/null +++ b/src/lib_gui/qt/element/QtPathListBox.h @@ -0,0 +1,42 @@ +#ifndef QT_PATH_LIST_BOX_H +#define QT_PATH_LIST_BOX_H + +#include "qt/element/QtListBox.h" + +class QtPathListBox + : public QtListBox +{ +public: + enum SelectionPolicyType + { + SELECTION_POLICY_FILES_ONLY, + SELECTION_POLICY_DIRECTORIES_ONLY, + SELECTION_POLICY_FILES_AND_DIRECTORIES + }; + + QtPathListBox(QWidget *parent, const QString& listName, SelectionPolicyType selectionPolicy); + + SelectionPolicyType getSelectionPolicy() const; + + const FilePath& getRelativeRootDirectory() const; + void setRelativeRootDirectory(const FilePath& dir); + + std::vector getPathsAsDisplayed() const; + std::vector getPathsAsAbsolute() const; + void setPaths(const std::vector& list, bool readOnly = false); + + void makeAbsolute(FilePath& path) const; + void makeRelative(FilePath& path) const; + +protected: + void dropEvent(QDropEvent *event) override; + void dragEnterEvent(QDragEnterEvent* event) override; + +private: + virtual QtListBoxItem* createListBoxItem(QListWidgetItem* item) override; + + const SelectionPolicyType m_selectionPolicy; + FilePath m_relativeRootDirectory; +}; + +#endif // QT_PATH_LIST_BOX_H diff --git a/src/lib_gui/qt/element/QtPathListBoxItem.cpp b/src/lib_gui/qt/element/QtPathListBoxItem.cpp new file mode 100644 index 00000000..c99b4627 --- /dev/null +++ b/src/lib_gui/qt/element/QtPathListBoxItem.cpp @@ -0,0 +1,72 @@ +#include "qt/element/QtPathListBoxItem.h" + +#include +#include +#include + +#include "qt/element/QtLineEdit.h" +#include "qt/element/QtPathListBox.h" +#include "qt/element/QtIconButton.h" +#include "qt/utility/QtFileDialog.h" +#include "utility/ResourcePaths.h" + +QtPathListBoxItem::QtPathListBoxItem(QtPathListBox* listBox, QListWidgetItem* item, QWidget *parent) + : QtListBoxItem(item, parent) + , m_listBox(listBox) +{ + m_button = new QtIconButton( + ResourcePaths::getGuiPath().concatenate(L"window/dots.png"), + ResourcePaths::getGuiPath().concatenate(L"window/dots_hover.png") + ); + m_button->setIconSize(QSize(16, 16)); + m_button->setObjectName("dotsButton"); + layout()->addWidget(m_button); + + connect(m_button, &QPushButton::clicked, this, &QtPathListBoxItem::handleButtonPress); +} + +QtListBox* QtPathListBoxItem::getListBox() +{ + return m_listBox; +} + +void QtPathListBoxItem::handleButtonPress() +{ + FilePath path(getText().toStdWString()); + m_listBox->makeAbsolute(path); + + QStringList list; + switch (m_listBox->getSelectionPolicy()) + { + case QtPathListBox::SELECTION_POLICY_FILES_ONLY: + list.append(QtFileDialog::getOpenFileName(this, "Select Directory", path, "")); + break; + case QtPathListBox::SELECTION_POLICY_DIRECTORIES_ONLY: + list.append(QtFileDialog::getExistingDirectory(this, "Select Directory", path)); + break; + case QtPathListBox::SELECTION_POLICY_FILES_AND_DIRECTORIES: + list = QtFileDialog::getFileNamesAndDirectories(this, path); + break; + } + + if (!list.isEmpty()) + { + FilePath path(list.at(0).toStdWString()); + m_listBox->makeRelative(path); + setText(QString::fromStdWString(path.wstr())); + } + + for (int i = 1; i < list.size(); i++) + { + FilePath path(list.at(i).toStdWString()); + m_listBox->makeRelative(path); + getListBox()->addListBoxItemWithText(QString::fromStdWString(path.wstr())); + } + + selectItem(); +} + +void QtPathListBoxItem::onReadOnlyChanged() +{ + m_button->setEnabled(!getReadOnly()); +} diff --git a/src/lib_gui/qt/element/QtPathListBoxItem.h b/src/lib_gui/qt/element/QtPathListBoxItem.h new file mode 100644 index 00000000..35725177 --- /dev/null +++ b/src/lib_gui/qt/element/QtPathListBoxItem.h @@ -0,0 +1,33 @@ +#ifndef QT_PATH_LIST_BOX_ITEM_H +#define QT_PATH_LIST_BOX_ITEM_H + +#include "qt/element/QtListBoxItem.h" + +class QPushButton; +class QListWidgetItem; + +class FilePath; +class QtPathListBox; + +class QtPathListBoxItem + : public QtListBoxItem +{ + Q_OBJECT + +public: + QtPathListBoxItem(QtPathListBox* listBox, QListWidgetItem* item, QWidget *parent = nullptr); + +protected: + virtual QtListBox* getListBox() override; + +private slots: + void handleButtonPress(); + +private: + virtual void onReadOnlyChanged() override; + + QtPathListBox* m_listBox; + QPushButton* m_button; +}; + +#endif // QT_PATH_LIST_BOX_ITEM_H diff --git a/src/lib_gui/qt/element/QtStringListBox.cpp b/src/lib_gui/qt/element/QtStringListBox.cpp new file mode 100644 index 00000000..ba99c77b --- /dev/null +++ b/src/lib_gui/qt/element/QtStringListBox.cpp @@ -0,0 +1,37 @@ +#include "qt/element/QtStringListBox.h" + +#include + +#include "qt/element/QtStringListBoxItem.h" + +QtStringListBox::QtStringListBox(QWidget *parent, const QString& listName) + : QtListBox(parent, listName) +{ +} + +std::vector QtStringListBox::getStrings() +{ + std::vector strings; + for (int i = 0; i < m_list->count(); ++i) + { + QtListBoxItem* widget = dynamic_cast(m_list->itemWidget(m_list->item(i))); + strings.push_back(widget->getText().toStdWString()); + } + return strings; +} + +void QtStringListBox::setStrings(const std::vector& strings, bool readOnly) +{ + clear(); + + for (const std::wstring& str : strings) + { + QtListBoxItem* itemWidget = addListBoxItemWithText(QString::fromStdWString(str)); + itemWidget->setReadOnly(readOnly); + } +} + +QtListBoxItem* QtStringListBox::createListBoxItem(QListWidgetItem* item) +{ + return new QtStringListBoxItem(this, item); +} diff --git a/src/lib_gui/qt/element/QtStringListBox.h b/src/lib_gui/qt/element/QtStringListBox.h new file mode 100644 index 00000000..dfc73049 --- /dev/null +++ b/src/lib_gui/qt/element/QtStringListBox.h @@ -0,0 +1,20 @@ +#ifndef QT_STRING_LIST_BOX_H +#define QT_STRING_LIST_BOX_H + +#include "qt/element/QtListBox.h" +#include "qt/element/QtStringListBoxItem.h" + +class QtStringListBox + : public QtListBox +{ +public: + QtStringListBox(QWidget *parent, const QString& listName); + + std::vector getStrings(); + void setStrings(const std::vector& strings, bool readOnly = false); + +private: + virtual QtListBoxItem* createListBoxItem(QListWidgetItem* item) override; +}; + +#endif // QT_STRING_LIST_BOX_H diff --git a/src/lib_gui/qt/element/QtStringListBoxItem.cpp b/src/lib_gui/qt/element/QtStringListBoxItem.cpp new file mode 100644 index 00000000..df4c1080 --- /dev/null +++ b/src/lib_gui/qt/element/QtStringListBoxItem.cpp @@ -0,0 +1,14 @@ +#include "qt/element/QtStringListBoxItem.h" + +#include "qt/element/QtStringListBox.h" + +QtStringListBoxItem::QtStringListBoxItem(QtStringListBox* listBox, QListWidgetItem* item, QWidget *parent) + : QtListBoxItem(item, parent) + , m_listBox(listBox) +{ +} + +QtListBox* QtStringListBoxItem::getListBox() +{ + return m_listBox; +} diff --git a/src/lib_gui/qt/element/QtStringListBoxItem.h b/src/lib_gui/qt/element/QtStringListBoxItem.h new file mode 100644 index 00000000..78ef856d --- /dev/null +++ b/src/lib_gui/qt/element/QtStringListBoxItem.h @@ -0,0 +1,26 @@ +#ifndef QT_STRING_LIST_BOX_ITEM_H +#define QT_STRING_LIST_BOX_ITEM_H + +#include "qt/element/QtListBoxItem.h" + +class QListWidgetItem; + +class QtListBox; +class QtStringListBox; + +class QtStringListBoxItem + : public QtListBoxItem +{ + Q_OBJECT + +public: + QtStringListBoxItem(QtStringListBox* listBox, QListWidgetItem* item, QWidget *parent = nullptr); + +protected: + virtual QtListBox* getListBox() override; + +private: + QtStringListBox* m_listBox; +}; + +#endif // QT_STRING_LIST_BOX_ITEM_H diff --git a/src/lib_gui/qt/window/QtPathListDialog.cpp b/src/lib_gui/qt/window/QtPathListDialog.cpp index 86ac26f2..df0bb39b 100644 --- a/src/lib_gui/qt/window/QtPathListDialog.cpp +++ b/src/lib_gui/qt/window/QtPathListDialog.cpp @@ -1,12 +1,12 @@ #include "qt/window/QtPathListDialog.h" #include -#include "qt/element/QtDirectoryListBox.h" -QtPathListDialog::QtPathListDialog(const QString& title, const QString& description, QWidget* parent) +QtPathListDialog::QtPathListDialog(const QString& title, const QString& description, QtPathListBox::SelectionPolicyType selectionPolicy, QWidget* parent) : QtWindow(false, parent) , m_title(title) , m_description(description) + , m_selectionPolicy(selectionPolicy) { } @@ -22,12 +22,12 @@ void QtPathListDialog::setRelativeRootDirectory(const FilePath& dir) void QtPathListDialog::setPaths(const std::vector& paths, bool readOnly) { - m_pathList->setList(paths, readOnly); + m_pathList->setPaths(paths, readOnly); } std::vector QtPathListDialog::getPaths() { - return m_pathList->getList(); + return m_pathList->getPathsAsDisplayed(); } void QtPathListDialog::populateWindow(QWidget* widget) @@ -42,7 +42,7 @@ void QtPathListDialog::populateWindow(QWidget* widget) layout->addSpacing(10); - m_pathList = new QtDirectoryListBox(nullptr, m_title); + m_pathList = new QtPathListBox(nullptr, m_title, m_selectionPolicy); m_pathList->setMaximumHeight(1000); layout->addWidget(m_pathList); diff --git a/src/lib_gui/qt/window/QtPathListDialog.h b/src/lib_gui/qt/window/QtPathListDialog.h index ed61ea84..b6294e4b 100644 --- a/src/lib_gui/qt/window/QtPathListDialog.h +++ b/src/lib_gui/qt/window/QtPathListDialog.h @@ -1,10 +1,10 @@ #ifndef QT_PATH_LIST_DIALOG_H #define QT_PATH_LIST_DIALOG_H +#include "qt/element/QtPathListBox.h" #include "qt/window/QtWindow.h" class FilePath; -class QtDirectoryListBox; class QtPathListDialog : public QtWindow @@ -12,7 +12,7 @@ class QtPathListDialog Q_OBJECT public: - QtPathListDialog(const QString& title, const QString& description, QWidget* parent = 0); + QtPathListDialog(const QString& title, const QString& description, QtPathListBox::SelectionPolicyType selectionPolicy, QWidget* parent = 0); QSize sizeHint() const override; @@ -24,11 +24,12 @@ protected: void populateWindow(QWidget* widget) override; void windowReady() override; - QString m_title; - QString m_description; + const QString m_title; + const QString m_description; private: - QtDirectoryListBox* m_pathList; + const QtPathListBox::SelectionPolicyType m_selectionPolicy; + QtPathListBox* m_pathList; }; #endif // QT_PATH_LIST_DIALOG_H diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentExtensions.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentExtensions.cpp index 68fe6bf7..c4a6dd85 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentExtensions.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentExtensions.cpp @@ -3,7 +3,7 @@ #include #include "settings/SourceGroupSettings.h" -#include "qt/element/QtDirectoryListBox.h" +#include "qt/element/QtStringListBox.h" QtProjectWizzardContentExtensions::QtProjectWizzardContentExtensions( std::shared_ptr settings, QtProjectWizzardWindow* window @@ -20,17 +20,17 @@ void QtProjectWizzardContentExtensions::populate(QGridLayout* layout, int& row) addHelpButton("Source File Extensions", "Define extensions for source files including the dot (e.g. .cpp or .java)", layout, row); - m_sourceList = new QtDirectoryListBox(this, sourceLabel->text(), true); - layout->addWidget(m_sourceList, row, QtProjectWizzardWindow::BACK_COL); + m_listBox = new QtStringListBox(this, sourceLabel->text()); + layout->addWidget(m_listBox, row, QtProjectWizzardWindow::BACK_COL); row++; } void QtProjectWizzardContentExtensions::load() { - m_sourceList->setStringList(m_settings->getSourceExtensions()); + m_listBox->setStrings(m_settings->getSourceExtensions()); } void QtProjectWizzardContentExtensions::save() { - m_settings->setSourceExtensions(m_sourceList->getStringList()); + m_settings->setSourceExtensions(m_listBox->getStrings()); } diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentExtensions.h b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentExtensions.h index 86f30beb..3a3f969f 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentExtensions.h +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentExtensions.h @@ -3,7 +3,7 @@ #include "qt/window/project_wizzard/QtProjectWizzardContent.h" -class QtDirectoryListBox; +class QtStringListBox; class SourceGroupSettings; class QtProjectWizzardContentExtensions @@ -23,7 +23,7 @@ public: private: std::shared_ptr m_settings; - QtDirectoryListBox* m_sourceList; + QtStringListBox* m_listBox; }; #endif // QT_PROJECT_WIZZARD_CONTENT_EXTENSIONS_H diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentFlags.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentFlags.cpp index 4d0ef87b..e796a5dd 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentFlags.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentFlags.cpp @@ -2,7 +2,7 @@ #include -#include "qt/element/QtDirectoryListBox.h" +#include "qt/element/QtStringListBox.h" #include "settings/SourceGroupSettingsCxx.h" QtProjectWizzardContentFlags::QtProjectWizzardContentFlags(std::shared_ptr settings, QtProjectWizzardWindow* window, bool isCDB) @@ -20,7 +20,7 @@ void QtProjectWizzardContentFlags::populate(QGridLayout* layout, int& row) addHelpButton(labelText, "Define additional Clang compiler flags used during indexing including the dash (e.g. use \"-D RELEASE\" to add a #define for \"RELEASE\").", layout, row); - m_list = new QtDirectoryListBox(this, label->text(), true); + m_list = new QtStringListBox(this, label->text()); layout->addWidget(m_list, row, QtProjectWizzardWindow::BACK_COL); row++; } @@ -30,7 +30,7 @@ void QtProjectWizzardContentFlags::load() std::shared_ptr cxxSettings = std::dynamic_pointer_cast(m_settings); if (cxxSettings) { - m_list->setStringList(cxxSettings->getCompilerFlags()); + m_list->setStrings(cxxSettings->getCompilerFlags()); } } @@ -39,6 +39,6 @@ void QtProjectWizzardContentFlags::save() std::shared_ptr cxxSettings = std::dynamic_pointer_cast(m_settings); if (cxxSettings) { - cxxSettings->setCompilerFlags(m_list->getStringList()); + cxxSettings->setCompilerFlags(m_list->getStrings()); } } diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentFlags.h b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentFlags.h index a43ced3e..670ef2ee 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentFlags.h +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentFlags.h @@ -3,7 +3,7 @@ #include "qt/window/project_wizzard/QtProjectWizzardContent.h" -class QtDirectoryListBox; +class QtStringListBox; class SourceGroupSettings; class QtProjectWizzardContentFlags @@ -24,7 +24,7 @@ private: std::shared_ptr m_settings; const bool m_isCdb; - QtDirectoryListBox* m_list; + QtStringListBox* m_list; }; #endif // QT_PROJECT_WIZZARD_CONTENT_FLAGS_H diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp index 9f6c7694..d8867d87 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp @@ -11,7 +11,6 @@ #include "data/indexer/IndexerCommandCxxCdb.h" #include "utility/IncludeDirective.h" #include "utility/IncludeProcessing.h" -#include "qt/element/QtDirectoryListBox.h" #include "qt/view/QtDialogView.h" #include "qt/window/QtPathListDialog.h" #include "qt/window/QtSelectPathsDialog.h" @@ -27,11 +26,15 @@ #include "utility/utilityString.h" QtProjectWizzardContentPaths::QtProjectWizzardContentPaths( - std::shared_ptr settings, QtProjectWizzardWindow* window, bool checkMissingPaths + std::shared_ptr settings, + QtProjectWizzardWindow* window, + QtPathListBox::SelectionPolicyType selectionPolicy, + bool checkMissingPaths ) : QtProjectWizzardContent(window) , m_settings(settings) , m_makePathsRelativeToProjectFileLocation(true) + , m_selectionPolicy(selectionPolicy) , m_checkMissingPaths(checkMissingPaths) { } @@ -46,7 +49,7 @@ void QtProjectWizzardContentPaths::populate(QGridLayout* layout, int& row) addHelpButton(m_titleString, m_helpString, layout, row); } - m_list = new QtDirectoryListBox(this, m_titleString); + m_list = new QtPathListBox(this, m_titleString, m_selectionPolicy); if (m_makePathsRelativeToProjectFileLocation && m_settings) { @@ -76,7 +79,7 @@ bool QtProjectWizzardContentPaths::check() QString missingPaths; std::vector existingPaths; - for (const FilePath& path : m_list->getList()) + for (const FilePath& path : m_list->getPathsAsDisplayed()) { std::vector expandedPaths(1, path); if (m_settings) @@ -117,7 +120,7 @@ bool QtProjectWizzardContentPaths::check() if (ret == QMessageBox::Yes) { - m_list->setList(existingPaths); + m_list->setPaths(existingPaths); save(); } else if (ret == QMessageBox::Cancel) @@ -175,15 +178,15 @@ void QtProjectWizzardContentPaths::addDetection(QGridLayout* layout, int row) void QtProjectWizzardContentPaths::detectionClicked() { std::vector paths = m_pathDetector->getPaths(m_detectorBox->currentText().toStdString()); - std::vector oldPaths = m_list->getList(); - m_list->setList(utility::unique(utility::concat(oldPaths, paths))); + std::vector oldPaths = m_list->getPathsAsDisplayed(); + m_list->setPaths(utility::unique(utility::concat(oldPaths, paths))); } QtProjectWizzardContentPathsSource::QtProjectWizzardContentPathsSource( std::shared_ptr settings, QtProjectWizzardWindow* window ) - : QtProjectWizzardContentPaths(settings, window) + : QtProjectWizzardContentPaths(settings, window, QtPathListBox::SELECTION_POLICY_FILES_AND_DIRECTORIES) { m_showFilesString = "show files"; @@ -201,12 +204,12 @@ QtProjectWizzardContentPathsSource::QtProjectWizzardContentPathsSource( void QtProjectWizzardContentPathsSource::load() { - m_list->setList(m_settings->getSourcePaths()); + m_list->setPaths(m_settings->getSourcePaths()); } void QtProjectWizzardContentPathsSource::save() { - m_settings->setSourcePaths(m_list->getList()); + m_settings->setSourcePaths(m_list->getPathsAsDisplayed()); } std::vector QtProjectWizzardContentPathsSource::getFilePaths() const @@ -340,7 +343,7 @@ void QtProjectWizzardContentPathsCDBHeader::load() bool QtProjectWizzardContentPathsCDBHeader::check() { - if (!m_list->getList().size()) + if (m_list->getPathsAsDisplayed().empty()) { QMessageBox msgBox; msgBox.setText("You didn't specify any Header Files & Directories to Index."); @@ -398,7 +401,7 @@ void QtProjectWizzardContentPathsCDBHeader::buttonClicked() void QtProjectWizzardContentPathsCDBHeader::savedFilesDialog() { // TODO: extend instead of replace - m_list->setList(dynamic_cast(m_filesDialog.get())->getPathsList()); + m_list->setPaths(dynamic_cast(m_filesDialog.get())->getPathsList()); closedFilesDialog(); } @@ -406,7 +409,7 @@ void QtProjectWizzardContentPathsCDBHeader::savedFilesDialog() QtProjectWizzardContentPathsExclude::QtProjectWizzardContentPathsExclude( std::shared_ptr settings, QtProjectWizzardWindow* window ) - : QtProjectWizzardContentPaths(settings, window, false) + : QtProjectWizzardContentPaths(settings, window, QtPathListBox::SELECTION_POLICY_FILES_AND_DIRECTORIES, false) { setTitleString("Excluded Files & Directories"); setHelpString( @@ -418,19 +421,19 @@ QtProjectWizzardContentPathsExclude::QtProjectWizzardContentPathsExclude( void QtProjectWizzardContentPathsExclude::load() { - m_list->setStringList(m_settings->getExcludeFilterStrings()); + m_list->setPaths(utility::convert(m_settings->getExcludeFilterStrings(), [](const std::wstring& s) { return FilePath(s); })); } void QtProjectWizzardContentPathsExclude::save() { - m_settings->setExcludeFilterStrings(m_list->getStringList()); + m_settings->setExcludeFilterStrings(utility::toWStrings(m_list->getPathsAsDisplayed())); } QtProjectWizzardContentPathsHeaderSearch::QtProjectWizzardContentPathsHeaderSearch( std::shared_ptr settings, QtProjectWizzardWindow* window, bool isCDB ) - : QtProjectWizzardContentPaths(settings, window) + : QtProjectWizzardContentPaths(settings, window, QtPathListBox::SELECTION_POLICY_DIRECTORIES_ONLY) , m_showDetectedIncludesResultFunctor(std::bind( &QtProjectWizzardContentPathsHeaderSearch::showDetectedIncludesResult, this, std::placeholders::_1)) , m_showValidationResultFunctor(std::bind( @@ -481,7 +484,7 @@ void QtProjectWizzardContentPathsHeaderSearch::load() std::shared_ptr cxxSettings = std::dynamic_pointer_cast(m_settings); if (cxxSettings) { - m_list->setList(cxxSettings->getHeaderSearchPaths()); + m_list->setPaths(cxxSettings->getHeaderSearchPaths()); } } @@ -490,7 +493,7 @@ void QtProjectWizzardContentPathsHeaderSearch::save() std::shared_ptr cxxSettings = std::dynamic_pointer_cast(m_settings); if (cxxSettings) { - cxxSettings->setHeaderSearchPaths(m_list->getList()); + cxxSettings->setHeaderSearchPaths(m_list->getPathsAsDisplayed()); } } @@ -508,7 +511,8 @@ void QtProjectWizzardContentPathsHeaderSearch::detectIncludesButtonClicked() "

Automatically search for header files in the paths provided below to find missing include paths for " "unresolved include directives in your source code.

" "

The \"Files & Directories to Index\" will be searched by default, but you can add further paths, such " - "as directories of third-party libraries, if required.

" + "as directories of third-party libraries, if required.

", + QtPathListBox::SELECTION_POLICY_DIRECTORIES_ONLY ); m_pathsDialog->setup(); @@ -653,18 +657,18 @@ void QtProjectWizzardContentPathsHeaderSearch::finishedAcceptDetectedIncludePath const std::vector detectedPaths = utility::split>(m_filesDialog->getText(), L"\n"); closedFilesDialog(); - std::vector headerSearchPaths = m_list->getStringList(); + std::vector headerSearchPaths = m_list->getPathsAsDisplayed(); headerSearchPaths.reserve(headerSearchPaths.size() + detectedPaths.size()); for (const std::wstring& detectedPath : detectedPaths) { if (!detectedPath.empty()) { - headerSearchPaths.push_back(detectedPath); + headerSearchPaths.push_back(FilePath(detectedPath)); } } - m_list->setStringList(headerSearchPaths); + m_list->setPaths(headerSearchPaths); } void QtProjectWizzardContentPathsHeaderSearch::closedPathsDialog() @@ -677,7 +681,7 @@ void QtProjectWizzardContentPathsHeaderSearch::closedPathsDialog() void QtProjectWizzardContentPathsHeaderSearch::showDetectedIncludesResult(const std::set& detectedHeaderSearchPaths) { - const std::set headerSearchPaths = utility::toSet(m_settings->makePathsExpandedAndAbsolute(m_list->getList())); + const std::set headerSearchPaths = utility::toSet(m_settings->makePathsExpandedAndAbsolute(m_list->getPathsAsDisplayed())); std::vector additionalHeaderSearchPaths; for (const FilePath& detectedHeaderSearchPath : detectedHeaderSearchPaths) @@ -697,7 +701,7 @@ void QtProjectWizzardContentPathsHeaderSearch::showDetectedIncludesResult(const else { std::wstring detailedText = L""; - FilePath relativeRoot = m_list->getRelativeRootDirectory(); + const FilePath relativeRoot = m_list->getRelativeRootDirectory(); for (const FilePath& path : additionalHeaderSearchPaths) { if (!relativeRoot.empty()) @@ -788,7 +792,7 @@ void QtProjectWizzardContentPathsHeaderSearch::showValidationResult(const std::v QtProjectWizzardContentPathsHeaderSearchGlobal::QtProjectWizzardContentPathsHeaderSearchGlobal( QtProjectWizzardWindow* window ) - : QtProjectWizzardContentPaths(std::shared_ptr(), window) + : QtProjectWizzardContentPaths(std::shared_ptr(), window, QtPathListBox::SELECTION_POLICY_DIRECTORIES_ONLY) { setTitleString("Global Include Paths"); setHelpString( @@ -805,12 +809,12 @@ QtProjectWizzardContentPathsHeaderSearchGlobal::QtProjectWizzardContentPathsHead void QtProjectWizzardContentPathsHeaderSearchGlobal::load() { - m_list->setList(ApplicationSettings::getInstance()->getHeaderSearchPaths()); + m_list->setPaths(ApplicationSettings::getInstance()->getHeaderSearchPaths()); } void QtProjectWizzardContentPathsHeaderSearchGlobal::save() { - ApplicationSettings::getInstance()->setHeaderSearchPaths(m_list->getList()); + ApplicationSettings::getInstance()->setHeaderSearchPaths(m_list->getPathsAsDisplayed()); ApplicationSettings::getInstance()->save(); } @@ -818,7 +822,7 @@ void QtProjectWizzardContentPathsHeaderSearchGlobal::save() QtProjectWizzardContentPathsFrameworkSearch::QtProjectWizzardContentPathsFrameworkSearch( std::shared_ptr settings, QtProjectWizzardWindow* window, bool isCDB ) - : QtProjectWizzardContentPaths(settings, window) + : QtProjectWizzardContentPaths(settings, window, QtPathListBox::SELECTION_POLICY_DIRECTORIES_ONLY) { setTitleString(isCDB ? "Additional Framework Search Paths" : "Framework Search Paths"); setHelpString( @@ -834,7 +838,7 @@ void QtProjectWizzardContentPathsFrameworkSearch::load() std::shared_ptr cxxSettings = std::dynamic_pointer_cast(m_settings); if (cxxSettings) { - m_list->setList(cxxSettings->getFrameworkSearchPaths()); + m_list->setPaths(cxxSettings->getFrameworkSearchPaths()); } } @@ -843,7 +847,7 @@ void QtProjectWizzardContentPathsFrameworkSearch::save() std::shared_ptr cxxSettings = std::dynamic_pointer_cast(m_settings); if (cxxSettings) { - cxxSettings->setFrameworkSearchPaths(m_list->getList()); + cxxSettings->setFrameworkSearchPaths(m_list->getPathsAsDisplayed()); } } @@ -855,7 +859,7 @@ bool QtProjectWizzardContentPathsFrameworkSearch::isScrollAble() const QtProjectWizzardContentPathsFrameworkSearchGlobal::QtProjectWizzardContentPathsFrameworkSearchGlobal( QtProjectWizzardWindow* window ) - : QtProjectWizzardContentPaths(std::shared_ptr(), window) + : QtProjectWizzardContentPaths(std::shared_ptr(), window, QtPathListBox::SELECTION_POLICY_DIRECTORIES_ONLY) { setTitleString("Global Framework Search Paths"); setHelpString( @@ -873,12 +877,12 @@ QtProjectWizzardContentPathsFrameworkSearchGlobal::QtProjectWizzardContentPathsF void QtProjectWizzardContentPathsFrameworkSearchGlobal::load() { - m_list->setList(ApplicationSettings::getInstance()->getFrameworkSearchPaths()); + m_list->setPaths(ApplicationSettings::getInstance()->getFrameworkSearchPaths()); } void QtProjectWizzardContentPathsFrameworkSearchGlobal::save() { - ApplicationSettings::getInstance()->setFrameworkSearchPaths(m_list->getList()); + ApplicationSettings::getInstance()->setFrameworkSearchPaths(m_list->getPathsAsDisplayed()); ApplicationSettings::getInstance()->save(); } @@ -886,7 +890,7 @@ void QtProjectWizzardContentPathsFrameworkSearchGlobal::save() QtProjectWizzardContentPathsClassJava::QtProjectWizzardContentPathsClassJava( std::shared_ptr settings, QtProjectWizzardWindow* window ) - : QtProjectWizzardContentPaths(settings, window) + : QtProjectWizzardContentPaths(settings, window, QtPathListBox::SELECTION_POLICY_FILES_AND_DIRECTORIES) { setTitleString("Class Path"); setHelpString( @@ -917,7 +921,7 @@ void QtProjectWizzardContentPathsClassJava::load() std::dynamic_pointer_cast(m_settings); if (javaSettings) { - m_list->setList(javaSettings->getClasspath()); + m_list->setPaths(javaSettings->getClasspath()); m_useJreSystemLibraryCheckBox->setChecked(javaSettings->getUseJreSystemLibrary()); } } @@ -928,7 +932,7 @@ void QtProjectWizzardContentPathsClassJava::save() std::dynamic_pointer_cast(m_settings); if (javaSettings) { - javaSettings->setClasspath(m_list->getList()); + javaSettings->setClasspath(m_list->getPathsAsDisplayed()); javaSettings->setUseJreSystemLibrary(m_useJreSystemLibraryCheckBox->isChecked()); } } diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h index 605cfec5..a1377f50 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h @@ -3,6 +3,7 @@ #include +#include "qt/element/QtPathListBox.h" #include "qt/window/project_wizzard/QtProjectWizzardContent.h" #include "utility/path_detector/CombinedPathDetector.h" @@ -10,7 +11,6 @@ class IncludeDirective; class QCheckBox; class QComboBox; class QPushButton; -class QtDirectoryListBox; class QtPathListDialog; class SourceGroupSettings; class SourceGroupSettingsCxxCdb; @@ -24,7 +24,11 @@ signals: void showSourceFiles(); public: - QtProjectWizzardContentPaths(std::shared_ptr settings, QtProjectWizzardWindow* window, bool checkMissingPaths = true); + QtProjectWizzardContentPaths( + std::shared_ptr settings, + QtProjectWizzardWindow* window, + QtPathListBox::SelectionPolicyType selectionPolicy, + bool checkMissingPaths = true); // QtSettingsWindow implementation virtual void populate(QGridLayout* layout, int& row) override; @@ -39,7 +43,7 @@ protected: std::shared_ptr m_settings; - QtDirectoryListBox* m_list; + QtPathListBox* m_list; QString m_showFilesString; std::shared_ptr m_pathDetector; @@ -50,6 +54,7 @@ private slots: void detectionClicked(); private: + const QtPathListBox::SelectionPolicyType m_selectionPolicy; const bool m_checkMissingPaths; QString m_titleString; QString m_helpString; diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.cpp index f2f694cd..968239c1 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.cpp @@ -332,7 +332,7 @@ void QtProjectWizzardContentPreferences::populate(QGridLayout* layout, int& row) "

Add the jar files of your JRE System Library. These jars can be found inside your JRE install directory.

", layout, row); - m_jreSystemLibraryPaths = new QtDirectoryListBox(this, title); + m_jreSystemLibraryPaths = new QtPathListBox(this, title, QtPathListBox::SELECTION_POLICY_FILES_ONLY); layout->addWidget(m_jreSystemLibraryPaths, row, QtProjectWizzardWindow::BACK_COL); row++; @@ -439,7 +439,7 @@ void QtProjectWizzardContentPreferences::load() m_jvmMaximumMemory->setText(QString::number(appSettings->getJavaMaximumMemory())); - m_jreSystemLibraryPaths->setList(appSettings->getJreSystemLibraryPaths()); + m_jreSystemLibraryPaths->setPaths(appSettings->getJreSystemLibraryPaths()); if (m_mavenPath) { @@ -498,7 +498,7 @@ void QtProjectWizzardContentPreferences::save() appSettings->setJavaPath(FilePath(m_javaPath->getText().toStdWString())); } - appSettings->setJreSystemLibraryPaths(m_jreSystemLibraryPaths->getList()); + appSettings->setJreSystemLibraryPaths(m_jreSystemLibraryPaths->getPathsAsAbsolute()); int jvmMaximumMemory = m_jvmMaximumMemory->text().toInt(); if (jvmMaximumMemory) appSettings->setJavaMaximumMemory(jvmMaximumMemory); @@ -535,8 +535,8 @@ void QtProjectWizzardContentPreferences::jreSystemLibraryPathsDetectionClicked() { std::vector paths = m_jreSystemLibraryPathsDetector->getPaths(m_jreSystemLibraryPathsDetectorBox->currentText().toStdString()); - std::vector oldPaths = m_jreSystemLibraryPaths->getList(); - m_jreSystemLibraryPaths->setList(utility::unique(utility::concat(oldPaths, paths))); + std::vector oldPaths = m_jreSystemLibraryPaths->getPathsAsAbsolute(); + m_jreSystemLibraryPaths->setPaths(utility::unique(utility::concat(oldPaths, paths))); } void QtProjectWizzardContentPreferences::mavenPathDetectionClicked() diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.h b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.h index f2e4665e..f61c74b1 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.h +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.h @@ -4,7 +4,7 @@ #include #include "qt/element/QtLocationPicker.h" -#include "qt/element/QtDirectoryListBox.h" +#include "qt/element/QtPathListBox.h" #include "qt/window/project_wizzard/QtProjectWizzardContent.h" #include "utility/path_detector/CombinedPathDetector.h" @@ -122,7 +122,7 @@ private: QComboBox* m_jreSystemLibraryPathsDetectorBox; QComboBox* m_mavenPathDetectorBox; QtLocationPicker* m_javaPath; - QtDirectoryListBox* m_jreSystemLibraryPaths; + QtPathListBox* m_jreSystemLibraryPaths; QLineEdit* m_jvmMaximumMemory; QtLocationPicker* m_mavenPath; };