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

preliminary Diff implementation for #230 (draft) #687

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- uses: actions/checkout@v4
- name: Checkout submodules
# submodules are not used by the build, but needed for `make dist`:
run: git submodule update --init deps/json deps/pugixml
run: git submodule update --init deps/json deps/pugixml deps/dtl
- name: Install dependencies
run: |
sudo apt-get update && \
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
[submodule "deps/pugixml"]
path = deps/pugixml
url = https://github.com/zeux/pugixml.git
[submodule "deps/dtl"]
path = deps/dtl
url = https://github.com/cubicdaiya/dtl
[submodule "deps/boost-subset"]
path = deps/boost
url = https://github.com/poedit/boost-subset.git
Expand Down
9 changes: 9 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ dist_metainfo_DATA = net.poedit.Poedit.appdata.xml
EXTRA_DIST = \
deps/json/LICENSE.MIT \
deps/json/single_include/nlohmann/json.hpp \
deps/dtl/COPYING \
deps/dtl/dtl/Diff3.hpp \
deps/dtl/dtl/Diff.hpp \
deps/dtl/dtl/dtl.hpp \
deps/dtl/dtl/functors.hpp \
deps/dtl/dtl/Lcs.hpp \
deps/dtl/dtl/Sequence.hpp \
deps/dtl/dtl/Ses.hpp \
deps/dtl/dtl/variables.hpp \
deps/pugixml/LICENSE.md \
deps/pugixml/src/pugiconfig.hpp \
deps/pugixml/src/pugixml.cpp \
Expand Down
1 change: 0 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ PKG_CHECK_MODULES([ICU], [icu-uc icu-i18n >= 54],
AC_MSG_ERROR([missing ICU library])
])


dnl we need GtkSpell and GTK+ >= 2 for this, check if we're compatible
AC_MSG_CHECKING([if wxWidgets toolkit uses GTK+ 3])
AC_COMPILE_IFELSE(
Expand Down
1 change: 1 addition & 0 deletions deps/dtl
Submodule dtl added at 831aee
13 changes: 9 additions & 4 deletions src/sidebar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,11 @@ class OldMsgidSidebarBlock : public SidebarBlock
: SidebarBlock(parent, _("Previous source text"))
{
m_innerSizer->AddSpacer(PX(2));
m_innerSizer->Add(new ExplanationLabel(parent, _("The old source text (before it changed during an update) that the now-inaccurate translation corresponds to.")),
m_innerSizer->Add(new ExplanationLabel(parent, _("The difference to old source text (before it changed during an update) that the now-inaccurate translation corresponds to.")),
wxSizerFlags().Expand());
m_innerSizer->AddSpacer(PX(5));
m_text = new SelectableAutoWrappingText(parent, WinID::PreviousSourceText, "");
//m_text = new SelectableAutoWrappingText(parent, WinID::PreviousSourceText, "");
m_text = new wxStaticText(parent, wxID_ANY, "");
m_innerSizer->Add(m_text, wxSizerFlags().Expand());
}

Expand All @@ -148,11 +149,15 @@ class OldMsgidSidebarBlock : public SidebarBlock

void Update(const CatalogItemPtr& item) override
{
m_text->SetAndWrapLabel(item->GetOldMsgid());
//m_text->SetAndWrapLabel(item->GetOldMsgid());
m_text->SetLabelMarkup(Diff(item->GetOldMsgid(), item->GetString()).getMarkup());
m_text->SetMinSize(wxSize(-1, 50));

}

private:
SelectableAutoWrappingText *m_text;
//SelectableAutoWrappingText *m_text;
wxStaticText *m_text;
};


Expand Down
63 changes: 63 additions & 0 deletions src/utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
#include <unistd.h>
#endif

#include "../deps/dtl/dtl/dtl.hpp"

#include "str_helpers.h"

wxString EscapeMarkup(const wxString& str)
Expand Down Expand Up @@ -117,6 +119,67 @@ wxFileName MakeFileName(const wxString& path)
return fn;
}

/// A convertor from dtl's to our own diff action type
Diff::Action dtl2DiffAction(dtl::edit_t lastType) {
switch (lastType) {
case dtl::SES_DELETE: return Diff::Action::Delete;
case dtl::SES_COMMON: return Diff::Action::Common;
case dtl::SES_ADD: return Diff::Action::Add;
}
// Shouldn't happend
throw std::invalid_argument("Unexpected dtl::edit_t value");
}

Diff::Diff(const wxString& from, const wxString& to) {
// Do the diff
dtl::Diff<wchar_t, wxString> d(from, to);
d.compose();
auto dtlSeq = d.getSes().getSequence();

// collapes per-symbol diff into string-size chunks
if (!dtlSeq.empty()) {
dtl::edit_t lastType = dtlSeq.front().second.type;
wxString curStr = dtlSeq.front().first;

for ( auto it = std::next(dtlSeq.cbegin()); it != dtlSeq.cend(); ++it ) {

if ( it->second.type != lastType ) {
ses.emplace_back( dtl2DiffAction(lastType), std::move(curStr) );
curStr.Empty();
lastType = it->second.type;
}
curStr.Append(it->first);
}

ses.emplace_back( dtl2DiffAction(lastType), std::move(curStr) );
curStr.Empty();
}
}

wxString Diff::getMarkup(const wxString &addColor, const wxString &deleteColor) {
wxString rv;

for (const auto& el: ses) {
switch (el.first) {
case Diff::Action::Common:
rv.Append(EscapeMarkup(el.second));
break;
case Diff::Action::Add:
rv.Append("<span bgcolor=\"").Append(addColor).Append("\">");
rv.Append(EscapeMarkup(el.second));
rv.Append("</span>");
break;
case Diff::Action::Delete:
rv.Append("<s><span bgcolor=\"").Append(deleteColor).Append("\">");
rv.Append(EscapeMarkup(el.second));
rv.Append("</span></s>");
break;
}
}

return rv;
}

#if wxUSE_GUI && defined(__WXMSW__)
bool IsRunningUnderScreenReader()
{
Expand Down
35 changes: 34 additions & 1 deletion src/utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#endif

#include <map>
#include <vector>

#include <wx/arrstr.h>
#include <wx/filename.h>
Expand Down Expand Up @@ -200,6 +201,39 @@ inline wxString MaskForType(const char *extensions, const wxString& description,
return wxString::Format("%s|%s", description, extensions);
}

/// A helper class to calculate a display diff of strings
class Diff
{
public:
/// Constructs a Diff object with a edit sequence from a string
/// @arg from to the string @arg to
Diff(const wxString& from, const wxString& to);

/// A type of element in the shortest edit sequence
enum class Action {
Common, ///< symbols are the same
Add, ///< symbols were added
Delete ///< symbols were removed
};

/// An element from the shortest edit sequence
typedef std::pair<Action, wxString> sequenceElement;
/// A type to represent a shortest edit sequence i.e. the sequence of
/// substrings with an action (add remove, don't change) attached to them
typedef std::vector<sequenceElement> sequence;

/// @returns the shortest edit sequence in a form suitable for interpretation
const sequence& getSes() { return ses; };

/// @returns the diff ready to be displayed as a markup
/// @arg addColor a background color for a string being added
/// @arg deleteColor a background color for a string being removed
wxString getMarkup(const wxString& addColor=wxString("lightgreen"),
const wxString& deleteColor=wxString("pink"));

private:
sequence ses;
};

#if wxUSE_GUI && defined(__WXMSW__)
bool IsRunningUnderScreenReader();
Expand Down Expand Up @@ -267,7 +301,6 @@ class TempOutputFileFor
wxString m_filenameFinal;
};


#ifdef __WXMSW__
/// Return filename safe for passing to CLI tools (gettext).
/// Uses 8.3 short names to avoid Unicode and codepage issues.
Expand Down