Skip to content

Commit

Permalink
Add option to show torrent's properties in panel in the main window (#82
Browse files Browse the repository at this point in the history
)
  • Loading branch information
equeim committed Jan 30, 2025
1 parent c747883 commit 05aee48
Show file tree
Hide file tree
Showing 7 changed files with 311 additions and 104 deletions.
4 changes: 3 additions & 1 deletion src/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,12 @@ namespace tremotesf {
SETTINGS_PROPERTY_DEF(bool, toolBarLocked, "toolBarLocked", true)
SETTINGS_PROPERTY_DEF(bool, sideBarVisible, "sideBarVisible", true)
SETTINGS_PROPERTY_DEF(bool, statusBarVisible, "statusBarVisible", true)
SETTINGS_PROPERTY_DEF(bool, showTorrentPropertiesInMainWindow, "showTorrentPropertiesInMainWindow", false)

SETTINGS_PROPERTY_DEF(QByteArray, mainWindowGeometry, "mainWindowGeometry", {})
SETTINGS_PROPERTY_DEF(QByteArray, mainWindowState, "mainWindowState", {})
SETTINGS_PROPERTY_DEF(QByteArray, splitterState, "splitterState", {})
SETTINGS_PROPERTY_DEF(QByteArray, horizontalSplitterState, "splitterState", {})
SETTINGS_PROPERTY_DEF(QByteArray, verticalSplitterState, "verticalSplitterState", {})

SETTINGS_PROPERTY_DEF(QByteArray, torrentsViewHeaderState, "torrentsViewHeaderState", {})
SETTINGS_PROPERTY_DEF(QByteArray, torrentPropertiesDialogGeometry, "torrentPropertiesDialogGeometry", {})
Expand Down
4 changes: 3 additions & 1 deletion src/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,12 @@ namespace tremotesf {
SETTINGS_PROPERTY(bool, toolBarLocked)
SETTINGS_PROPERTY(bool, sideBarVisible)
SETTINGS_PROPERTY(bool, statusBarVisible)
SETTINGS_PROPERTY(bool, showTorrentPropertiesInMainWindow)

SETTINGS_PROPERTY(QByteArray, mainWindowGeometry)
SETTINGS_PROPERTY(QByteArray, mainWindowState)
SETTINGS_PROPERTY(QByteArray, splitterState)
SETTINGS_PROPERTY(QByteArray, horizontalSplitterState)
SETTINGS_PROPERTY(QByteArray, verticalSplitterState)

SETTINGS_PROPERTY(QByteArray, torrentsViewHeaderState)
SETTINGS_PROPERTY(QByteArray, torrentPropertiesDialogGeometry)
Expand Down
165 changes: 138 additions & 27 deletions src/ui/screens/mainwindow/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#include "ui/screens/serverstatsdialog.h"
#include "ui/screens/settingsdialog.h"
#include "ui/screens/torrentproperties/torrentpropertiesdialog.h"
#include "ui/screens/torrentproperties/torrentpropertieswidget.h"
#include "ui/widgets/torrentremotedirectoryselectionwidget.h"
#include "ui/widgets/torrentfilesview.h"

Expand Down Expand Up @@ -237,28 +238,38 @@ namespace tremotesf {
public:
explicit Impl(QStringList&& commandLineFiles, QStringList&& commandLineUrls, MainWindow* window)
: mWindow(window), mViewModel{std::move(commandLineFiles), std::move(commandLineUrls)} {
mSplitter.setChildrenCollapsible(false);
mHorizontalSplitter.setChildrenCollapsible(false);
if (!Settings::instance()->get_sideBarVisible()) {
mSideBar.hide();
}
mSplitter.addWidget(&mSideBar);
mHorizontalSplitter.addWidget(&mSideBar);

auto mainWidgetContainer = new QWidget(mWindow);
mSplitter.addWidget(mainWidgetContainer);
mSplitter.setStretchFactor(1, 1);
auto mainWidgetLayout = new QVBoxLayout(mainWidgetContainer);
mainWidgetLayout->setContentsMargins(0, 0, 0, 0);
mHorizontalSplitter.addWidget(&mVerticalSplitter);
mHorizontalSplitter.setStretchFactor(1, 1);

mVerticalSplitter.setChildrenCollapsible(false);
mVerticalSplitter.setOrientation(Qt::Vertical);

auto torrentsListVBoxLayout = [this] {
auto widget = new QWidget();
mVerticalSplitter.addWidget(widget);
mVerticalSplitter.setStretchFactor(0, 1);
return new QVBoxLayout(widget);
}();
torrentsListVBoxLayout->setContentsMargins(0, 0, 0, 0);

mDelayedTorrentAddMessage.setWordWrap(true);
mDelayedTorrentAddMessage.hide();
mainWidgetLayout->addWidget(&mDelayedTorrentAddMessage);
torrentsListVBoxLayout->addWidget(&mDelayedTorrentAddMessage);

auto torrentsViewContainer = new QWidget(mWindow);
mainWidgetLayout->addWidget(torrentsViewContainer);
auto torrentsViewLayout = new QStackedLayout(torrentsViewContainer);
torrentsViewLayout->setStackingMode(QStackedLayout::StackAll);
auto torrentsListWithPlaceholderLayout = [&] {
auto widget = new QWidget();
torrentsListVBoxLayout->addWidget(widget);
return new QStackedLayout(widget);
}();
torrentsListWithPlaceholderLayout->setStackingMode(QStackedLayout::StackAll);

torrentsViewLayout->addWidget(&mTorrentsView);
torrentsListWithPlaceholderLayout->addWidget(&mTorrentsView);
QObject::connect(&mTorrentsView, &TorrentsView::customContextMenuRequested, this, [this](auto point) {
if (mTorrentsView.indexAt(point).isValid()) {
mTorrentMenu->popup(QCursor::pos());
Expand All @@ -271,11 +282,20 @@ namespace tremotesf {
&MainWindow::Impl::performTorrentDoubleClickAction
);

setupTorrentsPlaceholder(torrentsViewLayout);
QObject::connect(mViewModel.rpc(), &Rpc::connectedChanged, this, [this] {
if (mViewModel.rpc()->isConnected() && mTorrentsProxyModel.rowCount() > 0) {
mTorrentsView.setCurrentIndex(mTorrentsProxyModel.index(0, 0));
}
});

setupTorrentsPlaceholder(torrentsListWithPlaceholderLayout);

setupTorrentPropertiesWidget();

mSplitter.restoreState(Settings::instance()->get_splitterState());
mHorizontalSplitter.restoreState(Settings::instance()->get_horizontalSplitterState());
mVerticalSplitter.restoreState(Settings::instance()->get_verticalSplitterState());

mWindow->setCentralWidget(&mSplitter);
mWindow->setCentralWidget(&mHorizontalSplitter);

auto* const statusBar = new MainWindowStatusBar(mViewModel.rpc());
mWindow->setStatusBar(statusBar);
Expand Down Expand Up @@ -435,8 +455,12 @@ namespace tremotesf {
debug().log("Saving MainWindow state, window geometry is {}", mWindow->geometry());
Settings::instance()->set_mainWindowGeometry(mWindow->saveGeometry());
Settings::instance()->set_mainWindowState(mWindow->saveState());
Settings::instance()->set_splitterState(mSplitter.saveState());
Settings::instance()->set_horizontalSplitterState(mHorizontalSplitter.saveState());
Settings::instance()->set_verticalSplitterState(mVerticalSplitter.saveState());
mTorrentsView.saveState();
if (mTorrentPropertiesWidget) {
mTorrentPropertiesWidget->saveState();
}
}

#if defined(TREMOTESF_UNIX_FREEDESKTOP)
Expand All @@ -451,16 +475,18 @@ namespace tremotesf {
MainWindow* mWindow;
MainWindowViewModel mViewModel;

QSplitter mSplitter{};
QSplitter mHorizontalSplitter{};
QSplitter mVerticalSplitter{};

KMessageWidget mDelayedTorrentAddMessage{};

TorrentsModel mTorrentsModel{mViewModel.rpc()};
TorrentsProxyModel mTorrentsProxyModel{&mTorrentsModel};
TorrentsView mTorrentsView{&mTorrentsProxyModel};
TorrentPropertiesWidget* mTorrentPropertiesWidget{};

MainWindowSideBar mSideBar{mViewModel.rpc(), &mTorrentsProxyModel};
std::unordered_map<QString, TorrentPropertiesDialog*> mTorrentsDialogs{};
std::unordered_map<QString, TorrentPropertiesDialog*> mTorrentPropertiesDialogs{};

QAction mShowHideAppAction{};
//: Button / menu item to connect to server
Expand Down Expand Up @@ -553,6 +579,15 @@ namespace tremotesf {
this,
&MainWindow::Impl::showTorrentsPropertiesDialogs
);
torrentPropertiesAction->setVisible(!Settings::instance()->get_showTorrentPropertiesInMainWindow());
QObject::connect(
Settings::instance(),
&Settings::showTorrentPropertiesInMainWindowChanged,
this,
[torrentPropertiesAction] {
torrentPropertiesAction->setVisible(!Settings::instance()->get_showTorrentPropertiesInMainWindow());
}
);

mTorrentMenu->addSeparator();

Expand Down Expand Up @@ -885,6 +920,62 @@ namespace tremotesf {
}
}

void setupTorrentPropertiesWidget() {
const auto setup = [this] {
if (Settings::instance()->get_showTorrentPropertiesInMainWindow()) {
useTorrentPropertiesWidget();
} else {
useTorrentPropertiesDialogs();
}
};
setup();
QObject::connect(Settings::instance(), &Settings::showTorrentPropertiesInMainWindowChanged, this, setup);
}

void useTorrentPropertiesDialogs() {
if (!mTorrentPropertiesWidget) {
return;
}

mTorrentPropertiesWidget->deleteLater();
mTorrentPropertiesWidget = nullptr;
}

void useTorrentPropertiesWidget() {
if (mTorrentPropertiesWidget) {
return;
}

if (!mTorrentPropertiesDialogs.empty()) {
// Don't iterate over mTorrentPropertiesDialogs directly since call to reject() will modify it (through QDialog::finished slot)
const auto dialogs = mTorrentPropertiesDialogs;
mTorrentPropertiesDialogs.clear();
for (const auto& [hashString, dialog] : dialogs) {
dialog->reject();
}
}

mTorrentPropertiesWidget = new TorrentPropertiesWidget(mViewModel.rpc(), true, mWindow);
mVerticalSplitter.addWidget(mTorrentPropertiesWidget);

const auto updateCurrentTorrent = [this] {
const auto currentIndex = mTorrentsView.selectionModel()->currentIndex();
if (currentIndex.isValid()) {
auto source = mTorrentsProxyModel.sourceIndex(currentIndex);
mTorrentPropertiesWidget->setTorrent(mTorrentsModel.torrentAtIndex(source));
} else {
mTorrentPropertiesWidget->setTorrent(nullptr);
}
};
updateCurrentTorrent();
QObject::connect(
mTorrentsView.selectionModel(),
&QItemSelectionModel::selectionChanged,
mTorrentPropertiesWidget,
updateCurrentTorrent
);
}

void updateTorrentActions() {
const auto actions = mTorrentMenu->actions();

Expand Down Expand Up @@ -944,7 +1035,12 @@ namespace tremotesf {
void performTorrentDoubleClickAction() {
switch (Settings::instance()->get_torrentDoubleClickAction()) {
case Settings::TorrentDoubleClickAction::OpenPropertiesDialog:
showTorrentsPropertiesDialogs();
if (Settings::instance()->get_showTorrentPropertiesInMainWindow()) {
warning().log("torrentDoubleClickAction is OpenPropertiesDialog, but "
"showTorrentPropertiesInMainWindow is true");
} else {
showTorrentsPropertiesDialogs();
}
break;
case Settings::TorrentDoubleClickAction::OpenTorrentFile:
openTorrentsFiles();
Expand All @@ -962,16 +1058,16 @@ namespace tremotesf {
for (const auto& index : selectedRows) {
auto* const torrent = mTorrentsModel.torrentAtIndex(mTorrentsProxyModel.sourceIndex(index));
const auto hashString = torrent->data().hashString;
const auto existingDialog = mTorrentsDialogs.find(hashString);
if (existingDialog != mTorrentsDialogs.end()) {
const auto existingDialog = mTorrentPropertiesDialogs.find(hashString);
if (existingDialog != mTorrentPropertiesDialogs.end()) {
unminimizeAndRaiseWindow(existingDialog->second);
activateWindowCompat(existingDialog->second);
} else {
auto dialog = new TorrentPropertiesDialog(torrent, mViewModel.rpc(), mWindow);
dialog->setAttribute(Qt::WA_DeleteOnClose);
mTorrentsDialogs.emplace(hashString, dialog);
mTorrentPropertiesDialogs.emplace(hashString, dialog);
QObject::connect(dialog, &TorrentPropertiesDialog::finished, this, [hashString, this] {
mTorrentsDialogs.erase(hashString);
mTorrentPropertiesDialogs.erase(hashString);
});
dialog->show();
}
Expand Down Expand Up @@ -1036,10 +1132,10 @@ namespace tremotesf {
}
}

void setupTorrentsPlaceholder(QStackedLayout* parentLayout) {
void setupTorrentsPlaceholder(QStackedLayout* torrentsListStackedLayout) {
auto container = new QWidget(mWindow);
parentLayout->addWidget(container);
parentLayout->setCurrentWidget(container);
torrentsListStackedLayout->addWidget(container);
torrentsListStackedLayout->setCurrentWidget(container);
container->setAttribute(Qt::WA_TransparentForMouseEvents);

auto layout = new QVBoxLayout(container);
Expand Down Expand Up @@ -1222,6 +1318,21 @@ namespace tremotesf {
Settings::instance()->set_statusBarVisible(checked);
});

QAction* torrentPropertiesWidgetAction =
viewMenu->addAction(qApp->translate("tremotesf", "Torrent properties &panel"));
torrentPropertiesWidgetAction->setCheckable(true);
torrentPropertiesWidgetAction->setChecked(Settings::instance()->get_showTorrentPropertiesInMainWindow());
QObject::connect(
torrentPropertiesWidgetAction,
&QAction::triggered,
Settings::instance(),
&Settings::set_showTorrentPropertiesInMainWindow
);
QObject::connect(Settings::instance(), &Settings::showTorrentPropertiesInMainWindowChanged, this, [=] {
torrentPropertiesWidgetAction->setChecked(Settings::instance()->get_showTorrentPropertiesInMainWindow()
);
});

viewMenu->addSeparator();
QAction* lockToolBarAction = viewMenu->addAction(qApp->translate("tremotesf", "&Lock Toolbar"));
lockToolBarAction->setCheckable(true);
Expand Down
53 changes: 48 additions & 5 deletions src/ui/screens/settingsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,13 @@ namespace tremotesf {
systemAccentColorCheckBox->setChecked(settings->get_useSystemAccentColor());
#endif

auto connectOnStartupCheckBox = new QCheckBox(
auto showTorrentPropertiesInMainWindowCheckBox = new QCheckBox(
//: Check box label
qApp->translate("tremotesf", "Connect to server on startup"),
qApp->translate("tremotesf", "Show torrent properties in a panel in the main window"),
page
);
layout->addRow(connectOnStartupCheckBox);
connectOnStartupCheckBox->setChecked(settings->get_connectOnStartup());
layout->addRow(showTorrentPropertiesInMainWindowCheckBox);
showTorrentPropertiesInMainWindowCheckBox->setChecked(settings->get_showTorrentPropertiesInMainWindow());

auto torrentDoubleClickActionComboBox = new QComboBox(page);
layout->addRow(
Expand Down Expand Up @@ -116,6 +116,48 @@ namespace tremotesf {
.value()
);

auto dialogWarningMessage = new KMessageWidget(page);
layout->addRow(dialogWarningMessage);
dialogWarningMessage->setMessageType(KMessageWidget::Warning);
dialogWarningMessage->setCloseButtonVisible(false);
dialogWarningMessage->setText(qApp->translate(
"tremotesf",
"Properties dialog won't be shown because torrent properties are shown in the main window"
));
const auto updateDialogWarningMessage = [=] {
if (showTorrentPropertiesInMainWindowCheckBox->isChecked() &&
torrentDoubleClickActionComboBox->currentIndex() ==
indexOfCasted<int>(
torrentDoubleClickActionComboBoxValues,
Settings::TorrentDoubleClickAction::OpenPropertiesDialog
)) {
dialogWarningMessage->animatedShow();
} else {
dialogWarningMessage->animatedHide();
}
};
updateDialogWarningMessage();
QObject::connect(
showTorrentPropertiesInMainWindowCheckBox,
&QCheckBox::toggled,
dialogWarningMessage,
updateDialogWarningMessage
);
QObject::connect(
torrentDoubleClickActionComboBox,
&QComboBox::currentIndexChanged,
dialogWarningMessage,
updateDialogWarningMessage
);

auto connectOnStartupCheckBox = new QCheckBox(
//: Check box label
qApp->translate("tremotesf", "Connect to server on startup"),
page
);
layout->addRow(connectOnStartupCheckBox);
connectOnStartupCheckBox->setChecked(settings->get_connectOnStartup());

return [=] {
#ifdef Q_OS_WIN
if (const auto index = darkThemeComboBox->currentIndex(); index != -1) {
Expand All @@ -125,12 +167,13 @@ namespace tremotesf {
settings->set_useSystemAccentColor(systemAccentColorCheckBox->isChecked());
}
#endif
settings->set_connectOnStartup(connectOnStartupCheckBox->isChecked());
settings->set_showTorrentPropertiesInMainWindow(showTorrentPropertiesInMainWindowCheckBox->isChecked());
if (const auto index = torrentDoubleClickActionComboBox->currentIndex(); index != -1) {
settings->set_torrentDoubleClickAction(
torrentDoubleClickActionComboBoxValues[static_cast<size_t>(index)]
);
}
settings->set_connectOnStartup(connectOnStartupCheckBox->isChecked());
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ SPECIALIZE_FORMATTER_FOR_QDEBUG(QRect)

namespace tremotesf {
TorrentPropertiesDialog::TorrentPropertiesDialog(Torrent* torrent, Rpc* rpc, QWidget* parent)
: QDialog(parent), mTorrentPropertiesWidget(new TorrentPropertiesWidget(rpc, this)) {
: QDialog(parent), mTorrentPropertiesWidget(new TorrentPropertiesWidget(rpc, false, this)) {
auto layout = new QVBoxLayout(this);
auto messageWidget = new KMessageWidget(this);
layout->addWidget(messageWidget);
Expand Down
Loading

0 comments on commit 05aee48

Please sign in to comment.