diff --git a/resources/scripts/github-actions/build-windows.ps1 b/resources/scripts/github-actions/build-windows.ps1 index d1a2ed789..380cd03f4 100755 --- a/resources/scripts/github-actions/build-windows.ps1 +++ b/resources/scripts/github-actions/build-windows.ps1 @@ -10,6 +10,15 @@ $git_tag = git describe --tags $git_revlist $git_revision = git rev-parse --short HEAD $old_pwd = $pwd.Path +# Functions. +function Fetch-Latest-Release([string]$ReleasesUrl, [string]$TargetNamePrefix) { + $releases_req = Invoke-WebRequest -Uri "$ReleasesUrl" + $releases_json = $releases_req.Content | ConvertFrom-Json + $asset = $releases_json[0].assets | Where-Object {$_.name.StartsWith($TargetNamePrefix)} | Select-Object; + + return $asset +} + # Prepare environment. Install-Module Pscx -Scope CurrentUser -AllowClobber -Force Install-Module VSSetup -Scope CurrentUser -AllowClobber -Force @@ -45,7 +54,7 @@ $maria_version = "11.4.2" $maria_link = "https://archive.mariadb.org/mariadb-$maria_version/winx64-packages/mariadb-$maria_version-winx64.zip" $maria_output = "maria.zip" -$cmake_version = "3.29.6" +$cmake_version = "3.30.1" $cmake_link = "https://github.com/Kitware/CMake/releases/download/v$cmake_version/cmake-$cmake_version-windows-x86_64.zip" $cmake_output = "cmake.zip" @@ -53,15 +62,15 @@ $zlib_version = "1.3.1" $zlib_link = "https://github.com/madler/zlib/archive/refs/tags/v$zlib_version.zip" $zlib_output = "zlib.zip" -$libmpv_date = "2024-06-19" -$libmpv_commit = "8df4cb5" -$libmpv_version = "{0}-git-{1}"-f $libmpv_date.Replace("-", ""), $libmpv_commit -$libmpv_link = "https://github.com/zhongfly/mpv-winbuild/releases/download/$libmpv_date-$libmpv_commit/mpv-dev-x86_64-$libmpv_version.7z" +$asset_mpv = Fetch-Latest-Release -ReleasesUrl "https://api.github.com/repos/zhongfly/mpv-winbuild/releases" -TargetNamePrefix "mpv-dev-x86_64-2" + +$libmpv_link = $asset_mpv.browser_download_url $libmpv_output = "mpv.zip" -$ytdlp_version = "2024.05.27" -$ytdlp_link = "https://github.com/yt-dlp/yt-dlp/releases/download/$ytdlp_version/yt-dlp.exe" -$libmpv_output = "yt-dlp.exe" +$asset_ytdlp = Fetch-Latest-Release -ReleasesUrl "https://api.github.com/repos/yt-dlp/yt-dlp/releases" -TargetNamePrefix "yt-dlp.exe" + +$ytdlp_link = $asset_ytdlp.browser_download_url +$ytdlp_output = "yt-dlp.exe" Invoke-WebRequest -Uri "$maria_link" -OutFile "$maria_output" & ".\resources\scripts\7za\7za.exe" x "$maria_output" @@ -72,16 +81,15 @@ Invoke-WebRequest -Uri "$cmake_link" -OutFile "$cmake_output" Invoke-WebRequest -Uri "$zlib_link" -OutFile "$zlib_output" & ".\resources\scripts\7za\7za.exe" x "$zlib_output" -# User custom UA because SourceForge is very picky. -Invoke-WebRequest -UserAgent "Wget" -Uri "$libmpv_link" -OutFile "$libmpv_output" +Invoke-WebRequest -Uri "$libmpv_link" -OutFile "$libmpv_output" & ".\resources\scripts\7za\7za.exe" x "$libmpv_output" -ompv -Invoke-WebRequest -Uri "$ytdlp_link" -OutFile "$libmpv_output" +Invoke-WebRequest -Uri "$ytdlp_link" -OutFile "$ytdlp_output" $cmake_path = "$old_pwd\cmake-$cmake_version-windows-x86_64\bin\cmake.exe" $zlib_path = "$old_pwd\zlib-$zlib_version" $libmpv_path = "$old_pwd\mpv" -$ytdlp_path = "$old_pwd\$libmpv_output" +$ytdlp_path = "$old_pwd\$ytdlp_output" # Download Qt itself. $qt_path = "$old_pwd\qt" diff --git a/src/librssguard-standard/src/standardcategory.cpp b/src/librssguard-standard/src/standardcategory.cpp index d1f3a83fd..ffeb19b70 100644 --- a/src/librssguard-standard/src/standardcategory.cpp +++ b/src/librssguard-standard/src/standardcategory.cpp @@ -19,7 +19,7 @@ StandardServiceRoot* StandardCategory::serviceRoot() const { } Qt::ItemFlags StandardCategory::additionalFlags() const { - return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; + return Category::additionalFlags() | Qt::ItemFlag::ItemIsDragEnabled | Qt::ItemFlag::ItemIsDropEnabled; } bool StandardCategory::performDragDropChange(RootItem* target_item) { diff --git a/src/librssguard-standard/src/standardserviceroot.cpp b/src/librssguard-standard/src/standardserviceroot.cpp index 6cea9dbc7..03ba8ec80 100644 --- a/src/librssguard-standard/src/standardserviceroot.cpp +++ b/src/librssguard-standard/src/standardserviceroot.cpp @@ -192,7 +192,7 @@ void StandardServiceRoot::addNewFeed(RootItem* selected_item, const QString& url } Qt::ItemFlags StandardServiceRoot::additionalFlags() const { - return Qt::ItemFlag::ItemIsDropEnabled; + return ServiceRoot::additionalFlags() | Qt::ItemFlag::ItemIsDragEnabled | Qt::ItemFlag::ItemIsDropEnabled; } QList StandardServiceRoot::obtainNewMessages(Feed* feed, diff --git a/src/librssguard/core/feedsproxymodel.cpp b/src/librssguard/core/feedsproxymodel.cpp index 53fc34397..c5b3f043c 100644 --- a/src/librssguard/core/feedsproxymodel.cpp +++ b/src/librssguard/core/feedsproxymodel.cpp @@ -47,26 +47,6 @@ FeedsProxyModel::~FeedsProxyModel() { qDebugNN << LOGSEC_FEEDMODEL << "Destroying FeedsProxyModel instance"; } -bool FeedsProxyModel::canDropMimeData(const QMimeData* data, - Qt::DropAction action, - int row, - int column, - const QModelIndex& parent) const { - - auto src_idx = row < 0 ? mapToSource(parent) : mapToSource(index(row, column, parent)); - auto* src_item = m_sourceModel->itemForIndex(src_idx); - - if (src_item != nullptr) { - auto can_drop = src_item->kind() == RootItem::Kind::ServiceRoot || src_item->kind() == RootItem::Kind::Category || - src_item->kind() == RootItem::Kind::Feed; - - return QSortFilterProxyModel::canDropMimeData(data, action, row, column, parent) && can_drop; - } - else { - return false; - } -} - QModelIndexList FeedsProxyModel::match(const QModelIndex& start, int role, const QVariant& value, @@ -183,6 +163,75 @@ QModelIndexList FeedsProxyModel::match(const QModelIndex& start, return result; } +bool FeedsProxyModel::canDropMimeData(const QMimeData* data, + Qt::DropAction action, + int row, + int column, + const QModelIndex& parent) const { + QByteArray dragged_items_data = data->data(QSL(MIME_TYPE_ITEM_POINTER)); + QDataStream stream(&dragged_items_data, QIODevice::OpenModeFlag::ReadOnly); + const bool order_change = row >= 0 && !m_sortAlphabetically; + const QModelIndex target_parent = mapToSource(parent); + + if (stream.atEnd()) { + return false; + } + + quintptr pointer_to_item; + stream >> pointer_to_item; + + RootItem* dragged_item = RootItemPtr(pointer_to_item); + + // Dragged item must service root, feed or category. + // + // If row is less then zero, it means we are moving dragged item into new parent. + // + // Otherwise the target row identifies the item just below the drop target placement insertion line. + QModelIndex target_idx = order_change ? mapToSource(index(row, 0, parent)) : target_parent; + RootItem* target_item = m_sourceModel->itemForIndex(target_idx); + RootItem* target_parent_item = m_sourceModel->itemForIndex(target_parent); + + if (target_item != nullptr) { + qDebugNN << LOGSEC_FEEDMODEL << "Considering target for drop operation:" << QUOTE_W_SPACE(target_item->title()) + << "with index" << QUOTE_W_SPACE(target_idx) + << "and target parent:" << QUOTE_W_SPACE_DOT(target_parent_item->title()); + + switch (dragged_item->kind()) { + case RootItem::Kind::Feed: + // Feeds can be reordered or inserted under service root or category. + return target_parent_item->kind() == RootItem::Kind::Category || + target_parent_item->kind() == RootItem::Kind::ServiceRoot; + + case RootItem::Kind::Category: + // Categories can be reordered or inserted under service root or another category. + break; + + case RootItem::Kind::ServiceRoot: + // Service root cannot be inserted under different parent, can only be reordered. + if (!order_change) { + return false; + } + else { + return target_parent_item->kind() == RootItem::Kind::Root; + } + + default: + return false; + } + + return false; + /* + auto can_drop = target_item->kind() == RootItem::Kind::ServiceRoot || + target_item->kind() == RootItem::Kind::Category || target_item->kind() == RootItem::Kind::Feed; + + return QSortFilterProxyModel::canDropMimeData(data, action, row, column, parent) && can_drop; + */ + } + else { + return false; + } +} + bool FeedsProxyModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, @@ -212,7 +261,7 @@ bool FeedsProxyModel::dropMimeData(const QMimeData* data, stream >> pointer_to_item; // We have item we want to drag, we also determine the target item. - auto* dragged_item = RootItemPtr(pointer_to_item); + RootItemPtr dragged_item = RootItemPtr(pointer_to_item); RootItem* target_item = m_sourceModel->itemForIndex(source_parent); ServiceRoot* dragged_item_root = dragged_item->getParentServiceRoot(); ServiceRoot* target_item_root = target_item->getParentServiceRoot(); @@ -240,16 +289,26 @@ bool FeedsProxyModel::dropMimeData(const QMimeData* data, // Drag & drop is supported by the dragged item and was // completed on data level and in item hierarchy. emit requireItemValidationAfterDragDrop(m_sourceModel->indexForItem(dragged_item)); + + qDebugNN << LOGSEC_FEEDMODEL << "Dropping item" << QUOTE_W_SPACE(dragged_item->title()) << "under new parent" + << QUOTE_W_SPACE_DOT(target_item->title()); } if (order_change) { auto db = qApp->database()->driver()->connection(metaObject()->className()); + RootItem* place_above_item = m_sourceModel->itemForIndex(mapToSource(index(row, 0, parent))); + int target_sort_order = place_above_item->sortOrder(); - if (row > dragged_item->sortOrder()) { - row--; + qDebugNN << LOGSEC_FEEDMODEL << "Resorting/placing item" << QUOTE_W_SPACE(dragged_item->title()) + << "with sord order" << QUOTE_W_SPACE(dragged_item->sortOrder()) << "above item" + << QUOTE_W_SPACE(place_above_item->title()) << "with new sort order" + << QUOTE_W_SPACE_DOT(target_sort_order); + + if (target_sort_order > dragged_item->sortOrder()) { + target_sort_order--; } - DatabaseQueries::moveItem(dragged_item, false, false, row, db); + DatabaseQueries::moveItem(dragged_item, false, false, target_sort_order, db); } invalidate();