Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PDF bidirectional search with Evince (Linux) and SumatraPDF (Windows) #241

Merged
merged 20 commits into from
May 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d7ae084
PDFBridgeEvince
piernov Jun 26, 2021
3a58039
PDFBridgeEvince: do not attempt to load missing PDF file
piernov Mar 22, 2022
3168d12
PDFBridgeEvince: convert path to URI for proper handling of spaces or…
piernov Mar 22, 2022
9497f0e
PDFBridgeEvince: make sure that owner is not empty
piernov Mar 22, 2022
14ae393
PDFBridgeEvince: Add Whole words only and Case sensitive search options
piernov Mar 22, 2022
34ff0b0
PDFBridgeEvince handle SelectionChanged signal
piernov Apr 15, 2022
fe8449f
Search pin/parts on new PDFBridge selection
piernov Apr 15, 2022
ece1dd6
PDFBridgeEvince connect to DBus in OpenDocument rather than construct…
piernov Apr 17, 2022
db2fcbd
Cleanup Win32 UTF-8/UTF-16 conversion functions
piernov Apr 18, 2022
2fa810b
Only enable PDFBridgeEvince if Gio is found and not Win32
piernov Apr 18, 2022
08dda69
Add PDFBridgeSumatra (forward search only)
piernov Apr 18, 2022
f6d84f6
PDFBridgeSumatra add reverse search
piernov May 1, 2022
15eeb77
PDFBridgeSumatra: spawn SumatraPDF on OpenDocument and disconnect on …
piernov May 2, 2022
781e3ce
PDFBridgeSumatra configurable executable path
piernov May 22, 2022
d5ebf06
PDFBridgeSumatra refresh GUI after reverse search
piernov May 22, 2022
ab4d0f0
PDFBridgeSumatra better errors
piernov May 22, 2022
b412f7d
BoardSettings including PDFile and BackgroundImage
piernov May 22, 2022
5957377
Reload PDF on path change
piernov May 28, 2022
bd92f61
BoardSettings dialog fix BackgroundImage Save error popup
piernov May 28, 2022
36ea695
Add image loading error message
piernov May 28, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ execute_process(
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/stb)
add_definitions(-DSTBI_FAILURE_USERMSG)

## OpenBoardView ##
add_subdirectory(openboardview)
52 changes: 50 additions & 2 deletions src/openboardview/BoardView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "FileFormats/FZFile.h"
#include "annotations.h"
#include "imgui/imgui.h"
#include "imgui/misc/cpp/imgui_stdlib.h"

#include "NetList.h"
#include "PartList.h"
Expand Down Expand Up @@ -433,6 +434,7 @@ int BoardView::LoadFile(const filesystem::path &filepath) {
m_file = nullptr;
m_validBoard = false;
m_error_msg.clear();
pdfBridge.CloseDocument();

SetLastFileOpenName(filepath.string());
std::vector<char> buffer = file_as_buffer(filepath, m_error_msg);
Expand Down Expand Up @@ -477,6 +479,9 @@ int BoardView::LoadFile(const filesystem::path &filepath) {
auto conffilepath = filepath;
conffilepath.replace_extension("conf");
backgroundImage.loadFromConfig(conffilepath);
pdfFile.loadFromConfig(conffilepath);

pdfBridge.OpenDocument(pdfFile);

/*
* Set pins to a known lower size, they get resized
Expand Down Expand Up @@ -944,6 +949,20 @@ void BoardView::Preferences(void) {
obvconfig.WriteBool("showPinName", showPinName);
}

RA("PDF software executable", DPI(200));
ImGui::SameLine();
static std::string pdfSoftwarePath = obvconfig.ParseStr("pdfSoftwarePath", "SumatraPDF.exe");;
if (ImGui::InputText("##pdfSoftwarePath", &pdfSoftwarePath)) {
obvconfig.WriteStr("pdfSoftwarePath", pdfSoftwarePath.c_str());
}
ImGui::SameLine();
if (ImGui::Button("Browse##pdfSoftwarePath")) {
auto path = show_file_picker();
if (!path.empty()) {
pdfSoftwarePath = path.string();
obvconfig.WriteStr("pdfSoftwarePath", pdfSoftwarePath.c_str());
}
}

ImGui::Separator();
{
Expand Down Expand Up @@ -1304,6 +1323,20 @@ void BoardView::ShowInfoPane(void) {
ImGui::SetClipboardText(to_copy.c_str());
}
}

{
static bool wholeWordsOnly = true;
static bool caseSensitive = false;
std::string pdfButtonName = "PDF Search##" + part->name;
if (ImGui::SmallButton(pdfButtonName.c_str())) {
pdfBridge.DocumentSearch(part->name, wholeWordsOnly, caseSensitive);
}
ImGui::SameLine();
ImGui::Checkbox("Whole words only", &wholeWordsOnly);
ImGui::SameLine();
ImGui::Checkbox("Case sensitive", &caseSensitive);
}

if (part->mfgcode.size()) ImGui::TextWrapped("%s", part->mfgcode.c_str());

/*
Expand Down Expand Up @@ -1917,7 +1950,7 @@ void BoardView::Update() {
}

keyboardPreferences.menuItem();
backgroundImagePreferences.menuItem();
boardSettings.menuItem();

ImGui::Separator();

Expand Down Expand Up @@ -2134,7 +2167,7 @@ void BoardView::Update() {
}

keyboardPreferences.render();
backgroundImagePreferences.render();
boardSettings.render();

if (m_showSearch && m_file) {
ImGui::OpenPopup("Search for Component / Network");
Expand Down Expand Up @@ -2277,6 +2310,8 @@ void BoardView::Update() {

ImGui::PopStyleVar();

HandlePDFBridgeSelection();

} // main menu bar

void BoardView::Zoom(float osd_x, float osd_y, float zoom) {
Expand Down Expand Up @@ -4522,6 +4557,19 @@ void BoardView::FlipBoard(int mode) {
m_needsRedraw = true;
}

void BoardView::HandlePDFBridgeSelection() {
if (pdfBridge.HasNewSelection()) {
auto selection = pdfBridge.GetSelection();
if (selection.empty()) {
m_pinHighlighted.clear();
m_partHighlighted.clear();
} else {
SearchCompound(selection.c_str());
CenterZoomSearchResults();
}
};
}

BitVec::~BitVec() {
free(m_bits);
}
Expand Down
19 changes: 17 additions & 2 deletions src/openboardview/BoardView.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
#include "UI/Keyboard/KeyBindings.h"
#include "GUI/Preferences/Keyboard.h"
#include "GUI/BackgroundImage.h"
#include "GUI/Preferences/BackgroundImage.h"
#include "GUI/Preferences/BoardSettings/BoardSettings.h"
#include "PDFBridge/PDFBridge.h"
#include "PDFBridge/PDFBridgeEvince.h"
#include "PDFBridge/PDFBridgeSumatra.h"
#include "PDFBridge/PDFFile.h"
#include <cstdint>
#include <vector>

Expand Down Expand Up @@ -130,7 +134,17 @@ struct BoardView {
SpellCorrector scparts;
KeyBindings keybindings;
Preferences::Keyboard keyboardPreferences{keybindings, obvconfig};
Preferences::BackgroundImage backgroundImagePreferences{keybindings, backgroundImage};
Preferences::BoardSettings boardSettings{keybindings, backgroundImage, pdfFile};

#ifdef ENABLE_PDFBRIDGE_EVINCE
PDFBridgeEvince pdfBridge;
#elif defined(_WIN32)
PDFBridgeSumatra &pdfBridge = PDFBridgeSumatra::GetInstance(obvconfig);
#else
PDFBridge pdfBridge; // Dummy implementation
#endif
PDFFile pdfFile{pdfBridge};

bool debug = false;
int history_file_has_changed = 0;
int dpi = 0;
Expand Down Expand Up @@ -346,4 +360,5 @@ struct BoardView {

void SetLastFileOpenName(const std::string &name);
void FlipBoard(int mode = 0);
void HandlePDFBridgeSelection();
};
42 changes: 36 additions & 6 deletions src/openboardview/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ if(WIN32)
add_definitions(-DUNICODE)
add_definitions(-D_UNICODE)
else()
if(APPLE)
find_library(COCOA_LIBRARY Cocoa)
find_package(OpenGL REQUIRED)
set(OPENGL_INCLUDE_DIR ${OPENGL_INCLUDE_DIR}/Headers)
if(APPLE)
find_library(COCOA_LIBRARY Cocoa)
find_package(OpenGL REQUIRED)
set(OPENGL_INCLUDE_DIR ${OPENGL_INCLUDE_DIR}/Headers)
else(APPLE)
find_package(PkgConfig REQUIRED)
find_package(PkgConfig REQUIRED)

pkg_check_modules(FONTCONFIG REQUIRED fontconfig)
if(FONTCONFIG_FOUND)
Expand All @@ -37,6 +37,16 @@ find_package(PkgConfig REQUIRED)
else()
message(WARNING "GTK not found, file picker will be unavailable.")
endif()

pkg_search_module(GIO REQUIRED gio-2.0)
if(GIO_FOUND)
message(STATUS "Found GIO version ${GIO_VERSION}")
link_directories(${GIO_LIBRARY_DIRS}) # not linked since we load it at runtime
add_definitions(${GIO_CFLAGS_OTHER})
add_definitions(-DENABLE_PDFBRIDGE_EVINCE)
else()
message(SEND_ERROR "GIO not found, PDFBridgeEvince cannot be enabled.")
endif()
endif(APPLE)
endif()

Expand Down Expand Up @@ -82,8 +92,12 @@ set(SOURCES
UI/Keyboard/KeyModifiers.cpp
GUI/BackgroundImage.cpp
GUI/Image.cpp
GUI/Preferences/BackgroundImage.cpp
GUI/Preferences/BoardSettings/BackgroundImage.cpp
GUI/Preferences/BoardSettings/BoardSettings.cpp
GUI/Preferences/BoardSettings/PDFFile.cpp
GUI/Preferences/Keyboard.cpp
PDFBridge/PDFBridge.cpp
PDFBridge/PDFFile.cpp
main_opengl.cpp
)

Expand All @@ -98,8 +112,15 @@ if(ENABLE_GL3)
)
endif()

if(GIO_FOUND)
set(SOURCES ${SOURCES}
PDFBridge/PDFBridgeEvince.cpp
)
endif()

if(WIN32)
set(SOURCES ${SOURCES}
PDFBridge/PDFBridgeSumatra.cpp
win32.cpp
)
else()
Expand All @@ -113,6 +134,7 @@ endif()
)
endif()


# Must be defined in the same directory as the add_executable including the file
set_source_files_properties(${ASSETS} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)

Expand Down Expand Up @@ -145,6 +167,14 @@ if(NOT APPLE AND NOT MINGW)
${FONTCONFIG_LIBRARIES}
)
endif()

if(GIO_FOUND)
target_link_libraries(${PROJECT_NAME_LOWER}
${GIO_LIBRARIES}
)
endif()


if(MINGW)
target_link_libraries(${PROJECT_NAME_LOWER}
SDL2::SDL2-static
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,7 @@

namespace Preferences {

BackgroundImage::BackgroundImage(const KeyBindings &keybindings, ::BackgroundImage &backgroundImage) : keybindings(keybindings), backgroundImage(backgroundImage) {
}

void BackgroundImage::menuItem() {
if (ImGui::MenuItem("Background Image Preferences")) {
shown = true;
erroredFiles.clear(); // make sure to clean the errors
backgroundImageCopy = backgroundImage; // Make a copy to be able to restore if cancelled
}
BackgroundImage::BackgroundImage(::BackgroundImage &backgroundImage) : backgroundImage(backgroundImage) {
}

void BackgroundImage::errorPopup() {
Expand Down Expand Up @@ -68,57 +60,51 @@ void BackgroundImage::imageSettings(const std::string &name, Image &image) {
ImGui::SliderFloat(("Transparency##" + name).c_str(), &image.transparency, 0.0f, 1.0f);
}

void BackgroundImage::render() {
if (shown) {
ImGui::Begin("Background Image Preferences", &shown, ImGuiWindowFlags_AlwaysAutoResize);
void BackgroundImage::save() {
backgroundImage.writeToConfig(backgroundImage.configFilepath);
std::string error = backgroundImage.topImage.reload();
if (!error.empty()) {
erroredFiles.push_back(error);
}
error = backgroundImage.bottomImage.reload();
if (!error.empty()) {
erroredFiles.push_back(error);
}
}

ImGui::Separator();
imageSettings("Top", backgroundImage.topImage);
void BackgroundImage::cancel() {
backgroundImage = backgroundImageCopy;
backgroundImage.reload(); // don't care if there is an error here since the user cancelled
}

ImGui::Separator();
imageSettings("Bottom", backgroundImage.bottomImage);
void BackgroundImage::clear() {
backgroundImage.topImage = {};
backgroundImage.bottomImage = {};
backgroundImage.reload();
}

ImGui::Separator();
ImGui::Text("%s", "Note: background image preferences are stored in the .conf file associated with the boardview file.");
void BackgroundImage::render(bool shown) {
static bool wasShown = false;

if (!shown) { // modal just closed after title bar close button clicked, Save/Cancel modify shown so this must stay above
backgroundImage = backgroundImageCopy;
backgroundImage.reload(); // don't care if there is an error here since the user cancelled
}
if (ImGui::Button("Save")) {
shown = false;
backgroundImage.writeToConfig(backgroundImage.configFilepath);
std::string error = backgroundImage.topImage.reload();
if (!error.empty()) {
erroredFiles.push_back(error);
}
error = backgroundImage.bottomImage.reload();
if (!error.empty()) {
erroredFiles.push_back(error);
}
}
ImGui::SameLine();
if (ImGui::Button("Cancel") || this->keybindings.isPressed("CloseDialog")) {
shown = false;
backgroundImage = backgroundImageCopy;
backgroundImage.reload(); // don't care if there is an error here since the user cancelled
}
ImGui::SameLine();
if (ImGui::Button("Clear")) {
backgroundImage.topImage = {};
backgroundImage.bottomImage = {};
backgroundImage.reload();
if (shown) {
if (!wasShown) { // Panel just got opened
erroredFiles.clear(); // make sure to clean the errors
backgroundImageCopy = backgroundImage; // Make a copy to be able to restore if cancelled
}

ImGui::End();
imageSettings("Top", backgroundImage.topImage);

ImGui::Separator();
imageSettings("Bottom", backgroundImage.bottomImage);
}


if (!erroredFiles.empty()) {
ImGui::OpenPopup("Error##PreferencesBackgroundImage"); // Open error popup if there was an error
}
errorPopup(); // Render error popup if opened

wasShown = shown;
}

} // namespace Preferences
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
#ifndef _PREFERENCES_BACKGROUNDIMAGE_H_
#define _PREFERENCES_BACKGROUNDIMAGE_H_

#include "UI/Keyboard/KeyBindings.h"

#include "GUI/BackgroundImage.h"

#include <string>
#include <vector>

namespace Preferences {

class BackgroundImage {
private:
bool shown = false;
std::vector<std::string> erroredFiles;
const KeyBindings &keybindings;
::BackgroundImage &backgroundImage;
::BackgroundImage backgroundImageCopy{::BackgroundImage::defaultSide};

void imageSettings(const std::string &name, Image &image);
void errorPopup();
public:
BackgroundImage(const KeyBindings &keybindings, ::BackgroundImage &backgroundImage);
BackgroundImage(::BackgroundImage &backgroundImage);

void menuItem();
void render();
void render(bool shown);
void save();
void cancel();
void clear();
};

} // namespace Preferences
Expand Down