diff --git a/.travis.yml b/.travis.yml index e5bb3089b..6d0cef9fb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -146,7 +146,7 @@ jobs: - /opt/build-windows/x86_64 - stage: "macOS, AppImage and Flatpak" os: osx - osx_image: xcode9.2 + osx_image: xcode9.3 env: JOB=build-osx cache: timeout: 300 # seconds diff --git a/INSTALL.md b/INSTALL.md index 7d9069951..4bb117a9e 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -596,7 +596,7 @@ make install clean ## OS X -Supported OS X versions: >=10.8. (NOTE: only 10.12 is tested during CI) +Supported OS X versions: >=10.8. (NOTE: only 10.13 is tested during CI) Compiling qTox on OS X for development requires 2 tools: [Xcode](https://developer.apple.com/xcode/) and [homebrew](https://brew.sh). diff --git a/MAINTAINING.md b/MAINTAINING.md index 5a56b0183..c694981b0 100644 --- a/MAINTAINING.md +++ b/MAINTAINING.md @@ -58,7 +58,9 @@ git config --global alias.logs 'log --show-signature' merge-commit **must** be signed. To simplify the process, and ensure that things are done "right", it's preferable to use the [`merge-pr.sh`] script, which does that for you automatically. -- **use** [`merge-pr.sh`] script to merge PRs, e.g. `./merge-pr.sh 1234`. +- **use** [`merge-pr.sh`] script to merge PRs. First checkout the target + branch, usually either `master` or a release dev branch e.g. `v1.17-dev`, + make sure it's up to date with qTox/qTox, then e.g. `./merge-pr.sh 1234`. You don't have to use it, but then you're running into risk of breaking travis build of master & other PRs, since it verifies all commit messages, diff --git a/img/status/busy_notification.svg b/img/status/busy_notification.svg index e7cae2bec..e04e23fea 100644 --- a/img/status/busy_notification.svg +++ b/img/status/busy_notification.svg @@ -5,6 +5,8 @@ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" height="14" width="14" xml:space="preserve" @@ -13,29 +15,35 @@ y="0px" x="0px" id="Layer_1" - version="1.1">image/svg+xml \ No newline at end of file + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> \ No newline at end of file diff --git a/merge-pr.sh b/merge-pr.sh index 5f4bfdd2d..6e5bb50bd 100755 --- a/merge-pr.sh +++ b/merge-pr.sh @@ -52,6 +52,9 @@ source_functions() { main() { local remote_name="upstream" local merge_branch="merge" + local base_branch # because assigning on the same line will break error code parsing.. http://www.tldp.org/LDP/abs/html/localvar.html + base_branch=$(git symbolic-ref HEAD --short) + source_functions exit_if_not_pr $PR add_remote diff --git a/osx/qTox-Mac-Deployer-ULTIMATE.sh b/osx/qTox-Mac-Deployer-ULTIMATE.sh index b1e6b2a5b..86d277934 100755 --- a/osx/qTox-Mac-Deployer-ULTIMATE.sh +++ b/osx/qTox-Mac-Deployer-ULTIMATE.sh @@ -92,6 +92,26 @@ install() { read -n1 -rsp $'Press any key to continue or Ctrl+C to exit...\n' fi + # osx 10.13 High Sierra doesn't come with a /usr/local/sbin, yet it is needed by some brew packages + NEEDED_DEP_DIR="/usr/local/sbin" + if [[ $TRAVIS = true ]] + then + sudo mkdir -p $NEEDED_DEP_DIR + sudo chown -R $(whoami) $NEEDED_DEP_DIR + elif [[ ! -d $NEEDED_DEP_DIR ]] + then + fcho "The direcory $NEEDED_DEP_DIR must exist for some development packages." + read -r -p "Would you like to create it now, and set the owner to $(whoami)? [y/N] " response + if [[ $response =~ ^([yY][eE][sS]|[yY])$ ]] + then + sudo mkdir $NEEDED_DEP_DIR + sudo chown -R $(whoami) $NEEDED_DEP_DIR + else + fcho "Cannot proceed without $NEEDED_DEP_DIR. Exiting." + exit 0 + fi + fi + #fcho "Installing x-code Command line tools ..." #xcode-select --install @@ -170,9 +190,23 @@ install() { # needed for kf5-sonnet brew tap kde-mac/kde - # verbose so that build output is shown, otherwise qt5 build has no output for >10 mins - # and is killed by Travis CI - brew install --verbose ffmpeg libexif qrencode qt5 sqlcipher openal-soft #kf5-sonnet + # brew install qt5 might take a long time to build Qt. Travis kills us if + # we don't output for 10 minutes. Travis also kills us if we output too much, + # so verbose isn't an option. So just output some dots... + if [[ $TRAVIS = true ]] + then + echo "outputting dots to keep travis from killing us..." + while true; do + echo -n "." + sleep 10 + done & + DOT_PID=$! + fi + brew install ffmpeg libexif qrencode qt5 sqlcipher openal-soft #kf5-sonnet + if [[ $TRAVIS = true ]] + then + kill $DOT_PID + fi fcho "Cloning filter_audio ... " git clone --branch v0.0.1 --depth=1 https://github.com/irungentoo/filter_audio "$FILTERAUIO_DIR" diff --git a/src/chatlog/chatlog.cpp b/src/chatlog/chatlog.cpp index a1e615461..81408f73b 100644 --- a/src/chatlog/chatlog.cpp +++ b/src/chatlog/chatlog.cpp @@ -142,7 +142,7 @@ ChatLog::~ChatLog() void ChatLog::clearSelection() { - if (selectionMode == None) + if (selectionMode == SelectionMode::None) return; for (int i = selFirstRow; i <= selLastRow; ++i) @@ -153,7 +153,7 @@ void ChatLog::clearSelection() selClickedCol = -1; selClickedRow = -1; - selectionMode = None; + selectionMode = SelectionMode::None; emit selectionChanged(); updateMultiSelectionRect(); @@ -220,7 +220,7 @@ void ChatLog::mouseReleaseEvent(QMouseEvent* ev) { QGraphicsView::mouseReleaseEvent(ev); - selectionScrollDir = NoDirection; + selectionScrollDir = AutoScrollDirection::NoDirection; multiClickTimer->start(); } @@ -234,14 +234,14 @@ void ChatLog::mouseMoveEvent(QMouseEvent* ev) if (ev->buttons() & Qt::LeftButton) { // autoscroll if (ev->pos().y() < 0) - selectionScrollDir = Up; + selectionScrollDir = AutoScrollDirection::Up; else if (ev->pos().y() > height()) - selectionScrollDir = Down; + selectionScrollDir = AutoScrollDirection::Down; else - selectionScrollDir = NoDirection; + selectionScrollDir = AutoScrollDirection::NoDirection; // select - if (selectionMode == None + if (selectionMode == SelectionMode::None && (clickPos - ev->pos()).manhattanLength() > QApplication::startDragDistance()) { QPointF sceneClickPos = mapToScene(clickPos.toPoint()); ChatLine::Ptr line = findLineByPosY(scenePos.y()); @@ -255,7 +255,7 @@ void ChatLog::mouseMoveEvent(QMouseEvent* ev) content->selectionStarted(sceneClickPos); - selectionMode = Precise; + selectionMode = SelectionMode::Precise; // ungrab mouse grabber if (scene->mouseGrabberItem()) @@ -265,11 +265,11 @@ void ChatLog::mouseMoveEvent(QMouseEvent* ev) selFirstRow = selClickedRow; selLastRow = selClickedRow; - selectionMode = Multi; + selectionMode = SelectionMode::Multi; } } - if (selectionMode != None) { + if (selectionMode != SelectionMode::None) { ChatLineContent* content = getContentFromPos(scenePos); ChatLine::Ptr line = findLineByPosY(scenePos.y()); @@ -280,12 +280,12 @@ void ChatLog::mouseMoveEvent(QMouseEvent* ev) int col = content->getColumn(); if (row == selClickedRow && col == selClickedCol) { - selectionMode = Precise; + selectionMode = SelectionMode::Precise; content->selectionMouseMove(scenePos); selGraphItem->hide(); } else if (col != selClickedCol) { - selectionMode = Multi; + selectionMode = SelectionMode::Multi; lines[selClickedRow]->selectionCleared(); } @@ -293,7 +293,7 @@ void ChatLog::mouseMoveEvent(QMouseEvent* ev) row = line->getRow(); if (row != selClickedRow) { - selectionMode = Multi; + selectionMode = SelectionMode::Multi; lines[selClickedRow]->selectionCleared(); } } else { @@ -332,12 +332,12 @@ ChatLineContent* ChatLog::getContentFromPos(QPointF scenePos) const bool ChatLog::isOverSelection(QPointF scenePos) const { - if (selectionMode == Precise) { + if (selectionMode == SelectionMode::Precise) { ChatLineContent* content = getContentFromPos(scenePos); if (content) return content->isOverSelection(scenePos); - } else if (selectionMode == Multi) { + } else if (selectionMode == SelectionMode::Multi) { if (selGraphItem->rect().contains(scenePos)) return true; } @@ -457,7 +457,7 @@ void ChatLog::insertChatlinesOnTop(const QList& newLines) lines = combLines; - moveSelectionRectDownIfMulti(newLines.size()); + moveSelectionRectDownIfSelected(newLines.size()); scene->setItemIndexMethod(oldIndexMeth); @@ -528,7 +528,7 @@ void ChatLog::mouseDoubleClickEvent(QMouseEvent* ev) selClickedRow = content->getRow(); selFirstRow = content->getRow(); selLastRow = content->getRow(); - selectionMode = Precise; + selectionMode = SelectionMode::Precise; emit selectionChanged(); } @@ -549,9 +549,9 @@ void ChatLog::mouseDoubleClickEvent(QMouseEvent* ev) QString ChatLog::getSelectedText() const { - if (selectionMode == Precise) { + if (selectionMode == SelectionMode::Precise) { return lines[selClickedRow]->content[selClickedCol]->getSelectedText(); - } else if (selectionMode == Multi) { + } else if (selectionMode == SelectionMode::Multi) { // build a nicely formatted message QString out; @@ -582,7 +582,7 @@ bool ChatLog::isEmpty() const bool ChatLog::hasTextToBeCopied() const { - return selectionMode != None; + return selectionMode != SelectionMode::None; } ChatLine::Ptr ChatLog::getTypingNotification() const @@ -700,7 +700,7 @@ void ChatLog::selectAll() clearSelection(); - selectionMode = Multi; + selectionMode = SelectionMode::Multi; selFirstRow = 0; selLastRow = lines.size() - 1; @@ -727,51 +727,6 @@ void ChatLog::reloadTheme() } } -/** - * @brief Adjusts the multi line selection rectangle based on chatlog changing lines - * @param offset Amount to shift selection rect up by. Must be non-negative. - */ -void ChatLog::moveSelectionRectUpIfMulti(int offset) -{ - assert(offset >= 0); - if (selectionMode != Multi) { - return; - } - if (selLastRow < offset) { // entire selection now out of bounds - clearSelection(); - return; - } else { - selLastRow -= offset; - } - selClickedRow = std::max(0, selClickedRow - offset); - selFirstRow = std::max(0, selFirstRow - offset); - updateMultiSelectionRect(); - emit selectionChanged(); -} - -/** - * @brief Adjusts the multi line selection rectangle based on chatlog changing lines - * @param offset Amount to shift selection rect down by. Must be non-negative. - */ -void ChatLog::moveSelectionRectDownIfMulti(int offset) -{ - assert(offset >= 0); - if (selectionMode != Multi) { - return; - } - const int lastLine = lines.size() - 1; - if (selFirstRow + offset > lastLine) { // entire selection now out of bounds - clearSelection(); - return; - } else { - selFirstRow += offset; - } - selClickedRow = std::min(lastLine, selClickedRow + offset); - selLastRow = std::min(lastLine, selLastRow + offset); - updateMultiSelectionRect(); - emit selectionChanged(); -} - void ChatLog::removeFirsts(const int num) { if (lines.size() > num) { @@ -785,7 +740,7 @@ void ChatLog::removeFirsts(const int num) lines[i]->setRow(i); } - moveSelectionRectUpIfMulti(num); + moveSelectionRectUpIfSelected(num); } void ChatLog::removeLasts(const int num) @@ -889,7 +844,7 @@ void ChatLog::resizeEvent(QResizeEvent* ev) void ChatLog::updateMultiSelectionRect() { - if (selectionMode == Multi && selFirstRow >= 0 && selLastRow >= 0) { + if (selectionMode == SelectionMode::Multi && selFirstRow >= 0 && selLastRow >= 0) { QRectF selBBox; selBBox = selBBox.united(lines[selFirstRow]->sceneBoundingRect()); selBBox = selBBox.united(lines[selLastRow]->sceneBoundingRect()); @@ -954,10 +909,10 @@ void ChatLog::onSelectionTimerTimeout() const int scrollSpeed = 10; switch (selectionScrollDir) { - case Up: + case AutoScrollDirection::Up: verticalScrollBar()->setValue(verticalScrollBar()->value() - scrollSpeed); break; - case Down: + case AutoScrollDirection::Down: verticalScrollBar()->setValue(verticalScrollBar()->value() + scrollSpeed); break; default: @@ -1028,7 +983,7 @@ void ChatLog::handleMultiClickEvent() selClickedRow = content->getRow(); selFirstRow = content->getRow(); selLastRow = content->getRow(); - selectionMode = Precise; + selectionMode = SelectionMode::Precise; emit selectionChanged(); } @@ -1047,7 +1002,7 @@ void ChatLog::focusInEvent(QFocusEvent* ev) { QGraphicsView::focusInEvent(ev); - if (selectionMode != None) { + if (selectionMode != SelectionMode::None) { selGraphItem->setBrush(QBrush(selectionRectColor)); for (int i = selFirstRow; i <= selLastRow; ++i) @@ -1059,7 +1014,7 @@ void ChatLog::focusOutEvent(QFocusEvent* ev) { QGraphicsView::focusOutEvent(ev); - if (selectionMode != None) { + if (selectionMode != SelectionMode::None) { selGraphItem->setBrush(QBrush(selectionRectColor.lighter(120))); for (int i = selFirstRow; i <= selLastRow; ++i) @@ -1100,3 +1055,99 @@ bool ChatLog::isActiveFileTransfer(ChatLine::Ptr l) return false; } + +/** + * @brief Adjusts the selection based on chatlog changing lines + * @param offset Amount to shift selection rect up by. Must be non-negative. + */ +void ChatLog::moveSelectionRectUpIfSelected(int offset) +{ + assert(offset >= 0); + switch (selectionMode) + { + case SelectionMode::None: + return; + case SelectionMode::Precise: + movePreciseSelectionUp(offset); + break; + case SelectionMode::Multi: + moveMultiSelectionUp(offset); + break; + } +} + +/** + * @brief Adjusts the selections based on chatlog changing lines + * @param offset removed from the lines indexes. Must be non-negative. + */ +void ChatLog::moveSelectionRectDownIfSelected(int offset) +{ + assert(offset >= 0); + switch (selectionMode) + { + case SelectionMode::None: + return; + case SelectionMode::Precise: + movePreciseSelectionDown(offset); + break; + case SelectionMode::Multi: + moveMultiSelectionDown(offset); + break; + } +} + +void ChatLog::movePreciseSelectionDown(int offset) +{ + assert(selFirstRow == selLastRow && selFirstRow == selClickedRow); + const int lastLine = lines.size() - 1; + if (selClickedRow + offset > lastLine) { + clearSelection(); + } else { + const int newRow = selClickedRow + offset; + selClickedRow = newRow; + selLastRow = newRow; + selFirstRow = newRow; + emit selectionChanged(); + } +} + +void ChatLog::movePreciseSelectionUp(int offset) +{ + assert(selFirstRow == selLastRow && selFirstRow == selClickedRow); + if (selClickedRow < offset) { + clearSelection(); + } else { + const int newRow = selClickedRow - offset; + selClickedRow = newRow; + selLastRow = newRow; + selFirstRow = newRow; + emit selectionChanged(); + } +} + +void ChatLog::moveMultiSelectionUp(int offset) +{ + if (selLastRow < offset) { // entire selection now out of bounds + clearSelection(); + } else { + selLastRow -= offset; + selClickedRow = std::max(0, selClickedRow - offset); + selFirstRow = std::max(0, selFirstRow - offset); + updateMultiSelectionRect(); + emit selectionChanged(); + } +} + +void ChatLog::moveMultiSelectionDown(int offset) +{ + const int lastLine = lines.size() - 1; + if (selFirstRow + offset > lastLine) { // entire selection now out of bounds + clearSelection(); + } else { + selFirstRow += offset; + selClickedRow = std::min(lastLine, selClickedRow + offset); + selLastRow = std::min(lastLine, selLastRow + offset); + updateMultiSelectionRect(); + emit selectionChanged(); + } +} diff --git a/src/chatlog/chatlog.h b/src/chatlog/chatlog.h index 8b1e08c6e..8a36f4cc6 100644 --- a/src/chatlog/chatlog.h +++ b/src/chatlog/chatlog.h @@ -58,8 +58,6 @@ public: void selectAll(); void fontChanged(const QFont& font); void reloadTheme(); - void moveSelectionRectUpIfMulti(int offset); - void moveSelectionRectDownIfMulti(int offset); void removeFirsts(const int num); void removeLasts(const int num); void setScroll(const bool scroll); @@ -130,16 +128,22 @@ private: void retranslateUi(); bool isActiveFileTransfer(ChatLine::Ptr l); void handleMultiClickEvent(); + void moveSelectionRectUpIfSelected(int offset); + void moveSelectionRectDownIfSelected(int offset); + void movePreciseSelectionDown(int offset); + void movePreciseSelectionUp(int offset); + void moveMultiSelectionUp(int offset); + void moveMultiSelectionDown(int offset); private: - enum SelectionMode + enum class SelectionMode { None, Precise, Multi, }; - enum AutoScrollDirection + enum class AutoScrollDirection { NoDirection, Up, @@ -161,13 +165,13 @@ private: int selFirstRow = -1; int selLastRow = -1; QColor selectionRectColor = Style::getColor(Style::SelectText); - SelectionMode selectionMode = None; + SelectionMode selectionMode = SelectionMode::None; QPointF clickPos; QGraphicsRectItem* selGraphItem = nullptr; QTimer* selectionTimer = nullptr; QTimer* workerTimer = nullptr; QTimer* multiClickTimer = nullptr; - AutoScrollDirection selectionScrollDir = NoDirection; + AutoScrollDirection selectionScrollDir = AutoScrollDirection::NoDirection; int clickCount = 0; QPoint lastClickPos; Qt::MouseButton lastClickButton; diff --git a/src/core/core.cpp b/src/core/core.cpp index 4d93c9a84..eb253e0e8 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -797,24 +797,19 @@ void Core::bootstrapDht() QString dhtServerAddress = dhtServer.address.toLatin1(); QString port = QString::number(dhtServer.port); QString name = dhtServer.name; - qDebug() << QString("Connecting to %1:%2 (%3)").arg(dhtServerAddress, port, name); + qDebug() << QString("Connecting to a bootstrap node..."); QByteArray address = dhtServer.address.toLatin1(); // TODO: constucting the pk via ToxId is a workaround ToxPk pk = ToxId{dhtServer.userId}.getPublicKey(); - const uint8_t* pkPtr = pk.getData(); Tox_Err_Bootstrap error; tox_bootstrap(tox.get(), address.constData(), dhtServer.port, pkPtr, &error); - if (!PARSE_ERR(error)) { - qDebug() << "Error bootstrapping from " + dhtServer.name; - } + PARSE_ERR(error); tox_add_tcp_relay(tox.get(), address.constData(), dhtServer.port, pkPtr, &error); - if (!PARSE_ERR(error)) { - qDebug() << "Error adding TCP relay from " + dhtServer.name; - } + PARSE_ERR(error); ++j; ++i; @@ -1451,6 +1446,11 @@ QString Core::getGroupPeerName(int groupId, int peerId) const { QMutexLocker ml{&coreLoopLock}; + // from tox.h: "If peer_number == UINT32_MAX, then author is unknown (e.g. initial joining the conference)." + if (peerId != std::numeric_limits::max()) { + return {}; + } + Tox_Err_Conference_Peer_Query error; size_t length = tox_conference_peer_get_name_size(tox.get(), groupId, peerId, &error); if (!PARSE_ERR(error) || !length) { diff --git a/tools/lib/PR_bash.source b/tools/lib/PR_bash.source index 50663c806..4e1c24f72 100644 --- a/tools/lib/PR_bash.source +++ b/tools/lib/PR_bash.source @@ -60,24 +60,24 @@ add_remote() { after_merge_msg() { echo "" echo "PR #$PR was merged into «$@$PR» branch." - echo "To compare with master:" + echo "To compare with $base_branch:" echo "" - echo " git diff master..$@$PR" + echo " git diff $base_branch..$@$PR" echo "" if [[ "$@" == "merge" ]] then - echo "To push that to master on github:" + echo "To push that to $base_branch on github:" echo "" - echo " git checkout master && git merge --ff $@$PR && git push upstream master" + echo " git checkout $base_branch && git merge --ff $@$PR && git push upstream $base_branch" echo "" - echo "After pushing to master, delete branches:" + echo "After pushing to $base_branch, delete branches:" echo "" echo " git branch -d {$@,}$PR" echo "" fi echo "To discard any changes:" echo "" - echo " git checkout master && git branch -D {$@,}$PR" + echo " git checkout $base_branch && git branch -D {$@,}$PR" echo "" } @@ -88,7 +88,7 @@ after_merge_failure_msg() { echo "" echo "You may want to remove not merged branches, if they exist:" echo "" - echo " git checkout master && git branch -D {$@,}$PR" + echo " git checkout $base_branch && git branch -D {$@,}$PR" echo "" } @@ -100,16 +100,13 @@ rm_obsolete_branch() { get_sources() { add_remote rm_obsolete_branch - git fetch $remote_name && \ - git checkout master && \ - git rebase $remote_name/master master && \ git fetch $remote_name pull/$PR/head:$PR && \ - git checkout master -b $merge_branch$PR + git checkout $base_branch -b $merge_branch$PR } # check whether to sign merge() { "${@}" --no-ff $PR -m "Merge pull request #$PR $OPT_MSG -$(git shortlog master..$PR)" +$(git shortlog $base_branch..$PR)" }