Changeset View
Standalone View
src/dolphinmainwindow.cpp
Show First 20 Lines • Show All 64 Lines • ▼ Show 20 Line(s) | |||||
65 | #include <KShell> | 65 | #include <KShell> | ||
66 | #include <KStandardAction> | 66 | #include <KStandardAction> | ||
67 | #include <KToggleAction> | 67 | #include <KToggleAction> | ||
68 | #include <KUrlNavigator> | 68 | #include <KUrlNavigator> | ||
69 | #include <KToolInvocation> | 69 | #include <KToolInvocation> | ||
70 | #include <KUrlComboBox> | 70 | #include <KUrlComboBox> | ||
71 | 71 | | |||
72 | #include <QApplication> | 72 | #include <QApplication> | ||
73 | #include <QMenuBar> | 73 | #include <QMenuBar> | ||
elvisangelaccio: Not needed? (or at least, I can build without it) | |||||
74 | #include <QClipboard> | 74 | #include <QClipboard> | ||
elvisangelaccio: Not needed? (or at least, I can build without it) | |||||
75 | #include <QToolButton> | 75 | #include <QToolButton> | ||
76 | #include <QTimer> | 76 | #include <QTimer> | ||
77 | #include <QStandardPaths> | 77 | #include <QStandardPaths> | ||
78 | #include <QPushButton> | 78 | #include <QPushButton> | ||
79 | #include <QCloseEvent> | 79 | #include <QCloseEvent> | ||
80 | #include <QShowEvent> | 80 | #include <QShowEvent> | ||
81 | #include <QDialog> | 81 | #include <QDialog> | ||
82 | 82 | | |||
▲ Show 20 Lines • Show All 299 Lines • ▼ Show 20 Line(s) | 377 | if (m_tabWidget->count() > 1 && GeneralSettings::confirmClosingMultipleTabs() && closedByUser) { | |||
382 | // QDialogButtonBox::Cancel -> do nothing | 382 | // QDialogButtonBox::Cancel -> do nothing | ||
383 | QDialog *dialog = new QDialog(this, Qt::Dialog); | 383 | QDialog *dialog = new QDialog(this, Qt::Dialog); | ||
384 | dialog->setWindowTitle(i18nc("@title:window", "Confirmation")); | 384 | dialog->setWindowTitle(i18nc("@title:window", "Confirmation")); | ||
385 | dialog->setModal(true); | 385 | dialog->setModal(true); | ||
386 | QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Yes | QDialogButtonBox::No | QDialogButtonBox::Cancel); | 386 | QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Yes | QDialogButtonBox::No | QDialogButtonBox::Cancel); | ||
387 | KGuiItem::assign(buttons->button(QDialogButtonBox::Yes), KStandardGuiItem::quit()); | 387 | KGuiItem::assign(buttons->button(QDialogButtonBox::Yes), KStandardGuiItem::quit()); | ||
388 | KGuiItem::assign(buttons->button(QDialogButtonBox::No), KGuiItem(i18n("C&lose Current Tab"), QIcon::fromTheme(QStringLiteral("tab-close")))); | 388 | KGuiItem::assign(buttons->button(QDialogButtonBox::No), KGuiItem(i18n("C&lose Current Tab"), QIcon::fromTheme(QStringLiteral("tab-close")))); | ||
389 | KGuiItem::assign(buttons->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel()); | 389 | KGuiItem::assign(buttons->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel()); | ||
390 | buttons->button(QDialogButtonBox::Yes)->setDefault(true); | 390 | buttons->button(QDialogButtonBox::Yes)->setDefault(true); | ||
@ngraham rominf: @ngraham
How about this? Closing a window with all opened tabs is destructive in my opinion. My… | |||||
Yes, I think it's appropriate to have the cancel button be the default button for this dialog. ngraham: Yes, I think it's appropriate to have the cancel button be the default button for this dialog. | |||||
391 | 391 | | |||
392 | bool doNotAskAgainCheckboxResult = false; | 392 | bool doNotAskAgainCheckboxResult = false; | ||
393 | 393 | | |||
394 | const int result = KMessageBox::createKMessageBox(dialog, | 394 | const int result = KMessageBox::createKMessageBox(dialog, | ||
395 | buttons, | 395 | buttons, | ||
396 | QMessageBox::Warning, | 396 | QMessageBox::Warning, | ||
397 | i18n("You have multiple tabs open in this window, are you sure you want to quit?"), | 397 | i18n("You have multiple tabs open in this window, are you sure you want to quit?"), | ||
398 | QStringList(), | 398 | QStringList(), | ||
399 | i18n("Do not ask again"), | 399 | i18n("Do not ask again"), | ||
400 | &doNotAskAgainCheckboxResult, | 400 | &doNotAskAgainCheckboxResult, | ||
401 | KMessageBox::Notify); | 401 | KMessageBox::Notify); | ||
Unrelated change? (At least in Okular there were huge discussions on the type of icon, and I think it's bad form if you just sneak in such changes in this patch…) rkflx: Unrelated change?
(At least in Okular there were huge discussions on the type of icon, and I… | |||||
I thought that making the separate patch because of one line of code is too much. Sorry. Do you agree with the change by itself? Should I do it in the separate patch? rominf: I thought that making the separate patch because of one line of code is too much. Sorry. Do you… | |||||
One-line patches are perfectly fine. In general, keep to one change per patch, and don't try to sneak unrelated changes into patches. ngraham: One-line patches are perfectly fine. In general, keep to one change per patch, and don't try to… | |||||
OK. See D11293. rominf: OK. See D11293. | |||||
rkflx: > Do you agree with the change by itself?
That's for #dolphin to decide. Personally I think… | |||||
Usability-wise, Cancel is the appropriate default. The default button should never cause you to lose work or state. If tab state is considered unimportant, then we shouldn't have a "close multiple tabs" confirmation in the first place. But if we do have one, then the safe/non-destructive choice must be default. ngraham: Usability-wise, {nav Cancel} is the appropriate default. The default button should never cause… | |||||
What you say applies for regular dialogs. However, here we are in a confirmation dialog, where we already saved the user from a destructive action. Now we should present the sensible choice by default, which IMO is quitting. Or do you want another safety net? Anyway, do what you want and talk to Dolphin's maintainers, I don't have time to discuss this right now. Maybe we'll change it back later when this is unified across all apps. rkflx: What you say applies for regular dialogs. However, here we are in a //confirmation// dialog… | |||||
Okay, looking at the new Okular dialog, I'm pretty sure it should work like this:
IOW, window state is less important (but still worth a confirmation) than unsaved user files (which are worth a warning). rkflx: Okay, looking at the new Okular dialog, I'm pretty sure it should work like this:
- "Are you… | |||||
ngraham: Hmm, you make some good points. I'll have a think. | |||||
Cannot edit inline comments, therefore let me clarify:
For unsaved changes, the "Save" action should be default, of course. What I meant here was when you can only choose between losing all work and cancelling. rkflx: Cannot edit inline comments, therefore let me clarify:
> "Discard changes"-type dialog: Cancel… | |||||
+1 elvisangelaccio: > What you say applies for regular dialogs. However, here we are in a confirmation dialog… | |||||
ngraham: OK, you guys have convinced me! Good arguments. | |||||
402 | 402 | | |||
403 | if (doNotAskAgainCheckboxResult) { | 403 | if (doNotAskAgainCheckboxResult) { | ||
404 | GeneralSettings::setConfirmClosingMultipleTabs(false); | 404 | GeneralSettings::setConfirmClosingMultipleTabs(false); | ||
405 | } | 405 | } | ||
406 | 406 | | |||
407 | switch (result) { | 407 | switch (result) { | ||
408 | case QDialogButtonBox::Yes: | 408 | case QDialogButtonBox::Yes: | ||
409 | // Quit | 409 | // Quit | ||
410 | break; | 410 | break; | ||
411 | case QDialogButtonBox::No: | 411 | case QDialogButtonBox::No: | ||
412 | // Close only the current tab | 412 | // Close only the current tab | ||
413 | m_tabWidget->closeTab(); | 413 | m_tabWidget->closeTab(); | ||
414 | // fall through | ||||
415 | default: | ||||
416 | event->ignore(); | ||||
417 | return; | ||||
418 | } | ||||
419 | } | ||||
420 | | ||||
421 | if (m_terminalPanel->isAnyProgramRunning() && GeneralSettings::confirmClosingTerminalRunningProgram() && closedByUser) { | ||||
422 | // Ask if the user really wants to quit Dolphin with a program that is still running in the Terminal panel | ||||
In general we try to avoid gendered language where possible, even in a code comment. How about: "Ask if the user really wants to..." ngraham: In general we try to avoid gendered language where possible, even in a code comment. How about… | |||||
423 | // Open a confirmation dialog with 3 buttons: | ||||
424 | // QDialogButtonBox::Yes -> Quit | ||||
425 | // QDialogButtonBox::No -> Show Terminal Panel | ||||
426 | // QDialogButtonBox::Cancel -> do nothing | ||||
427 | QDialog *dialog = new QDialog(this, Qt::Dialog); | ||||
428 | dialog->setWindowTitle(i18nc("@title:window", "Confirmation")); | ||||
429 | dialog->setModal(true); | ||||
430 | QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Yes | QDialogButtonBox::No | QDialogButtonBox::Cancel); | ||||
431 | KGuiItem::assign(buttons->button(QDialogButtonBox::Yes), KStandardGuiItem::quit()); | ||||
432 | KGuiItem::assign(buttons->button(QDialogButtonBox::No), KGuiItem(i18n("Show &Terminal Panel"), QIcon::fromTheme(QStringLiteral("utilities-terminal")))); | ||||
The Show Terminal Panel button should probably only be displayed if the Terminal panel is hidden. Otherwise it seems odd that it's there, and when you click on it, nothing different appears to happen compared to just hitting the cancel button. ngraham: The {nav Show Terminal Panel} button should probably only be displayed if the Terminal panel is… | |||||
Terminal panel gets focus. I think it's reasonable to keep the button. Your opinion? rominf: > Otherwise it seems odd that it's there, and when you click on it, nothing different appears… | |||||
Regardless, some kind of change is needed, because the button says "Show Terminal Panel", not "Focus Terminal Panel". A button should always do what it says it'll do, or else users learn not to truth the software. If we want to do make it simply focus the Terminal panel when the Terminal panel is open, then the text should change accordingly. ngraham: Regardless, some kind of change is needed, because the button says "Show Terminal Panel", not… | |||||
433 | KGuiItem::assign(buttons->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel()); | ||||
434 | buttons->button(QDialogButtonBox::Cancel)->setDefault(true); | ||||
A dialog box's default button should never invoke a destructive action. In this context, killing the process is akin to quitting with unsaved changes and should be considered destructive. The button's red icon also provides a hint. :) The Cancel button should be the default button here. ngraham: A dialog box's default button should //never// invoke a destructive action. In this context… | |||||
435 | | ||||
436 | bool doNotAskAgainCheckboxResult = false; | ||||
437 | | ||||
438 | const int result = KMessageBox::createKMessageBox( | ||||
Please use const auto result, since this function returns a QDialogButtonBox::StandardButton. elvisangelaccio: Please use `const auto result`, since this function returns a `QDialogButtonBox… | |||||
439 | dialog, | ||||
440 | buttons, | ||||
441 | QMessageBox::Warning, | ||||
442 | i18n("The program '%1' is still running in the Terminal panel. Are you sure you want to quit?", m_terminalPanel->runningProgramName()), | ||||
With the actual program name in the string (thumbs up for that), we need a small change to make it grammatically correct: A program -> The program ngraham: With the actual program name in the string (thumbs up for that), we need a small change to make… | |||||
443 | QStringList(), | ||||
444 | i18n("Do not ask again"), | ||||
No word puzzles, please. Let's add the program within the i18n function call using a format string, rather than string concatenation. ngraham: No word puzzles, please. Let's add the program within the `i18n` function call using a format… | |||||
rominf: Sorry, I didn't know that `i18n` works that way. Fixed it. | |||||
445 | &doNotAskAgainCheckboxResult, | ||||
446 | KMessageBox::Notify); | ||||
447 | | ||||
448 | if (doNotAskAgainCheckboxResult) { | ||||
449 | GeneralSettings::setConfirmClosingTerminalRunningProgram(false); | ||||
450 | } | ||||
451 | | ||||
452 | switch (result) { | ||||
453 | case QDialogButtonBox::Yes: | ||||
454 | // Quit | ||||
455 | break; | ||||
456 | case QDialogButtonBox::No: | ||||
457 | if (!m_terminalPanel->isVisible()) | ||||
458 | actionCollection()->action("show_terminal_panel")->trigger(); | ||||
459 | else | ||||
460 | m_terminalPanel->setFocus(); | ||||
elvisangelaccio: Missing braces | |||||
461 | // Do not quit | ||||
462 | // fall through | ||||
414 | default: | 463 | default: | ||
415 | event->ignore(); | 464 | event->ignore(); | ||
416 | return; | 465 | return; | ||
417 | } | 466 | } | ||
This switch now exists twice in the same function. There must be a smarter way of doing that, right? markg: This switch now exists twice in the same function. There must be a smarter way of doing that… | |||||
That's 2 different switches. Look at case QDialogButtonBox::No: branch. I'm sure it's possible to merge them, but that would hurt readability. rominf: That's 2 different switches. Look at `case QDialogButtonBox::No:` branch. I'm sure it's… | |||||
Right, but this also hurts ;) markg: Right, but this also hurts ;)
Oke, it's a tradeoff i suppose. Readability over duplication. | |||||
418 | } | 467 | } | ||
419 | 468 | | |||
420 | GeneralSettings::setVersion(CurrentDolphinVersion); | 469 | GeneralSettings::setVersion(CurrentDolphinVersion); | ||
421 | GeneralSettings::self()->save(); | 470 | GeneralSettings::self()->save(); | ||
422 | 471 | | |||
423 | KXmlGuiWindow::closeEvent(event); | 472 | KXmlGuiWindow::closeEvent(event); | ||
424 | } | 473 | } | ||
425 | 474 | | |||
Can't you use any of KMessageBox's built-in dialogs rather than creating the entire QDialog yourself? broulik: Can't you use any of `KMessageBox`'s built-in dialogs rather than creating the entire `QDialog`… | |||||
I just copy pasted ConfirmClosingMultipleTabs code because that's my first written dialog in KDE and I don't know how the things are done. If you think that this should be changed, then we have to change ConfirmClosingMultipleTabs too. rominf: I just copy pasted `ConfirmClosingMultipleTabs` code because that's my first written dialog in… | |||||
See also T7022: Improve confirmation dialog when closing multiple tabs. TL;DR: Everybody does it differently, in the far future it would be nice to make it consistent across apps. Perhaps I'd keep Dolphin's style here for now, but that's for Dolphin to decide. rkflx: See also {T7022}.
TL;DR: Everybody does it differently, in the far future it would be nice to… | |||||
426 | void DolphinMainWindow::saveProperties(KConfigGroup& group) | 475 | void DolphinMainWindow::saveProperties(KConfigGroup& group) | ||
427 | { | 476 | { | ||
428 | m_tabWidget->saveProperties(group); | 477 | m_tabWidget->saveProperties(group); | ||
429 | } | 478 | } | ||
430 | 479 | | |||
431 | void DolphinMainWindow::readProperties(const KConfigGroup& group) | 480 | void DolphinMainWindow::readProperties(const KConfigGroup& group) | ||
432 | { | 481 | { | ||
433 | m_tabWidget->readProperties(group); | 482 | m_tabWidget->readProperties(group); | ||
434 | } | 483 | } | ||
435 | 484 | | |||
Why another if (!m_terminalPanel->isVisible()) block? Can't we merge this with the one above? elvisangelaccio: Why another `if (!m_terminalPanel->isVisible())` block? Can't we merge this with the one above? | |||||
We actually can't--at least not cleanly. The top block modifies standardButtons, which is consumed later, the product of which (buttons) is needed in the second block. ngraham: We actually can't--at least not cleanly. The top block modifies `standardButtons`, which is… | |||||
436 | void DolphinMainWindow::updateNewMenu() | 485 | void DolphinMainWindow::updateNewMenu() | ||
437 | { | 486 | { | ||
438 | m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->hiddenFilesShown()); | 487 | m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->hiddenFilesShown()); | ||
Let's phrase this text in a more standard, grammatically correct manner: "A program is still running in the Terminal panel. Are you sure you want to quit?" Bonus points if we can get the actual running command and display it in the text here somehow. Also +1 for @rkflx's suggestion for a button that will show the terminal panel if it's hidden. ngraham: Let's phrase this text in a more standard, grammatically correct manner:
"A program is still… | |||||
Done your task for bonus points and @rkflx's suggestion. rominf: Done your task for bonus points and @rkflx's suggestion. | |||||
439 | m_newFileMenu->checkUpToDate(); | 488 | m_newFileMenu->checkUpToDate(); | ||
440 | m_newFileMenu->setPopupFiles(activeViewContainer()->url()); | 489 | m_newFileMenu->setPopupFiles(activeViewContainer()->url()); | ||
This is the name of the key that will be stored in settings to remember this. The text in the user interface is always "Do not ask again" broulik: This is the name of the key that will be stored in settings to remember this. The text in the… | |||||
441 | } | 490 | } | ||
But it is a default. Why isn't this working? rominf: > but the Cancel button still isn't the default
But it is a default. Why isn't this working? | |||||
Does it work for you? If not, you need to test the changes you're making. As for why, I don't know; it's your patch. :) One of the fun parts of producing a patch is that you often go down the rabbit hole of finding other bugs in the code you're touching! ngraham: Does it work for you? If not, you need to test the changes you're making. As for why, I don't… | |||||
442 | 491 | | |||
443 | void DolphinMainWindow::createDirectory() | 492 | void DolphinMainWindow::createDirectory() | ||
444 | { | 493 | { | ||
445 | m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->hiddenFilesShown()); | 494 | m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->hiddenFilesShown()); | ||
446 | m_newFileMenu->setPopupFiles(activeViewContainer()->url()); | 495 | m_newFileMenu->setPopupFiles(activeViewContainer()->url()); | ||
447 | m_newFileMenu->createDirectory(); | 496 | m_newFileMenu->createDirectory(); | ||
448 | } | 497 | } | ||
449 | 498 | | |||
450 | void DolphinMainWindow::quit() | 499 | void DolphinMainWindow::quit() | ||
451 | { | 500 | { | ||
452 | close(); | 501 | close(); | ||
453 | } | 502 | } | ||
454 | 503 | | |||
455 | void DolphinMainWindow::showErrorMessage(const QString& message) | 504 | void DolphinMainWindow::showErrorMessage(const QString& message) | ||
456 | { | 505 | { | ||
457 | m_activeViewContainer->showMessage(message, DolphinViewContainer::Error); | 506 | m_activeViewContainer->showMessage(message, DolphinViewContainer::Error); | ||
458 | } | 507 | } | ||
459 | 508 | | |||
460 | void DolphinMainWindow::slotUndoAvailable(bool available) | 509 | void DolphinMainWindow::slotUndoAvailable(bool available) | ||
461 | { | 510 | { | ||
462 | QAction* undoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Undo)); | 511 | QAction* undoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Undo)); | ||
463 | if (undoAction) { | 512 | if (undoAction) { | ||
464 | undoAction->setEnabled(available); | 513 | undoAction->setEnabled(available); | ||
465 | } | 514 | } | ||
elvisangelaccio: Please use `Q_FALLTHROUGH` instead. | |||||
466 | } | 515 | } | ||
467 | 516 | | |||
468 | void DolphinMainWindow::slotUndoTextChanged(const QString& text) | 517 | void DolphinMainWindow::slotUndoTextChanged(const QString& text) | ||
469 | { | 518 | { | ||
470 | QAction* undoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Undo)); | 519 | QAction* undoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Undo)); | ||
471 | if (undoAction) { | 520 | if (undoAction) { | ||
472 | undoAction->setText(text); | 521 | undoAction->setText(text); | ||
473 | } | 522 | } | ||
▲ Show 20 Lines • Show All 1129 Lines • Show Last 20 Lines |
Not needed? (or at least, I can build without it)