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

Update to Quotient 0.9 #910

Merged
merged 3 commits into from
Oct 28, 2024
Merged
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
6 changes: 4 additions & 2 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,14 @@ EmptyLineBeforeAccessModifier: LogicalBlock
FixNamespaceComments: true
IncludeBlocks: Regroup
IncludeCategories:
- Regex: 'csapi/'
- Regex: '[</](events|jobs)/'
Priority: 8
- Regex: '(events|jobs)/'
- Regex: '[</]csapi/'
Priority: 12
- Regex: '^<(Quotient/)?.+\.h>'
Priority: 16
- Regex: '^<Qt(Core|Network|Gui)/.+'
Priority: 28
- Regex: '^<Qt.+(/.+)?'
Priority: 24
- Regex: '^<'
Expand Down
46 changes: 18 additions & 28 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ ubuntu-22.04, macos-latest, windows-latest ]
os: [ ubuntu-24.04, macos-latest, windows-latest ]
qt-version: [ 6 ]
override-compiler: [ '', GCC ] # Defaults: MSVC on Windows, Clang elsewhere
composition: [ own-quotient, static, dynamic ]
Expand All @@ -61,20 +61,17 @@ jobs:
- os: macos-latest
override-compiler: GCC
include:
- os: ubuntu-22.04
qt-version: 5
- os: ubuntu-24.04
composition: own-quotient
check: appstream # Use one of faster paths for validation
- os: ubuntu-22.04
qt-version: 5
composition: static
- os: ubuntu-22.04
qt-version: 5 # Use one variation with external libQuotient
composition: dynamic # to do CodeQL analysis (libQuotient is analysed
check: codeql # in its own repo)
- os: ubuntu-24.04
# Use the variation with external libQuotient to do CodeQL analysis
# (libQuotient is analysed in its own repo)
composition: dynamic
check: codeql

env:
QTKEYCHAIN_REF: v0.13.2
QTKEYCHAIN_REF: 0.14.3
QUOTIENT_REF: dev
VERSION: ${{ needs.Prepare.outputs.version }}

Expand All @@ -87,42 +84,35 @@ jobs:
if: "!startsWith(matrix.os, 'ubuntu')"
uses: jurplel/[email protected]
with:
version: "6.6" # "${{ startsWith(matrix.os, 'windows') && '6.5' || '6.4' }}" # CI doesn't use Qt 5 on non-Linux any more
version: "6.6"
cache: true
cache-key-prefix: Qt
modules: 'qtmultimedia'
tools: "tools_ninja${{ startsWith(matrix.os, 'windows') && ' tools_opensslv3_x64' || '' }}"

# Install on Linux via apt to get Qt built with OpenSSL 3
# Install on Linux via apt to test against Qt coming from the package manager
- name: Install dependencies (Linux)
if: startsWith(matrix.os, 'ubuntu')
run: |
COMMON_PKGS="libolm-dev ninja-build"
COMMON_PKGS="$COMMON_PKGS clang-15" # Workaround for https://github.com/actions/runner-images/issues/8659
sudo apt-get -qq update
sudo apt-get -qq install $COMMON_PKGS \
${{ matrix.qt-version == 5
&& 'qtdeclarative5-dev qttools5-dev qml-module-qtquick-controls2 qtquickcontrols2-5-dev qtmultimedia5-dev qt5keychain-dev'
|| 'libgl1-mesa-dev qt6-declarative-dev qt6-tools-dev qt6-tools-dev-tools qt6-l10n-tools qml6-module-qtquick-controls qt6-multimedia-dev qtkeychain-qt6-dev'
}}
sudo apt-get -qq install libolm-dev ninja-build \
qt6-declarative-dev qt6-base-private-dev qt6-tools-dev qt6-tools-dev-tools \
qt6-l10n-tools qml6-module-qtquick-controls qt6-multimedia-dev qtkeychain-qt6-dev

- name: Setup environment
run: |
if [[ '${{ matrix.override-compiler }}' == 'GCC' ]]; then
echo "CC=gcc" >>$GITHUB_ENV
echo "CXX=g++" >>$GITHUB_ENV
elif [[ '${{ runner.os }}' == 'Linux' ]]; then
# Workaround for https://github.com/actions/runner-images/issues/8659
echo "CC=clang-15" >>$GITHUB_ENV
echo "CXX=clang++-15" >>$GITHUB_ENV
echo "CC=clang" >>$GITHUB_ENV
echo "CXX=clang++" >>$GITHUB_ENV
fi
echo "CMAKE_ARGS=-GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo \
${{ runner.os != 'Linux' && '-DCMAKE_MAKE_PROGRAM=$IQTA_TOOLS/Ninja/ninja' || '' }} \
-DCMAKE_PREFIX_PATH=~/.local \
${{ runner.os == 'macOS' && '-DOPENSSL_ROOT_DIR=`brew --prefix openssl`' ||
runner.os == 'Windows' && '-DOPENSSL_ROOT_DIR=$IQTA_TOOLS/OpenSSLv3/Win_x64/' || '' }} \
-DBUILD_SHARED_LIBS=${{ matrix.composition == 'dynamic' }} \
-DBUILD_WITH_QT6=${{ matrix.qt-version == 6 }}" \
-DBUILD_SHARED_LIBS=${{ matrix.composition == 'dynamic' }}" \
>>$GITHUB_ENV

- name: Setup MSVC environment
Expand All @@ -136,7 +126,7 @@ jobs:
run: |
git clone --depth=1 -b $QTKEYCHAIN_REF https://github.com/frankosterfeld/qtkeychain
cd qtkeychain
cmake -S . -B build $CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=~/.local
cmake -S . -B build $CMAKE_ARGS -DBUILD_WITH_QT6=ON -DCMAKE_INSTALL_PREFIX=~/.local
cmake --build build --target install
if [[ '${{ matrix.composition }}' == 'dynamic' ]]; then
QTKEYCHAIN_SO_PATH=$(dirname $(find ~/.local/lib* -name 'libqt?keychain.so'))
Expand Down Expand Up @@ -211,7 +201,7 @@ jobs:
fi

- name: Make a package
if: matrix.composition == 'own-quotient' && matrix.qt-version == 6 && matrix.override-compiler == ''
if: matrix.composition == 'own-quotient' && matrix.override-compiler == ''
id: package
env:
DEPLOY_VERBOSITY: 1
Expand Down
70 changes: 48 additions & 22 deletions client/chatedit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,34 +86,66 @@ void ChatEdit::contextMenuEvent(QContextMenuEvent *event)
menu->popup(event->globalPos());
}

void ChatEdit::insertFromMimeData(const QMimeData* source) { acceptMimeData(source); }

void ChatEdit::switchContext(QObject* contextKey)
{
cancelCompletion();
KChatEdit::switchContext(contextKey);
}

bool ChatEdit::canInsertFromMimeData(const QMimeData *source) const
bool ChatEdit::canInsertFromMimeData(const QMimeData* source) const
{
if (!source)
return false;
// When not in a room, only allow dropping plain text (for commands)
if (!chatRoomWidget->currentRoom())
return source->hasText();

return source->hasImage() || KChatEdit::canInsertFromMimeData(source);
}

QString ChatEdit::checkDndEvent(QDropEvent* event)
{
if (const auto* data = event->mimeData(); data->hasHtml()) {
const auto [cleanHtml, errorPos, errorString] =
HtmlFilter::fromLocalHtml(data->html());
if (errorPos != -1) {
qCWarning(MSGINPUT) << "HTML validation failed at position"
<< errorPos << "with error" << errorString;
event->ignore();
return tr(
"Cannot insert HTML - it's either invalid or unsupported");
}
}
event->setDropAction(Qt::CopyAction);
event->accept();
return {};
}

void ChatEdit::dragEnterEvent(QDragEnterEvent* event)
{
KChatEdit::dragEnterEvent(event);
if (event->source() != this)
checkDndEvent(event);
}

void ChatEdit::alternatePaste()
{
m_pastePlaintext = !pastePlaintextByDefault();
paste();
m_pastePlaintext = pastePlaintextByDefault();
}

void ChatEdit::insertFromMimeData(const QMimeData *source)
bool ChatEdit::acceptMimeData(const QMimeData* source)
{
if (!source) {
qCWarning(MSGINPUT) << "Nothing to insert";
return;
qCWarning(MSGINPUT) << "Nothing to insert from the drop event";
return true; // Treat it as nothing to do, not an error
}

if (source->hasImage())
chatRoomWidget->attachImage(source->imageData().value<QImage>(),
source->urls());
chatRoomWidget->attachImage(source->imageData().value<QImage>(), source->urls());
else if (source->hasHtml()) {
if (m_pastePlaintext) {
QTextDocument document;
Expand All @@ -126,29 +158,23 @@ void ChatEdit::insertFromMimeData(const QMimeData *source)
if (errorPos != -1) {
qCWarning(MSGINPUT) << "HTML insertion failed at pos"
<< errorPos << "with error" << errorString;
// FIXME: Come on... It should be app->showStatusMessage() or smth
emit chatRoomWidget->timelineWidget()->showStatusMessage(
tr("Could not insert HTML - it's either invalid or unsupported"),
5000);
return;
chatRoomWidget->showStatusMessage(
tr("Could not insert HTML - it's either invalid or unsupported"), 5000);
return false;
}
insertHtml(cleanHtml);
}
ensureCursorVisible();
} else if (source->hasUrls()) {
bool hasAnyProcessed = false;
for (const QUrl &url : source->urls())
if (url.isLocalFile()) {
chatRoomWidget->dropFile(url.toLocalFile());
hasAnyProcessed = true;
// Only the first url is processed for now
break;
}
if (!hasAnyProcessed) {
const auto& urls = source->urls();
// Only the first local url is processed for now
if (auto urlIt = std::ranges::find(urls, true, &QUrl::isLocalFile); urlIt != urls.cend())
chatRoomWidget->dropFile(urlIt->toLocalFile());
else
KChatEdit::insertFromMimeData(source);
}
} else
KChatEdit::insertFromMimeData(source);
return true;
}

void ChatEdit::appendMentionAt(QTextCursor& cursor, QString mention,
Expand Down Expand Up @@ -243,7 +269,7 @@ void ChatEdit::triggerCompletion()
QStringList matchesForSignal;
for (const auto& p: completionMatches)
matchesForSignal.push_back(p.first);
emit proposedCompletion(matchesForSignal, matchesListPosition);
chatRoomWidget->showCompletions(matchesForSignal, matchesListPosition);
matchesListPosition = (matchesListPosition + 1) % completionMatches.length();
}

Expand Down
18 changes: 11 additions & 7 deletions client/chatedit.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,21 @@ class ChatEdit : public KChatEdit
bool isCompletionActive();

void insertMention(QString author, QUrl url);
bool acceptMimeData(const QMimeData* source);
QString checkDndEvent(QDropEvent* event);

// NB: the following virtual functions are protected in QTextEdit but
// ChatRoomWidget delegates to them

bool canInsertFromMimeData(const QMimeData* source) const override;

public slots:
void switchContext(QObject* contextKey) override;
void alternatePaste();

signals:
void proposedCompletion(const QStringList& allCompletions, int curIndex);
void cancelledCompletion();

protected:
bool canInsertFromMimeData(const QMimeData* source) const override;
void insertFromMimeData(const QMimeData* source) override;

private:
ChatRoomWidget* chatRoomWidget;

Expand All @@ -60,7 +62,9 @@ class ChatEdit : public KChatEdit
QUrl mentionUrl, bool select);
void keyPressEvent(QKeyEvent* event) override;
void contextMenuEvent(QContextMenuEvent* event) override;
bool pastePlaintextByDefault();
};
void insertFromMimeData(const QMimeData* source) override;
void dragEnterEvent(QDragEnterEvent* event) override;

static bool pastePlaintextByDefault();

};
Loading
Loading