diff --git a/src/lib/fcitx-utils/macros.h b/src/lib/fcitx-utils/macros.h index 5e7072a0..0d7a285e 100644 --- a/src/lib/fcitx-utils/macros.h +++ b/src/lib/fcitx-utils/macros.h @@ -46,6 +46,8 @@ #define FCITX_WHITESPACE "\f\n\r\t\v " #define FCITX_EXPAND(x) x +#define FCITX_REMOVE_PARENS_(...) __VA_ARGS__ +#define FCITX_REMOVE_PARENS(X) FCITX_REMOVE_PARENS_ X #define FCITX_FOR_EACH_0(...) #define FCITX_FOR_EACH_1(what, x, ...) what(x) diff --git a/src/lib/fcitx-utils/tuplehelpers.h b/src/lib/fcitx-utils/tuplehelpers.h index 5d02aa85..16e96134 100644 --- a/src/lib/fcitx-utils/tuplehelpers.h +++ b/src/lib/fcitx-utils/tuplehelpers.h @@ -7,6 +7,7 @@ #ifndef _FCITX_UTILS_COMBINETUPLES_H_ #define _FCITX_UTILS_COMBINETUPLES_H_ +#include #include namespace fcitx { diff --git a/src/lib/fcitx/candidatelist.cpp b/src/lib/fcitx/candidatelist.cpp index c2daa8f9..05d6acbd 100644 --- a/src/lib/fcitx/candidatelist.cpp +++ b/src/lib/fcitx/candidatelist.cpp @@ -6,8 +6,10 @@ */ #include "candidatelist.h" +#include #include #include +#include #include namespace fcitx { @@ -29,6 +31,50 @@ void fillLabels(std::vector &labels, const Container &container, } } +template +class CandidateListInterfaceAdapter : public QPtrHolder, + public InterfaceType { +public: + CandidateListInterfaceAdapter(CandidateListType *q) + : QPtrHolder(q) {} +}; + +#define FCITX_COMMA_IF_2 , +#define FCITX_COMMA_IF_1 +#define FCITX_COMMA_IF(X) FCITX_EXPAND(FCITX_CONCATENATE(FCITX_COMMA_IF_, X)) + +#define FCITX_FORWARD_METHOD_ARG(N, ARG) ARG arg##N FCITX_COMMA_IF(N) + +#define FCITX_FORWARD_METHOD_ARG_NAME(N, ARG) arg##N FCITX_COMMA_IF(N) + +#define FCITX_FORWARD_METHOD(RETURN_TYPE, METHOD_NAME, ARGS, ...) \ + RETURN_TYPE METHOD_NAME(FCITX_FOR_EACH_IDX(FCITX_FORWARD_METHOD_ARG, \ + FCITX_REMOVE_PARENS(ARGS))) \ + __VA_ARGS__ override { \ + FCITX_Q(); \ + return q->METHOD_NAME(FCITX_FOR_EACH_IDX( \ + FCITX_FORWARD_METHOD_ARG_NAME, FCITX_REMOVE_PARENS(ARGS))); \ + } + +class BulkCursorAdaptorForCommonCandidateList + : public CandidateListInterfaceAdapter { +public: + using CandidateListInterfaceAdapter::CandidateListInterfaceAdapter; + + FCITX_FORWARD_METHOD(void, setGlobalCursorIndex, (int)); + FCITX_FORWARD_METHOD(int, globalCursorIndex, (), const); +}; + +class CursorModifiableAdaptorForCommonCandidateList + : public CandidateListInterfaceAdapter { +public: + using CandidateListInterfaceAdapter::CandidateListInterfaceAdapter; + + FCITX_FORWARD_METHOD(void, setCursorIndex, (int)); +}; + } // namespace class CandidateListPrivate { @@ -37,6 +83,8 @@ class CandidateListPrivate { ModifiableCandidateList *modifiable_ = nullptr; PageableCandidateList *pageable_ = nullptr; CursorMovableCandidateList *cursorMovable_ = nullptr; + BulkCursorCandidateList *bulkCursor_ = nullptr; + CursorModifiableCandidateList *cursorModifiable_ = nullptr; }; CandidateList::CandidateList() @@ -66,6 +114,16 @@ CursorMovableCandidateList *CandidateList::toCursorMovable() const { return d->cursorMovable_; } +CursorModifiableCandidateList *CandidateList::toCursorModifiable() const { + FCITX_D(); + return d->cursorModifiable_; +} + +BulkCursorCandidateList *CandidateList::toBulkCursor() const { + FCITX_D(); + return d->bulkCursor_; +} + void CandidateList::setBulk(BulkCandidateList *list) { FCITX_D(); d->bulk_ = list; @@ -86,6 +144,16 @@ void CandidateList::setCursorMovable(CursorMovableCandidateList *list) { d->cursorMovable_ = list; } +void CandidateList::setCursorModifiable(CursorModifiableCandidateList *list) { + FCITX_D(); + d->cursorModifiable_ = list; +} + +void CandidateList::setBulkCursor(BulkCursorCandidateList *list) { + FCITX_D(); + d->bulkCursor_ = list; +} + class CandidateWordPrivate { public: CandidateWordPrivate(Text &&text) : text_(std::move(text)) {} @@ -245,6 +313,11 @@ CandidateLayoutHint DisplayOnlyCandidateList::layoutHint() const { class CommonCandidateListPrivate { public: + CommonCandidateListPrivate(CommonCandidateList *q) + : bulkCursor_(q), cursorModifiable_(q) {} + + BulkCursorAdaptorForCommonCandidateList bulkCursor_; + CursorModifiableAdaptorForCommonCandidateList cursorModifiable_; bool usedNextBefore_ = false; int cursorIndex_ = -1; int currentPage_ = 0; @@ -307,11 +380,14 @@ class CommonCandidateListPrivate { }; CommonCandidateList::CommonCandidateList() - : d_ptr(std::make_unique()) { + : d_ptr(std::make_unique(this)) { + FCITX_D(); setPageable(this); setModifiable(this); setBulk(this); setCursorMovable(this); + setBulkCursor(&d->bulkCursor_); + setCursorModifiable(&d->cursorModifiable_); setLabels(); } @@ -492,6 +568,13 @@ void CommonCandidateList::setGlobalCursorIndex(int index) { } } +void CommonCandidateList::setCursorIndex(int index) { + FCITX_D(); + d->checkIndex(index); + auto globalIndex = d->toGlobalIndex(index); + setGlobalCursorIndex(globalIndex); +} + int CommonCandidateList::globalCursorIndex() const { FCITX_D(); return d->cursorIndex_; diff --git a/src/lib/fcitx/candidatelist.h b/src/lib/fcitx/candidatelist.h index 91d54d8b..424209c5 100644 --- a/src/lib/fcitx/candidatelist.h +++ b/src/lib/fcitx/candidatelist.h @@ -17,6 +17,8 @@ class PageableCandidateList; class BulkCandidateList; class ModifiableCandidateList; class CursorMovableCandidateList; +class CursorModifiableCandidateList; +class BulkCursorCandidateList; class CandidateListPrivate; @@ -92,12 +94,16 @@ class FCITXCORE_EXPORT CandidateList { BulkCandidateList *toBulk() const; ModifiableCandidateList *toModifiable() const; CursorMovableCandidateList *toCursorMovable() const; + CursorModifiableCandidateList *toCursorModifiable() const; + BulkCursorCandidateList *toBulkCursor() const; protected: void setPageable(PageableCandidateList *list); void setBulk(BulkCandidateList *list); void setModifiable(ModifiableCandidateList *list); void setCursorMovable(CursorMovableCandidateList *list); + void setCursorModifiable(CursorModifiableCandidateList *list); + void setBulkCursor(BulkCursorCandidateList *list); private: std::unique_ptr d_ptr; @@ -127,6 +133,11 @@ class FCITXCORE_EXPORT CursorMovableCandidateList { virtual void nextCandidate() = 0; }; +class FCITXCORE_EXPORT CursorModifiableCandidateList { +public: + virtual void setCursorIndex(int index) = 0; +}; + // useful for virtual keyboard class FCITXCORE_EXPORT BulkCandidateList { public: @@ -170,6 +181,12 @@ class FCITXCORE_EXPORT DisplayOnlyCandidateWord : public CandidateWord { void select(InputContext *) const override {} }; +class FCITXCORE_EXPORT BulkCursorCandidateList { +public: + virtual int globalCursorIndex() const = 0; + virtual void setGlobalCursorIndex(int index) = 0; +}; + class DisplayOnlyCandidateListPrivate; class FCITXCORE_EXPORT DisplayOnlyCandidateList : public CandidateList { @@ -244,6 +261,14 @@ class FCITXCORE_EXPORT CommonCandidateList : public CandidateList, */ int globalCursorIndex() const; + /** + * Set cursor index on current page. + * + * @param index index on current page; + * @since 5.1.9 + */ + void setCursorIndex(int index); + // CandidateList const fcitx::Text &label(int idx) const override; const CandidateWord &candidate(int idx) const override; diff --git a/src/ui/virtualkeyboard/virtualkeyboard.cpp b/src/ui/virtualkeyboard/virtualkeyboard.cpp index 0b8cfa69..787ba438 100644 --- a/src/ui/virtualkeyboard/virtualkeyboard.cpp +++ b/src/ui/virtualkeyboard/virtualkeyboard.cpp @@ -459,13 +459,12 @@ std::vector VirtualKeyboard::makeBulkCandidateTextList( int VirtualKeyboard::globalCursorIndex( std::shared_ptr candidateList) const { - auto *commonCandidateList = - dynamic_cast(candidateList.get()); - if (commonCandidateList == nullptr) { + auto *bulkCursor = candidateList->toBulkCursor(); + if (bulkCursor == nullptr) { return -1; } - return commonCandidateList->globalCursorIndex(); + return bulkCursor->globalCursorIndex(); } void VirtualKeyboard::updateCandidateArea( diff --git a/test/testcandidatelist.cpp b/test/testcandidatelist.cpp index 28a38bc9..5eca5348 100644 --- a/test/testcandidatelist.cpp +++ b/test/testcandidatelist.cpp @@ -312,10 +312,26 @@ void test_comment() { FCITX_ASSERT(candidate.textWithComment().toString() == "1 comment"); } +void test_cursor() { + CommonCandidateList candidatelist; + candidatelist.setPageSize(5); + candidatelist.setSelectionKey( + Key::keyListFromString("1 2 3 4 5 6 7 8 9 0")); + for (int i = 0; i < 10; i++) { + candidatelist.append(i); + } + candidatelist.setPage(1); + candidatelist.toCursorModifiable()->setCursorIndex(3); + FCITX_ASSERT(candidatelist.toBulkCursor()->globalCursorIndex(), 8); + candidatelist.setCursorIndex(0); + FCITX_ASSERT(candidatelist.toBulkCursor()->globalCursorIndex(), 5); +} + int main() { test_basic(); test_faulty_placeholder(); test_label(); test_comment(); + test_cursor(); return 0; }