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..e3cc285
--- /dev/null
+++ b/Pdf4QtViewer/pdfactioncombobox.cpp
@@ -0,0 +1,211 @@
+// 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
+#include
+#include
+
+namespace pdfviewer
+{
+
+PDFActionComboBox::PDFActionComboBox(QWidget* parent) :
+ BaseClass(parent),
+ m_model(nullptr)
+{
+ setPlaceholderText(tr("Find action..."));
+ setClearButtonEnabled(true);
+ setMinimumWidth(pdf::PDFWidgetUtils::scaleDPI_x(this, DEFAULT_WIDTH));
+
+ m_model = new QStandardItemModel(this);
+
+ QCompleter* completer = new QCompleter(m_model, this);
+ setFocusPolicy(Qt::StrongFocus);
+ setCompleter(completer);
+
+ completer->setCompletionMode(QCompleter::PopupCompletion);
+ completer->setCompletionColumn(0);
+ completer->setCompletionRole(Qt::DisplayRole);
+ completer->setFilterMode(Qt::MatchContains);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+ completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ completer->setWrapAround(false);
+ completer->setMaxVisibleItems(20);
+
+ connect(this, &QLineEdit::editingFinished, this, &PDFActionComboBox::performExecuteAction, Qt::QueuedConnection);
+}
+
+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);
+ }
+}
+
+bool PDFActionComboBox::event(QEvent* event)
+{
+ if (event->type() == QEvent::ShortcutOverride)
+ {
+ QKeyEvent* keyEvent = dynamic_cast(event);
+ switch (keyEvent->key())
+ {
+ case Qt::Key_Down:
+ case Qt::Key_Up:
+ event->accept();
+ return true;
+ }
+ }
+
+ if (event->type() == QEvent::KeyPress)
+ {
+ QKeyEvent* keyEvent = dynamic_cast(event);
+
+ // Redirect up and down arrows to the completer
+ switch (keyEvent->key())
+ {
+ case Qt::Key_Down:
+ case Qt::Key_Up:
+ {
+ if (completer())
+ {
+ if (completer()->popup()->isVisible())
+ {
+ QCoreApplication::sendEvent(completer()->popup(), event);
+ }
+ else
+ {
+ completer()->complete();
+ }
+ }
+ return true;
+ }
+
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ clearFocus();
+ return true;
+
+ default:
+ break;
+ }
+ }
+
+ return BaseClass::event(event);
+}
+
+void PDFActionComboBox::onActionChanged()
+{
+ QAction* action = qobject_cast(sender());
+ updateAction(action);
+}
+
+void PDFActionComboBox::performExecuteAction()
+{
+ QString text = this->text();
+
+ QAction* action = nullptr;
+ for (QAction* currentAction : m_actions)
+ {
+ if (currentAction->text() == text)
+ {
+ action = currentAction;
+ }
+ }
+
+ clear();
+ completer()->setCompletionPrefix(QString());
+
+ if (action)
+ {
+ action->trigger();
+ }
+}
+
+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);
+ }
+ }
+}
+
+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..7c3a545
--- /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
+#include
+
+class QStandardItemModel;
+class QSortFilterProxyModel;
+
+namespace pdfviewer
+{
+
+class PDFActionComboBox : public QLineEdit
+{
+ Q_OBJECT
+
+private:
+ using BaseClass = QLineEdit;
+
+public:
+ PDFActionComboBox(QWidget* parent);
+
+ virtual QSize sizeHint() const override;
+ virtual QSize minimumSizeHint() const override;
+ virtual bool event(QEvent* event) override;
+
+ void addQuickFindAction(QAction* action);
+
+private:
+ static constexpr int DEFAULT_WIDTH = 220;
+
+ void onActionChanged();
+ void performExecuteAction();
+
+ void updateAction(QAction* action);
+ int findAction(QAction* action);
+
+ std::vector m_actions;
+ QStandardItemModel* m_model;
+};
+
+} // 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()
diff --git a/RELEASES.txt b/RELEASES.txt
index 08eb77f..d970570 100644
--- a/RELEASES.txt
+++ b/RELEASES.txt
@@ -1,4 +1,5 @@
CURRENT:
+ - Issue #134: Add search bar for actions
- Issue #129: Cannot compile with lcms 2.16
- Issue #128: Create list of markup annotations
- Issue #126: Remove include from main headers