diff --git a/Pdf4QtViewer/CMakeLists.txt b/Pdf4QtViewer/CMakeLists.txt
index e15e348..e470d80 100644
--- a/Pdf4QtViewer/CMakeLists.txt
+++ b/Pdf4QtViewer/CMakeLists.txt
@@ -73,6 +73,8 @@ add_library(Pdf4QtViewer SHARED
pdfbookmarkmanager.cpp
pdfbookmarkui.h
pdfbookmarkui.cpp
+ pdfactioncombobox.h
+ pdfactioncombobox.cpp
)
add_compile_definitions(QT_INSTALL_DIRECTORY="${QT6_INSTALL_PREFIX}")
diff --git a/Pdf4QtViewer/pdfactioncombobox.cpp b/Pdf4QtViewer/pdfactioncombobox.cpp
new file mode 100644
index 0000000..b94fc9b
--- /dev/null
+++ b/Pdf4QtViewer/pdfactioncombobox.cpp
@@ -0,0 +1,191 @@
+// Copyright (C) 2023 Jakub Melka
+//
+// This file is part of PDF4QT.
+//
+// PDF4QT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// with the written consent of the copyright owner, any later version.
+//
+// PDF4QT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with PDF4QT. If not, see .
+
+#include "pdfactioncombobox.h"
+#include "pdfwidgetutils.h"
+
+#include
+#include
+#include
+#include
+
+namespace pdfviewer
+{
+
+PDFActionComboBox::PDFActionComboBox(QWidget* parent) :
+ BaseClass(parent),
+ m_model(nullptr)
+{
+ setEditable(true);
+ lineEdit()->setPlaceholderText(tr("Find action..."));
+ lineEdit()->setClearButtonEnabled(true);
+ setMinimumWidth(pdf::PDFWidgetUtils::scaleDPI_x(this, DEFAULT_WIDTH));
+
+ m_model = new QStandardItemModel(this);
+ m_proxyModel = new QSortFilterProxyModel(this);
+
+ m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+ m_proxyModel->setDynamicSortFilter(true);
+ m_proxyModel->setFilterKeyColumn(0);
+ m_proxyModel->setFilterRole(Qt::DisplayRole);
+ m_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
+ m_proxyModel->setSortLocaleAware(true);
+ m_proxyModel->setSortRole(Qt::DisplayRole);
+ m_proxyModel->setSourceModel(m_model);
+
+ setFocusPolicy(Qt::StrongFocus);
+ setCompleter(nullptr);
+ setInsertPolicy(QComboBox::NoInsert);
+/*
+ completer()->setCompletionMode(QCompleter::PopupCompletion);
+ completer()->setCompletionColumn(-1);
+ completer()->setFilterMode(Qt::MatchContains | Qt::MatchWildcard);
+ completer()->setCaseSensitivity(Qt::CaseInsensitive);
+ completer()->setModelSorting(QCompleter::UnsortedModel);*/
+
+ connect(this, &PDFActionComboBox::activated, this, &PDFActionComboBox::onActionActivated);
+ connect(this, &PDFActionComboBox::editTextChanged, this, &PDFActionComboBox::onEditTextChanged, Qt::QueuedConnection);
+
+ setModel(m_proxyModel);
+}
+
+QSize PDFActionComboBox::sizeHint() const
+{
+ QSize sizeHint = BaseClass::sizeHint();
+ sizeHint.setWidth(pdf::PDFWidgetUtils::scaleDPI_x(this, DEFAULT_WIDTH));
+ return sizeHint;
+}
+
+QSize PDFActionComboBox::minimumSizeHint() const
+{
+ QSize sizeHint = BaseClass::minimumSizeHint();
+ sizeHint.setWidth(pdf::PDFWidgetUtils::scaleDPI_x(this, DEFAULT_WIDTH));
+ return sizeHint;
+}
+
+void PDFActionComboBox::addQuickFindAction(QAction* action)
+{
+ if (std::find(m_actions.begin(), m_actions.end(), action) == m_actions.end())
+ {
+ m_actions.push_back(action);
+ connect(action, &QAction::changed, this, &PDFActionComboBox::onActionChanged);
+ updateAction(action);
+ }
+}
+
+void PDFActionComboBox::onActionChanged()
+{
+ QAction* action = qobject_cast(sender());
+ updateAction(action);
+}
+
+void PDFActionComboBox::onActionActivated(int index)
+{
+ QVariant actionData = itemData(index, Qt::UserRole);
+ QAction* action = actionData.value();
+
+ lineEdit()->clear();
+ setCurrentIndex(-1);
+
+ if (action && action->isEnabled())
+ {
+ action->trigger();
+ }
+}
+
+void PDFActionComboBox::onEditTextChanged(const QString& text)
+{
+ if (text.isEmpty())
+ {
+ m_proxyModel->setFilterFixedString(QString());
+ }
+ else if (text.contains(QChar('*')) || text.contains(QChar('?')))
+ {
+ m_proxyModel->setFilterWildcard(text);
+ }
+ else
+ {
+ m_proxyModel->setFilterFixedString(text);
+ }
+
+ if (!text.isEmpty())
+ {
+ showPopup();
+ }
+ else
+ {
+ hidePopup();
+ }
+
+ lineEdit()->setFocus();
+ lineEdit()->setCursorPosition(text.size());
+}
+
+void PDFActionComboBox::updateAction(QAction* action)
+{
+ if (!action)
+ {
+ return;
+ }
+
+ int actionIndex = findAction(action);
+ if (action->isEnabled())
+ {
+ if (actionIndex == -1)
+ {
+ QStandardItem* item = new QStandardItem(action->icon(), action->text());
+ item->setData(QVariant::fromValue(action), Qt::UserRole);
+ m_model->appendRow(item);
+ }
+ else
+ {
+ QStandardItem* item = m_model->item(actionIndex);
+ item->setIcon(action->icon());
+ item->setText(action->text());
+ }
+ }
+ else
+ {
+ // Remove action from the model
+ if (actionIndex != -1)
+ {
+ m_model->removeRow(actionIndex);
+ }
+ }
+
+ setCurrentIndex(-1);
+}
+
+int PDFActionComboBox::findAction(QAction* action)
+{
+ const int rowCount = m_model->rowCount();
+
+ for (int i = 0; i < rowCount; ++i)
+ {
+ QModelIndex index = m_model->index(i, 0);
+ QAction* currentAction = index.data(Qt::UserRole).value();
+
+ if (currentAction == action)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+} // namespace pdfviewer
diff --git a/Pdf4QtViewer/pdfactioncombobox.h b/Pdf4QtViewer/pdfactioncombobox.h
new file mode 100644
index 0000000..32709c7
--- /dev/null
+++ b/Pdf4QtViewer/pdfactioncombobox.h
@@ -0,0 +1,64 @@
+// Copyright (C) 2023 Jakub Melka
+//
+// This file is part of PDF4QT.
+//
+// PDF4QT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// with the written consent of the copyright owner, any later version.
+//
+// PDF4QT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with PDF4QT. If not, see .
+
+#ifndef PDFACTIONCOMBOBOX_H
+#define PDFACTIONCOMBOBOX_H
+
+#include "pdfwidgetsglobal.h"
+
+#include
+#include
+
+class QStandardItemModel;
+class QSortFilterProxyModel;
+
+namespace pdfviewer
+{
+
+class PDFActionComboBox : public QComboBox
+{
+ Q_OBJECT
+
+private:
+ using BaseClass = QComboBox;
+
+public:
+ PDFActionComboBox(QWidget* parent);
+
+ virtual QSize sizeHint() const override;
+ virtual QSize minimumSizeHint() const override;
+
+ void addQuickFindAction(QAction* action);
+
+private:
+ static constexpr int DEFAULT_WIDTH = 220;
+
+ void onActionChanged();
+ void onActionActivated(int index);
+ void onEditTextChanged(const QString& text);
+
+ void updateAction(QAction* action);
+ int findAction(QAction* action);
+
+ std::vector m_actions;
+ QStandardItemModel* m_model;
+ QSortFilterProxyModel* m_proxyModel;
+};
+
+} // namespace pdfviewer
+
+#endif // PDFACTIONCOMBOBOX_H
diff --git a/Pdf4QtViewer/pdfprogramcontroller.cpp b/Pdf4QtViewer/pdfprogramcontroller.cpp
index fdd8059..b6bfd96 100644
--- a/Pdf4QtViewer/pdfprogramcontroller.cpp
+++ b/Pdf4QtViewer/pdfprogramcontroller.cpp
@@ -43,6 +43,7 @@
#include "pdfencryptionsettingsdialog.h"
#include "pdfwidgetannotation.h"
#include "pdfwidgetformmanager.h"
+#include "pdfactioncombobox.h"
#include
#include
@@ -56,6 +57,8 @@
#include
#include
#include
+#include
+#include
#include "pdfdbgheap.h"
@@ -366,6 +369,7 @@ PDFProgramController::PDFProgramController(QObject* parent) :
m_annotationManager(nullptr),
m_formManager(nullptr),
m_bookmarkManager(nullptr),
+ m_actionComboBox(nullptr),
m_isBusy(false),
m_isFactorySettingsBeingRestored(false),
m_progress(nullptr)
@@ -673,6 +677,24 @@ void PDFProgramController::initialize(Features features,
}
}
+void PDFProgramController::initActionComboBox(PDFActionComboBox* comboBox)
+{
+ m_actionComboBox = comboBox;
+
+ if (m_actionComboBox)
+ {
+ bool updatesEnabled = m_actionComboBox->updatesEnabled();
+ m_actionComboBox->setUpdatesEnabled(false);
+
+ for (QAction* action : m_actionManager->getActions())
+ {
+ m_actionComboBox->addQuickFindAction(action);
+ }
+
+ m_actionComboBox->setUpdatesEnabled(updatesEnabled);
+ }
+}
+
void PDFProgramController::finishInitialization()
{
readSettings(Settings(WindowSettings | ActionSettings));
diff --git a/Pdf4QtViewer/pdfprogramcontroller.h b/Pdf4QtViewer/pdfprogramcontroller.h
index 76507c5..fb382d1 100644
--- a/Pdf4QtViewer/pdfprogramcontroller.h
+++ b/Pdf4QtViewer/pdfprogramcontroller.h
@@ -35,6 +35,7 @@
#include
class QMainWindow;
+class QComboBox;
class QToolBar;
namespace pdf
@@ -53,6 +54,7 @@ class PDFViewerSettings;
class PDFUndoRedoManager;
class PDFRecentFileManager;
class PDFTextToSpeech;
+class PDFActionComboBox;
class IMainWindow
{
@@ -291,6 +293,7 @@ public:
IMainWindow* mainWindowInterface,
PDFActionManager* actionManager,
pdf::PDFProgress* progress);
+ void initActionComboBox(PDFActionComboBox* comboBox);
void finishInitialization();
void writeSettings();
void resetSettings();
@@ -440,6 +443,7 @@ private:
pdf::PDFWidgetAnnotationManager* m_annotationManager;
pdf::PDFWidgetFormManager* m_formManager;
PDFBookmarkManager* m_bookmarkManager;
+ PDFActionComboBox* m_actionComboBox;
PDFFileInfo m_fileInfo;
QFileSystemWatcher m_fileWatcher;
diff --git a/Pdf4QtViewer/pdfviewermainwindow.cpp b/Pdf4QtViewer/pdfviewermainwindow.cpp
index e4fbcc1..9634b97 100644
--- a/Pdf4QtViewer/pdfviewermainwindow.cpp
+++ b/Pdf4QtViewer/pdfviewermainwindow.cpp
@@ -41,6 +41,7 @@
#include "pdfsignaturehandler.h"
#include "pdfadvancedtools.h"
#include "pdfwidgetutils.h"
+#include "pdfactioncombobox.h"
#include
#include
@@ -310,6 +311,9 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
connect(m_progress, &pdf::PDFProgress::progressStep, this, &PDFViewerMainWindow::onProgressStep);
connect(m_progress, &pdf::PDFProgress::progressFinished, this, &PDFViewerMainWindow::onProgressFinished);
+ PDFActionComboBox* actionComboBox = new PDFActionComboBox(this);
+ menuBar()->setCornerWidget(actionComboBox);
+
m_programController->finishInitialization();
updateDeveloperMenu();
@@ -319,6 +323,7 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
}
m_actionManager->styleActions();
+ m_programController->initActionComboBox(actionComboBox);
}
PDFViewerMainWindow::~PDFViewerMainWindow()
diff --git a/Pdf4QtViewer/pdfviewermainwindowlite.cpp b/Pdf4QtViewer/pdfviewermainwindowlite.cpp
index 0eb6576..385318d 100644
--- a/Pdf4QtViewer/pdfviewermainwindowlite.cpp
+++ b/Pdf4QtViewer/pdfviewermainwindowlite.cpp
@@ -41,6 +41,7 @@
#include "pdfsignaturehandler.h"
#include "pdfadvancedtools.h"
#include "pdfwidgetutils.h"
+#include "pdfactioncombobox.h"
#include
#include
@@ -228,6 +229,8 @@ PDFViewerMainWindowLite::PDFViewerMainWindowLite(QWidget* parent) :
connect(m_progress, &pdf::PDFProgress::progressStep, this, &PDFViewerMainWindowLite::onProgressStep);
connect(m_progress, &pdf::PDFProgress::progressFinished, this, &PDFViewerMainWindowLite::onProgressFinished);
+ PDFActionComboBox* actionComboBox = new PDFActionComboBox(this);
+ menuBar()->setCornerWidget(actionComboBox);
m_programController->finishInitialization();
if (pdf::PDFToolManager* toolManager = m_programController->getToolManager())
@@ -236,6 +239,7 @@ PDFViewerMainWindowLite::PDFViewerMainWindowLite(QWidget* parent) :
}
m_actionManager->styleActions();
+ m_programController->initActionComboBox(actionComboBox);
}
PDFViewerMainWindowLite::~PDFViewerMainWindowLite()