#include "./pathselection.h" #include "./clearlineedit.h" #include "../misc/desktoputils.h" #include #include #include #include #include #include #include #include #ifndef QT_NO_CONTEXTMENU #include #endif #include #include using namespace std; namespace QtUtilities { /*! * \class PathSelection * \brief A QLineEdit with a QPushButton next to it which allows to select * file/directory via QFileDialog. */ QCompleter *PathSelection::s_completer = nullptr; /*! * \brief Constructs a path selection widget. */ PathSelection::PathSelection(QWidget *parent) : QWidget(parent) , m_lineEdit(new ClearLineEdit(this)) , m_button(new QPushButton(this)) , m_customDialog(nullptr) , m_customMode(QFileDialog::Directory) { if (!s_completer) { s_completer = new QCompleter; s_completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion); auto *const fileSystemModel = new QFileSystemModel(s_completer); fileSystemModel->setRootPath(QString()); s_completer->setModel(fileSystemModel); } m_lineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); m_lineEdit->installEventFilter(this); m_lineEdit->setCompleter(s_completer); m_button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); setTexts(); auto *const layout = new QHBoxLayout(this); layout->setSpacing(3); layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(m_lineEdit); layout->addWidget(m_button); setLayout(layout); connect(m_button, &QPushButton::clicked, this, &PathSelection::showFileDialog); } bool PathSelection::event(QEvent *event) { switch (event->type()) { case QEvent::LanguageChange: setTexts(); break; default:; } return QWidget::event(event); } bool PathSelection::eventFilter(QObject *obj, QEvent *event) { #ifndef QT_NO_CONTEXTMENU if (obj == m_lineEdit) { switch (event->type()) { case QEvent::ContextMenu: { unique_ptr menu(m_lineEdit->createStandardContextMenu()); menu->addSeparator(); connect(menu->addAction(QIcon::fromTheme(QStringLiteral("document-open")), tr("Select ...")), &QAction::triggered, this, &PathSelection::showFileDialog); QFileInfo fileInfo(m_lineEdit->text()); if (fileInfo.exists()) { if (fileInfo.isFile()) { connect(menu->addAction(QIcon::fromTheme(QStringLiteral("system-run")), tr("Open")), &QAction::triggered, bind(&openLocalFileOrDir, m_lineEdit->text())); } else if (fileInfo.isDir()) { connect(menu->addAction(QIcon::fromTheme(QStringLiteral("system-file-manager")), tr("Explore")), &QAction::triggered, bind(&openLocalFileOrDir, m_lineEdit->text())); } } menu->exec(static_cast(event)->globalPos()); } return true; default:; } } #endif return QWidget::eventFilter(obj, event); } void PathSelection::showFileDialog() { QString directory; QFileInfo fileInfo(m_lineEdit->text()); if (fileInfo.exists()) { if (fileInfo.isFile()) { directory = fileInfo.absoluteDir().absolutePath(); } else { directory = fileInfo.absolutePath(); } } if (m_customDialog) { m_customDialog->setDirectory(directory); if (m_customDialog->exec() == QFileDialog::Accepted) { m_lineEdit->selectAll(); m_lineEdit->insert(m_customDialog->selectedFiles().join(SEARCH_PATH_SEP_CHAR)); } } else { QFileDialog dialog(this); dialog.setDirectory(directory); dialog.setFileMode(m_customMode); if (window()) { dialog.setWindowTitle(tr("Select path") % QStringLiteral(" - ") % window()->windowTitle()); } else { dialog.setWindowTitle(tr("Select path")); } if (dialog.exec() == QFileDialog::Accepted) { m_lineEdit->selectAll(); m_lineEdit->insert(dialog.selectedFiles().join(SEARCH_PATH_SEP_CHAR)); } } } void PathSelection::setTexts() { m_button->setText(tr("Select ...")); } } // namespace QtUtilities