From 6497837b2d5df0b4464bf43d7374441301464d3d Mon Sep 17 00:00:00 2001 From: Amol Godbole Date: Sun, 7 Oct 2012 19:37:32 +0200 Subject: [PATCH 1/8] Use not only Alt+Return, but also Alt+Enter as shortcut for "Properties" BUG: 307603 REVIEW: 106753 FIXED-IN: 4.9.3 --- dolphin/src/views/dolphinviewactionhandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dolphin/src/views/dolphinviewactionhandler.cpp b/dolphin/src/views/dolphinviewactionhandler.cpp index 7f23b7d54f..0249964ac6 100644 --- a/dolphin/src/views/dolphinviewactionhandler.cpp +++ b/dolphin/src/views/dolphinviewactionhandler.cpp @@ -137,7 +137,7 @@ void DolphinViewActionHandler::createActions() // Well, it's the File menu in dolphinmainwindow and the Edit menu in dolphinpart... :) propertiesAction->setText( i18nc("@action:inmenu File", "Properties") ); propertiesAction->setIcon(KIcon("document-properties")); - propertiesAction->setShortcut(Qt::ALT | Qt::Key_Return); + propertiesAction->setShortcuts(QList() << Qt::ALT + Qt::Key_Return << Qt::ALT + Qt::Key_Enter); connect(propertiesAction, SIGNAL(triggered()), SLOT(slotProperties())); // View menu From bc465e4e8e4aa4d24263d153ac008cbfeb1d67ee Mon Sep 17 00:00:00 2001 From: "T.C. Hollingsworth" Date: Thu, 11 Oct 2012 22:08:29 -0400 Subject: [PATCH 2/8] docs: add id attribute to and
elements this commit was automated; please revert if it causes trouble for details see http://lists.kde.org/?l=kde-doc-english&m=134965352825792&w=2 SVN_SILENT --- doc/dolphin/index.docbook | 4 ++-- doc/kdepasswd/index.docbook | 4 ++-- doc/kfind/index.docbook | 4 ++-- doc/konqueror/index.docbook | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/dolphin/index.docbook b/doc/dolphin/index.docbook index 71480a2835..4916e8e0ec 100644 --- a/doc/dolphin/index.docbook +++ b/doc/dolphin/index.docbook @@ -7,9 +7,9 @@ ]> - + - + The &dolphin; Handbook diff --git a/doc/kdepasswd/index.docbook b/doc/kdepasswd/index.docbook index 438825c107..30514fca13 100644 --- a/doc/kdepasswd/index.docbook +++ b/doc/kdepasswd/index.docbook @@ -4,9 +4,9 @@ ]> -
+
Password & User Account - +
Michael diff --git a/doc/kfind/index.docbook b/doc/kfind/index.docbook index 5a76d0a44e..ba611e285a 100644 --- a/doc/kfind/index.docbook +++ b/doc/kfind/index.docbook @@ -7,9 +7,9 @@ ]> - + - + The &kfind; Handbook diff --git a/doc/konqueror/index.docbook b/doc/konqueror/index.docbook index 7fa6a87177..0d34c6b943 100644 --- a/doc/konqueror/index.docbook +++ b/doc/konqueror/index.docbook @@ -22,9 +22,9 @@ ]> - + - + The &konqueror; Handbook From a78c6a50dcb33028eb572bc260bdaca8f30a597a Mon Sep 17 00:00:00 2001 From: Dawit Alemayehu Date: Wed, 19 Sep 2012 00:12:38 -0400 Subject: [PATCH 3/8] In the session restore dialog, allow the user to select which sessions should be restored. BUG: 260282 FIXED-IN: 4.10 REVIEW: 106503 GUI: new strings DIGEST: Ability to select the session(s) to be restored in Konqueror. (cherry picked from commit 0142a8ca11b00b5b24347b92700b7f6c5bdb3e75) --- konqueror/src/konqsessionmanager.cpp | 394 +++++++++++++++++++++++---- konqueror/src/konqsessionmanager.h | 51 ++++ 2 files changed, 388 insertions(+), 57 deletions(-) diff --git a/konqueror/src/konqsessionmanager.cpp b/konqueror/src/konqsessionmanager.cpp index 68a003f1c3..ac5c691f6c 100644 --- a/konqueror/src/konqsessionmanager.cpp +++ b/konqueror/src/konqsessionmanager.cpp @@ -33,12 +33,14 @@ #include #include #include -#include +#include #include #include +#include #include -#include +#include +#include #include #include #include @@ -47,6 +49,12 @@ #include #include #include +#include +#include +#include +#include +#include + class KonqSessionManagerPrivate { @@ -66,8 +74,291 @@ public: K_GLOBAL_STATIC(KonqSessionManagerPrivate, myKonqSessionManagerPrivate) +static QString viewIdFor(const QString& sessionFile, const QString& viewId) +{ + return (sessionFile + viewId); +} + +static const QList windowConfigGroups(const KConfig& config) +{ + QList groups; + KConfigGroup generalGroup(&config, "General"); + const int size = generalGroup.readEntry("Number of Windows", 0); + for(int i = 0; i < size; i++) { + groups << KConfigGroup(&config, "Window" + QString::number(i)); + } + return groups; +} + +SessionRestoreDialog::SessionRestoreDialog(const QStringList& sessionFilePaths, QWidget* parent) + : KDialog(parent, 0) + ,m_sessionItemsCount(0) + ,m_dontShowChecked(false) +{ + setCaption(i18nc("@title:window", "Restore Session?")); + setButtons(KDialog::Yes | KDialog::No | KDialog::Cancel); + setObjectName(QLatin1String("restoresession")); + setButtonGuiItem(KDialog::Yes, KGuiItem(i18nc("@action:button yes", "Restore Session"), "window-new")); + setButtonGuiItem(KDialog::No, KGuiItem(i18nc("@action:button no","Do Not Restore"), "dialog-close")); + setButtonGuiItem(KDialog::Cancel, KGuiItem(i18nc("@action:button ask later","Ask Me Later"), "chronometer")); + setDefaultButton(KDialog::Yes); + setButtonFocus(KDialog::Yes); + setModal(true); + + QWidget *mainWidget = new QWidget(this); + QVBoxLayout *mainLayout = new QVBoxLayout(mainWidget); + mainLayout->setSpacing(KDialog::spacingHint() * 2); // provide extra spacing + mainLayout->setMargin(0); + + QHBoxLayout *hLayout = new QHBoxLayout(); + hLayout->setMargin(0); + hLayout->setSpacing(-1); // use default spacing + mainLayout->addLayout(hLayout,5); + + KIcon icon (QLatin1String("dialog-warning")); + if (!icon.isNull()) { + QLabel *iconLabel = new QLabel(mainWidget); + QStyleOption option; + option.initFrom(mainWidget); + iconLabel->setPixmap(icon.pixmap(mainWidget->style()->pixelMetric(QStyle::PM_MessageBoxIconSize, &option, mainWidget))); + QVBoxLayout *iconLayout = new QVBoxLayout(); + iconLayout->addStretch(1); + iconLayout->addWidget(iconLabel); + iconLayout->addStretch(5); + hLayout->addLayout(iconLayout,0); + } + + const QString text (i18n("Konqueror did not close correctly. Would you like to restore these previous sessions?")); + QLabel *messageLabel = new QLabel(text, mainWidget); + Qt::TextInteractionFlags flags = (Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); + messageLabel->setTextInteractionFlags(flags); + messageLabel->setWordWrap(true); + + hLayout->addSpacing(KDialog::spacingHint()); + hLayout->addWidget(messageLabel,5); + + QTreeWidget* treeWidget = 0; + if (!sessionFilePaths.isEmpty()) { + treeWidget = new QTreeWidget(mainWidget); + treeWidget->setHeader(0); + treeWidget->setHeaderHidden(true); + treeWidget->setToolTip(i18nc("@tooltip:session list", "Uncheck the sessions you do not want to be restored")); + + QStyleOptionViewItem styleOption; + styleOption.initFrom(treeWidget); + QFontMetrics fm(styleOption.font); + int w = treeWidget->width(); + const QRect desktop = KGlobalSettings::desktopGeometry(this); + + // Collect info from the sessions to restore + Q_FOREACH(const QString& sessionFile, sessionFilePaths) { + kDebug() << sessionFile; + QTreeWidgetItem* windowItem = 0; + const KConfig config(sessionFile, KConfig::SimpleConfig); + const QList groups = windowConfigGroups(config); + Q_FOREACH(const KConfigGroup& group, groups) { + // To avoid a recursive search, let's do linear search on Foo_CurrentHistoryItem=1 + Q_FOREACH(const QString& key, group.keyList()) { + if (key.endsWith(QLatin1String("_CurrentHistoryItem"))) { + const QString viewId = key.left(key.length() - qstrlen("_CurrentHistoryItem")); + const QString historyIndex = group.readEntry(key, QString()); + const QString prefix = "HistoryItem" + viewId + '_' + historyIndex; + // Ignore the sidebar views + if (group.readEntry(prefix + "StrServiceName", QString()).startsWith("konq_sidebar")) + continue; + const QString url = group.readEntry(prefix + "Url", QString()); + const QString title = group.readEntry(prefix + "Title", QString()); + kDebug() << viewId << url << title; + const QString displayText = (title.trimmed().isEmpty() ? url : title); + if (!displayText.isEmpty()) { + if (!windowItem) { + windowItem = new QTreeWidgetItem(treeWidget); + const int index = sessionFilePaths.indexOf(sessionFile) + 1; + windowItem->setText(0, i18nc("@item:treewidget", "Window %1", index)); + windowItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable); + windowItem->setCheckState(0, Qt::Checked); + windowItem->setExpanded(true); + } + QTreeWidgetItem* item = new QTreeWidgetItem (windowItem); + item->setText(0, displayText); + item->setData(0, Qt::UserRole, viewIdFor(sessionFile, viewId)); + item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable); + item->setCheckState(0, Qt::Checked); + w = qMax(w, fm.width(displayText)); + m_sessionItemsCount++; + } + } + } + } + + if (windowItem) { + m_checkedSessionItems.insert(windowItem, windowItem->childCount()); + } + } + + const int borderWidth = treeWidget->width() - treeWidget->viewport()->width() + treeWidget->verticalScrollBar()->height(); + w += borderWidth; + if (w > desktop.width() * 0.85) { // limit treeWidget size to 85% of screen width + w = qRound(desktop.width() * 0.85); + } + treeWidget->setMinimumWidth(w); + mainLayout->addWidget(treeWidget, 50); + treeWidget->setSelectionMode(QTreeWidget::NoSelection); + messageLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); + } + + // Do not connect the itemChanged signal until after the treewidget + // is completely populated to prevent the firing of the itemChanged + // signal while in the process of adding the original session items. + if (treeWidget && treeWidget->topLevelItemCount() > 0) { + connect(treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)), + this, SLOT(slotItemChanged(QTreeWidgetItem*,int))); + } + + QCheckBox* checkbox = new QCheckBox(i18n("Do not ask again"), mainWidget); + connect(checkbox, SIGNAL(clicked(bool)), this, SLOT(slotClicked(bool))); + mainLayout->addWidget(checkbox); + + setMainWidget(mainWidget); +} + +SessionRestoreDialog::~SessionRestoreDialog() +{ +} + +QStringList SessionRestoreDialog::discardedSessionList() const +{ + return m_discardedSessionList; +} + +bool SessionRestoreDialog::isDontShowChecked() const +{ + return m_dontShowChecked; +} + +void SessionRestoreDialog::slotClicked(bool checked) +{ + m_dontShowChecked = checked; +} + +static void setCheckState(QTreeWidgetItem* item, int column, Qt::CheckState state) +{ + const bool blocked = item->treeWidget()->blockSignals(true); + item->setCheckState(column, state); + item->treeWidget()->blockSignals(blocked); +} + +void SessionRestoreDialog::slotItemChanged(QTreeWidgetItem* item, int column) +{ + Q_ASSERT(item); + + const int itemChildCount = item->childCount(); + QTreeWidgetItem* parentItem = 0; + + const bool blocked = item->treeWidget()->blockSignals(true); + if (itemChildCount > 0) { + parentItem = item; + for (int i = 0; i < itemChildCount; ++i) { + QTreeWidgetItem* childItem = item->child(i); + if (childItem) { + childItem->setCheckState(column, item->checkState(column)); + switch (childItem->checkState(column)) { + case Qt::Checked: + m_sessionItemsCount++; + m_discardedSessionList.removeAll(childItem->data(column, Qt::UserRole).toString()); + m_checkedSessionItems[item]++; + break; + case Qt::Unchecked: + m_sessionItemsCount--; + m_discardedSessionList.append(childItem->data(column, Qt::UserRole).toString()); + m_checkedSessionItems[item]--; + break; + default: + break; + } + } + } + } else { + parentItem = item->parent(); + switch (item->checkState(column)) { + case Qt::Checked: + m_sessionItemsCount++; + m_discardedSessionList.removeAll(item->data(column, Qt::UserRole).toString()); + m_checkedSessionItems[parentItem]++; + break; + case Qt::Unchecked: + m_sessionItemsCount--; + m_discardedSessionList.append(item->data(column, Qt::UserRole).toString()); + m_checkedSessionItems[parentItem]--; + break; + default: + break; + } + } + + const int numCheckSessions = m_checkedSessionItems.value(parentItem); + switch (parentItem->checkState(column)) { + case Qt::Checked: + if (numCheckSessions == 0) { + parentItem->setCheckState(column, Qt::Unchecked); + } + case Qt::Unchecked: + if (numCheckSessions > 0) { + parentItem->setCheckState(column, Qt::Checked); + } + default: + break; + } + + enableButton(KDialog::Yes, m_sessionItemsCount > 0); + item->treeWidget()->blockSignals(blocked); +} + +void SessionRestoreDialog::saveDontShow(const QString& dontShowAgainName, int result) +{ + if (dontShowAgainName.isEmpty()) { + return; + } + + KConfigGroup::WriteConfigFlags flags = KConfig::Persistent; + if (dontShowAgainName[0] == ':') { + flags |= KConfigGroup::Global; + } + + KConfigGroup cg(KGlobal::config().data(), "Notification Messages"); + cg.writeEntry( dontShowAgainName, result==Yes, flags ); + cg.sync(); +} + +bool SessionRestoreDialog::shouldBeShown(const QString& dontShowAgainName, int* result) +{ + if (dontShowAgainName.isEmpty()) { + return true; + } + + KConfigGroup cg(KGlobal::config().data(), "Notification Messages"); + const QString dontAsk = cg.readEntry(dontShowAgainName, QString()).toLower(); + + if (dontAsk == "yes" || dontAsk == "true") { + if (result) { + *result = Yes; + } + return false; + } + + if (dontAsk == "no" || dontAsk == "false") { + if (result) { + *result = No; + } + return false; + } + + return true; +} + KonqSessionManager::KonqSessionManager() : m_autosaveDir(KStandardDirs::locateLocal("appdata", "autosave")) + , m_autosaveEnabled(false) // so that enableAutosave works { // Initialize dbus interfaces new KonqSessionManagerAdaptor ( this ); @@ -87,7 +378,6 @@ KonqSessionManager::KonqSessionManager() connect( &m_autoSaveTimer, SIGNAL(timeout()), this, SLOT(autoSaveSession()) ); } - m_autosaveEnabled = false; // so that enableAutosave works enableAutosave(); } @@ -261,17 +551,6 @@ void KonqSessionManager::restoreSessions(const QString &sessionsDir, bool } } -static const QList windowConfigGroups(const KConfig& config) -{ - QList groups; - KConfigGroup generalGroup(&config, "General"); - const int size = generalGroup.readEntry("Number of Windows", 0); - for(int i = 0; i < size; i++) { - groups << KConfigGroup(&config, "Window" + QString::number(i)); - } - return groups; -} - void KonqSessionManager::restoreSession(const QString &sessionFilePath, bool openTabsInsideCurrentWindow, KonqMainWindow *parent) { @@ -288,6 +567,30 @@ void KonqSessionManager::restoreSession(const QString &sessionFilePath, bool } } +static void removeDiscardedSessions(const QStringList& sessionFiles, const QStringList& discardedSessions) +{ + if (discardedSessions.isEmpty()) { + return; + } + + Q_FOREACH(const QString& sessionFile, sessionFiles) { + const KConfig config(sessionFile, KConfig::SimpleConfig); + QList groups = windowConfigGroups(config); + for (int i = 0, count = groups.count(); i < count; ++i) { + KConfigGroup& group = groups[i]; + const QString rootItem = group.readEntry("RootItem", "empty"); + const QString viewsKey (rootItem + QLatin1String("_Children")); + QStringList views = group.readEntry(viewsKey, QStringList()); + QMutableStringListIterator it (views); + while (it.hasNext()) { + if (discardedSessions.contains(viewIdFor(sessionFile, it.next()))) { + it.remove(); + } + } + group.writeEntry(viewsKey, views); + } + } +} bool KonqSessionManager::askUserToRestoreAutosavedAbandonedSessions() { @@ -295,52 +598,30 @@ bool KonqSessionManager::askUserToRestoreAutosavedAbandonedSessions() if(sessionFilePaths.isEmpty()) return false; - QStringList detailsList; - // Collect info from the sessions to restore - Q_FOREACH(const QString& sessionFile, sessionFilePaths) { - kDebug() << sessionFile; - const KConfig config(sessionFile, KConfig::SimpleConfig); - const QList groups = windowConfigGroups(config); - Q_FOREACH(const KConfigGroup& group, groups) { - // To avoid a recursive search, let's do linear search on Foo_CurrentHistoryItem=1 - Q_FOREACH(const QString& key, group.keyList()) { - if (key.endsWith("_CurrentHistoryItem")) { - const QString viewId = key.left(key.length() - strlen("_CurrentHistoryItem")); - const QString historyIndex = group.readEntry(key, QString()); - const QString prefix = "HistoryItem" + viewId + '_' + historyIndex; - // Ignore the sidebar views - if (group.readEntry(prefix + "StrServiceName", QString()).startsWith("konq_sidebar")) - continue; - const QString url = group.readEntry(prefix + "Url", QString()); - const QString title = group.readEntry(prefix + "Title", QString()); - kDebug() << viewId << url << title; - if (title.trimmed().isEmpty()) { - detailsList << url; - } else { - detailsList << title; - } - } - } - } - } - disableAutosave(); - switch(KMessageBox::warningYesNoCancelList(0, // there is no questionYesNoCancelList - i18n("Konqueror did not close correctly. Would you like to restore the previous session?"), - detailsList, - i18nc("@title:window", "Restore Session?"), - KGuiItem(i18n("Restore Session"), "window-new"), - KGuiItem(i18n("Do Not Restore"), "dialog-close"), - KGuiItem(i18n("Ask Me Later"), "chronometer"), - "Restore session when konqueror didn't close correctly" - )) - { - case KMessageBox::Yes: + int result; + QStringList discardedSessionList; + const QLatin1String dontAskAgainName ("Restore session when konqueror didn't close correctly"); + + if (SessionRestoreDialog::shouldBeShown(dontAskAgainName, &result)) { + SessionRestoreDialog* restoreDlg = new SessionRestoreDialog(sessionFilePaths); + result = restoreDlg->exec(); + discardedSessionList = restoreDlg->discardedSessionList(); + if (restoreDlg->isDontShowChecked()) { + SessionRestoreDialog::saveDontShow(dontAskAgainName, result); + } + delete restoreDlg; + } + + switch (result) { + case KDialog::Yes: + // Remove the discarded session list files. + removeDiscardedSessions(sessionFilePaths, discardedSessionList); restoreSessions(sessionFilePaths); enableAutosave(); return true; - case KMessageBox::No: + case KDialog::No: deleteOwnedSessions(); enableAutosave(); return false; @@ -349,8 +630,7 @@ bool KonqSessionManager::askUserToRestoreAutosavedAbandonedSessions() QDirIterator it(dirForMyOwnedSessionFiles(), QDir::Writable|QDir::Files); - while (it.hasNext()) - { + while (it.hasNext()) { it.next(); // remove ownership of the abandoned file QFile::rename(it.filePath(), m_autosaveDir + '/' + it.fileName()); diff --git a/konqueror/src/konqsessionmanager.h b/konqueror/src/konqsessionmanager.h index ee629e4664..d3103ac36a 100644 --- a/konqueror/src/konqsessionmanager.h +++ b/konqueror/src/konqsessionmanager.h @@ -27,10 +27,61 @@ #include #include +#include #include class QDBusMessage; class KonqMainWindow; +class QTreeWidgetItem; + +class SessionRestoreDialog : public KDialog +{ + Q_OBJECT +public: + explicit SessionRestoreDialog(const QStringList& sessionFilePaths, QWidget* parent=0); + virtual ~SessionRestoreDialog(); + + /** + * Returns the list of session discarded/unselected by the user. + */ + QStringList discardedSessionList() const; + + /** + * Returns true if the don't show checkbox is checked. + */ + bool isDontShowChecked() const; + + /** + * Returns true if the corresponding session restore dialog should be shown. + * + * @param dontShowAgainName the name that identify the session restore dialog box. + * @param result if not null, it will be set to the result that was chosen the last + * time the dialog box was shown. This is only useful if the restore dialog box should + * be shown. + */ + static bool shouldBeShown(const QString &dontShowAgainName, int* result); + + /** + * Save the fact that the session restore dialog should not be shown again. + * + * @param dontShowAgainName the name that identify the session restore dialog. If + * empty, this method does nothing. + * @param result the value (Yes or No) that should be used as the result + * for the message box. + */ + static void saveDontShow(const QString &dontShowAgainName, int result); + +private Q_SLOTS: + void slotClicked(bool); + void slotItemChanged(QTreeWidgetItem*, int); + +private: + QStringList m_discardedSessionList; + QHash m_checkedSessionItems; + int m_sessionItemsCount; + bool m_dontShowChecked; +}; + /** * This class is a singleton. It does some session related tasks: From ac70302ee08d01793b3c22d288c19117c384e028 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Fri, 12 Oct 2012 13:12:28 +0200 Subject: [PATCH 4/8] Revert "In the session restore dialog, allow the user to select which sessions should" Not meant for 4.9. CCBUG: 260282 This reverts commit a78c6a50dcb33028eb572bc260bdaca8f30a597a. --- konqueror/src/konqsessionmanager.cpp | 392 ++++----------------------- konqueror/src/konqsessionmanager.h | 51 ---- 2 files changed, 56 insertions(+), 387 deletions(-) diff --git a/konqueror/src/konqsessionmanager.cpp b/konqueror/src/konqsessionmanager.cpp index ac5c691f6c..68a003f1c3 100644 --- a/konqueror/src/konqsessionmanager.cpp +++ b/konqueror/src/konqsessionmanager.cpp @@ -33,14 +33,12 @@ #include #include #include -#include +#include #include #include -#include #include -#include -#include +#include #include #include #include @@ -49,12 +47,6 @@ #include #include #include -#include -#include -#include -#include -#include - class KonqSessionManagerPrivate { @@ -74,291 +66,8 @@ public: K_GLOBAL_STATIC(KonqSessionManagerPrivate, myKonqSessionManagerPrivate) -static QString viewIdFor(const QString& sessionFile, const QString& viewId) -{ - return (sessionFile + viewId); -} - -static const QList windowConfigGroups(const KConfig& config) -{ - QList groups; - KConfigGroup generalGroup(&config, "General"); - const int size = generalGroup.readEntry("Number of Windows", 0); - for(int i = 0; i < size; i++) { - groups << KConfigGroup(&config, "Window" + QString::number(i)); - } - return groups; -} - -SessionRestoreDialog::SessionRestoreDialog(const QStringList& sessionFilePaths, QWidget* parent) - : KDialog(parent, 0) - ,m_sessionItemsCount(0) - ,m_dontShowChecked(false) -{ - setCaption(i18nc("@title:window", "Restore Session?")); - setButtons(KDialog::Yes | KDialog::No | KDialog::Cancel); - setObjectName(QLatin1String("restoresession")); - setButtonGuiItem(KDialog::Yes, KGuiItem(i18nc("@action:button yes", "Restore Session"), "window-new")); - setButtonGuiItem(KDialog::No, KGuiItem(i18nc("@action:button no","Do Not Restore"), "dialog-close")); - setButtonGuiItem(KDialog::Cancel, KGuiItem(i18nc("@action:button ask later","Ask Me Later"), "chronometer")); - setDefaultButton(KDialog::Yes); - setButtonFocus(KDialog::Yes); - setModal(true); - - QWidget *mainWidget = new QWidget(this); - QVBoxLayout *mainLayout = new QVBoxLayout(mainWidget); - mainLayout->setSpacing(KDialog::spacingHint() * 2); // provide extra spacing - mainLayout->setMargin(0); - - QHBoxLayout *hLayout = new QHBoxLayout(); - hLayout->setMargin(0); - hLayout->setSpacing(-1); // use default spacing - mainLayout->addLayout(hLayout,5); - - KIcon icon (QLatin1String("dialog-warning")); - if (!icon.isNull()) { - QLabel *iconLabel = new QLabel(mainWidget); - QStyleOption option; - option.initFrom(mainWidget); - iconLabel->setPixmap(icon.pixmap(mainWidget->style()->pixelMetric(QStyle::PM_MessageBoxIconSize, &option, mainWidget))); - QVBoxLayout *iconLayout = new QVBoxLayout(); - iconLayout->addStretch(1); - iconLayout->addWidget(iconLabel); - iconLayout->addStretch(5); - hLayout->addLayout(iconLayout,0); - } - - const QString text (i18n("Konqueror did not close correctly. Would you like to restore these previous sessions?")); - QLabel *messageLabel = new QLabel(text, mainWidget); - Qt::TextInteractionFlags flags = (Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); - messageLabel->setTextInteractionFlags(flags); - messageLabel->setWordWrap(true); - - hLayout->addSpacing(KDialog::spacingHint()); - hLayout->addWidget(messageLabel,5); - - QTreeWidget* treeWidget = 0; - if (!sessionFilePaths.isEmpty()) { - treeWidget = new QTreeWidget(mainWidget); - treeWidget->setHeader(0); - treeWidget->setHeaderHidden(true); - treeWidget->setToolTip(i18nc("@tooltip:session list", "Uncheck the sessions you do not want to be restored")); - - QStyleOptionViewItem styleOption; - styleOption.initFrom(treeWidget); - QFontMetrics fm(styleOption.font); - int w = treeWidget->width(); - const QRect desktop = KGlobalSettings::desktopGeometry(this); - - // Collect info from the sessions to restore - Q_FOREACH(const QString& sessionFile, sessionFilePaths) { - kDebug() << sessionFile; - QTreeWidgetItem* windowItem = 0; - const KConfig config(sessionFile, KConfig::SimpleConfig); - const QList groups = windowConfigGroups(config); - Q_FOREACH(const KConfigGroup& group, groups) { - // To avoid a recursive search, let's do linear search on Foo_CurrentHistoryItem=1 - Q_FOREACH(const QString& key, group.keyList()) { - if (key.endsWith(QLatin1String("_CurrentHistoryItem"))) { - const QString viewId = key.left(key.length() - qstrlen("_CurrentHistoryItem")); - const QString historyIndex = group.readEntry(key, QString()); - const QString prefix = "HistoryItem" + viewId + '_' + historyIndex; - // Ignore the sidebar views - if (group.readEntry(prefix + "StrServiceName", QString()).startsWith("konq_sidebar")) - continue; - const QString url = group.readEntry(prefix + "Url", QString()); - const QString title = group.readEntry(prefix + "Title", QString()); - kDebug() << viewId << url << title; - const QString displayText = (title.trimmed().isEmpty() ? url : title); - if (!displayText.isEmpty()) { - if (!windowItem) { - windowItem = new QTreeWidgetItem(treeWidget); - const int index = sessionFilePaths.indexOf(sessionFile) + 1; - windowItem->setText(0, i18nc("@item:treewidget", "Window %1", index)); - windowItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable); - windowItem->setCheckState(0, Qt::Checked); - windowItem->setExpanded(true); - } - QTreeWidgetItem* item = new QTreeWidgetItem (windowItem); - item->setText(0, displayText); - item->setData(0, Qt::UserRole, viewIdFor(sessionFile, viewId)); - item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable); - item->setCheckState(0, Qt::Checked); - w = qMax(w, fm.width(displayText)); - m_sessionItemsCount++; - } - } - } - } - - if (windowItem) { - m_checkedSessionItems.insert(windowItem, windowItem->childCount()); - } - } - - const int borderWidth = treeWidget->width() - treeWidget->viewport()->width() + treeWidget->verticalScrollBar()->height(); - w += borderWidth; - if (w > desktop.width() * 0.85) { // limit treeWidget size to 85% of screen width - w = qRound(desktop.width() * 0.85); - } - treeWidget->setMinimumWidth(w); - mainLayout->addWidget(treeWidget, 50); - treeWidget->setSelectionMode(QTreeWidget::NoSelection); - messageLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); - } - - // Do not connect the itemChanged signal until after the treewidget - // is completely populated to prevent the firing of the itemChanged - // signal while in the process of adding the original session items. - if (treeWidget && treeWidget->topLevelItemCount() > 0) { - connect(treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)), - this, SLOT(slotItemChanged(QTreeWidgetItem*,int))); - } - - QCheckBox* checkbox = new QCheckBox(i18n("Do not ask again"), mainWidget); - connect(checkbox, SIGNAL(clicked(bool)), this, SLOT(slotClicked(bool))); - mainLayout->addWidget(checkbox); - - setMainWidget(mainWidget); -} - -SessionRestoreDialog::~SessionRestoreDialog() -{ -} - -QStringList SessionRestoreDialog::discardedSessionList() const -{ - return m_discardedSessionList; -} - -bool SessionRestoreDialog::isDontShowChecked() const -{ - return m_dontShowChecked; -} - -void SessionRestoreDialog::slotClicked(bool checked) -{ - m_dontShowChecked = checked; -} - -static void setCheckState(QTreeWidgetItem* item, int column, Qt::CheckState state) -{ - const bool blocked = item->treeWidget()->blockSignals(true); - item->setCheckState(column, state); - item->treeWidget()->blockSignals(blocked); -} - -void SessionRestoreDialog::slotItemChanged(QTreeWidgetItem* item, int column) -{ - Q_ASSERT(item); - - const int itemChildCount = item->childCount(); - QTreeWidgetItem* parentItem = 0; - - const bool blocked = item->treeWidget()->blockSignals(true); - if (itemChildCount > 0) { - parentItem = item; - for (int i = 0; i < itemChildCount; ++i) { - QTreeWidgetItem* childItem = item->child(i); - if (childItem) { - childItem->setCheckState(column, item->checkState(column)); - switch (childItem->checkState(column)) { - case Qt::Checked: - m_sessionItemsCount++; - m_discardedSessionList.removeAll(childItem->data(column, Qt::UserRole).toString()); - m_checkedSessionItems[item]++; - break; - case Qt::Unchecked: - m_sessionItemsCount--; - m_discardedSessionList.append(childItem->data(column, Qt::UserRole).toString()); - m_checkedSessionItems[item]--; - break; - default: - break; - } - } - } - } else { - parentItem = item->parent(); - switch (item->checkState(column)) { - case Qt::Checked: - m_sessionItemsCount++; - m_discardedSessionList.removeAll(item->data(column, Qt::UserRole).toString()); - m_checkedSessionItems[parentItem]++; - break; - case Qt::Unchecked: - m_sessionItemsCount--; - m_discardedSessionList.append(item->data(column, Qt::UserRole).toString()); - m_checkedSessionItems[parentItem]--; - break; - default: - break; - } - } - - const int numCheckSessions = m_checkedSessionItems.value(parentItem); - switch (parentItem->checkState(column)) { - case Qt::Checked: - if (numCheckSessions == 0) { - parentItem->setCheckState(column, Qt::Unchecked); - } - case Qt::Unchecked: - if (numCheckSessions > 0) { - parentItem->setCheckState(column, Qt::Checked); - } - default: - break; - } - - enableButton(KDialog::Yes, m_sessionItemsCount > 0); - item->treeWidget()->blockSignals(blocked); -} - -void SessionRestoreDialog::saveDontShow(const QString& dontShowAgainName, int result) -{ - if (dontShowAgainName.isEmpty()) { - return; - } - - KConfigGroup::WriteConfigFlags flags = KConfig::Persistent; - if (dontShowAgainName[0] == ':') { - flags |= KConfigGroup::Global; - } - - KConfigGroup cg(KGlobal::config().data(), "Notification Messages"); - cg.writeEntry( dontShowAgainName, result==Yes, flags ); - cg.sync(); -} - -bool SessionRestoreDialog::shouldBeShown(const QString& dontShowAgainName, int* result) -{ - if (dontShowAgainName.isEmpty()) { - return true; - } - - KConfigGroup cg(KGlobal::config().data(), "Notification Messages"); - const QString dontAsk = cg.readEntry(dontShowAgainName, QString()).toLower(); - - if (dontAsk == "yes" || dontAsk == "true") { - if (result) { - *result = Yes; - } - return false; - } - - if (dontAsk == "no" || dontAsk == "false") { - if (result) { - *result = No; - } - return false; - } - - return true; -} - KonqSessionManager::KonqSessionManager() : m_autosaveDir(KStandardDirs::locateLocal("appdata", "autosave")) - , m_autosaveEnabled(false) // so that enableAutosave works { // Initialize dbus interfaces new KonqSessionManagerAdaptor ( this ); @@ -378,6 +87,7 @@ KonqSessionManager::KonqSessionManager() connect( &m_autoSaveTimer, SIGNAL(timeout()), this, SLOT(autoSaveSession()) ); } + m_autosaveEnabled = false; // so that enableAutosave works enableAutosave(); } @@ -551,6 +261,17 @@ void KonqSessionManager::restoreSessions(const QString &sessionsDir, bool } } +static const QList windowConfigGroups(const KConfig& config) +{ + QList groups; + KConfigGroup generalGroup(&config, "General"); + const int size = generalGroup.readEntry("Number of Windows", 0); + for(int i = 0; i < size; i++) { + groups << KConfigGroup(&config, "Window" + QString::number(i)); + } + return groups; +} + void KonqSessionManager::restoreSession(const QString &sessionFilePath, bool openTabsInsideCurrentWindow, KonqMainWindow *parent) { @@ -567,30 +288,6 @@ void KonqSessionManager::restoreSession(const QString &sessionFilePath, bool } } -static void removeDiscardedSessions(const QStringList& sessionFiles, const QStringList& discardedSessions) -{ - if (discardedSessions.isEmpty()) { - return; - } - - Q_FOREACH(const QString& sessionFile, sessionFiles) { - const KConfig config(sessionFile, KConfig::SimpleConfig); - QList groups = windowConfigGroups(config); - for (int i = 0, count = groups.count(); i < count; ++i) { - KConfigGroup& group = groups[i]; - const QString rootItem = group.readEntry("RootItem", "empty"); - const QString viewsKey (rootItem + QLatin1String("_Children")); - QStringList views = group.readEntry(viewsKey, QStringList()); - QMutableStringListIterator it (views); - while (it.hasNext()) { - if (discardedSessions.contains(viewIdFor(sessionFile, it.next()))) { - it.remove(); - } - } - group.writeEntry(viewsKey, views); - } - } -} bool KonqSessionManager::askUserToRestoreAutosavedAbandonedSessions() { @@ -598,30 +295,52 @@ bool KonqSessionManager::askUserToRestoreAutosavedAbandonedSessions() if(sessionFilePaths.isEmpty()) return false; - disableAutosave(); - - int result; - QStringList discardedSessionList; - const QLatin1String dontAskAgainName ("Restore session when konqueror didn't close correctly"); - - if (SessionRestoreDialog::shouldBeShown(dontAskAgainName, &result)) { - SessionRestoreDialog* restoreDlg = new SessionRestoreDialog(sessionFilePaths); - result = restoreDlg->exec(); - discardedSessionList = restoreDlg->discardedSessionList(); - if (restoreDlg->isDontShowChecked()) { - SessionRestoreDialog::saveDontShow(dontAskAgainName, result); + QStringList detailsList; + // Collect info from the sessions to restore + Q_FOREACH(const QString& sessionFile, sessionFilePaths) { + kDebug() << sessionFile; + const KConfig config(sessionFile, KConfig::SimpleConfig); + const QList groups = windowConfigGroups(config); + Q_FOREACH(const KConfigGroup& group, groups) { + // To avoid a recursive search, let's do linear search on Foo_CurrentHistoryItem=1 + Q_FOREACH(const QString& key, group.keyList()) { + if (key.endsWith("_CurrentHistoryItem")) { + const QString viewId = key.left(key.length() - strlen("_CurrentHistoryItem")); + const QString historyIndex = group.readEntry(key, QString()); + const QString prefix = "HistoryItem" + viewId + '_' + historyIndex; + // Ignore the sidebar views + if (group.readEntry(prefix + "StrServiceName", QString()).startsWith("konq_sidebar")) + continue; + const QString url = group.readEntry(prefix + "Url", QString()); + const QString title = group.readEntry(prefix + "Title", QString()); + kDebug() << viewId << url << title; + if (title.trimmed().isEmpty()) { + detailsList << url; + } else { + detailsList << title; + } + } + } } - delete restoreDlg; } - switch (result) { - case KDialog::Yes: - // Remove the discarded session list files. - removeDiscardedSessions(sessionFilePaths, discardedSessionList); + disableAutosave(); + + switch(KMessageBox::warningYesNoCancelList(0, // there is no questionYesNoCancelList + i18n("Konqueror did not close correctly. Would you like to restore the previous session?"), + detailsList, + i18nc("@title:window", "Restore Session?"), + KGuiItem(i18n("Restore Session"), "window-new"), + KGuiItem(i18n("Do Not Restore"), "dialog-close"), + KGuiItem(i18n("Ask Me Later"), "chronometer"), + "Restore session when konqueror didn't close correctly" + )) + { + case KMessageBox::Yes: restoreSessions(sessionFilePaths); enableAutosave(); return true; - case KDialog::No: + case KMessageBox::No: deleteOwnedSessions(); enableAutosave(); return false; @@ -630,7 +349,8 @@ bool KonqSessionManager::askUserToRestoreAutosavedAbandonedSessions() QDirIterator it(dirForMyOwnedSessionFiles(), QDir::Writable|QDir::Files); - while (it.hasNext()) { + while (it.hasNext()) + { it.next(); // remove ownership of the abandoned file QFile::rename(it.filePath(), m_autosaveDir + '/' + it.fileName()); diff --git a/konqueror/src/konqsessionmanager.h b/konqueror/src/konqsessionmanager.h index d3103ac36a..ee629e4664 100644 --- a/konqueror/src/konqsessionmanager.h +++ b/konqueror/src/konqsessionmanager.h @@ -27,61 +27,10 @@ #include #include -#include #include class QDBusMessage; class KonqMainWindow; -class QTreeWidgetItem; - -class SessionRestoreDialog : public KDialog -{ - Q_OBJECT -public: - explicit SessionRestoreDialog(const QStringList& sessionFilePaths, QWidget* parent=0); - virtual ~SessionRestoreDialog(); - - /** - * Returns the list of session discarded/unselected by the user. - */ - QStringList discardedSessionList() const; - - /** - * Returns true if the don't show checkbox is checked. - */ - bool isDontShowChecked() const; - - /** - * Returns true if the corresponding session restore dialog should be shown. - * - * @param dontShowAgainName the name that identify the session restore dialog box. - * @param result if not null, it will be set to the result that was chosen the last - * time the dialog box was shown. This is only useful if the restore dialog box should - * be shown. - */ - static bool shouldBeShown(const QString &dontShowAgainName, int* result); - - /** - * Save the fact that the session restore dialog should not be shown again. - * - * @param dontShowAgainName the name that identify the session restore dialog. If - * empty, this method does nothing. - * @param result the value (Yes or No) that should be used as the result - * for the message box. - */ - static void saveDontShow(const QString &dontShowAgainName, int result); - -private Q_SLOTS: - void slotClicked(bool); - void slotItemChanged(QTreeWidgetItem*, int); - -private: - QStringList m_discardedSessionList; - QHash m_checkedSessionItems; - int m_sessionItemsCount; - bool m_dontShowChecked; -}; - /** * This class is a singleton. It does some session related tasks: From fe8b9eafcb938ba06ed7cc4b7494dc33addea1ab Mon Sep 17 00:00:00 2001 From: Ignat Semenov Date: Sat, 13 Oct 2012 00:43:49 +0400 Subject: [PATCH 5/8] check if the model index list is empty in PopupView::contextMenuRequest TODO: Context menu code is duplicated between FolderView and PopupView, and needs to be factored out. BUG:292127 FIXED-IN:4.9.3 --- plasma/applets/folderview/popupview.cpp | 11 ++++++++++- plasma/applets/folderview/popupview.h | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/plasma/applets/folderview/popupview.cpp b/plasma/applets/folderview/popupview.cpp index 99aa1fd8bd..e909653937 100644 --- a/plasma/applets/folderview/popupview.cpp +++ b/plasma/applets/folderview/popupview.cpp @@ -296,13 +296,22 @@ void PopupView::createActions() m_actionCollection.addAction("empty_trash", emptyTrash); } -void PopupView::contextMenuRequest(QWidget *widget, const QPoint &screenPos) +void PopupView::contextMenuRequest(QWidget* widget, const QPoint& screenPos) +{ + showContextMenu(widget, screenPos, m_selectionModel->selectedIndexes()); +} + +void PopupView::showContextMenu(QWidget *widget, const QPoint &screenPos, const QList &indexes) { Q_UNUSED(widget) // contextMenuRequest is only called from the icon view, which is created in init() // which mean m_model should always be initialized Q_ASSERT(m_model); + if (indexes.isEmpty()) { + return; + } + if (m_actionCollection.isEmpty()) { createActions(); } diff --git a/plasma/applets/folderview/popupview.h b/plasma/applets/folderview/popupview.h index 375db7290c..5c1a010888 100644 --- a/plasma/applets/folderview/popupview.h +++ b/plasma/applets/folderview/popupview.h @@ -76,6 +76,7 @@ private: void createActions(); bool callOnParent(const char *method); KUrl::List selectedUrls() const; + void showContextMenu(QWidget *widget, const QPoint &pos, const QList &indexes); private slots: void init(); From f8309bec7316e6bb6ff90b76cc99c798ff045f6f Mon Sep 17 00:00:00 2001 From: Dawit Alemayehu Date: Thu, 27 Sep 2012 02:08:29 -0400 Subject: [PATCH 6/8] If the "Middle click on tab to close" option is checked, do not select the tab when the MMB is clicked on it. Instead simply close the tab. BUG: 264058 FIXED-IN: 4.9.3 REVIEW: 106615 --- konqueror/src/konqtabs.cpp | 45 +++++++++++++++++++++++++++----------- konqueror/src/konqtabs.h | 7 ++++++ 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/konqueror/src/konqtabs.cpp b/konqueror/src/konqtabs.cpp index 611659fa91..2a6c894758 100644 --- a/konqueror/src/konqtabs.cpp +++ b/konqueror/src/konqtabs.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -43,9 +44,7 @@ #include #include #include -#include - -#include +#include //################################################################### @@ -134,7 +133,10 @@ KonqFrameTabs::KonqFrameTabs(QWidget* parent, KonqFrameContainerBase* parentCont connect( this, SIGNAL(initiateDrag(QWidget*)), SLOT(slotInitiateDrag(QWidget*)) ); - +#ifdef QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) +#pragma message("KF5: revert the commit that introduced this line") +#endif + tabBar()->installEventFilter(this); initPopupMenu(); } @@ -382,15 +384,11 @@ void KonqFrameTabs::slotMouseMiddleClick() void KonqFrameTabs::slotMouseMiddleClick(QWidget *w) { - if (KonqSettings::mouseMiddleClickClosesTab()) { - slotCloseRequest(w); - } else { - KUrl filteredURL(KonqMisc::konqFilteredURL(m_pViewManager->mainWindow(), QApplication::clipboard()->text(QClipboard::Selection))); - if (filteredURL.isValid() && filteredURL.protocol() != QLatin1String("error")) { - KonqFrameBase* frame = dynamic_cast(w); - if (frame) { - m_pViewManager->mainWindow()->openUrl(frame->activeChildView(), filteredURL); - } + KUrl filteredURL(KonqMisc::konqFilteredURL(m_pViewManager->mainWindow(), QApplication::clipboard()->text(QClipboard::Selection))); + if (filteredURL.isValid() && filteredURL.protocol() != QLatin1String("error")) { + KonqFrameBase* frame = dynamic_cast(w); + if (frame) { + m_pViewManager->mainWindow()->openUrl(frame->activeChildView(), filteredURL); } } } @@ -601,4 +599,25 @@ KonqFrameBase* KonqFrameTabs::currentTab() const return tabAt(currentIndex()); } +bool KonqFrameTabs::eventFilter(QObject* watched, QEvent* event) +{ + if (KonqSettings::mouseMiddleClickClosesTab()) { + KTabBar* bar = qobject_cast(tabBar()); + if (watched == bar && + (event->type() == QEvent::MouseButtonPress || + event->type() == QEvent::MouseButtonRelease)) { + QMouseEvent* e = static_cast(event); + if (e->button() == Qt::MidButton) { + if (event->type() == QEvent::MouseButtonRelease) { + const int index = bar->selectTab(e->pos()); + slotCloseRequest(widget(index)); + } + e->accept(); + return true; + } + } + } + return KTabWidget::eventFilter(watched, event); +} + #include "konqtabs.moc" diff --git a/konqueror/src/konqtabs.h b/konqueror/src/konqtabs.h index 4b6f1f102f..3d050e5f81 100644 --- a/konqueror/src/konqtabs.h +++ b/konqueror/src/konqtabs.h @@ -100,6 +100,13 @@ public: */ int tabIndexContaining(KonqFrameBase* frame) const; + /** + * Implemented to catch MMB click when KonqSettings::mouseMiddleClickClosesTab() + * returns true so that the tab can be properly closed without being activated + * first. + */ + virtual bool eventFilter(QObject*, QEvent*); + public Q_SLOTS: void slotCurrentChanged( int index ); void setAlwaysTabbedMode( bool ); From 831663a092909e7f9e0bb9ddd9d1352403b7572a Mon Sep 17 00:00:00 2001 From: Luigi Toscano Date: Sat, 13 Oct 2012 01:55:06 +0200 Subject: [PATCH 7/8] docs: fix s and s --- doc/dolphin/index.docbook | 2 +- doc/kdepasswd/index.docbook | 2 +- doc/kfind/index.docbook | 2 +- doc/konqueror/index.docbook | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/dolphin/index.docbook b/doc/dolphin/index.docbook index 4916e8e0ec..f1eb24a10f 100644 --- a/doc/dolphin/index.docbook +++ b/doc/dolphin/index.docbook @@ -9,7 +9,7 @@ - + The &dolphin; Handbook diff --git a/doc/kdepasswd/index.docbook b/doc/kdepasswd/index.docbook index 30514fca13..7852d13ba3 100644 --- a/doc/kdepasswd/index.docbook +++ b/doc/kdepasswd/index.docbook @@ -6,7 +6,7 @@ ]>
Password & User Account -
+ Michael diff --git a/doc/kfind/index.docbook b/doc/kfind/index.docbook index ba611e285a..6b5b404477 100644 --- a/doc/kfind/index.docbook +++ b/doc/kfind/index.docbook @@ -9,7 +9,7 @@ - + The &kfind; Handbook diff --git a/doc/konqueror/index.docbook b/doc/konqueror/index.docbook index 0d34c6b943..3d9823a233 100644 --- a/doc/konqueror/index.docbook +++ b/doc/konqueror/index.docbook @@ -24,7 +24,7 @@ - + The &konqueror; Handbook From b65a026e91f147febd5b1a4943056e9082c790a7 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Sat, 13 Oct 2012 09:26:57 +0200 Subject: [PATCH 8/8] docs: remove comflicting id's --- doc/kfind/index.docbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/kfind/index.docbook b/doc/kfind/index.docbook index 6b5b404477..5a76d0a44e 100644 --- a/doc/kfind/index.docbook +++ b/doc/kfind/index.docbook @@ -7,7 +7,7 @@ ]> - + The &kfind; Handbook