diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..c7c8acd --- /dev/null +++ b/debian/patches/series @@ -0,0 +1 @@ +support-viewing-current-item.patch diff --git a/debian/patches/support-viewing-current-item.patch b/debian/patches/support-viewing-current-item.patch new file mode 100644 index 0000000..dff883d --- /dev/null +++ b/debian/patches/support-viewing-current-item.patch @@ -0,0 +1,480 @@ +Description: Support viewing (launching) current item + By double-clicking it or through its context menu item if it's a file. + . + Also, remember the last dir on opening files in each session. + . + Also, set `Qt::AA_UseHighDpiPixmaps`. + . + Also, commented out `QDebug` messages to be able to see temporary ones ;) +Author: Tsu Jan +Origin: upstream +Bug: https://github.com/lxqt/lxqt-archiver/pull/10 +Last-Update: 2018-07-09 +--- a/src/archiver.cpp ++++ b/src/archiver.cpp +@@ -338,7 +338,7 @@ void Archiver::rebuildDirTree() { + std::string dirName = stripTrailingSlash(item->fullPath()); + dirMap_[dirName] = item; + } +- ++ + if(fileData->encrypted) { + isEncrypted_ = true; + } +@@ -385,8 +385,8 @@ void Archiver::rebuildDirTree() { + g_free(tmp); + } + +- qDebug("op: %s, %s", fileData->original_path, item->originalPath()); +- qDebug("fp: %s, %s", fileData->full_path, item->fullPath()); ++ //qDebug("op: %s, %s", fileData->original_path, item->originalPath()); ++ //qDebug("fp: %s, %s", fileData->full_path, item->fullPath()); + fileData->name = g_path_get_basename(dirName.c_str()); + fileData->dir = 1; + file_data_update_content_type(fileData); +@@ -419,9 +419,9 @@ void Archiver::rebuildDirTree() { + } + rootItem_ = dirMap_["/"]; + +- for(auto& kv: dirMap_) { ++ /*for(auto& kv: dirMap_) { + qDebug("dir: %s: %d", kv.first.c_str(), kv.second->children().size()); +- } ++ }*/ + } + + void Archiver::stopCurrentAction() { +@@ -519,14 +519,14 @@ const FileData* Archiver::fileDataByOrig + // We use the workaround provided here: https://bugreports.qt.io/browse/QTBUG-18434 + + void Archiver::onStart(FrArchive*, FrAction action, Archiver* _this) { +- qDebug("start"); ++ //qDebug("start"); + + _this->busy_ = true; + QMetaObject::invokeMethod(_this, "start", Qt::QueuedConnection, QGenericReturnArgument(), Q_ARG(FrAction, action)); + } + + void Archiver::onDone(FrArchive*, FrAction action, FrProcError* error, Archiver* _this) { +- qDebug("done: %s", error && error->gerror ? error->gerror->message : ""); ++ //qDebug("done: %s", error && error->gerror ? error->gerror->message : ""); + // FIXME: error might become dangling pointer for queued connections. :-( + + switch(action) { +@@ -546,11 +546,11 @@ void Archiver::onDone(FrArchive*, FrActi + + void Archiver::onProgress(FrArchive*, double fraction, Archiver* _this) { + QMetaObject::invokeMethod(_this, "progress", Qt::QueuedConnection, QGenericReturnArgument(), Q_ARG(double, fraction)); +- qDebug("progress: %lf", fraction); ++ //qDebug("progress: %lf", fraction); + } + + void Archiver::onMessage(FrArchive*, const char* msg, Archiver* _this) { +- qDebug("message: %s", msg); ++ //qDebug("message: %s", msg); + QMetaObject::invokeMethod(_this, "message", Qt::QueuedConnection, QGenericReturnArgument(), Q_ARG(QString, QString::fromUtf8(msg))); + } + +@@ -560,6 +560,6 @@ void Archiver::onStoppable(FrArchive*, g + + void Archiver::onWorkingArchive(FrCommand* comm, const char* filename, Archiver* _this) { + // FIXME: why the first param is comm? +- qDebug("working: %s", filename); ++ //qDebug("working: %s", filename); + Q_EMIT _this->workingArchive(filename); + } +--- a/src/main.cpp ++++ b/src/main.cpp +@@ -334,6 +334,7 @@ int main(int argc, char** argv) { + QApplication app(argc, argv); + app.setApplicationVersion(LXQT_ARCHIVER_VERSION); + app.setQuitOnLastWindowClosed(true); ++ app.setAttribute(Qt::AA_UseHighDpiPixmaps); + + // load translations + // install the translations built-into Qt itself +--- a/src/mainwindow.cpp ++++ b/src/mainwindow.cpp +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + #include + +@@ -41,6 +42,7 @@ + #include + #include + #include ++#include + // #include + + #include +@@ -82,6 +84,8 @@ MainWindow::MainWindow(QWidget* parent): + popupMenu_ = new QMenu{this}; + popupMenu_->addAction(ui_->actionExtract); + popupMenu_->addAction(ui_->actionDelete); ++ popupMenu_->addSeparator(); ++ popupMenu_->addAction(ui_->actionView); + + // proxy model used to filter and sort the items + proxyModel_ = new ArchiverProxyModel{this}; +@@ -98,6 +102,7 @@ MainWindow::MainWindow(QWidget* parent): + // show context menu + ui_->fileListView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui_->fileListView, &QAbstractItemView::customContextMenuRequested, this, &MainWindow::onFileListContextMenu); ++ connect(ui_->fileListView, &QAbstractItemView::doubleClicked, this, &MainWindow::onFileListDoubleClicked); + + connect(archiver_.get(), &Archiver::invalidateContent, this, &MainWindow::onInvalidateContent); + connect(archiver_.get(), &Archiver::start, this, &MainWindow::onActionStarted); +@@ -115,9 +120,16 @@ MainWindow::MainWindow(QWidget* parent): + ui_->actionPaste->deleteLater(); + ui_->actionRename->deleteLater(); + ui_->actionFind->deleteLater(); ++ ++ lasrDir_ = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); ++ ++ setAttribute(Qt::WA_DeleteOnClose, true); + } + + MainWindow::~MainWindow() { ++ if(!tempDir_.isEmpty()) { // remove the temp dir if any ++ QDir(tempDir_).removeRecursively(); ++ } + } + + void MainWindow::loadFile(const Fm::FilePath &file) { +@@ -127,6 +139,18 @@ void MainWindow::loadFile(const Fm::File + splitVolumes_ = false; + volumeSize_ = 0; + ++ // find the name of temporary extraction directory (used for viewing files) ++ if(!tempDir_.isEmpty()) { // remove the last temp dir ++ QDir(tempDir_).removeRecursively(); ++ } ++ QString tmp = QStandardPaths::writableLocation(QStandardPaths::TempLocation); ++ if(!tmp.isEmpty()) { ++ if(QDir(tmp).exists()) { ++ tempDir_ = tmp + "/" + "lxqt-archiver-" ++ + QDateTime::currentDateTime().toString("yyyyMMddhhmmss"); ++ } ++ } ++ + archiver_->openArchive(file.uri().get(), nullptr); + } + +@@ -155,15 +179,17 @@ void MainWindow::on_actionCreateNew_trig + } + + void MainWindow::on_actionOpen_triggered(bool /*checked*/) { +- qDebug("open"); ++ //qDebug("open"); + Fm::FileDialog dlg{this}; + dlg.setFileMode(QFileDialog::ExistingFile); + dlg.setNameFilters(Archiver::supportedOpenNameFilters() << tr("All files (*)")); +- qDebug() << Archiver::supportedOpenMimeTypes(); ++ //qDebug() << Archiver::supportedOpenMimeTypes(); + dlg.setAcceptMode(QFileDialog::AcceptOpen); ++ dlg.setDirectory(lasrDir_); + if(dlg.exec() == QDialog::Accepted) { + auto url = dlg.selectedFiles()[0]; + if(!url.isEmpty()) { ++ lasrDir_ = dlg.directory(); + loadFile(Fm::FilePath::fromUri(url.toEncoded())); + } + } +@@ -187,6 +213,7 @@ void MainWindow::on_actionAddFiles_trigg + dlg.setFileMode(QFileDialog::ExistingFiles); + dlg.setNameFilters(QStringList{} << tr("All files (*)")); + dlg.setAcceptMode(QFileDialog::AcceptOpen); ++ dlg.setDirectory(lasrDir_); + + // only add the files if they are newer + auto onlyIfNewerCheckbox = new QCheckBox{tr("Add only if &newer"), &dlg}; +@@ -199,8 +226,9 @@ void MainWindow::on_actionAddFiles_trigg + return; + + auto fileUrls = dlg.selectedFiles(); +- qDebug() << "selected:" << fileUrls; ++ //qDebug() << "selected:" << fileUrls; + if(!fileUrls.isEmpty()) { ++ lasrDir_ = dlg.directory(); + auto srcPaths = Fm::pathListFromQUrls(fileUrls); + archiver_->addFiles(srcPaths, + currentDirPath_.c_str(), +@@ -218,6 +246,7 @@ void MainWindow::on_actionAddFolder_trig + dlg.setFileMode(QFileDialog::Directory); + dlg.setNameFilters(QStringList{} << tr("All files (*)")); + dlg.setAcceptMode(QFileDialog::AcceptOpen); ++ dlg.setDirectory(lasrDir_); + + // only add the files if they are newer + auto onlyIfNewerCheckbox = new QCheckBox{tr("Add only if &newer"), &dlg}; +@@ -232,6 +261,7 @@ void MainWindow::on_actionAddFolder_trig + + QUrl dirUrl = dlg.selectedFiles()[0]; + if(!dirUrl.isEmpty()) { ++ lasrDir_ = dlg.directory(); + auto path = Fm::FilePath::fromUri(dirUrl.toEncoded().constData()); + archiver_->addDirectory(path, + currentDirPath_.c_str(), +@@ -247,7 +277,7 @@ void MainWindow::on_actionDelete_trigger + if(QMessageBox::question(this, tr("Confirm"), tr("Are you sure you want to delete selected files?"), QMessageBox::Yes|QMessageBox::No) != QMessageBox::Yes) { + return; + } +- qDebug("delete"); ++ //qDebug("delete"); + auto files = selectedFiles(true); + if(!files.empty()) { + archiver_->removeFiles(files, FR_COMPRESSION_NORMAL); +@@ -259,7 +289,7 @@ void MainWindow::on_actionSelectAll_trig + } + + void MainWindow::on_actionExtract_triggered(bool /*checked*/) { +- qDebug("extract"); ++ //qDebug("extract"); + ExtractFileDialog dlg{this}; + + auto files = selectedFiles(true); +@@ -312,6 +342,62 @@ void MainWindow::on_actionExtract_trigge + } + } + ++void MainWindow::tempExtractCurFile(bool launch) { ++ launchPath_.clear(); ++ if(tempDir_.isEmpty()) { ++ return; ++ } ++ if(auto selModel = ui_->fileListView->selectionModel()) { ++ QModelIndex idx = selModel->currentIndex(); ++ auto item = itemFromIndex(idx); ++ if(item && !item->isDir()) { ++ const QString fileName = tempDir_ + item->fullPath(); ++ if(QFile::exists(fileName)) { // already extracted under tmp ++ if(launch) { ++ Fm::FilePathList paths; ++ paths.push_back(Fm::FilePath::fromLocalPath(fileName.toLocal8Bit().constData())); ++ Fm::FileLauncher().launchPaths(nullptr, std::move(paths)); ++ } ++ return; ++ } ++ ++ if (launch) { ++ launchPath_ = fileName; ++ } ++ ++ QString dest = tempDir_; ++ QDir dir(tempDir_); ++ const QString curDirPath = QString::fromStdString(currentDirPath_); ++ if(curDirPath.contains("/")) { ++ dest = tempDir_ + "/" + curDirPath.section("/", 0, -2); ++ dir.mkpath(dest); // also creates "dir" if needed ++ } ++ else if(!dir.exists()) { ++ dir.mkpath(tempDir_); ++ } ++ ++ if(archiver_->isEncrypted() && password_.empty()) { ++ password_ = PasswordDialog::askPassword(this).toStdString(); ++ } ++ auto destDir = Fm::FilePath::fromLocalPath(dest.toLocal8Bit().constData()); ++ std::vector files; ++ files.emplace_back(item->data()); ++ archiver_->extractFiles(files, ++ destDir, ++ currentDirPath_.c_str(), ++ false, ++ false, ++ false, ++ password_.empty() ? nullptr : password_.c_str() ++ ); ++ } ++ } ++} ++ ++void MainWindow::on_actionView_triggered(bool /*checked*/) { ++ tempExtractCurFile(true); ++} ++ + void MainWindow::on_actionTest_triggered(bool /*checked*/) { + if(archiver_->isLoaded()) { + archiver_->testArchiveIntegrity(nullptr); +@@ -379,11 +465,20 @@ void MainWindow::onFileListSelectionChan + } + + void MainWindow::onFileListContextMenu(const QPoint &pos) { ++ if(auto selModel = ui_->fileListView->selectionModel()) { ++ QModelIndex idx = selModel->currentIndex(); ++ auto item = itemFromIndex(idx); ++ ui_->actionView->setVisible(item && !item->isDir()); ++ } + // QAbstractScrollArea and its subclasses map the context menu event to coordinates of the viewport(). + auto globalPos = ui_->fileListView->viewport()->mapToGlobal(pos); + popupMenu_->popup(globalPos); + } + ++void MainWindow::onFileListDoubleClicked(const QModelIndex & /*index*/) { ++ tempExtractCurFile(true); ++} ++ + void MainWindow::onFileListActivated(const QModelIndex &index) { + auto item = itemFromIndex(index); + if(item && item->isDir()) { +@@ -408,11 +503,11 @@ void MainWindow::onActionStarted(FrActio + progressBar_->show(); + progressBar_->setFormat(tr("%p %")); + +- qDebug("action start: %d", action); ++ //qDebug("action start: %d", action); + + switch(action) { + case FR_ACTION_CREATING_NEW_ARCHIVE: +- qDebug("new archive"); ++ //qDebug("new archive"); + setFileName(archiver_->archiveDisplayName()); + break; + case FR_ACTION_LOADING_ARCHIVE: /* loading the archive from a remote location */ +@@ -463,16 +558,16 @@ void MainWindow::onActionFinished(FrActi + setBusyState(false); + progressBar_->hide(); + +- qDebug("action finished: %d", action); ++ //qDebug("action finished: %d", action); + + switch(action) { + case FR_ACTION_LOADING_ARCHIVE: /* loading the archive from a remote location */ +- qDebug("finish! %d", action); ++ //qDebug("finish! %d", action); + break; + case FR_ACTION_CREATING_NEW_ARCHIVE: // same as listing empty content + case FR_ACTION_CREATING_ARCHIVE: /* creating a local archive */ + case FR_ACTION_LISTING_CONTENT: /* listing the content of the archive */ +- qDebug("content listed"); ++ //qDebug("content listed"); + // content dir list of the archive is fully loaded + updateDirTree(); + +@@ -504,6 +599,14 @@ void MainWindow::onActionFinished(FrActi + archiver_->reloadArchive(nullptr); + break; + case FR_ACTION_EXTRACTING_FILES: /* extracting files */ ++ if(!launchPath_.isEmpty()) { ++ if(!err.hasError() && QFile::exists(launchPath_)) { ++ Fm::FilePathList paths; ++ paths.push_back(Fm::FilePath::fromLocalPath(launchPath_.toLocal8Bit().constData())); ++ Fm::FileLauncher().launchPaths(this, std::move(paths)); ++ } ++ launchPath_.clear(); ++ } + break; + case FR_ACTION_COPYING_FILES_TO_REMOTE: /* copying extracted files to a remote location */ + break; +@@ -613,7 +716,7 @@ void MainWindow::showFileList(const std: + if(currentDirItem_) { + auto parent = archiver_->parentDir(currentDirItem_); + if(parent) { +- qDebug("parent: %s", parent ? parent->fullPath() : "null"); ++ //qDebug("parent: %s", parent ? parent->fullPath() : "null"); + auto parentRow = createFileListRow(parent); + parentRow[0]->setText(".."); + model->appendRow(parentRow); +@@ -711,7 +814,7 @@ std::vector MainWindow: + // FIXME: the old code uses FileData here. Later we should all use ArchiveItem instead. + for(auto& item: items) { + if(item->data()) { +- qDebug("SEL: %s", item->fullPath()); ++ //qDebug("SEL: %s", item->fullPath()); + results.emplace_back(item->data()); + } + } +--- a/src/mainwindow.h ++++ b/src/mainwindow.h +@@ -72,10 +72,12 @@ private Q_SLOTS: + + void on_actionExtract_triggered(bool checked); + ++ void on_actionView_triggered(bool checked); ++ + void on_actionTest_triggered(bool checked); + + void on_actionPassword_triggered(bool checked); +- ++ + void on_actionDirTree_toggled(bool checked); + + void on_actionDirTreeMode_toggled(bool checked); +@@ -94,6 +96,8 @@ private Q_SLOTS: + + void onFileListContextMenu(const QPoint &pos); + ++ void onFileListDoubleClicked(const QModelIndex &index); ++ + void onFileListActivated(const QModelIndex &index); + + private Q_SLOTS: +@@ -137,7 +141,9 @@ private: + const ArchiverItem* itemFromIndex(const QModelIndex& index); + + QModelIndex indexFromItem(const QModelIndex& parent, const ArchiverItem* item); +- ++ ++ void tempExtractCurFile(bool launch); ++ + private: + std::unique_ptr ui_; + std::shared_ptr archiver_; +@@ -153,6 +159,10 @@ private: + bool encryptHeader_; + bool splitVolumes_; + unsigned int volumeSize_; ++ ++ QString tempDir_; ++ QString launchPath_; ++ QUrl lasrDir_; + }; + + #endif // MAINWINDOW_H +--- a/src/mainwindow.ui ++++ b/src/mainwindow.ui +@@ -410,6 +410,11 @@ + Filename &Encoding + + ++ ++ ++ &View Current Item ++ ++ + + + +--- a/src/progressdialog.cpp ++++ b/src/progressdialog.cpp +@@ -45,7 +45,7 @@ void ProgressDialog::reject() { + } + + void ProgressDialog::onProgress(double fraction) { +- qDebug("progress: %lf", fraction); ++ //qDebug("progress: %lf", fraction); + if(fraction < 0.0) { + // negative progress indicates that progress is unknown + ui_->progressBar->setRange(0, 0); // set it to undertermined state +@@ -60,7 +60,7 @@ void ProgressDialog::onFinished(FrAction + } + + void ProgressDialog::onMessage(QString msg) { +- qDebug("progress: %s", msg.toUtf8().constData()); ++ //qDebug("progress: %s", msg.toUtf8().constData()); + ui_->message->setText(msg); + } + +@@ -69,7 +69,7 @@ void ProgressDialog::onStoppableChanged( + } + + void ProgressDialog::onWorkingArchive(QString filename) { +- qDebug("progress: %s", filename.toUtf8().constData()); ++ //qDebug("progress: %s", filename.toUtf8().constData()); + ui_->currentFile->setText(filename); + } +