diff --git a/resource/icon/film.png b/resource/icon/film.png new file mode 100644 index 0000000..c8bd259 Binary files /dev/null and b/resource/icon/film.png differ diff --git a/resource/language/en.ts b/resource/language/en.ts index a943e3b..ed323ea 100644 --- a/resource/language/en.ts +++ b/resource/language/en.ts @@ -778,6 +778,74 @@ header_time Time + + label_copy + Enter destination path to copy files to + + + label_move + Enter destination path to move files to + + + label_rename + Enter new file name + + + message_copy + Do you really wish to copy %1 file(s) to %2? + + + message_copy_failed + Successfully copied: %1, failed: %2 + + + message_move + Do you really wish to move %1 file(s) to %2? + + + message_move_failed + Failed to move all or few of selected file(s) to %1 + + + message_pull_failed + Successfully pulled: %1, failed: %2 + + + message_remove + Do you really wish to remove %1 file(s)/folder(s)? + + + message_remove_failed + Successfully removed: %1, failed: %2 + + + message_rename_failed + Successfully renamed: %1, failed: %2 + + + title_browse + Select Folder + + + title_copy + Copy Song(s) + + + title_failure + Failure + + + title_move + Move Song(s) + + + title_remove + Remove + + + title_rename + Rename Song(s) + outline @@ -874,6 +942,74 @@ header_time Time + + label_copy + Enter destination path to copy files to + + + label_move + Enter destination path to move files to + + + label_rename + Enter new file name + + + message_copy + Do you really wish to copy %1 file(s) to %2? + + + message_copy_failed + Successfully copied: %1, failed: %2 + + + message_move + Do you really wish to move %1 file(s) to %2? + + + message_move_failed + Failed to move all or few of selected file(s) to %1 + + + message_pull_failed + Successfully pulled: %1, failed: %2 + + + message_remove + Do you really wish to remove %1 file(s)/folder(s)? + + + message_remove_failed + Successfully removed: %1, failed: %2 + + + message_rename_failed + Successfully renamed: %1, failed: %2 + + + title_browse + Select Folder + + + title_copy + Copy Photo(s) + + + title_failure + Failure + + + title_move + Move Photo(s) + + + title_remove + Remove + + + title_rename + Rename Photo(s) + projects @@ -1115,14 +1251,14 @@ message_push_failed Successfully pushed: %1, failed: %2 - - message_remove_failed - Successfully removed: %1, failed: %2 - message_remove Do you really wish to remove %1 file(s)/folder(s)? + + message_remove_failed + Successfully removed: %1, failed: %2 + message_rename_failed Successfully renamed: %1, failed: %2 @@ -1139,6 +1275,10 @@ title_create Create New Folder + + title_failure + Failure + title_move Move File(s)/Folder(s) @@ -1159,10 +1299,6 @@ title_select Select Files - - title_failure - Failure - toolbar @@ -1248,6 +1384,74 @@ header_time Time + + label_copy + Enter destination path to copy files to + + + label_move + Enter destination path to move files to + + + label_rename + Enter new file name + + + message_copy + Do you really wish to copy %1 file(s) to %2? + + + message_copy_failed + Successfully copied: %1, failed: %2 + + + message_move + Do you really wish to move %1 file(s) to %2? + + + message_move_failed + Failed to move all or few of selected file(s) to %1 + + + message_pull_failed + Successfully pulled: %1, failed: %2 + + + message_remove + Do you really wish to remove %1 file(s)/folder(s)? + + + message_remove_failed + Successfully removed: %1, failed: %2 + + + message_rename_failed + Successfully renamed: %1, failed: %2 + + + title_browse + Select Folder + + + title_copy + Copy Video(s) + + + title_failure + Failure + + + title_move + Move Video(s) + + + title_remove + Remove + + + title_rename + Rename Video(s) + viewer diff --git a/resource/resources.qrc b/resource/resources.qrc index b69f1ae..5dad6bd 100644 --- a/resource/resources.qrc +++ b/resource/resources.qrc @@ -96,5 +96,6 @@ icon/lock_unlock.png icon/lock_warning.png icon/music.png + icon/film.png diff --git a/source/components/vpz/apkstudio/components/applications.cpp b/source/components/vpz/apkstudio/components/applications.cpp index 96e2096..a3be9bc 100644 --- a/source/components/vpz/apkstudio/components/applications.cpp +++ b/source/components/vpz/apkstudio/components/applications.cpp @@ -28,7 +28,9 @@ Applications::Applications(const QString &device, QWidget *parent) : setSortingEnabled(true); sortByColumn(0, Qt::AscendingOrder); // -- // + new QShortcut(QKeySequence(Qt::Key_Return), this, SLOT(onDetails())); new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_I), this, SLOT(onInstall())); + new QShortcut(QKeySequence(Qt::Key_F5), this, SLOT(onRefresh())); new QShortcut(QKeySequence(Qt::Key_Delete), this, SLOT(onUninstall())); } diff --git a/source/components/vpz/apkstudio/components/music.cpp b/source/components/vpz/apkstudio/components/music.cpp index 7879c2b..00f86ad 100644 --- a/source/components/vpz/apkstudio/components/music.cpp +++ b/source/components/vpz/apkstudio/components/music.cpp @@ -25,6 +25,13 @@ Music::Music(const QString &device, QWidget *parent) : setSelectionMode(QAbstractItemView::ExtendedSelection); setSortingEnabled(true); sortByColumn(3, Qt::DescendingOrder); + // -- // + new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_C), this, SLOT(onCopy())); + new QShortcut(QKeySequence(Qt::Key_Return), this, SLOT(onDetails())); + new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_X), this, SLOT(onMove())); + new QShortcut(QKeySequence(Qt::Key_F5), this, SLOT(onRefresh())); + new QShortcut(QKeySequence(Qt::Key_F2), this, SLOT(onRename())); + new QShortcut(QKeySequence(Qt::Key_Delete), this, SLOT(onRemove())); } void Music::onAction(QAction *action) @@ -73,7 +80,7 @@ void Music::onCopy() failed++; } if (failed >= 1) - QMessageBox::critical(this, translate("title_failure"), translate("message_copy_failed").arg(failed, successful), QMessageBox::Close); + QMessageBox::critical(this, translate("title_failure"), translate("message_copy_failed").arg(QString::number(successful), QString::number(failed)), QMessageBox::Close); } void Music::onDetails() @@ -125,7 +132,7 @@ void Music::onPull() failed++; } if (failed >= 1) - QMessageBox::critical(this, translate("title_failure"), translate("message_pull_failed").arg(successful, failed), QMessageBox::Close); + QMessageBox::critical(this, translate("title_failure"), translate("message_pull_failed").arg(QString::number(successful), QString::number(failed)), QMessageBox::Close); } void Music::onRefresh() @@ -169,7 +176,7 @@ void Music::onRemove() failed++; } if (failed >= 1) - QMessageBox::critical(this, translate("title_failure"), translate("message_remove_failed").arg(successful, failed), QMessageBox::Close); + QMessageBox::critical(this, translate("title_failure"), translate("message_remove_failed").arg(QString::number(successful), QString::number(failed)), QMessageBox::Close); } void Music::onRename() @@ -208,7 +215,7 @@ void Music::onRename() failed++; } if (failed >= 1) - QMessageBox::critical(this, translate("title_failure"), translate("message_rename_failed").arg(successful, failed), QMessageBox::Close); + QMessageBox::critical(this, translate("title_failure"), translate("message_rename_failed").arg(QString::number(successful), QString::number(failed)), QMessageBox::Close); } QVector Music::selected() diff --git a/source/components/vpz/apkstudio/components/music.hpp b/source/components/vpz/apkstudio/components/music.hpp index 42e4fa6..452242f 100644 --- a/source/components/vpz/apkstudio/components/music.hpp +++ b/source/components/vpz/apkstudio/components/music.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "helpers/adb.hpp" #include "helpers/format.hpp" diff --git a/source/components/vpz/apkstudio/components/partitions.cpp b/source/components/vpz/apkstudio/components/partitions.cpp index b38314b..865d56f 100644 --- a/source/components/vpz/apkstudio/components/partitions.cpp +++ b/source/components/vpz/apkstudio/components/partitions.cpp @@ -23,6 +23,8 @@ Partitions::Partitions(const QString &device, QWidget *parent) : setSelectionMode(QAbstractItemView::SingleSelection); setSortingEnabled(true); sortByColumn(3, Qt::DescendingOrder); + // -- // + new QShortcut(QKeySequence(Qt::Key_F5), this, SLOT(onRefresh())); } void Partitions::onAction(QAction *action) diff --git a/source/components/vpz/apkstudio/components/partitions.hpp b/source/components/vpz/apkstudio/components/partitions.hpp index e7241a2..9a1dd11 100644 --- a/source/components/vpz/apkstudio/components/partitions.hpp +++ b/source/components/vpz/apkstudio/components/partitions.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include "helpers/adb.hpp" #include "helpers/text.hpp" diff --git a/source/components/vpz/apkstudio/components/photos.cpp b/source/components/vpz/apkstudio/components/photos.cpp index 52df2df..1fad3e7 100644 --- a/source/components/vpz/apkstudio/components/photos.cpp +++ b/source/components/vpz/apkstudio/components/photos.cpp @@ -26,6 +26,13 @@ Photos::Photos(const QString &device, QWidget *parent) : setSelectionMode(QAbstractItemView::ExtendedSelection); setSortingEnabled(true); sortByColumn(3, Qt::DescendingOrder); + // -- // + new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_C), this, SLOT(onCopy())); + new QShortcut(QKeySequence(Qt::Key_Return), this, SLOT(onDetails())); + new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_X), this, SLOT(onMove())); + new QShortcut(QKeySequence(Qt::Key_F5), this, SLOT(onRefresh())); + new QShortcut(QKeySequence(Qt::Key_F2), this, SLOT(onRename())); + new QShortcut(QKeySequence(Qt::Key_Delete), this, SLOT(onRemove())); } void Photos::onAction(QAction *action) @@ -55,6 +62,26 @@ void Photos::onAction(QAction *action) void Photos::onCopy() { + QVector files = selected(); + if (files.isEmpty()) + return; + bool ok = false; + QString destination = QInputDialog::getText(this, translate("title_copy"), translate("label_copy"), QLineEdit::Normal, "/", &ok); + if (!ok || destination.trimmed().isEmpty()) + return; + int result = QMessageBox::question(this, translate("title_copy"), translate("message_copy").arg(QString::number(files.count()), destination), QMessageBox::No | QMessageBox::Yes); + if (result != QMessageBox::Yes) + return; + int failed = 0; + int successful = 0; + foreach (const Photo &file, files) { + if (ADB::instance()->copy(device, file.path, destination, false)) + successful++; + else + failed++; + } + if (failed >= 1) + QMessageBox::critical(this, translate("title_failure"), translate("message_copy_failed").arg(QString::number(successful), QString::number(failed)), QMessageBox::Close); } void Photos::onDetails() @@ -63,10 +90,50 @@ void Photos::onDetails() void Photos::onMove() { + QVector files = selected(); + if (files.isEmpty()) + return; + QStringList sources; + foreach (const Photo &file, files) + sources << file.path; + bool ok = false; + QString destination = QInputDialog::getText(this, translate("title_move"), translate("label_move"), QLineEdit::Normal, "/", &ok); + if (!ok || destination.trimmed().isEmpty()) + return; + int result = QMessageBox::question(this, translate("title_move"), translate("message_move").arg(QString::number(files.count()), destination), QMessageBox::No | QMessageBox::Yes); + if (result != QMessageBox::Yes) + return; + if (ADB::instance()->move(device, sources, destination)) + onRefresh(); + else + QMessageBox::critical(this, translate("title_failure"), translate("message_move_failed").arg(destination), QMessageBox::Close); } void Photos::onPull() { + QVector files = selected(); + if (files.isEmpty()) + return; + QFileDialog dialog(this, translate("title_browse"), Helpers::Settings::previousDirectory()); + dialog.setAcceptMode(QFileDialog::AcceptOpen); + dialog.setFileMode(QFileDialog::Directory); + if (dialog.exec() != QFileDialog::Accepted) + return; + QStringList folders = dialog.selectedFiles(); + if (folders.count() != 1) + return; + QDir directory(folders.first()); + Helpers::Settings::previousDirectory(directory.absolutePath()); + int failed = 0; + int successful = 0; + foreach (const Photo &file, files) { + if (ADB::instance()->pull(device, file.path, directory.absolutePath())) + successful++; + else + failed++; + } + if (failed >= 1) + QMessageBox::critical(this, translate("title_failure"), translate("message_pull_failed").arg(QString::number(successful), QString::number(failed)), QMessageBox::Close); } void Photos::onRefresh() @@ -91,10 +158,73 @@ void Photos::onRefresh() void Photos::onRemove() { + QVector files = selected(); + if (files.isEmpty()) + return; + int result = QMessageBox::question(this, translate("title_remove"), translate("message_remove").arg(QString::number(files.count())), QMessageBox::No | QMessageBox::Yes); + if (result != QMessageBox::Yes) + return; + int failed = 0; + int successful = 0; + foreach (const Photo &file, files) { + if (ADB::instance()->remove(device, file.path, false)) { + successful++; + QList rows = findItems(file.name, Qt::MatchExactly, 0); + if (rows.count() != 1) + continue; + delete rows.first(); + } else + failed++; + } + if (failed >= 1) + QMessageBox::critical(this, translate("title_failure"), translate("message_remove_failed").arg(QString::number(successful), QString::number(failed)), QMessageBox::Close); } void Photos::onRename() { + QVector files = selected(); + if (files.isEmpty()) + return; + bool ok = false; + QString name = QInputDialog::getText(this, translate("title_rename"), translate("label_rename"), QLineEdit::Normal, files.first().name, &ok); + if (!ok || name.trimmed().isEmpty()) + return; + bool multiple = (files.count() > 1); + int failed = 0; + int successful = 0; + for (int i = 0; i < files.count(); ++i) { + QString newname(name); + if (multiple) + newname.prepend(QString("(%1) ").arg(QString::number(i + 1))); + Photo file = files.at(i); + QString newpath(file.path.section('/', 0, -2)); + newpath.append('/'); + newpath.append(newname); + if (ADB::instance()->rename(device, file.path, newpath)) { + successful++; + QList rows = findItems(file.name, Qt::MatchExactly, 0); + if (rows.count() != 1) + continue; + file.name = newname; + file.path = newpath; + QTreeWidgetItem *row = rows.first(); + for (int i = 0; i < 6; ++i) + row->setData(i, ROLE_STRUCT, QVariant::fromValue(file)); + row->setText(0, newname); + row->setToolTip(0, newpath); + } else + failed++; + } + if (failed >= 1) + QMessageBox::critical(this, translate("title_failure"), translate("message_rename_failed").arg(QString::number(successful), QString::number(failed)), QMessageBox::Close); +} + +QVector Photos::selected() +{ + QVector files; + foreach (QTreeWidgetItem *item, selectedItems()) + files.append(item->data(0, ROLE_STRUCT).value()); + return files; } Photos::~Photos() diff --git a/source/components/vpz/apkstudio/components/photos.hpp b/source/components/vpz/apkstudio/components/photos.hpp index 273006a..0adb4c7 100644 --- a/source/components/vpz/apkstudio/components/photos.hpp +++ b/source/components/vpz/apkstudio/components/photos.hpp @@ -2,8 +2,10 @@ #define VPZ_APKSTUDIO_COMPONENTS_PHOTOS_HPP #include +#include #include #include +#include #include #include "helpers/adb.hpp" #include "helpers/format.hpp" @@ -28,6 +30,7 @@ class Photos : public QTreeWidget void onPull(); void onRemove(); void onRename(); + QVector selected(); static QString translate(const char *key) { return Helpers::Text::translate("photos", key); } diff --git a/source/components/vpz/apkstudio/components/storage.cpp b/source/components/vpz/apkstudio/components/storage.cpp index a5c2455..2588de3 100644 --- a/source/components/vpz/apkstudio/components/storage.cpp +++ b/source/components/vpz/apkstudio/components/storage.cpp @@ -1,5 +1,4 @@ #include "storage.hpp" -#include using namespace VPZ::APKStudio::Helpers; using namespace VPZ::APKStudio::Resources; @@ -124,7 +123,7 @@ void Storage::onCopy(const QVector &files, const QString &destination) failed++; } if (failed >= 1) - QMessageBox::critical(this, translate("title_failure"), translate("message_copy_failed").arg(failed, successful), QMessageBox::Close); + QMessageBox::critical(this, translate("title_failure"), translate("message_copy_failed").arg(QString::number(successful), QString::number(failed)), QMessageBox::Close); } void Storage::onCreate() @@ -194,7 +193,7 @@ void Storage::onFilesDropped(const QStringList &files, const QModelIndex &at) failed++; } if (failed >= 1) - QMessageBox::critical(this, translate("title_failure"), translate("message_push_failed").arg(successful, failed), QMessageBox::Close); + QMessageBox::critical(this, translate("title_failure"), translate("message_push_failed").arg(QString::number(successful), QString::number(failed)), QMessageBox::Close); if (successful >= 1) onRefresh(); } @@ -276,7 +275,7 @@ void Storage::onPull() failed++; } if (failed >= 1) - QMessageBox::critical(this, translate("title_failure"), translate("message_pull_failed").arg(successful, failed), QMessageBox::Close); + QMessageBox::critical(this, translate("title_failure"), translate("message_pull_failed").arg(QString::number(successful), QString::number(failed)), QMessageBox::Close); } void Storage::onPush() @@ -403,7 +402,7 @@ void Storage::onRemove() failed++; } if (failed >= 1) - QMessageBox::critical(this, translate("title_failure"), translate("message_remove_failed").arg(successful, failed), QMessageBox::Close); + QMessageBox::critical(this, translate("title_failure"), translate("message_remove_failed").arg(QString::number(successful), QString::number(failed)), QMessageBox::Close); } void Storage::onRename() @@ -442,7 +441,7 @@ void Storage::onRename() failed++; } if (failed >= 1) - QMessageBox::critical(this, translate("title_failure"), translate("message_rename_failed").arg(successful, failed), QMessageBox::Close); + QMessageBox::critical(this, translate("title_failure"), translate("message_rename_failed").arg(QString::number(successful), QString::number(failed)), QMessageBox::Close); } void Storage::onReturn() diff --git a/source/components/vpz/apkstudio/components/videos.cpp b/source/components/vpz/apkstudio/components/videos.cpp index 5e33674..8bd880c 100644 --- a/source/components/vpz/apkstudio/components/videos.cpp +++ b/source/components/vpz/apkstudio/components/videos.cpp @@ -1,5 +1,8 @@ #include "videos.hpp" +using namespace VPZ::APKStudio::Helpers; +using namespace VPZ::APKStudio::Resources; + namespace VPZ { namespace APKStudio { namespace Components { @@ -20,6 +23,13 @@ Videos::Videos(const QString &device, QWidget *parent) : setSelectionMode(QAbstractItemView::ExtendedSelection); setSortingEnabled(true); sortByColumn(3, Qt::DescendingOrder); + // -- // + new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_C), this, SLOT(onCopy())); + new QShortcut(QKeySequence(Qt::Key_Return), this, SLOT(onDetails())); + new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_X), this, SLOT(onMove())); + new QShortcut(QKeySequence(Qt::Key_F5), this, SLOT(onRefresh())); + new QShortcut(QKeySequence(Qt::Key_F2), this, SLOT(onRename())); + new QShortcut(QKeySequence(Qt::Key_Delete), this, SLOT(onRemove())); } void Videos::onAction(QAction *action) @@ -49,6 +59,26 @@ void Videos::onAction(QAction *action) void Videos::onCopy() { + QVector