diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 589a32f5..5b366c64 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,219 +1,226 @@ # cmake-options : -DCMAKE_DISABLE_FIND_PACKAGE_LibKonq=TRUE or FALSE; default is FALSE add_definitions(-DTRANSLATION_DOMAIN=\"konsole\") # When Qt5.9+ is required, consider using QOperatingSystemVersion ### Too many crashes/issues with detaching on MacOSX IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(ENABLE_DETACHING 0) else() set(ENABLE_DETACHING 1) endif() ### Handle DragonFlyBSD here instead of using __DragonFly__ IF(${CMAKE_SYSTEM_NAME} MATCHES "DragonFly") set(HAVE_OS_DRAGONFLYBSD 1) else() set(HAVE_OS_DRAGONFLYBSD 0) endif() include(CheckIncludeFiles) include(ECMAddAppIcon) configure_file(config-konsole.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-konsole.h) ### Tests if(BUILD_TESTING) find_package(Qt5Test ${QT_MIN_VERSION} CONFIG REQUIRED) add_subdirectory(autotests) add_subdirectory(tests) endif() ### Security concerns about sendText and runCommand dbus methods being public option(REMOVE_SENDTEXT_RUNCOMMAND_DBUS_METHODS "Konsole: remove sendText and runCommand dbus methods" OFF) ### Development tools option(KONSOLE_BUILD_FONTEMBEDDER "Konsole: build fontembedder executable" OFF) option(KONSOLE_GENERATE_LINEFONT "Konsole: regenerate LineFont file" OFF) option(KONSOLE_BUILD_UNI2CHARACTERWIDTH "Konsole: build uni2characterwidth executable" OFF) ### Konsole source files shared between embedded terminal and main application # qdbuscpp2xml -m Session.h -o org.kde.konsole.Session.xml # qdbuscpp2xml -M -s ViewManager.h -o org.kde.konsole.Konsole.xml # Generate dbus .xml files; do not store .xml in source folder qt5_generate_dbus_interface(Session.h org.kde.konsole.Session.xml OPTIONS -m) qt5_generate_dbus_interface(ViewManager.h org.kde.konsole.Window.xml OPTIONS -m) qt5_add_dbus_adaptor(sessionadaptors_SRCS ${CMAKE_CURRENT_BINARY_DIR}/org.kde.konsole.Session.xml Session.h Konsole::Session) qt5_add_dbus_adaptor(windowadaptors_SRCS ${CMAKE_CURRENT_BINARY_DIR}/org.kde.konsole.Window.xml ViewManager.h Konsole::ViewManager) set(konsoleprivate_SRCS ${sessionadaptors_SRCS} ${windowadaptors_SRCS} BookmarkHandler.cpp ColorScheme.cpp ColorSchemeManager.cpp ColorSchemeEditor.cpp CopyInputDialog.cpp EditProfileDialog.cpp + FontDialog.cpp Emulation.cpp DetachableTabBar.cpp Filter.cpp History.cpp HistorySizeDialog.cpp HistorySizeWidget.cpp IncrementalSearchBar.cpp KeyBindingEditor.cpp KeyboardTranslator.cpp KeyboardTranslatorManager.cpp ProcessInfo.cpp Profile.cpp ProfileList.cpp ProfileReader.cpp ProfileWriter.cpp ProfileManager.cpp Pty.cpp RenameTabDialog.cpp RenameTabWidget.cpp SaveHistoryTask.cpp SearchHistoryTask.cpp Screen.cpp ScreenWindow.cpp ScrollState.cpp Session.cpp SessionController.cpp SessionManager.cpp SessionListModel.cpp SessionTask.cpp ShellCommand.cpp TabTitleFormatButton.cpp TerminalCharacterDecoder.cpp ExtendedCharTable.cpp TerminalDisplay.cpp TerminalDisplayAccessible.cpp ViewContainer.cpp ViewManager.cpp ViewProperties.cpp ViewSplitter.cpp Vt102Emulation.cpp ZModemDialog.cpp PrintOptions.cpp WindowSystemInfo.cpp CharacterWidth.cpp ${CMAKE_CURRENT_BINARY_DIR}/org.kde.konsole.Window.xml ${CMAKE_CURRENT_BINARY_DIR}/org.kde.konsole.Session.xml) ecm_qt_declare_logging_category(konsoleprivate_SRCS HEADER konsoledebug.h IDENTIFIER KonsoleDebug CATEGORY_NAME org.kde.konsole) kconfig_add_kcfg_files(konsoleprivate_SRCS settings/KonsoleSettings.kcfgc) set(konsole_LIBS KF5::XmlGui Qt5::PrintSupport Qt5::Xml KF5::Notifications KF5::WindowSystem KF5::TextWidgets KF5::GuiAddons KF5::IconThemes KF5::Bookmarks KF5::I18n KF5::Pty KF5::KIOWidgets KF5::DBusAddons KF5::GlobalAccel KF5::NewStuff ) if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") #kinfo_getfile() is in libutil list(APPEND konsole_LIBS util) endif() ### Konsole Application ki18n_wrap_ui(konsoleprivate_SRCS ColorSchemeEditor.ui CopyInputDialog.ui - EditProfileDialog.ui + EditProfileGeneralPage.ui + EditProfileTabsPage.ui + EditProfileAppearancePage.ui + EditProfileScrollingPage.ui + EditProfileKeyboardPage.ui + EditProfileMousePage.ui + EditProfileAdvancedPage.ui KeyBindingEditor.ui RenameTabDialog.ui RenameTabWidget.ui HistorySizeDialog.ui HistorySizeWidget.ui PrintOptions.ui settings/FileLocationSettings.ui settings/GeneralSettings.ui settings/PartInfo.ui settings/ProfileSettings.ui settings/TabBarSettings.ui) # add the resource files for the ui files qt5_add_resources( konsoleprivate_SRCS ../desktop/konsole.qrc) add_library(konsoleprivate ${konsoleprivate_SRCS}) generate_export_header(konsoleprivate BASE_NAME konsoleprivate) target_link_libraries(konsoleprivate PUBLIC ${konsole_LIBS}) set_target_properties(konsoleprivate PROPERTIES VERSION ${KONSOLEPRIVATE_VERSION_STRING} SOVERSION ${KONSOLEPRIVATE_SOVERSION} ) install(TARGETS konsoleprivate ${KDE_INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP) set(konsole_KDEINIT_SRCS Application.cpp MainWindow.cpp main.cpp settings/FileLocationSettings.cpp settings/GeneralSettings.cpp settings/ProfileSettings.cpp settings/TabBarSettings.cpp) # Sets the icon on Windows and OSX file(GLOB ICONS_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/../data/icons/*.png") ecm_add_app_icon(kdeinit_konsole ICONS ${ICONS_SRCS}) kf5_add_kdeinit_executable(konsole ${konsole_KDEINIT_SRCS}) target_link_libraries(kdeinit_konsole konsoleprivate KF5::XmlGui KF5::WindowSystem KF5::Bookmarks KF5::I18n KF5::KIOWidgets KF5::NotifyConfig KF5::Crash ) if(APPLE) set_target_properties(konsole PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER "org.kde.konsole" MACOSX_BUNDLE_BUNDLE_NAME "Konsole" MACOSX_BUNDLE_DISPLAY_NAME "Konsole" MACOSX_BUNDLE_INFO_STRING "Konsole, the KDE terminal emulator" MACOSX_BUNDLE_LONG_VERSION_STRING "Konsole ${KDE_APPLICATIONS_VERSION}" MACOSX_BUNDLE_SHORT_VERSION_STRING "${KDE_APPLICATIONS_VERSION_MAJOR}.${KDE_APPLICATIONS_VERSION_MINOR}" MACOSX_BUNDLE_BUNDLE_VERSION "${KDE_APPLICATIONS_VERSION}" MACOSX_BUNDLE_COPYRIGHT "1997-2016 The Konsole Developers") endif() install(TARGETS kdeinit_konsole konsole ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) ### Embedded Konsole KPart set(konsolepart_PART_SRCS Part.cpp settings/PartInfo.cpp settings/ProfileSettings.cpp) add_library(konsolepart MODULE ${konsolepart_PART_SRCS}) generate_export_header(konsolepart BASE_NAME konsole) kcoreaddons_desktop_to_json(konsolepart ../desktop/konsolepart.desktop) set_target_properties(konsolepart PROPERTIES DEFINE_SYMBOL KONSOLE_PART) target_link_libraries(konsolepart KF5::Parts KF5::XmlGui konsoleprivate) install(TARGETS konsolepart DESTINATION ${KDE_INSTALL_PLUGINDIR}) diff --git a/src/CharacterColor.h b/src/CharacterColor.h index 12f79055..83d5f6e7 100644 --- a/src/CharacterColor.h +++ b/src/CharacterColor.h @@ -1,253 +1,256 @@ /* This file is part of Konsole, KDE's terminal. Copyright 2007-2008 by Robert Knight Copyright 1997,1998 by Lars Doelle This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef CHARACTERCOLOR_H #define CHARACTERCOLOR_H // Qt #include namespace Konsole { /** * An entry in a terminal display's color palette. * * A color palette is an array of 16 ColorEntry instances which map * system color indexes (from 0 to 15) into actual colors. */ typedef QColor ColorEntry; // Attributed Character Representations /////////////////////////////// // Colors #define BASE_COLORS (2+8) #define INTENSITIES 3 #define TABLE_COLORS (INTENSITIES*BASE_COLORS) #define DEFAULT_FORE_COLOR 0 #define DEFAULT_BACK_COLOR 1 /* CharacterColor is a union of the various color spaces. Assignment is as follows: Type - Space - Values 0 - Undefined - u: 0, v:0 w:0 1 - Default - u: 0..1 v:intense w:0 2 - System - u: 0..7 v:intense w:0 3 - Index(256) - u: 16..255 v:0 w:0 4 - RGB - u: 0..255 v:0..256 w:0..256 ``intense'' is either 0 (normal), 1 (intensive), or 2 (faint) Default color space has two separate colors, namely default foreground and default background color. */ #define COLOR_SPACE_UNDEFINED 0 #define COLOR_SPACE_DEFAULT 1 #define COLOR_SPACE_SYSTEM 2 #define COLOR_SPACE_256 3 #define COLOR_SPACE_RGB 4 /** * Describes the color of a single character in the terminal. */ class CharacterColor { friend class Character; public: /** Constructs a new CharacterColor whose color and color space are undefined. */ CharacterColor() : _colorSpace(COLOR_SPACE_UNDEFINED), _u(0), _v(0), _w(0) { } /** * Constructs a new CharacterColor using the specified @p colorSpace and with * color value @p co * * The meaning of @p co depends on the @p colorSpace used. * * TODO : Document how @p co relates to @p colorSpace * * TODO : Add documentation about available color spaces. */ CharacterColor(quint8 colorSpace, int co) : _colorSpace(colorSpace), _u(0), _v(0), _w(0) { switch (colorSpace) { case COLOR_SPACE_DEFAULT: _u = co & 1; break; case COLOR_SPACE_SYSTEM: _u = co & 7; _v = (co >> 3) & 3; break; case COLOR_SPACE_256: _u = co & 255; break; case COLOR_SPACE_RGB: _u = co >> 16; _v = co >> 8; _w = co; break; default: _colorSpace = COLOR_SPACE_UNDEFINED; } } + quint8 colorSpace() { return _colorSpace; } + void termColor(int *u, int *v, int *w) { *u = _u; *v = _v; *w = _w; } + /** * Returns true if this character color entry is valid. */ bool isValid() const { return _colorSpace != COLOR_SPACE_UNDEFINED; } /** * Set this color as an intensive system color. * * This is only applicable if the color is using the COLOR_SPACE_DEFAULT or COLOR_SPACE_SYSTEM * color spaces. */ void setIntensive(); /** * Set this color as a faint system color. * * This is only applicable if the color is using the COLOR_SPACE_DEFAULT or COLOR_SPACE_SYSTEM * color spaces. */ void setFaint(); /** * Returns the color within the specified color @p base * * The @p base is only used if this color is one of the 16 system colors, otherwise * it is ignored. */ QColor color(const ColorEntry *base) const; /** * Compares two colors and returns true if they represent the same color value and * use the same color space. */ friend bool operator ==(const CharacterColor &a, const CharacterColor &b); /** * Compares two colors and returns true if they represent different color values * or use different color spaces. */ friend bool operator !=(const CharacterColor &a, const CharacterColor &b); private: quint8 _colorSpace; // bytes storing the character color quint8 _u; quint8 _v; quint8 _w; }; inline bool operator ==(const CharacterColor &a, const CharacterColor &b) { return a._colorSpace == b._colorSpace && a._u == b._u && a._v == b._v && a._w == b._w; } inline bool operator !=(const CharacterColor &a, const CharacterColor &b) { return !operator==(a, b); } inline const QColor color256(quint8 u, const ColorEntry *base) { // 0.. 16: system colors if (u < 8) { return base[u + 2]; } u -= 8; if (u < 8) { return base[u + 2 + BASE_COLORS]; } u -= 8; // 16..231: 6x6x6 rgb color cube if (u < 216) { return QColor(((u / 36) % 6) ? (40 * ((u / 36) % 6) + 55) : 0, ((u / 6) % 6) ? (40 * ((u / 6) % 6) + 55) : 0, ((u / 1) % 6) ? (40 * ((u / 1) % 6) + 55) : 0); } u -= 216; // 232..255: gray, leaving out black and white int gray = u * 10 + 8; return QColor(gray, gray, gray); } inline QColor CharacterColor::color(const ColorEntry *base) const { switch (_colorSpace) { case COLOR_SPACE_DEFAULT: return base[_u + 0 + (_v * BASE_COLORS)]; case COLOR_SPACE_SYSTEM: return base[_u + 2 + (_v * BASE_COLORS)]; case COLOR_SPACE_256: return color256(_u, base); case COLOR_SPACE_RGB: return QColor(_u, _v, _w); case COLOR_SPACE_UNDEFINED: return QColor(); } Q_ASSERT(false); // invalid color space return QColor(); } inline void CharacterColor::setIntensive() { if (_colorSpace == COLOR_SPACE_SYSTEM || _colorSpace == COLOR_SPACE_DEFAULT) { _v = 1; } } inline void CharacterColor::setFaint() { if (_colorSpace == COLOR_SPACE_SYSTEM || _colorSpace == COLOR_SPACE_DEFAULT) { _v = 2; } } } #endif // CHARACTERCOLOR_H diff --git a/src/EditProfileAdvancedPage.ui b/src/EditProfileAdvancedPage.ui new file mode 100644 index 00000000..d752693e --- /dev/null +++ b/src/EditProfileAdvancedPage.ui @@ -0,0 +1,298 @@ + + + EditProfileAdvancedPage + + + + 0 + 0 + 400 + 400 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 6 + + + + + Key combination to show URL hints: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 0 + + + 0 + + + 0 + + + + + 6 + + + + + + 0 + 0 + + + + Shift + + + true + + + Qt::ToolButtonFollowStyle + + + + + + + + 0 + 0 + + + + Ctrl + + + true + + + Qt::ToolButtonFollowStyle + + + + + + + + 0 + 0 + + + + Alt + + + true + + + Qt::ToolButtonFollowStyle + + + + + + + + 0 + 0 + + + + Meta + + + true + + + Qt::ToolButtonFollowStyle + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 16 + + + + + + + + Miscellaneous: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Number URL hints in reverse, starting from the bottom + + + Reverse URL hint numbering + + + + + + + + 0 + 0 + + + + Allow terminal programs to create blinking sections of text + + + Allow blinking text + + + + + + + + 0 + 0 + + + + Allow the output to be suspended by pressing Ctrl+S + + + Flow control + + + + + + + + 0 + 0 + + + + Enable Bi-Directional display on terminals (valid for Arabic, Farsi or Hebrew only) + + + Bi-Directional text rendering + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 16 + + + + + + + + Default character encoding: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + selectEncodingButton + + + + + + + DEFAULTENCODING + + + + + + + + + Qt::Vertical + + + + 20 + 111 + + + + + + + + urlHintsModifierShift + urlHintsModifierCtrl + urlHintsModifierAlt + urlHintsModifierMeta + + + + \ No newline at end of file diff --git a/src/EditProfileAppearancePage.ui b/src/EditProfileAppearancePage.ui new file mode 100644 index 00000000..6f8acb9b --- /dev/null +++ b/src/EditProfileAppearancePage.ui @@ -0,0 +1,696 @@ + + + EditProfileAppearancePage + + + + 0 + 0 + 400 + 400 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + Color scheme && font + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + QAbstractItemView::ScrollPerPixel + + + + + + + 0 + + + + + 6 + + + + + Create a new color scheme based upon the selected scheme + + + New... + + + + + + + Edit the selected color scheme + + + Edit... + + + + + + + Delete the selected color scheme + + + Remove + + + + + + + Reset the selected color scheme settings to the default values + + + Defaults + + + + + + + Get New... + + + + + + + + + Qt::Vertical + + + + 20 + 20 + + + + + + + + + + + + + + 0 + 0 + + + + Font: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + Qt::PlainText + + + chooseFontButton + + + + + + + Choose... + + + + + + + Smooth fonts + + + + + + + Draw intense colors in bold font + + + + + + + Use the selected font for line characters instead of the builtin code + + + Use line characters contained in font + + + + + + + + Cursor + + + + 0 + + + + + 6 + + + + + + 0 + 0 + + + + Shape: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Block + + + cursorShape + + + + + + + I-Beam + + + cursorShape + + + + + + + Underline + + + cursorShape + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 16 + + + + + + + + + 0 + 0 + + + + Color: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + Set the cursor to match the color of the character underneath it. + + + Match current character + + + cursorColor + + + + + + + 0 + + + + + + 0 + 0 + + + + Use a custom, fixed color for the cursor + + + Custom cursor color: + + + cursorColor + + + + + + + + 0 + 0 + + + + Select the color used to draw the cursor + + + + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 16 + + + + + + + + Blinking: + + + enableBlinkingCursorButton + + + + + + + + 0 + 0 + + + + Make the cursor blink regularly + + + + + + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + Miscellaneous + + + + 0 + + + + + 6 + + + + + Terminal contents + + + + + + + 0 + 0 + + + + Line spacing: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + lineSpacingSpinner + + + + + + + 0 + + + + + The number of pixels between two lines + + + px + + + 0 + + + 20 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + Margins: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + marginsSpinner + + + + + + + 0 + + + + + px + + + 99 + + + 1 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + Align to center: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + alignToCenterButton + + + + + + + Enabled + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 16 + + + + + + + + Window: + + + + + + + Show terminal size in columns and lines in the center of window after resizing + + + Show hint for terminal size after resizing + + + + + + + Indicate whether the window is active by dimming the colors + + + Dim the colors when the window loses focus + + + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + + + + + + KColorButton + QPushButton +
kcolorbutton.h
+
+ + KMessageWidget + QFrame +
kmessagewidget.h
+ 1 +
+ + KNS3::Button + QPushButton +
KNS3/Button
+
+
+ + tabWidget + colorSchemeList + newColorSchemeButton + editColorSchemeButton + removeColorSchemeButton + resetColorSchemeButton + downloadColorSchemeButton + chooseFontButton + antialiasTextButton + boldIntenseButton + useFontLineCharactersButton + cursorShapeBlock + cursorShapeIBeam + cursorShapeUnderline + autoCursorColorButton + customCursorColorButton + customColorSelectButton + enableBlinkingCursorButton + lineSpacingSpinner + marginsSpinner + alignToCenterButton + showTerminalSizeHintButton + dimWhenInactiveCheckbox + + + + + + + +
\ No newline at end of file diff --git a/src/EditProfileDialog.cpp b/src/EditProfileDialog.cpp index 1c096925..7d18463b 100644 --- a/src/EditProfileDialog.cpp +++ b/src/EditProfileDialog.cpp @@ -1,1766 +1,1934 @@ /* Copyright 2007-2008 by Robert Knight Copyright 2018 by Harald Sitter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ // Own #include "EditProfileDialog.h" // Standard #include // Qt #include #include #include #include -#include #include #include #include #include #include #include #include #include #include #include #include +#include // KDE #include #include #include #include #include #include // Konsole +#include "ui_EditProfileGeneralPage.h" +#include "ui_EditProfileTabsPage.h" +#include "ui_EditProfileAppearancePage.h" +#include "ui_EditProfileScrollingPage.h" +#include "ui_EditProfileKeyboardPage.h" +#include "ui_EditProfileMousePage.h" +#include "ui_EditProfileAdvancedPage.h" #include "ColorSchemeManager.h" -#include "ui_EditProfileDialog.h" #include "KeyBindingEditor.h" #include "KeyboardTranslator.h" #include "KeyboardTranslatorManager.h" #include "ProfileManager.h" #include "ShellCommand.h" #include "WindowSystemInfo.h" #include "Shortcut_p.h" +#include "FontDialog.h" using namespace Konsole; -EditProfileDialog::EditProfileDialog(QWidget *parent) : - QDialog(parent), - _ui(nullptr), - _tempProfile(nullptr), - _profile(nullptr), - _pageNeedsUpdate(QVector()), - _previewedProperties(QHash()), - _delayedPreviewProperties(QHash()), - _delayedPreviewTimer(new QTimer(this)), - _colorDialog(nullptr), - mButtonBox(nullptr) +EditProfileDialog::EditProfileDialog(QWidget *parent) + : KPageDialog(parent) + , _generalUi(nullptr) + , _tabsUi(nullptr) + , _appearanceUi(nullptr) + , _scrollingUi(nullptr) + , _keyboardUi(nullptr) + , _mouseUi(nullptr) + , _advancedUi(nullptr) + , _tempProfile(nullptr) + , _profile(nullptr) + , _previewedProperties(QHash()) + , _delayedPreviewProperties(QHash()) + , _delayedPreviewTimer(new QTimer(this)) + , _colorDialog(nullptr) + , _buttonBox(nullptr) + , _fontDialog(nullptr) { setWindowTitle(i18n("Edit Profile")); - mButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel|QDialogButtonBox::Apply); - auto mainWidget = new QWidget(this); - auto mainLayout = new QVBoxLayout; - setLayout(mainLayout); - mainLayout->addWidget(mainWidget); - QPushButton *okButton = mButtonBox->button(QDialogButtonBox::Ok); + setFaceType(KPageDialog::List); + + _buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply); + setButtonBox(_buttonBox); + + QPushButton *okButton = _buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); - connect(mButtonBox, &QDialogButtonBox::accepted, this, &Konsole::EditProfileDialog::accept); - connect(mButtonBox, &QDialogButtonBox::rejected, this, &Konsole::EditProfileDialog::reject); + connect(_buttonBox, &QDialogButtonBox::accepted, this, &Konsole::EditProfileDialog::accept); + connect(_buttonBox, &QDialogButtonBox::rejected, this, &Konsole::EditProfileDialog::reject); // disable the apply button , since no modification has been made - mButtonBox->button(QDialogButtonBox::Apply)->setEnabled(false); + _buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); - connect(mButtonBox->button(QDialogButtonBox::Apply), + connect(_buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked, this, &Konsole::EditProfileDialog::apply); connect(_delayedPreviewTimer, &QTimer::timeout, this, &Konsole::EditProfileDialog::delayedPreviewActivate); - _ui = new Ui::EditProfileDialog(); - _ui->setupUi(mainWidget); - mainLayout->addWidget(mButtonBox); + // General page + + const QString generalPageName = i18nc("@title:tab Generic, common options", "General"); + auto *generalPageWidget = new QWidget(this); + _generalUi = new Ui::EditProfileGeneralPage(); + _generalUi->setupUi(generalPageWidget); + auto *generalPageItem = addPage(generalPageWidget, generalPageName); + generalPageItem->setHeader(generalPageName); + generalPageItem->setIcon(QIcon::fromTheme(QStringLiteral("utilities-terminal"))); + _pages[generalPageItem] = Page(&EditProfileDialog::setupGeneralPage); + + // Tabs page + + const QString tabsPageName = i18n("Tabs"); + auto *tabsPageWidget = new QWidget(this); + _tabsUi = new Ui::EditProfileTabsPage(); + _tabsUi->setupUi(tabsPageWidget); + auto *tabsPageItem = addPage(tabsPageWidget, tabsPageName); + tabsPageItem->setHeader(tabsPageName); + tabsPageItem->setIcon(QIcon::fromTheme(QStringLiteral("tab-duplicate"))); + _pages[tabsPageItem] = Page(&EditProfileDialog::setupTabsPage); + + LabelsAligner tabsAligner(tabsPageWidget); + tabsAligner.addLayout(dynamic_cast(_tabsUi->tabMonitoringGroup->layout())); + tabsAligner.addLayout(dynamic_cast(_tabsUi->renameTabWidget->layout())); + tabsAligner.updateLayouts(); + tabsAligner.align(); + + // Appearance page + + const QString appearancePageName = i18n("Appearance"); + auto *appearancePageWidget = new QWidget(this); + _appearanceUi = new Ui::EditProfileAppearancePage(); + _appearanceUi->setupUi(appearancePageWidget); + auto *appearancePageItem = addPage(appearancePageWidget, appearancePageName); + appearancePageItem->setHeader(appearancePageName); + appearancePageItem->setIcon(QIcon::fromTheme(QStringLiteral("kcolorchooser"))); + _pages[appearancePageItem] = Page(&EditProfileDialog::setupAppearancePage); + + LabelsAligner appearanceAligner(appearancePageWidget); + appearanceAligner.addLayout(dynamic_cast(_appearanceUi->miscTabLayout)); + appearanceAligner.addLayout(dynamic_cast(_appearanceUi->contentsGroup->layout())); + appearanceAligner.updateLayouts(); + appearanceAligner.align(); + + // Scrolling page + + const QString scrollingPageName = i18n("Scrolling"); + auto *scrollingPageWidget = new QWidget(this); + _scrollingUi = new Ui::EditProfileScrollingPage(); + _scrollingUi->setupUi(scrollingPageWidget); + auto *scrollingPageItem = addPage(scrollingPageWidget, scrollingPageName); + scrollingPageItem->setHeader(scrollingPageName); + scrollingPageItem->setIcon(QIcon::fromTheme(QStringLiteral("transform-move-vertical"))); + _pages[scrollingPageItem] = Page(&EditProfileDialog::setupScrollingPage); + + // adjust "history size" label height to match history size widget's first radio button + _scrollingUi->historySizeLabel->setFixedHeight(_scrollingUi->historySizeWidget->preferredLabelHeight()); + + // Keyboard page + + const QString keyboardPageName = i18n("Keyboard"); + const QString keyboardPageTitle = i18n("Key bindings"); + auto *keyboardPageWidget = new QWidget(this); + _keyboardUi = new Ui::EditProfileKeyboardPage(); + _keyboardUi->setupUi(keyboardPageWidget); + auto *keyboardPageItem = addPage(keyboardPageWidget, keyboardPageName); + keyboardPageItem->setHeader(keyboardPageTitle); + keyboardPageItem->setIcon(QIcon::fromTheme(QStringLiteral("input-keyboard"))); + _pages[keyboardPageItem] = Page(&EditProfileDialog::setupKeyboardPage); + + // Mouse page + + const QString mousePageName = i18n("Mouse"); + auto *mousePageWidget = new QWidget(this); + _mouseUi = new Ui::EditProfileMousePage(); + _mouseUi->setupUi(mousePageWidget); + auto *mousePageItem = addPage(mousePageWidget, mousePageName); + mousePageItem->setHeader(mousePageName); + mousePageItem->setIcon(QIcon::fromTheme(QStringLiteral("input-mouse"))); + _pages[mousePageItem] = Page(&EditProfileDialog::setupMousePage); + + // Advanced page + + const QString advancedPageName = i18nc("@title:tab Complex options", "Advanced"); + auto *advancedPageWidget = new QWidget(this); + _advancedUi = new Ui::EditProfileAdvancedPage(); + _advancedUi->setupUi(advancedPageWidget); + auto *advancedPageItem = addPage(advancedPageWidget, advancedPageName); + advancedPageItem->setHeader(advancedPageName); + advancedPageItem->setIcon(QIcon::fromTheme(QStringLiteral("configure"))); + _pages[advancedPageItem] = Page(&EditProfileDialog::setupAdvancedPage); // there are various setupXYZPage() methods to load the items // for each page and update their states to match the profile // being edited. // // these are only called when needed ( ie. when the user clicks // the tab to move to that page ). // // the _pageNeedsUpdate vector keeps track of the pages that have // not been updated since the last profile change and will need // to be refreshed when the user switches to them - _pageNeedsUpdate.resize(_ui->tabWidget->count()); - connect(_ui->tabWidget, &QTabWidget::currentChanged, this, - &Konsole::EditProfileDialog::preparePage); + connect(this, &KPageDialog::currentPageChanged, + this, &Konsole::EditProfileDialog::preparePage); + + QFontMetrics fm(font()); + const int ch = fm.width(QLatin1Char('0')); + + // Increase width a bit instead of using possible minimum + resize(sizeHint().width() + 10*ch, sizeHint().height()); createTempProfile(); } EditProfileDialog::~EditProfileDialog() { - delete _ui; + delete _generalUi; + delete _tabsUi; + delete _appearanceUi; + delete _scrollingUi; + delete _keyboardUi; + delete _mouseUi; + delete _advancedUi; } void EditProfileDialog::save() { if (_tempProfile->isEmpty()) { return; } ProfileManager::instance()->changeProfile(_profile, _tempProfile->setProperties()); // ensure that these settings are not undone by a call // to unpreview() QHashIterator iter(_tempProfile->setProperties()); while (iter.hasNext()) { iter.next(); _previewedProperties.remove(iter.key()); } createTempProfile(); - mButtonBox->button(QDialogButtonBox::Apply)->setEnabled(false); + _buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); } void EditProfileDialog::reject() { unpreviewAll(); QDialog::reject(); } void EditProfileDialog::accept() { // if the Apply button is disabled then no settings were changed // or the changes have already been saved by apply() - if (mButtonBox->button(QDialogButtonBox::Apply)->isEnabled()) { + if (_buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) { if (!isValidProfileName()) { return; } save(); } unpreviewAll(); QDialog::accept(); } void EditProfileDialog::apply() { if (!isValidProfileName()) { return; } save(); } bool EditProfileDialog::isValidProfileName() { Q_ASSERT(_profile); Q_ASSERT(_tempProfile); // check whether the user has enough permissions to save the profile QFileInfo fileInfo(_profile->path()); if (fileInfo.exists() && !fileInfo.isWritable()) { if (!_tempProfile->isPropertySet(Profile::Name) || (_tempProfile->name() == _profile->name())) { KMessageBox::sorry(this, i18n("

Konsole does not have permission to save this profile to:
\"%1\"

" "

To be able to save settings you can either change the permissions " "of the profile configuration file or change the profile name to save " "the settings to a new profile.

", _profile->path())); return false; } } const QList existingProfiles = ProfileManager::instance()->allProfiles(); QStringList otherExistingProfileNames; foreach(auto existingProfile, existingProfiles) { if (existingProfile->name() != _profile->name()) { otherExistingProfileNames.append(existingProfile->name()); } } if ((_tempProfile->isPropertySet(Profile::Name) && _tempProfile->name().isEmpty()) || (_profile->name().isEmpty() && _tempProfile->name().isEmpty())) { KMessageBox::sorry(this, i18n("

Each profile must have a name before it can be saved " "into disk.

")); // revert the name in the dialog - _ui->profileNameEdit->setText(_profile->name()); + _generalUi->profileNameEdit->setText(_profile->name()); selectProfileName(); return false; } else if (!_tempProfile->name().isEmpty() && otherExistingProfileNames.contains(_tempProfile->name())) { KMessageBox::sorry(this, i18n("

A profile with this name already exists.

")); // revert the name in the dialog - _ui->profileNameEdit->setText(_profile->name()); + _generalUi->profileNameEdit->setText(_profile->name()); selectProfileName(); return false; } else { return true; } } QString EditProfileDialog::groupProfileNames(const ProfileGroup::Ptr group, int maxLength) { QString caption; int count = group->profiles().count(); for (int i = 0; i < count; i++) { caption += group->profiles()[i]->name(); if (i < (count - 1)) { caption += QLatin1Char(','); // limit caption length to prevent very long window titles if (maxLength > 0 && caption.length() > maxLength) { caption += QLatin1String("..."); break; } } } return caption; } void EditProfileDialog::updateCaption(const Profile::Ptr profile) { const int MAX_GROUP_CAPTION_LENGTH = 25; ProfileGroup::Ptr group = profile->asGroup(); if (group && group->profiles().count() > 1) { QString caption = groupProfileNames(group, MAX_GROUP_CAPTION_LENGTH); setWindowTitle(i18np("Editing profile: %2", "Editing %1 profiles: %2", group->profiles().count(), caption)); } else { setWindowTitle(i18n("Edit Profile \"%1\"", profile->name())); } } -void EditProfileDialog::setProfile(Profile::Ptr profile) +void EditProfileDialog::setProfile(Konsole::Profile::Ptr profile) { Q_ASSERT(profile); _profile = profile; // update caption updateCaption(profile); // mark each page of the dialog as out of date // and force an update of the currently visible page // // the other pages will be updated as necessary - _pageNeedsUpdate.fill(true); - preparePage(_ui->tabWidget->currentIndex()); + for (Page &page: _pages) { + page.needsUpdate = true; + } + preparePage(currentPage()); if (_tempProfile) { createTempProfile(); } } const Profile::Ptr EditProfileDialog::lookupProfile() const { return _profile; } const QString EditProfileDialog::currentColorSchemeName() const { const QString ¤tColorSchemeName = lookupProfile()->colorScheme(); return currentColorSchemeName; } -void EditProfileDialog::preparePage(int page) +void EditProfileDialog::preparePage(KPageWidgetItem *current, KPageWidgetItem *before) { - const Profile::Ptr profile = lookupProfile(); + Q_UNUSED(before); + Q_ASSERT(current); + Q_ASSERT(_pages.contains(current)); - Q_ASSERT(_pageNeedsUpdate.count() > page); + const Profile::Ptr profile = lookupProfile(); + auto setupPage = _pages[current].setupPage; Q_ASSERT(profile); + Q_ASSERT(setupPage); - QWidget *pageWidget = _ui->tabWidget->widget(page); - - if (_pageNeedsUpdate[page]) { - if (pageWidget == _ui->generalTab) { - setupGeneralPage(profile); - } else if (pageWidget == _ui->tabsTab) { - setupTabsPage(profile); - } else if (pageWidget == _ui->appearanceTab) { - setupAppearancePage(profile); - } else if (pageWidget == _ui->scrollingTab) { - setupScrollingPage(profile); - } else if (pageWidget == _ui->keyboardTab) { - setupKeyboardPage(profile); - } else if (pageWidget == _ui->mouseTab) { - setupMousePage(profile); - } else if (pageWidget == _ui->advancedTab) { - setupAdvancedPage(profile); - } else { - Q_ASSERT(false); - } - - _pageNeedsUpdate[page] = false; + if (_pages[current].needsUpdate) { + (*this.*setupPage)(profile); + _pages[current].needsUpdate = false; } } -void EditProfileDialog::selectProfileName() +void Konsole::EditProfileDialog::selectProfileName() { - _ui->profileNameEdit->setFocus(); - _ui->profileNameEdit->selectAll(); + _generalUi->profileNameEdit->setFocus(); + _generalUi->profileNameEdit->selectAll(); } -void EditProfileDialog::setupGeneralPage(const Profile::Ptr profile) +void EditProfileDialog::setupGeneralPage(const Profile::Ptr &profile) { // basic profile options { - _ui->profileNameEdit->setPlaceholderText(i18nc("@label:textbox", "Enter descriptive label")); - ProfileGroup::Ptr group = profile->asGroup(); if (!group || group->profiles().count() < 2) { - _ui->profileNameEdit->setText(profile->name()); - _ui->profileNameEdit->setClearButtonEnabled(true); + _generalUi->profileNameEdit->setText(profile->name()); + _generalUi->profileNameEdit->setClearButtonEnabled(true); } else { - _ui->profileNameEdit->setText(groupProfileNames(group, -1)); - _ui->profileNameEdit->setEnabled(false); - _ui->profileNameLabel->setEnabled(false); + _generalUi->profileNameEdit->setText(groupProfileNames(group, -1)); + _generalUi->profileNameEdit->setEnabled(false); } } ShellCommand command(profile->command(), profile->arguments()); - _ui->commandEdit->setText(command.fullCommand()); + _generalUi->commandEdit->setText(command.fullCommand()); // If a "completion" is requested, consider changing this to KLineEdit // and using KCompletion. - _ui->initialDirEdit->setText(profile->defaultWorkingDirectory()); - _ui->initialDirEdit->setClearButtonEnabled(true); - - _ui->dirSelectButton->setIcon(QIcon::fromTheme(QStringLiteral("folder-open"))); - _ui->iconSelectButton->setIcon(QIcon::fromTheme(profile->icon())); - _ui->startInSameDirButton->setChecked(profile->startInCurrentSessionDir()); - - // terminal options - _ui->terminalColumnsEntry->setValue(profile->terminalColumns()); - _ui->terminalRowsEntry->setValue(profile->terminalRows()); - - // window options - _ui->showTerminalSizeHintButton->setChecked(profile->showTerminalSizeHint()); - _ui->dimWhenInactiveCheckbox->setChecked(profile->dimWhenInactive()); + _generalUi->initialDirEdit->setText(profile->defaultWorkingDirectory()); + _generalUi->initialDirEdit->setClearButtonEnabled(true); + _generalUi->initialDirEdit->setPlaceholderText(QStandardPaths::standardLocations(QStandardPaths::HomeLocation).value(0)); + + _generalUi->dirSelectButton->setIcon(QIcon::fromTheme(QStringLiteral("folder-open"))); + _generalUi->iconSelectButton->setIcon(QIcon::fromTheme(profile->icon())); + _generalUi->startInSameDirButton->setChecked(profile->startInCurrentSessionDir()); + + // initial terminal size + const auto rowsSuffix = ki18ncp("Suffix of the number of columns (N columns)", " column", " columns"); + const auto colsSuffix = ki18ncp("Suffix of the number of rows (N rows)", " row", " rows"); + _generalUi->terminalColumnsEntry->setValue(profile->terminalColumns()); + _generalUi->terminalRowsEntry->setValue(profile->terminalRows()); + _generalUi->terminalColumnsEntry->setSuffix(colsSuffix); + _generalUi->terminalRowsEntry->setSuffix(rowsSuffix); + // make width of initial terminal size spinboxes equal + const int sizeEntryWidth = qMax(maxSpinBoxWidth(_generalUi->terminalColumnsEntry, colsSuffix), + maxSpinBoxWidth(_generalUi->terminalRowsEntry, rowsSuffix)); + _generalUi->terminalColumnsEntry->setFixedWidth(sizeEntryWidth); + _generalUi->terminalRowsEntry->setFixedWidth(sizeEntryWidth); // signals and slots - connect(_ui->dirSelectButton, &QToolButton::clicked, this, + connect(_generalUi->dirSelectButton, &QToolButton::clicked, this, &Konsole::EditProfileDialog::selectInitialDir); - connect(_ui->iconSelectButton, &QPushButton::clicked, this, + connect(_generalUi->iconSelectButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::selectIcon); - connect(_ui->startInSameDirButton, &QCheckBox::toggled, this, + connect(_generalUi->startInSameDirButton, &QCheckBox::toggled, this, &Konsole::EditProfileDialog::startInSameDir); - connect(_ui->profileNameEdit, &QLineEdit::textChanged, this, + connect(_generalUi->profileNameEdit, &QLineEdit::textChanged, this, &Konsole::EditProfileDialog::profileNameChanged); - connect(_ui->initialDirEdit, &QLineEdit::textChanged, this, + connect(_generalUi->initialDirEdit, &QLineEdit::textChanged, this, &Konsole::EditProfileDialog::initialDirChanged); - connect(_ui->commandEdit, &QLineEdit::textChanged, this, + connect(_generalUi->commandEdit, &QLineEdit::textChanged, this, &Konsole::EditProfileDialog::commandChanged); - connect(_ui->environmentEditButton, &QPushButton::clicked, this, + connect(_generalUi->environmentEditButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::showEnvironmentEditor); - connect(_ui->terminalColumnsEntry, + connect(_generalUi->terminalColumnsEntry, static_cast(&QSpinBox::valueChanged), this, &Konsole::EditProfileDialog::terminalColumnsEntryChanged); - connect(_ui->terminalRowsEntry, static_cast(&QSpinBox::valueChanged), + connect(_generalUi->terminalRowsEntry, static_cast(&QSpinBox::valueChanged), this, &Konsole::EditProfileDialog::terminalRowsEntryChanged); - - connect(_ui->showTerminalSizeHintButton, &QCheckBox::toggled, this, - &Konsole::EditProfileDialog::showTerminalSizeHint); - - connect(_ui->dimWhenInactiveCheckbox, &QCheckBox::toggled, this, - &Konsole::EditProfileDialog::setDimWhenInactive); } void EditProfileDialog::showEnvironmentEditor() { bool ok; const Profile::Ptr profile = lookupProfile(); QStringList currentEnvironment; // The user could re-open the environment editor before clicking // OK/Apply in the parent edit profile dialog, so we make sure // to show the new environment vars if (_tempProfile->isPropertySet(Profile::Environment)) { currentEnvironment = _tempProfile->environment(); } else { currentEnvironment = profile->environment(); } QString text = QInputDialog::getMultiLineText(this, i18n("Edit Environment"), i18n("One environment variable per line"), currentEnvironment.join(QStringLiteral("\n")), &ok); QStringList newEnvironment; if (ok) { if(!text.isEmpty()) { newEnvironment = text.split(QLatin1Char('\n')); updateTempProfileProperty(Profile::Environment, newEnvironment); } else { // the user could have removed all entries so we return an empty list updateTempProfileProperty(Profile::Environment, newEnvironment); } } } -void EditProfileDialog::setupTabsPage(const Profile::Ptr profile) +void EditProfileDialog::setupTabsPage(const Profile::Ptr &profile) { // tab title format - _ui->renameTabWidget->setTabTitleText(profile->localTabTitleFormat()); - _ui->renameTabWidget->setRemoteTabTitleText(profile->remoteTabTitleFormat()); + _tabsUi->renameTabWidget->setTabTitleText(profile->localTabTitleFormat()); + _tabsUi->renameTabWidget->setRemoteTabTitleText(profile->remoteTabTitleFormat()); - connect(_ui->renameTabWidget, &Konsole::RenameTabWidget::tabTitleFormatChanged, this, + connect(_tabsUi->renameTabWidget, &Konsole::RenameTabWidget::tabTitleFormatChanged, this, &Konsole::EditProfileDialog::tabTitleFormatChanged); - connect(_ui->renameTabWidget, &Konsole::RenameTabWidget::remoteTabTitleFormatChanged, this, + connect(_tabsUi->renameTabWidget, &Konsole::RenameTabWidget::remoteTabTitleFormatChanged, this, &Konsole::EditProfileDialog::remoteTabTitleFormatChanged); // tab monitoring const int silenceSeconds = profile->silenceSeconds(); - _ui->silenceSecondsSpinner->setValue(silenceSeconds); - _ui->silenceSecondsSpinner->setSuffix(ki18ncp("Unit of time", " second", " seconds")); + _tabsUi->silenceSecondsSpinner->setValue(silenceSeconds); + auto suffix = ki18ncp("Unit of time", " second", " seconds"); + _tabsUi->silenceSecondsSpinner->setSuffix(suffix); + int silenceCheckBoxWidth = maxSpinBoxWidth(_generalUi->terminalColumnsEntry, suffix); + _tabsUi->silenceSecondsSpinner->setFixedWidth(silenceCheckBoxWidth); - connect(_ui->silenceSecondsSpinner, + connect(_tabsUi->silenceSecondsSpinner, static_cast(&QSpinBox::valueChanged), this, &Konsole::EditProfileDialog::silenceSecondsChanged); } void EditProfileDialog::terminalColumnsEntryChanged(int value) { updateTempProfileProperty(Profile::TerminalColumns, value); } void EditProfileDialog::terminalRowsEntryChanged(int value) { updateTempProfileProperty(Profile::TerminalRows, value); } void EditProfileDialog::showTerminalSizeHint(bool value) { updateTempProfileProperty(Profile::ShowTerminalSizeHint, value); } void EditProfileDialog::setDimWhenInactive(bool value) { updateTempProfileProperty(Profile::DimWhenInactive, value); } void EditProfileDialog::tabTitleFormatChanged(const QString &format) { updateTempProfileProperty(Profile::LocalTabTitleFormat, format); } void EditProfileDialog::remoteTabTitleFormatChanged(const QString &format) { updateTempProfileProperty(Profile::RemoteTabTitleFormat, format); } void EditProfileDialog::silenceSecondsChanged(int seconds) { updateTempProfileProperty(Profile::SilenceSeconds, seconds); } void EditProfileDialog::selectIcon() { const QString &icon = KIconDialog::getIcon(KIconLoader::Desktop, KIconLoader::Application, false, 0, false, this); if (!icon.isEmpty()) { - _ui->iconSelectButton->setIcon(QIcon::fromTheme(icon)); + _generalUi->iconSelectButton->setIcon(QIcon::fromTheme(icon)); updateTempProfileProperty(Profile::Icon, icon); } } void EditProfileDialog::profileNameChanged(const QString &name) { updateTempProfileProperty(Profile::Name, name); updateTempProfileProperty(Profile::UntranslatedName, name); updateCaption(_tempProfile); } void EditProfileDialog::startInSameDir(bool sameDir) { updateTempProfileProperty(Profile::StartInCurrentSessionDir, sameDir); } void EditProfileDialog::initialDirChanged(const QString &dir) { updateTempProfileProperty(Profile::Directory, dir); } void EditProfileDialog::commandChanged(const QString &command) { ShellCommand shellCommand(command); updateTempProfileProperty(Profile::Command, shellCommand.command()); updateTempProfileProperty(Profile::Arguments, shellCommand.arguments()); } void EditProfileDialog::selectInitialDir() { const QUrl url = QFileDialog::getExistingDirectoryUrl(this, i18n("Select Initial Directory"), - QUrl::fromUserInput(_ui->initialDirEdit-> - text())); + QUrl::fromUserInput(_generalUi->initialDirEdit->text())); if (!url.isEmpty()) { - _ui->initialDirEdit->setText(url.path()); + _generalUi->initialDirEdit->setText(url.path()); } } -void EditProfileDialog::setupAppearancePage(const Profile::Ptr profile) +void EditProfileDialog::setupAppearancePage(const Profile::Ptr &profile) { auto delegate = new ColorSchemeViewDelegate(this); - _ui->colorSchemeList->setItemDelegate(delegate); + _appearanceUi->colorSchemeList->setItemDelegate(delegate); - _ui->transparencyWarningWidget->setVisible(false); - _ui->transparencyWarningWidget->setWordWrap(true); - _ui->transparencyWarningWidget->setCloseButtonVisible(false); - _ui->transparencyWarningWidget->setMessageType(KMessageWidget::Warning); + _appearanceUi->transparencyWarningWidget->setVisible(false); + _appearanceUi->transparencyWarningWidget->setWordWrap(true); + _appearanceUi->transparencyWarningWidget->setCloseButtonVisible(false); + _appearanceUi->transparencyWarningWidget->setMessageType(KMessageWidget::Warning); - _ui->colorSchemeMessageWidget->setVisible(false); - _ui->colorSchemeMessageWidget->setWordWrap(true); - _ui->colorSchemeMessageWidget->setCloseButtonVisible(false); - _ui->colorSchemeMessageWidget->setMessageType(KMessageWidget::Warning); + _appearanceUi->colorSchemeMessageWidget->setVisible(false); + _appearanceUi->colorSchemeMessageWidget->setWordWrap(true); + _appearanceUi->colorSchemeMessageWidget->setCloseButtonVisible(false); + _appearanceUi->colorSchemeMessageWidget->setMessageType(KMessageWidget::Warning); - _ui->editColorSchemeButton->setEnabled(false); - _ui->removeColorSchemeButton->setEnabled(false); - _ui->resetColorSchemeButton->setEnabled(false); + _appearanceUi->editColorSchemeButton->setEnabled(false); + _appearanceUi->removeColorSchemeButton->setEnabled(false); + _appearanceUi->resetColorSchemeButton->setEnabled(false); - _ui->downloadColorSchemeButton->setConfigFile(QStringLiteral("konsole.knsrc")); + _appearanceUi->downloadColorSchemeButton->setConfigFile(QStringLiteral("konsole.knsrc")); // setup color list // select the colorScheme used in the current profile updateColorSchemeList(currentColorSchemeName()); - _ui->colorSchemeList->setMouseTracking(true); - _ui->colorSchemeList->installEventFilter(this); - _ui->colorSchemeList->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + _appearanceUi->colorSchemeList->setMouseTracking(true); + _appearanceUi->colorSchemeList->installEventFilter(this); + _appearanceUi->colorSchemeList->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - connect(_ui->colorSchemeList->selectionModel(), + connect(_appearanceUi->colorSchemeList->selectionModel(), &QItemSelectionModel::selectionChanged, this, &Konsole::EditProfileDialog::colorSchemeSelected); - connect(_ui->colorSchemeList, &QListView::entered, this, + connect(_appearanceUi->colorSchemeList, &QListView::entered, this, &Konsole::EditProfileDialog::previewColorScheme); updateColorSchemeButtons(); - connect(_ui->editColorSchemeButton, &QPushButton::clicked, this, + connect(_appearanceUi->editColorSchemeButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::editColorScheme); - connect(_ui->removeColorSchemeButton, &QPushButton::clicked, this, + connect(_appearanceUi->removeColorSchemeButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::removeColorScheme); - connect(_ui->newColorSchemeButton, &QPushButton::clicked, this, + connect(_appearanceUi->newColorSchemeButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::newColorScheme); - connect(_ui->downloadColorSchemeButton, &KNS3::Button::dialogFinished, this, + connect(_appearanceUi->downloadColorSchemeButton, &KNS3::Button::dialogFinished, this, &Konsole::EditProfileDialog::gotNewColorSchemes); - connect(_ui->resetColorSchemeButton, &QPushButton::clicked, this, + connect(_appearanceUi->resetColorSchemeButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::resetColorScheme); + connect(_appearanceUi->chooseFontButton, &QAbstractButton::clicked, this, + &EditProfileDialog::showFontDialog); + // setup font preview const bool antialias = profile->antiAliasFonts(); QFont profileFont = profile->font(); profileFont.setStyleStrategy(antialias ? QFont::PreferAntialias : QFont::NoAntialias); - _ui->fontPreviewLabel->installEventFilter(this); - _ui->fontPreviewLabel->setFont(profileFont); - setFontInputValue(profileFont); - - // Always set to unchecked - _ui->showAllFontsButton->setChecked(false); - connect(_ui->showAllFontsButton, &QCheckBox::toggled, this, - &Konsole::EditProfileDialog::showAllFontsButtonWarning); - - connect(_ui->fontSizeInput, - static_cast(&QDoubleSpinBox::valueChanged), this, - &Konsole::EditProfileDialog::setFontSize); - connect(_ui->selectFontButton, &QPushButton::clicked, this, - &Konsole::EditProfileDialog::showFontDialog); + _appearanceUi->fontPreview->setFont(profileFont); + _appearanceUi->fontPreview->setText(QStringLiteral("%1 %2pt").arg(profileFont.family()).arg(profileFont.pointSize())); // setup font smoothing - _ui->antialiasTextButton->setChecked(antialias); - connect(_ui->antialiasTextButton, &QCheckBox::toggled, this, + _appearanceUi->antialiasTextButton->setChecked(antialias); + connect(_appearanceUi->antialiasTextButton, &QCheckBox::toggled, this, &Konsole::EditProfileDialog::setAntialiasText); - _ui->boldIntenseButton->setChecked(profile->boldIntense()); - connect(_ui->boldIntenseButton, &QCheckBox::toggled, this, + _appearanceUi->boldIntenseButton->setChecked(profile->boldIntense()); + connect(_appearanceUi->boldIntenseButton, &QCheckBox::toggled, this, &Konsole::EditProfileDialog::setBoldIntense); - _ui->useFontLineCharactersButton->setChecked(profile->useFontLineCharacters()); - connect(_ui->useFontLineCharactersButton, &QCheckBox::toggled, this, + _appearanceUi->useFontLineCharactersButton->setChecked(profile->useFontLineCharacters()); + connect(_appearanceUi->useFontLineCharactersButton, &QCheckBox::toggled, this, &Konsole::EditProfileDialog::useFontLineCharacters); - _ui->enableMouseWheelZoomButton->setChecked(profile->mouseWheelZoomEnabled()); - connect(_ui->enableMouseWheelZoomButton, &QCheckBox::toggled, this, + _mouseUi->enableMouseWheelZoomButton->setChecked(profile->mouseWheelZoomEnabled()); + connect(_mouseUi->enableMouseWheelZoomButton, &QCheckBox::toggled, this, &Konsole::EditProfileDialog::toggleMouseWheelZoom); -} -void EditProfileDialog::showAllFontsButtonWarning(bool enable) -{ - if (enable) { - KMessageBox::information(this, - QStringLiteral( - "By its very nature, a terminal program requires font characters that are equal width (monospace). Any non monospaced font may cause display issues. This should not be necessary except in rare cases."), - QStringLiteral("Warning")); + // cursor options + const auto options = QVector{ + { + _appearanceUi->enableBlinkingCursorButton, Profile::BlinkingCursorEnabled, + SLOT(toggleBlinkingCursor(bool)) + }, + }; + setupCheckBoxes(options, profile); + + if (profile->useCustomCursorColor()) { + _appearanceUi->customCursorColorButton->setChecked(true); + } else { + _appearanceUi->autoCursorColorButton->setChecked(true); } + + _appearanceUi->customColorSelectButton->setColor(profile->customCursorColor()); + + connect(_appearanceUi->customCursorColorButton, &QRadioButton::clicked, this, &Konsole::EditProfileDialog::customCursorColor); + connect(_appearanceUi->autoCursorColorButton, &QRadioButton::clicked, this, &Konsole::EditProfileDialog::autoCursorColor); + connect(_appearanceUi->customColorSelectButton, &KColorButton::changed, this, &Konsole::EditProfileDialog::customCursorColorChanged); + + // Make radio buttons height equal + int cursorColorRadioHeight = qMax(_appearanceUi->autoCursorColorButton->minimumSizeHint().height(), + _appearanceUi->customColorSelectButton->minimumSizeHint().height()); + _appearanceUi->autoCursorColorButton->setMinimumHeight(cursorColorRadioHeight); + _appearanceUi->customCursorColorButton->setMinimumHeight(cursorColorRadioHeight); + + const ButtonGroupOptions cursorShapeOptions = { + _appearanceUi->cursorShape, // group + Profile::CursorShape, // profileProperty + true, // preview + { // buttons + {_appearanceUi->cursorShapeBlock, Enum::BlockCursor}, + {_appearanceUi->cursorShapeIBeam, Enum::IBeamCursor}, + {_appearanceUi->cursorShapeUnderline, Enum::UnderlineCursor}, + }, + }; + setupButtonGroup(cursorShapeOptions, profile); + + _appearanceUi->marginsSpinner->setValue(profile->terminalMargin()); + connect(_appearanceUi->marginsSpinner, static_cast(&QSpinBox::valueChanged), this, &Konsole::EditProfileDialog::terminalMarginChanged); + + _appearanceUi->lineSpacingSpinner->setValue(profile->lineSpacing()); + connect(_appearanceUi->lineSpacingSpinner, static_cast(&QSpinBox::valueChanged), this, &Konsole::EditProfileDialog::lineSpacingChanged); + + _appearanceUi->alignToCenterButton->setChecked(profile->terminalCenter()); + connect(_appearanceUi->alignToCenterButton, &QCheckBox::toggled, this, + &Konsole::EditProfileDialog::setTerminalCenter); + + _appearanceUi->showTerminalSizeHintButton->setChecked(profile->showTerminalSizeHint()); + connect(_appearanceUi->showTerminalSizeHintButton, &QCheckBox::toggled, this, + &Konsole::EditProfileDialog::showTerminalSizeHint); + + _appearanceUi->dimWhenInactiveCheckbox->setChecked(profile->dimWhenInactive()); + connect(_appearanceUi->dimWhenInactiveCheckbox, &QCheckBox::toggled, this, + &Konsole::EditProfileDialog::setDimWhenInactive); } void EditProfileDialog::setAntialiasText(bool enable) { - QFont profileFont = _ui->fontPreviewLabel->font(); - profileFont.setStyleStrategy(enable ? QFont::PreferAntialias : QFont::NoAntialias); - - // update preview to reflect text smoothing state - fontSelected(profileFont); preview(Profile::AntiAliasFonts, enable); updateTempProfileProperty(Profile::AntiAliasFonts, enable); + + const QFont font = _profile->font(); + updateFontPreview(font); } void EditProfileDialog::setBoldIntense(bool enable) { preview(Profile::BoldIntense, enable); updateTempProfileProperty(Profile::BoldIntense, enable); } void EditProfileDialog::useFontLineCharacters(bool enable) { preview(Profile::UseFontLineCharacters, enable); updateTempProfileProperty(Profile::UseFontLineCharacters, enable); } +void EditProfileDialog::toggleBlinkingCursor(bool enable) +{ + preview(Profile::BlinkingCursorEnabled, enable); + updateTempProfileProperty(Profile::BlinkingCursorEnabled, enable); +} + +void EditProfileDialog::setCursorShape(int index) +{ + preview(Profile::CursorShape, index); + updateTempProfileProperty(Profile::CursorShape, index); +} + +void EditProfileDialog::autoCursorColor() +{ + preview(Profile::UseCustomCursorColor, false); + updateTempProfileProperty(Profile::UseCustomCursorColor, false); +} + +void EditProfileDialog::customCursorColor() +{ + preview(Profile::UseCustomCursorColor, true); + updateTempProfileProperty(Profile::UseCustomCursorColor, true); +} + +void EditProfileDialog::customCursorColorChanged(const QColor &color) +{ + preview(Profile::CustomCursorColor, color); + updateTempProfileProperty(Profile::CustomCursorColor, color); + + // ensure that custom cursor colors are enabled + _appearanceUi->customCursorColorButton->click(); +} + +void EditProfileDialog::terminalMarginChanged(int margin) +{ + preview(Profile::TerminalMargin, margin); + updateTempProfileProperty(Profile::TerminalMargin, margin); +} + +void EditProfileDialog::lineSpacingChanged(int spacing) +{ + preview(Profile::LineSpacing, spacing); + updateTempProfileProperty(Profile::LineSpacing, spacing); +} + +void EditProfileDialog::setTerminalCenter(bool enable) +{ + preview(Profile::TerminalCenter, enable); + updateTempProfileProperty(Profile::TerminalCenter, enable); +} + void EditProfileDialog::toggleMouseWheelZoom(bool enable) { updateTempProfileProperty(Profile::MouseWheelZoomEnabled, enable); } void EditProfileDialog::toggleAlternateScrolling(bool enable) { updateTempProfileProperty(Profile::AlternateScrolling, enable); } void EditProfileDialog::updateColorSchemeList(const QString &selectedColorSchemeName) { - if (_ui->colorSchemeList->model() == nullptr) { - _ui->colorSchemeList->setModel(new QStandardItemModel(this)); + if (_appearanceUi->colorSchemeList->model() == nullptr) { + _appearanceUi->colorSchemeList->setModel(new QStandardItemModel(this)); } const ColorScheme *selectedColorScheme = ColorSchemeManager::instance()->findColorScheme(selectedColorSchemeName); - auto *model = qobject_cast(_ui->colorSchemeList->model()); + auto *model = qobject_cast(_appearanceUi->colorSchemeList->model()); Q_ASSERT(model); model->clear(); QStandardItem *selectedItem = nullptr; QList schemeList = ColorSchemeManager::instance()->allColorSchemes(); foreach (const ColorScheme *scheme, schemeList) { QStandardItem *item = new QStandardItem(scheme->description()); item->setData(QVariant::fromValue(scheme), Qt::UserRole + 1); item->setData(QVariant::fromValue(_profile->font()), Qt::UserRole + 2); item->setFlags(item->flags()); // if selectedColorSchemeName is not empty then select that scheme // after saving the changes in the colorScheme editor if (selectedColorScheme == scheme) { selectedItem = item; } model->appendRow(item); } model->sort(0); if (selectedItem != nullptr) { - _ui->colorSchemeList->updateGeometry(); - _ui->colorSchemeList->selectionModel()->setCurrentIndex(selectedItem->index(), + _appearanceUi->colorSchemeList->updateGeometry(); + _appearanceUi->colorSchemeList->selectionModel()->setCurrentIndex(selectedItem->index(), QItemSelectionModel::Select); // update transparency warning label updateTransparencyWarning(); } } void EditProfileDialog::updateKeyBindingsList(const QString &selectKeyBindingsName) { - if (_ui->keyBindingList->model() == nullptr) { - _ui->keyBindingList->setModel(new QStandardItemModel(this)); + if (_keyboardUi->keyBindingList->model() == nullptr) { + _keyboardUi->keyBindingList->setModel(new QStandardItemModel(this)); } - auto *model = qobject_cast(_ui->keyBindingList->model()); + auto *model = qobject_cast(_keyboardUi->keyBindingList->model()); Q_ASSERT(model); model->clear(); QStandardItem *selectedItem = nullptr; const QStringList &translatorNames = _keyManager->allTranslators(); for (const QString &translatorName : translatorNames) { const KeyboardTranslator *translator = _keyManager->findTranslator(translatorName); if (translator == nullptr) { continue; } QStandardItem *item = new QStandardItem(translator->description()); item->setEditable(false); item->setData(QVariant::fromValue(translator), Qt::UserRole + 1); item->setData(QVariant::fromValue(_keyManager->findTranslatorPath(translatorName)), Qt::ToolTipRole); item->setData(QVariant::fromValue(_profile->font()), Qt::UserRole + 2); item->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-keyboard"))); if (selectKeyBindingsName == translatorName) { selectedItem = item; } model->appendRow(item); } model->sort(0); if (selectedItem != nullptr) { - _ui->keyBindingList->selectionModel()->setCurrentIndex(selectedItem->index(), + _keyboardUi->keyBindingList->selectionModel()->setCurrentIndex(selectedItem->index(), QItemSelectionModel::Select); } } bool EditProfileDialog::eventFilter(QObject *watched, QEvent *event) { - if (watched == _ui->colorSchemeList && event->type() == QEvent::Leave) { + if (watched == _appearanceUi->colorSchemeList && event->type() == QEvent::Leave) { if (_tempProfile->isPropertySet(Profile::ColorScheme)) { preview(Profile::ColorScheme, _tempProfile->colorScheme()); } else { unpreview(Profile::ColorScheme); } } - if (watched == _ui->fontPreviewLabel && event->type() == QEvent::FontChange) { - const QFont &labelFont = _ui->fontPreviewLabel->font(); - _ui->fontPreviewLabel->setText(i18n("%1", labelFont.family())); - } return QDialog::eventFilter(watched, event); } +QSize EditProfileDialog::sizeHint() const +{ +// return QSize(); + return QDialog::sizeHint(); +} + void EditProfileDialog::unpreviewAll() { _delayedPreviewTimer->stop(); _delayedPreviewProperties.clear(); QHash map; QHashIterator iter(_previewedProperties); while (iter.hasNext()) { iter.next(); map.insert(static_cast(iter.key()), iter.value()); } // undo any preview changes if (!map.isEmpty()) { ProfileManager::instance()->changeProfile(_profile, map, false); } } void EditProfileDialog::unpreview(int property) { _delayedPreviewProperties.remove(property); if (!_previewedProperties.contains(property)) { return; } QHash map; map.insert(static_cast(property), _previewedProperties[property]); ProfileManager::instance()->changeProfile(_profile, map, false); _previewedProperties.remove(property); } void EditProfileDialog::delayedPreview(int property, const QVariant &value) { _delayedPreviewProperties.insert(property, value); _delayedPreviewTimer->stop(); _delayedPreviewTimer->start(300); } void EditProfileDialog::delayedPreviewActivate() { Q_ASSERT(qobject_cast(sender())); QMutableHashIterator iter(_delayedPreviewProperties); if (iter.hasNext()) { iter.next(); preview(iter.key(), iter.value()); } } void EditProfileDialog::preview(int property, const QVariant &value) { QHash map; map.insert(static_cast(property), value); _delayedPreviewProperties.remove(property); const Profile::Ptr original = lookupProfile(); // skip previews for profile groups if the profiles in the group // have conflicting original values for the property // // TODO - Save the original values for each profile and use to unpreview properties ProfileGroup::Ptr group = original->asGroup(); if (group && group->profiles().count() > 1 && original->property(static_cast(property)).isNull()) { return; } if (!_previewedProperties.contains(property)) { _previewedProperties.insert(property, original->property(static_cast(property))); } // temporary change to color scheme ProfileManager::instance()->changeProfile(_profile, map, false); } void EditProfileDialog::previewColorScheme(const QModelIndex &index) { const QString &name = index.data(Qt::UserRole + 1).value()->name(); - delayedPreview(Profile::ColorScheme, name); } +void EditProfileDialog::showFontDialog() +{ + if (!_fontDialog) { + _fontDialog = new FontDialog(this); + connect(_fontDialog, &FontDialog::fontChanged, this, [this](const QFont font) { + preview(Profile::Font, font); + updateFontPreview(font); + }); + connect(_fontDialog, &FontDialog::accepted, this, [this]() { + const QFont font = _fontDialog->font(); + preview(Profile::Font, font); + updateTempProfileProperty(Profile::Font, font); + updateFontPreview(font); + }); + connect(_fontDialog, &FontDialog::rejected, this, [this]() { + unpreview(Profile::Font); + const QFont font = _profile->font(); + updateFontPreview(font); + }); + } + const QFont font = _profile->font(); + _fontDialog->setFont(font); + _fontDialog->exec(); +} + +void EditProfileDialog::updateFontPreview(QFont font) +{ + bool aa = _profile->antiAliasFonts(); + font.setStyleStrategy(aa ? QFont::PreferAntialias : QFont::NoAntialias); + + _appearanceUi->fontPreview->setFont(font); + _appearanceUi->fontPreview->setText(QStringLiteral("%1 %2pt").arg(font.family()).arg(font.pointSize())); +} + void EditProfileDialog::removeColorScheme() { - QModelIndexList selected = _ui->colorSchemeList->selectionModel()->selectedIndexes(); + QModelIndexList selected = _appearanceUi->colorSchemeList->selectionModel()->selectedIndexes(); if (selected.isEmpty()) { return; } // The actual delete runs async because we need to on-demand query // files managed by KNS. Deleting files managed by KNS screws up the // KNS states (entry gets shown as installed when in fact we deleted it). auto *manager = new KNSCore::DownloadManager(QStringLiteral("konsole.knsrc"), this); connect(manager, &KNSCore::DownloadManager::searchResult, - [=](const KNSCore::EntryInternal::List &entries) { + this, [=](const KNSCore::EntryInternal::List &entries) { const QString &name = selected.first().data(Qt::UserRole + 1).value()->name(); Q_ASSERT(!name.isEmpty()); bool uninstalled = false; // Check if the theme was installed by KNS, if so uninstall it through // there and unload it. - for (auto entry : entries) { + for (auto &entry : entries) { for (const auto &file : entry.installedFiles()) { if (ColorSchemeManager::colorSchemeNameFromPath(file) != name) { continue; } // Make sure the manager can unload it before uninstalling it. if (ColorSchemeManager::instance()->unloadColorScheme(file)) { manager->uninstallEntry(entry); uninstalled = true; } } if (uninstalled) { break; } } // If KNS wasn't able to remove it is a custom theme and we'll drop // it manually. if (!uninstalled) { uninstalled = ColorSchemeManager::instance()->deleteColorScheme(name); } if (uninstalled) { - _ui->colorSchemeList->model()->removeRow(selected.first().row()); + _appearanceUi->colorSchemeList->model()->removeRow(selected.first().row()); } manager->deleteLater(); }); manager->checkForInstalled(); } void EditProfileDialog::gotNewColorSchemes(const KNS3::Entry::List &changedEntries) { int failures = 0; - for (auto entry : changedEntries) { + for (auto &entry : changedEntries) { switch (entry.status()) { case KNS3::Entry::Installed: for (const auto &file : entry.installedFiles()) { if (ColorSchemeManager::instance()->loadColorScheme(file)) { continue; } qWarning() << "Failed to load file" << file; ++failures; } if (failures == entry.installedFiles().size()) { - _ui->colorSchemeMessageWidget->setText( + _appearanceUi->colorSchemeMessageWidget->setText( xi18nc("@info", "Scheme %1 failed to load.", entry.name())); - _ui->colorSchemeMessageWidget->animatedShow(); + _appearanceUi->colorSchemeMessageWidget->animatedShow(); QTimer::singleShot(8000, - _ui->colorSchemeMessageWidget, + _appearanceUi->colorSchemeMessageWidget, &KMessageWidget::animatedHide); } break; case KNS3::Entry::Deleted: for (const auto &file : entry.uninstalledFiles()) { if (ColorSchemeManager::instance()->unloadColorScheme(file)) { continue; } qWarning() << "Failed to unload file" << file; // If unloading fails we do not care. Iff the scheme failed here // it either wasn't loaded or was invalid to begin with. } break; case KNS3::Entry::Invalid: case KNS3::Entry::Installing: case KNS3::Entry::Downloadable: case KNS3::Entry::Updateable: case KNS3::Entry::Updating: // Not interesting. break; } } updateColorSchemeList(currentColorSchemeName()); } void EditProfileDialog::resetColorScheme() { - QModelIndexList selected = _ui->colorSchemeList->selectionModel()->selectedIndexes(); + QModelIndexList selected = _appearanceUi->colorSchemeList->selectionModel()->selectedIndexes(); if (!selected.isEmpty()) { const QString &name = selected.first().data(Qt::UserRole + 1).value()->name(); ColorSchemeManager::instance()->deleteColorScheme(name); // select the colorScheme used in the current profile updateColorSchemeList(currentColorSchemeName()); } } void EditProfileDialog::showColorSchemeEditor(bool isNewScheme) { // Finding selected ColorScheme - QModelIndexList selected = _ui->colorSchemeList->selectionModel()->selectedIndexes(); - QAbstractItemModel *model = _ui->colorSchemeList->model(); + QModelIndexList selected = _appearanceUi->colorSchemeList->selectionModel()->selectedIndexes(); + QAbstractItemModel *model = _appearanceUi->colorSchemeList->model(); const ColorScheme *colors = nullptr; if (!selected.isEmpty()) { colors = model->data(selected.first(), Qt::UserRole + 1).value(); } else { colors = ColorSchemeManager::instance()->defaultColorScheme(); } Q_ASSERT(colors); // Setting up ColorSchemeEditor ui // close any running ColorSchemeEditor if (_colorDialog != nullptr) { closeColorSchemeEditor(); } _colorDialog = new ColorSchemeEditor(this); connect(_colorDialog, &Konsole::ColorSchemeEditor::colorSchemeSaveRequested, this, &Konsole::EditProfileDialog::saveColorScheme); _colorDialog->setup(colors, isNewScheme); _colorDialog->show(); } void EditProfileDialog::closeColorSchemeEditor() { if (_colorDialog != nullptr) { _colorDialog->close(); delete _colorDialog; } } void EditProfileDialog::newColorScheme() { showColorSchemeEditor(true); } void EditProfileDialog::editColorScheme() { showColorSchemeEditor(false); } void EditProfileDialog::saveColorScheme(const ColorScheme &scheme, bool isNewScheme) { auto newScheme = new ColorScheme(scheme); // if this is a new color scheme, pick a name based on the description if (isNewScheme) { newScheme->setName(newScheme->description()); } ColorSchemeManager::instance()->addColorScheme(newScheme); const QString &selectedColorSchemeName = newScheme->name(); // select the edited or the new colorScheme after saving the changes updateColorSchemeList(selectedColorSchemeName); preview(Profile::ColorScheme, newScheme->name()); } void EditProfileDialog::colorSchemeSelected() { - QModelIndexList selected = _ui->colorSchemeList->selectionModel()->selectedIndexes(); + QModelIndexList selected = _appearanceUi->colorSchemeList->selectionModel()->selectedIndexes(); if (!selected.isEmpty()) { - QAbstractItemModel *model = _ui->colorSchemeList->model(); + QAbstractItemModel *model = _appearanceUi->colorSchemeList->model(); const auto *colors = model->data(selected.first(), Qt::UserRole + 1).value(); if (colors != nullptr) { updateTempProfileProperty(Profile::ColorScheme, colors->name()); previewColorScheme(selected.first()); updateTransparencyWarning(); } } updateColorSchemeButtons(); } void EditProfileDialog::updateColorSchemeButtons() { - enableIfNonEmptySelection(_ui->editColorSchemeButton, _ui->colorSchemeList->selectionModel()); + enableIfNonEmptySelection(_appearanceUi->editColorSchemeButton, _appearanceUi->colorSchemeList->selectionModel()); - QModelIndexList selected = _ui->colorSchemeList->selectionModel()->selectedIndexes(); + QModelIndexList selected = _appearanceUi->colorSchemeList->selectionModel()->selectedIndexes(); if (!selected.isEmpty()) { const QString &name = selected.first().data(Qt::UserRole + 1).value()->name(); bool isResettable = ColorSchemeManager::instance()->canResetColorScheme(name); - _ui->resetColorSchemeButton->setEnabled(isResettable); + _appearanceUi->resetColorSchemeButton->setEnabled(isResettable); bool isDeletable = ColorSchemeManager::instance()->isColorSchemeDeletable(name); // if a colorScheme can be restored then it can't be deleted - _ui->removeColorSchemeButton->setEnabled(isDeletable && !isResettable); + _appearanceUi->removeColorSchemeButton->setEnabled(isDeletable && !isResettable); } else { - _ui->removeColorSchemeButton->setEnabled(false); - _ui->resetColorSchemeButton->setEnabled(false); + _appearanceUi->removeColorSchemeButton->setEnabled(false); + _appearanceUi->resetColorSchemeButton->setEnabled(false); } } void EditProfileDialog::updateKeyBindingsButtons() { - QModelIndexList selected = _ui->keyBindingList->selectionModel()->selectedIndexes(); + QModelIndexList selected = _keyboardUi->keyBindingList->selectionModel()->selectedIndexes(); if (!selected.isEmpty()) { - _ui->editKeyBindingsButton->setEnabled(true); + _keyboardUi->editKeyBindingsButton->setEnabled(true); const QString &name = selected.first().data(Qt::UserRole + 1).value()->name(); bool isResettable = _keyManager->isTranslatorResettable(name); - _ui->resetKeyBindingsButton->setEnabled(isResettable); + _keyboardUi->resetKeyBindingsButton->setEnabled(isResettable); bool isDeletable = _keyManager->isTranslatorDeletable(name); // if a key bindings scheme can be reset then it can't be deleted - _ui->removeKeyBindingsButton->setEnabled(isDeletable && !isResettable); + _keyboardUi->removeKeyBindingsButton->setEnabled(isDeletable && !isResettable); } } void EditProfileDialog::enableIfNonEmptySelection(QWidget *widget, QItemSelectionModel *selectionModel) { widget->setEnabled(selectionModel->hasSelection()); } void EditProfileDialog::updateTransparencyWarning() { // zero or one indexes can be selected - foreach (const QModelIndex &index, _ui->colorSchemeList->selectionModel()->selectedIndexes()) { + foreach (const QModelIndex &index, _appearanceUi->colorSchemeList->selectionModel()->selectedIndexes()) { bool needTransparency = index.data(Qt::UserRole + 1).value()->opacity() < 1.0; if (!needTransparency) { - _ui->transparencyWarningWidget->setHidden(true); + _appearanceUi->transparencyWarningWidget->setHidden(true); } else if (!KWindowSystem::compositingActive()) { - _ui->transparencyWarningWidget->setText(i18n( + _appearanceUi->transparencyWarningWidget->setText(i18n( "This color scheme uses a transparent background" " which does not appear to be supported on your" " desktop")); - _ui->transparencyWarningWidget->setHidden(false); + _appearanceUi->transparencyWarningWidget->setHidden(false); } else if (!WindowSystemInfo::HAVE_TRANSPARENCY) { - _ui->transparencyWarningWidget->setText(i18n( + _appearanceUi->transparencyWarningWidget->setText(i18n( "Konsole was started before desktop effects were enabled." " You need to restart Konsole to see transparent background.")); - _ui->transparencyWarningWidget->setHidden(false); + _appearanceUi->transparencyWarningWidget->setHidden(false); } } } void EditProfileDialog::createTempProfile() { _tempProfile = Profile::Ptr(new Profile); _tempProfile->setHidden(true); } void EditProfileDialog::updateTempProfileProperty(Profile::Property property, const QVariant &value) { _tempProfile->setProperty(property, value); updateButtonApply(); } void EditProfileDialog::updateButtonApply() { bool userModified = false; QHashIterator iter(_tempProfile->setProperties()); while (iter.hasNext()) { iter.next(); Profile::Property property = iter.key(); QVariant value = iter.value(); // for previewed property if (_previewedProperties.contains(static_cast(property))) { if (value != _previewedProperties.value(static_cast(property))) { userModified = true; break; } // for not-previewed property // // for the Profile::KeyBindings property, if it's set in the _tempProfile // then the user opened the edit key bindings dialog and clicked // OK, and could have add/removed a key bindings rule } else if (property == Profile::KeyBindings || (value != _profile->property(property))) { userModified = true; break; } } - mButtonBox->button(QDialogButtonBox::Apply)->setEnabled(userModified); + _buttonBox->button(QDialogButtonBox::Apply)->setEnabled(userModified); } -void EditProfileDialog::setupKeyboardPage(const Profile::Ptr /* profile */) +void EditProfileDialog::setupKeyboardPage(const Profile::Ptr &/* profile */) { // setup translator list updateKeyBindingsList(lookupProfile()->keyBindings()); - connect(_ui->keyBindingList->selectionModel(), + connect(_keyboardUi->keyBindingList->selectionModel(), &QItemSelectionModel::selectionChanged, this, &Konsole::EditProfileDialog::keyBindingSelected); - connect(_ui->newKeyBindingsButton, &QPushButton::clicked, this, + connect(_keyboardUi->newKeyBindingsButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::newKeyBinding); - _ui->editKeyBindingsButton->setEnabled(false); - _ui->removeKeyBindingsButton->setEnabled(false); - _ui->resetKeyBindingsButton->setEnabled(false); + _keyboardUi->editKeyBindingsButton->setEnabled(false); + _keyboardUi->removeKeyBindingsButton->setEnabled(false); + _keyboardUi->resetKeyBindingsButton->setEnabled(false); updateKeyBindingsButtons(); - connect(_ui->editKeyBindingsButton, &QPushButton::clicked, this, + connect(_keyboardUi->editKeyBindingsButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::editKeyBinding); - connect(_ui->removeKeyBindingsButton, &QPushButton::clicked, this, + connect(_keyboardUi->removeKeyBindingsButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::removeKeyBinding); - connect(_ui->resetKeyBindingsButton, &QPushButton::clicked, this, + connect(_keyboardUi->resetKeyBindingsButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::resetKeyBindings); } void EditProfileDialog::keyBindingSelected() { - QModelIndexList selected = _ui->keyBindingList->selectionModel()->selectedIndexes(); + QModelIndexList selected = _keyboardUi->keyBindingList->selectionModel()->selectedIndexes(); if (!selected.isEmpty()) { - QAbstractItemModel *model = _ui->keyBindingList->model(); + QAbstractItemModel *model = _keyboardUi->keyBindingList->model(); const auto *translator = model->data(selected.first(), Qt::UserRole + 1) .value(); if (translator != nullptr) { updateTempProfileProperty(Profile::KeyBindings, translator->name()); } } updateKeyBindingsButtons(); } void EditProfileDialog::removeKeyBinding() { - QModelIndexList selected = _ui->keyBindingList->selectionModel()->selectedIndexes(); + QModelIndexList selected = _keyboardUi->keyBindingList->selectionModel()->selectedIndexes(); if (!selected.isEmpty()) { const QString &name = selected.first().data(Qt::UserRole + 1).value()->name(); if (KeyboardTranslatorManager::instance()->deleteTranslator(name)) { - _ui->keyBindingList->model()->removeRow(selected.first().row()); + _keyboardUi->keyBindingList->model()->removeRow(selected.first().row()); } } } void EditProfileDialog::showKeyBindingEditor(bool isNewTranslator) { - QModelIndexList selected = _ui->keyBindingList->selectionModel()->selectedIndexes(); - QAbstractItemModel *model = _ui->keyBindingList->model(); + QModelIndexList selected = _keyboardUi->keyBindingList->selectionModel()->selectedIndexes(); + QAbstractItemModel *model = _keyboardUi->keyBindingList->model(); const KeyboardTranslator *translator = nullptr; if (!selected.isEmpty()) { translator = model->data(selected.first(), Qt::UserRole + 1).value(); } else { translator = _keyManager->defaultTranslator(); } Q_ASSERT(translator); auto editor = new KeyBindingEditor(this); if (translator != nullptr) { editor->setup(translator, lookupProfile()->keyBindings(), isNewTranslator); } connect(editor, &Konsole::KeyBindingEditor::updateKeyBindingsListRequest, this, &Konsole::EditProfileDialog::updateKeyBindingsList); connect(editor, &Konsole::KeyBindingEditor::updateTempProfileKeyBindingsRequest, this, &Konsole::EditProfileDialog::updateTempProfileProperty); editor->exec(); } void EditProfileDialog::newKeyBinding() { showKeyBindingEditor(true); } void EditProfileDialog::editKeyBinding() { showKeyBindingEditor(false); } void EditProfileDialog::resetKeyBindings() { - QModelIndexList selected = _ui->keyBindingList->selectionModel()->selectedIndexes(); + QModelIndexList selected = _keyboardUi->keyBindingList->selectionModel()->selectedIndexes(); if (!selected.isEmpty()) { const QString &name = selected.first().data(Qt::UserRole + 1).value()->name(); _keyManager->deleteTranslator(name); // find and load the translator _keyManager->findTranslator(name); updateKeyBindingsList(name); } } -void EditProfileDialog::setupCheckBoxes(const QVector& options, const Profile::Ptr profile) +void EditProfileDialog::setupCheckBoxes(const QVector& options, const Profile::Ptr &profile) { for(const auto& option : options) { option.button->setChecked(profile->property(option.property)); connect(option.button, SIGNAL(toggled(bool)), this, option.slot); } } void EditProfileDialog::setupRadio(const QVector& possibilities, int actual) { for(const auto& possibility : possibilities) { possibility.button->setChecked(possibility.value == actual); connect(possibility.button, SIGNAL(clicked()), this, possibility.slot); } } -void EditProfileDialog::setupScrollingPage(const Profile::Ptr profile) +void EditProfileDialog::setupButtonGroup(const ButtonGroupOptions &options, const Profile::Ptr &profile) { - // setup scrollbar radio - auto scrollBarPosition = profile->property(Profile::ScrollBarPosition); + auto currentValue = profile->property(options.profileProperty); + + for (auto option: options.buttons) { + options.group->setId(option.button, option.value); + } + + Q_ASSERT(options.buttons.count() > 0); + auto *activeButton = options.group->button(currentValue); + if (!activeButton) { + activeButton = options.buttons[0].button; + } + activeButton->setChecked(true); - const auto positions = QVector{ {_ui->scrollBarHiddenButton, Enum::ScrollBarHidden, SLOT(hideScrollBar())}, - {_ui->scrollBarLeftButton, Enum::ScrollBarLeft, SLOT(showScrollBarLeft())}, - {_ui->scrollBarRightButton, Enum::ScrollBarRight, SLOT(showScrollBarRight())}}; + connect(options.group, QOverload::of(&QButtonGroup::buttonClicked), + this, [this, options](int value) { + if (options.preview) { + preview(options.profileProperty, value); + } + updateTempProfileProperty(options.profileProperty, value); + }); +} - setupRadio(positions, scrollBarPosition); +void EditProfileDialog::setupScrollingPage(const Profile::Ptr &profile) +{ + // setup scrollbar radio + const ButtonGroupOptions scrollBarPositionOptions = { + _scrollingUi->scrollBarPosition, // group + Profile::ScrollBarPosition, // profileProperty + false, // preview + { // buttons + {_scrollingUi->scrollBarRightButton, Enum::ScrollBarRight}, + {_scrollingUi->scrollBarLeftButton, Enum::ScrollBarLeft}, + {_scrollingUi->scrollBarHiddenButton, Enum::ScrollBarHidden}, + }, + }; + setupButtonGroup(scrollBarPositionOptions, profile); // setup scrollback type radio auto scrollBackType = profile->property(Profile::HistoryMode); - _ui->historySizeWidget->setMode(Enum::HistoryModeEnum(scrollBackType)); - connect(_ui->historySizeWidget, &Konsole::HistorySizeWidget::historyModeChanged, this, + _scrollingUi->historySizeWidget->setMode(Enum::HistoryModeEnum(scrollBackType)); + connect(_scrollingUi->historySizeWidget, &Konsole::HistorySizeWidget::historyModeChanged, this, &Konsole::EditProfileDialog::historyModeChanged); // setup scrollback line count spinner const int historySize = profile->historySize(); - _ui->historySizeWidget->setLineCount(historySize); + _scrollingUi->historySizeWidget->setLineCount(historySize); // setup scrollpageamount type radio auto scrollFullPage = profile->property(Profile::ScrollFullPage); const auto pageamounts = QVector{ - {_ui->scrollHalfPage, Enum::ScrollPageHalf, SLOT(scrollHalfPage())}, - {_ui->scrollFullPage, Enum::ScrollPageFull, SLOT(scrollFullPage())} + {_scrollingUi->scrollHalfPage, Enum::ScrollPageHalf, SLOT(scrollHalfPage())}, + {_scrollingUi->scrollFullPage, Enum::ScrollPageFull, SLOT(scrollFullPage())} }; setupRadio(pageamounts, scrollFullPage); // signals and slots - connect(_ui->historySizeWidget, &Konsole::HistorySizeWidget::historySizeChanged, this, + connect(_scrollingUi->historySizeWidget, &Konsole::HistorySizeWidget::historySizeChanged, this, &Konsole::EditProfileDialog::historySizeChanged); } void EditProfileDialog::historySizeChanged(int lineCount) { updateTempProfileProperty(Profile::HistorySize, lineCount); } void EditProfileDialog::historyModeChanged(Enum::HistoryModeEnum mode) { updateTempProfileProperty(Profile::HistoryMode, mode); } -void EditProfileDialog::hideScrollBar() -{ - updateTempProfileProperty(Profile::ScrollBarPosition, Enum::ScrollBarHidden); -} - -void EditProfileDialog::showScrollBarLeft() -{ - updateTempProfileProperty(Profile::ScrollBarPosition, Enum::ScrollBarLeft); -} - -void EditProfileDialog::showScrollBarRight() -{ - updateTempProfileProperty(Profile::ScrollBarPosition, Enum::ScrollBarRight); -} - void EditProfileDialog::scrollFullPage() { updateTempProfileProperty(Profile::ScrollFullPage, Enum::ScrollPageFull); } void EditProfileDialog::scrollHalfPage() { updateTempProfileProperty(Profile::ScrollFullPage, Enum::ScrollPageHalf); } -void EditProfileDialog::setupMousePage(const Profile::Ptr profile) +void EditProfileDialog::setupMousePage(const Profile::Ptr &profile) { const auto options = QVector{ { - _ui->underlineLinksButton, Profile::UnderlineLinksEnabled, + _mouseUi->underlineLinksButton, Profile::UnderlineLinksEnabled, SLOT(toggleUnderlineLinks(bool)) }, { - _ui->underlineFilesButton, Profile::UnderlineFilesEnabled, + _mouseUi->underlineFilesButton, Profile::UnderlineFilesEnabled, SLOT(toggleUnderlineFiles(bool)) }, { - _ui->ctrlRequiredForDragButton, Profile::CtrlRequiredForDrag, + _mouseUi->ctrlRequiredForDragButton, Profile::CtrlRequiredForDrag, SLOT(toggleCtrlRequiredForDrag(bool)) }, { - _ui->copyTextAsHTMLButton, Profile::CopyTextAsHTML, + _mouseUi->copyTextAsHTMLButton, Profile::CopyTextAsHTML, SLOT(toggleCopyTextAsHTML(bool)) }, { - _ui->copyTextToClipboardButton, Profile::AutoCopySelectedText, + _mouseUi->copyTextToClipboardButton, Profile::AutoCopySelectedText, SLOT(toggleCopyTextToClipboard(bool)) }, { - _ui->trimLeadingSpacesButton, Profile::TrimLeadingSpacesInSelectedText, + _mouseUi->trimLeadingSpacesButton, Profile::TrimLeadingSpacesInSelectedText, SLOT(toggleTrimLeadingSpacesInSelectedText(bool)) }, { - _ui->trimTrailingSpacesButton, Profile::TrimTrailingSpacesInSelectedText, + _mouseUi->trimTrailingSpacesButton, Profile::TrimTrailingSpacesInSelectedText, SLOT(toggleTrimTrailingSpacesInSelectedText(bool)) }, { - _ui->openLinksByDirectClickButton, Profile::OpenLinksByDirectClickEnabled, + _mouseUi->openLinksByDirectClickButton, Profile::OpenLinksByDirectClickEnabled, SLOT(toggleOpenLinksByDirectClick(bool)) }, { - _ui->dropUrlsAsText, Profile::DropUrlsAsText, + _mouseUi->dropUrlsAsText, Profile::DropUrlsAsText, SLOT(toggleDropUrlsAsText(bool)) }, { - _ui->enableAlternateScrollingButton, Profile::AlternateScrolling, + _mouseUi->enableAlternateScrollingButton, Profile::AlternateScrolling, SLOT(toggleAlternateScrolling(bool)) } }; setupCheckBoxes(options, profile); // setup middle click paste mode const auto middleClickPasteMode = profile->property(Profile::MiddleClickPasteMode); const auto pasteModes = QVector { - {_ui->pasteFromX11SelectionButton, Enum::PasteFromX11Selection, SLOT(pasteFromX11Selection())}, - {_ui->pasteFromClipboardButton, Enum::PasteFromClipboard, SLOT(pasteFromClipboard())} }; + {_mouseUi->pasteFromX11SelectionButton, Enum::PasteFromX11Selection, SLOT(pasteFromX11Selection())}, + {_mouseUi->pasteFromClipboardButton, Enum::PasteFromClipboard, SLOT(pasteFromClipboard())} }; setupRadio(pasteModes, middleClickPasteMode); // interaction options - _ui->wordCharacterEdit->setText(profile->wordCharacters()); - - connect(_ui->wordCharacterEdit, &QLineEdit::textChanged, this, &Konsole::EditProfileDialog::wordCharactersChanged); + _mouseUi->wordCharacterEdit->setText(profile->wordCharacters()); - auto tripleClickMode = profile->property(Profile::TripleClickMode); - _ui->tripleClickModeCombo->setCurrentIndex(tripleClickMode); + connect(_mouseUi->wordCharacterEdit, &QLineEdit::textChanged, this, &Konsole::EditProfileDialog::wordCharactersChanged); - connect(_ui->tripleClickModeCombo, static_cast(&KComboBox::activated), this, &Konsole::EditProfileDialog::TripleClickModeChanged); + const ButtonGroupOptions tripleClickModeOptions = { + _mouseUi->tripleClickMode, // group + Profile::TripleClickMode, // profileProperty + false, // preview + { // buttons + {_mouseUi->tripleClickSelectsTheWholeLine, Enum::SelectWholeLine}, + {_mouseUi->tripleClickSelectsFromMousePosition, Enum::SelectForwardsFromCursor}, + }, + }; + setupButtonGroup(tripleClickModeOptions, profile); - _ui->openLinksByDirectClickButton->setEnabled(_ui->underlineLinksButton->isChecked() || _ui->underlineFilesButton->isChecked()); + _mouseUi->openLinksByDirectClickButton->setEnabled(_mouseUi->underlineLinksButton->isChecked() || _mouseUi->underlineFilesButton->isChecked()); - _ui->enableMouseWheelZoomButton->setChecked(profile->mouseWheelZoomEnabled()); - connect(_ui->enableMouseWheelZoomButton, &QCheckBox::toggled, this, &Konsole::EditProfileDialog::toggleMouseWheelZoom); + _mouseUi->enableMouseWheelZoomButton->setChecked(profile->mouseWheelZoomEnabled()); + connect(_mouseUi->enableMouseWheelZoomButton, &QCheckBox::toggled, this, &Konsole::EditProfileDialog::toggleMouseWheelZoom); } -void EditProfileDialog::setupAdvancedPage(const Profile::Ptr profile) +void EditProfileDialog::setupAdvancedPage(const Profile::Ptr &profile) { const auto options = QVector{ { - _ui->enableBlinkingTextButton, Profile::BlinkingTextEnabled, + _advancedUi->enableBlinkingTextButton, Profile::BlinkingTextEnabled, SLOT(toggleBlinkingText(bool)) }, { - _ui->enableFlowControlButton, Profile::FlowControlEnabled, + _advancedUi->enableFlowControlButton, Profile::FlowControlEnabled, SLOT(toggleFlowControl(bool)) }, { - _ui->enableBlinkingCursorButton, Profile::BlinkingCursorEnabled, + _appearanceUi->enableBlinkingCursorButton, Profile::BlinkingCursorEnabled, SLOT(toggleBlinkingCursor(bool)) }, { - _ui->enableBidiRenderingButton, Profile::BidiRenderingEnabled, + _advancedUi->enableBidiRenderingButton, Profile::BidiRenderingEnabled, SLOT(togglebidiRendering(bool)) }, { - _ui->enableReverseUrlHints, Profile::ReverseUrlHints, + _advancedUi->enableReverseUrlHints, Profile::ReverseUrlHints, SLOT(toggleReverseUrlHints(bool)) } }; setupCheckBoxes(options, profile); // Setup the URL hints modifier checkboxes { auto modifiers = profile->property(Profile::UrlHintsModifiers); - _ui->urlHintsModifierShift->setChecked((modifiers &Qt::ShiftModifier) != 0u); - _ui->urlHintsModifierCtrl->setChecked((modifiers &Qt::ControlModifier) != 0u); - _ui->urlHintsModifierAlt->setChecked((modifiers &Qt::AltModifier) != 0u); - _ui->urlHintsModifierMeta->setChecked((modifiers &Qt::MetaModifier) != 0u); - connect(_ui->urlHintsModifierShift, &QCheckBox::toggled, this, &EditProfileDialog::updateUrlHintsModifier); - connect(_ui->urlHintsModifierCtrl, &QCheckBox::toggled, this, &EditProfileDialog::updateUrlHintsModifier); - connect(_ui->urlHintsModifierAlt, &QCheckBox::toggled, this, &EditProfileDialog::updateUrlHintsModifier); - connect(_ui->urlHintsModifierMeta, &QCheckBox::toggled, this, &EditProfileDialog::updateUrlHintsModifier); - } - - const int lineSpacing = profile->lineSpacing(); - _ui->lineSpacingSpinner->setValue(lineSpacing); - - connect(_ui->lineSpacingSpinner, static_cast(&QSpinBox::valueChanged), this, &Konsole::EditProfileDialog::lineSpacingChanged); - - // cursor options - if (profile->useCustomCursorColor()) { - _ui->customCursorColorButton->setChecked(true); - } else { - _ui->autoCursorColorButton->setChecked(true); + _advancedUi->urlHintsModifierShift->setChecked((modifiers &Qt::ShiftModifier) != 0u); + _advancedUi->urlHintsModifierCtrl->setChecked((modifiers &Qt::ControlModifier) != 0u); + _advancedUi->urlHintsModifierAlt->setChecked((modifiers &Qt::AltModifier) != 0u); + _advancedUi->urlHintsModifierMeta->setChecked((modifiers &Qt::MetaModifier) != 0u); + connect(_advancedUi->urlHintsModifierShift, &QCheckBox::toggled, this, &EditProfileDialog::updateUrlHintsModifier); + connect(_advancedUi->urlHintsModifierCtrl, &QCheckBox::toggled, this, &EditProfileDialog::updateUrlHintsModifier); + connect(_advancedUi->urlHintsModifierAlt, &QCheckBox::toggled, this, &EditProfileDialog::updateUrlHintsModifier); + connect(_advancedUi->urlHintsModifierMeta, &QCheckBox::toggled, this, &EditProfileDialog::updateUrlHintsModifier); } - _ui->customColorSelectButton->setColor(profile->customCursorColor()); - - connect(_ui->customCursorColorButton, &QRadioButton::clicked, this, &Konsole::EditProfileDialog::customCursorColor); - connect(_ui->autoCursorColorButton, &QRadioButton::clicked, this, &Konsole::EditProfileDialog::autoCursorColor); - connect(_ui->customColorSelectButton, &KColorButton::changed, this, &Konsole::EditProfileDialog::customCursorColorChanged); - - auto shape = profile->property(Profile::CursorShape); - _ui->cursorShapeCombo->setCurrentIndex(shape); - - connect(_ui->cursorShapeCombo, static_cast(&KComboBox::activated), this, &Konsole::EditProfileDialog::setCursorShape); - // encoding options auto codecAction = new KCodecAction(this); - _ui->selectEncodingButton->setMenu(codecAction->menu()); + _advancedUi->selectEncodingButton->setMenu(codecAction->menu()); connect(codecAction, static_cast(&KCodecAction::triggered), this, &Konsole::EditProfileDialog::setDefaultCodec); - _ui->characterEncodingLabel->setText(profile->defaultEncoding()); + _advancedUi->selectEncodingButton->setText(profile->defaultEncoding()); } -void EditProfileDialog::setDefaultCodec(QTextCodec *codec) +int EditProfileDialog::maxSpinBoxWidth(const KPluralHandlingSpinBox *spinBox, const KLocalizedString &suffix) { - QString name = QString::fromLocal8Bit(codec->name()); + static const int cursorWidth = 2; - updateTempProfileProperty(Profile::DefaultEncoding, name); - _ui->characterEncodingLabel->setText(name); -} + const QFontMetrics fm(spinBox->fontMetrics()); + const QString plural = suffix.subs(2).toString(); + const QString singular = suffix.subs(1).toString(); + const QString min = QString::number(spinBox->minimum()); + const QString max = QString::number(spinBox->maximum()); + const int pluralWidth = fm.width(plural); + const int singularWidth = fm.width(singular); + const int minWidth = fm.width(min); + const int maxWidth = fm.width(max); + const int width = qMax(pluralWidth, singularWidth) + qMax(minWidth, maxWidth) + cursorWidth; -void EditProfileDialog::customCursorColorChanged(const QColor &color) -{ - updateTempProfileProperty(Profile::CustomCursorColor, color); + // Based on QAbstractSpinBox::initStyleOption() from Qt + QStyleOptionSpinBox opt; + opt.initFrom(spinBox); + opt.activeSubControls = QStyle::SC_None; + opt.buttonSymbols = spinBox->buttonSymbols(); + // Assume all spinboxes have buttons + opt.subControls = QStyle::SC_SpinBoxFrame | QStyle::SC_SpinBoxEditField + | QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown; + opt.frame = spinBox->hasFrame(); - // ensure that custom cursor colors are enabled - _ui->customCursorColorButton->click(); -} + const QSize hint(width, spinBox->sizeHint().height()); + const QSize spinBoxSize = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, spinBox) + .expandedTo(QApplication::globalStrut()); -void EditProfileDialog::wordCharactersChanged(const QString &text) -{ - updateTempProfileProperty(Profile::WordCharacters, text); + return spinBoxSize.width(); } -void EditProfileDialog::autoCursorColor() +void EditProfileDialog::setDefaultCodec(QTextCodec *codec) { - updateTempProfileProperty(Profile::UseCustomCursorColor, false); -} + QString name = QString::fromLocal8Bit(codec->name()); -void EditProfileDialog::customCursorColor() -{ - updateTempProfileProperty(Profile::UseCustomCursorColor, true); + updateTempProfileProperty(Profile::DefaultEncoding, name); + _advancedUi->selectEncodingButton->setText(name); } -void EditProfileDialog::setCursorShape(int index) +void EditProfileDialog::wordCharactersChanged(const QString &text) { - updateTempProfileProperty(Profile::CursorShape, index); + updateTempProfileProperty(Profile::WordCharacters, text); } void EditProfileDialog::togglebidiRendering(bool enable) { updateTempProfileProperty(Profile::BidiRenderingEnabled, enable); } -void EditProfileDialog::lineSpacingChanged(int spacing) -{ - updateTempProfileProperty(Profile::LineSpacing, spacing); -} - -void EditProfileDialog::toggleBlinkingCursor(bool enable) -{ - updateTempProfileProperty(Profile::BlinkingCursorEnabled, enable); -} - void EditProfileDialog::toggleUnderlineLinks(bool enable) { updateTempProfileProperty(Profile::UnderlineLinksEnabled, enable); - bool enableClick = _ui->underlineFilesButton->isChecked() || enable; - _ui->openLinksByDirectClickButton->setEnabled(enableClick); + bool enableClick = _mouseUi->underlineFilesButton->isChecked() || enable; + _mouseUi->openLinksByDirectClickButton->setEnabled(enableClick); } void EditProfileDialog::toggleUnderlineFiles(bool enable) { updateTempProfileProperty(Profile::UnderlineFilesEnabled, enable); - bool enableClick = _ui->underlineLinksButton->isChecked() || enable; - _ui->openLinksByDirectClickButton->setEnabled(enableClick); + bool enableClick = _mouseUi->underlineLinksButton->isChecked() || enable; + _mouseUi->openLinksByDirectClickButton->setEnabled(enableClick); } void EditProfileDialog::toggleCtrlRequiredForDrag(bool enable) { updateTempProfileProperty(Profile::CtrlRequiredForDrag, enable); } void EditProfileDialog::toggleDropUrlsAsText(bool enable) { updateTempProfileProperty(Profile::DropUrlsAsText, enable); } void EditProfileDialog::toggleOpenLinksByDirectClick(bool enable) { updateTempProfileProperty(Profile::OpenLinksByDirectClickEnabled, enable); } void EditProfileDialog::toggleCopyTextAsHTML(bool enable) { updateTempProfileProperty(Profile::CopyTextAsHTML, enable); } void EditProfileDialog::toggleCopyTextToClipboard(bool enable) { updateTempProfileProperty(Profile::AutoCopySelectedText, enable); } void EditProfileDialog::toggleTrimLeadingSpacesInSelectedText(bool enable) { updateTempProfileProperty(Profile::TrimLeadingSpacesInSelectedText, enable); } void EditProfileDialog::toggleTrimTrailingSpacesInSelectedText(bool enable) { updateTempProfileProperty(Profile::TrimTrailingSpacesInSelectedText, enable); } void EditProfileDialog::pasteFromX11Selection() { updateTempProfileProperty(Profile::MiddleClickPasteMode, Enum::PasteFromX11Selection); } void EditProfileDialog::pasteFromClipboard() { updateTempProfileProperty(Profile::MiddleClickPasteMode, Enum::PasteFromClipboard); } void EditProfileDialog::TripleClickModeChanged(int newValue) { updateTempProfileProperty(Profile::TripleClickMode, newValue); } void EditProfileDialog::updateUrlHintsModifier(bool) { Qt::KeyboardModifiers modifiers; - if (_ui->urlHintsModifierShift->isChecked()) { + if (_advancedUi->urlHintsModifierShift->isChecked()) { modifiers |= Qt::ShiftModifier; } - if (_ui->urlHintsModifierCtrl->isChecked()) { + if (_advancedUi->urlHintsModifierCtrl->isChecked()) { modifiers |= Qt::ControlModifier; } - if (_ui->urlHintsModifierAlt->isChecked()) { + if (_advancedUi->urlHintsModifierAlt->isChecked()) { modifiers |= Qt::AltModifier; } - if (_ui->urlHintsModifierMeta->isChecked()) { + if (_advancedUi->urlHintsModifierMeta->isChecked()) { modifiers |= Qt::MetaModifier; } updateTempProfileProperty(Profile::UrlHintsModifiers, int(modifiers)); } void EditProfileDialog::toggleReverseUrlHints(bool enable) { updateTempProfileProperty(Profile::ReverseUrlHints, enable); } void EditProfileDialog::toggleBlinkingText(bool enable) { updateTempProfileProperty(Profile::BlinkingTextEnabled, enable); } void EditProfileDialog::toggleFlowControl(bool enable) { updateTempProfileProperty(Profile::FlowControlEnabled, enable); } -void EditProfileDialog::fontSelected(const QFont &aFont) -{ - QFont previewFont = aFont; - - setFontInputValue(aFont); - - _ui->fontPreviewLabel->setFont(previewFont); - - preview(Profile::Font, aFont); - updateTempProfileProperty(Profile::Font, aFont); -} - -void EditProfileDialog::showFontDialog() -{ - QFont currentFont = _ui->fontPreviewLabel->font(); - bool showAllFonts = _ui->showAllFontsButton->isChecked(); - - bool result; - if (showAllFonts) { - currentFont = QFontDialog::getFont(&result, currentFont, this, - i18n("Select Any Font")); - } else { - currentFont = QFontDialog::getFont(&result, currentFont, this, - i18n("Select Fixed Width Font"), - QFontDialog::MonospacedFonts); - } - if (!result) { - return; - } - - fontSelected(currentFont); -} - -void EditProfileDialog::setFontSize(double pointSize) -{ - QFont newFont = _ui->fontPreviewLabel->font(); - newFont.setPointSizeF(pointSize); - _ui->fontPreviewLabel->setFont(newFont); - - preview(Profile::Font, newFont); - updateTempProfileProperty(Profile::Font, newFont); -} - -void EditProfileDialog::setFontInputValue(const QFont &aFont) -{ - _ui->fontSizeInput->setValue(aFont.pointSizeF()); -} - ColorSchemeViewDelegate::ColorSchemeViewDelegate(QObject *parent) : QAbstractItemDelegate(parent) { } void ColorSchemeViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { const auto *scheme = index.data(Qt::UserRole + 1).value(); QFont profileFont = index.data(Qt::UserRole + 2).value(); Q_ASSERT(scheme); if (scheme == nullptr) { return; } painter->setRenderHint(QPainter::Antialiasing); // Draw background QStyle *style = option.widget != nullptr ? option.widget->style() : QApplication::style(); style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, option.widget); // Draw name QPalette::ColorRole textColor = ((option.state & QStyle::State_Selected) != 0) ? QPalette::HighlightedText : QPalette::Text; painter->setPen(option.palette.color(textColor)); painter->setFont(option.font); // Determine width of sample text using profile's font const QString sampleText = i18n("AaZz09..."); QFontMetrics profileFontMetrics(profileFont); const int sampleTextWidth = profileFontMetrics.width(sampleText); painter->drawText(option.rect.adjusted(sampleTextWidth + 15, 0, 0, 0), Qt::AlignLeft | Qt::AlignVCenter, index.data(Qt::DisplayRole).toString()); // Draw the preview const int x = option.rect.left(); const int y = option.rect.top(); QRect previewRect(x + 4, y + 4, sampleTextWidth + 8, option.rect.height() - 8); bool transparencyAvailable = KWindowSystem::compositingActive(); if (transparencyAvailable) { painter->save(); QColor color = scheme->backgroundColor(); color.setAlphaF(scheme->opacity()); painter->setPen(Qt::NoPen); painter->setCompositionMode(QPainter::CompositionMode_Source); painter->setBrush(color); painter->drawRect(previewRect); painter->restore(); } else { painter->setPen(Qt::NoPen); painter->setBrush(scheme->backgroundColor()); painter->drawRect(previewRect); } // draw color scheme name using scheme's foreground color QPen pen(scheme->foregroundColor()); painter->setPen(pen); // TODO: respect antialias setting painter->setFont(profileFont); painter->drawText(previewRect, Qt::AlignCenter, sampleText); } QSize ColorSchemeViewDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex & /*index*/) const { const int width = 200; const int margin = 5; const int colorWidth = width / TABLE_COLORS; const int heightForWidth = (colorWidth * 2) + option.fontMetrics.height() + margin; // temporary return {width, heightForWidth}; } diff --git a/src/EditProfileDialog.h b/src/EditProfileDialog.h index ad037f6f..6fa5d43f 100644 --- a/src/EditProfileDialog.h +++ b/src/EditProfileDialog.h @@ -1,320 +1,481 @@ /* Copyright 2007-2008 by Robert Knight Copyright 2018 by Harald Sitter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef EDITPROFILEDIALOG_H #define EDITPROFILEDIALOG_H // Qt #include #include #include #include +#include +#include +#include +#include +#include // KDE +#include #include // Konsole #include "Profile.h" #include "Enumeration.h" #include "ColorScheme.h" #include "ColorSchemeEditor.h" #include "KeyboardTranslatorManager.h" +#include "FontDialog.h" -class QAbstractButton; +// Backward compatibility +#if QT_VERSION < QT_VERSION_CHECK(5, 7, 0) +#define qAsConst(code) +#endif + +class KPluralHandlingSpinBox; +class KLocalizedString; class QItemSelectionModel; -class QTextCodec; -class QDialogButtonBox; namespace Ui { -class EditProfileDialog; + class EditProfileGeneralPage; + class EditProfileTabsPage; + class EditProfileAppearancePage; + class EditProfileScrollingPage; + class EditProfileKeyboardPage; + class EditProfileMousePage; + class EditProfileAdvancedPage; } namespace Konsole { /** * A dialog which allows the user to edit a profile. * After the dialog is created, it can be initialized with the settings * for a profile using setProfile(). When the user makes changes to the * dialog and accepts the changes, the dialog will update the * profile in the SessionManager by calling the SessionManager's * changeProfile() method. * * Some changes made in the dialog are preview-only changes which cause * the SessionManager's changeProfile() method to be called with * the persistent argument set to false. These changes are then * un-done when the dialog is closed. */ -class KONSOLEPRIVATE_EXPORT EditProfileDialog : public QDialog +class KONSOLEPRIVATE_EXPORT EditProfileDialog: public KPageDialog { Q_OBJECT public: /** Constructs a new dialog with the specified parent. */ explicit EditProfileDialog(QWidget *parent = nullptr); ~EditProfileDialog() Q_DECL_OVERRIDE; /** * Initializes the dialog with the settings for the specified session * type. * * When the dialog closes, the profile will be updated in the SessionManager * with the altered settings. * * @param profile The profile to be edited */ void setProfile(Profile::Ptr profile); /** * Selects the text in the profile name edit area. * When the dialog is being used to create a new profile, * this can be used to draw the user's attention to the profile name * and make it easy for them to change it. */ void selectProfileName(); const Profile::Ptr lookupProfile() const; public Q_SLOTS: // reimplemented void accept() Q_DECL_OVERRIDE; // reimplemented void reject() Q_DECL_OVERRIDE; void apply(); protected: bool eventFilter(QObject *watched, QEvent *event) Q_DECL_OVERRIDE; private Q_SLOTS: + QSize sizeHint() const override; + // sets up the specified tab page if necessary - void preparePage(int); + void preparePage(KPageWidgetItem *current, KPageWidgetItem *before = nullptr); // saves changes to profile void save(); // general page void selectInitialDir(); void selectIcon(); void profileNameChanged(const QString &name); void initialDirChanged(const QString &dir); void startInSameDir(bool); void commandChanged(const QString &command); void tabTitleFormatChanged(const QString &format); void remoteTabTitleFormatChanged(const QString &format); void terminalColumnsEntryChanged(int); void terminalRowsEntryChanged(int); void showTerminalSizeHint(bool); void setDimWhenInactive(bool); void showEnvironmentEditor(); void silenceSecondsChanged(int); // appearance page - void setFontSize(double pointSize); - void setFontInputValue(const QFont &); - void showAllFontsButtonWarning(bool enable); void setAntialiasText(bool enable); void setBoldIntense(bool enable); void useFontLineCharacters(bool enable); - void showFontDialog(); void newColorScheme(); void editColorScheme(); void saveColorScheme(const ColorScheme &scheme, bool isNewScheme); void removeColorScheme(); void gotNewColorSchemes(const KNS3::Entry::List &changedEntries); + void toggleBlinkingCursor(bool); + void setCursorShape(int); + void autoCursorColor(); + void customCursorColor(); + void customCursorColorChanged(const QColor &); + void terminalMarginChanged(int margin); + void lineSpacingChanged(int); + void setTerminalCenter(bool enable); + /** * Deletes the selected colorscheme from the user's home dir location * so that the original one from the system-wide location can be used * instead */ void resetColorScheme(); void colorSchemeSelected(); void previewColorScheme(const QModelIndex &index); - void fontSelected(const QFont &); + void showFontDialog(); void toggleMouseWheelZoom(bool enable); // scrolling page void historyModeChanged(Enum::HistoryModeEnum mode); void historySizeChanged(int); - void hideScrollBar(); - void showScrollBarLeft(); - void showScrollBarRight(); - void scrollFullPage(); void scrollHalfPage(); // keyboard page void editKeyBinding(); void newKeyBinding(); void keyBindingSelected(); void removeKeyBinding(); void resetKeyBindings(); // mouse page void toggleUnderlineFiles(bool enable); void toggleUnderlineLinks(bool); void toggleOpenLinksByDirectClick(bool); void toggleCtrlRequiredForDrag(bool); void toggleDropUrlsAsText(bool); void toggleCopyTextToClipboard(bool); void toggleCopyTextAsHTML(bool); void toggleTrimLeadingSpacesInSelectedText(bool); void toggleTrimTrailingSpacesInSelectedText(bool); void pasteFromX11Selection(); void pasteFromClipboard(); void toggleAlternateScrolling(bool enable); void TripleClickModeChanged(int); void wordCharactersChanged(const QString &); // advanced page void toggleBlinkingText(bool); void toggleFlowControl(bool); void togglebidiRendering(bool); - void lineSpacingChanged(int); - void toggleBlinkingCursor(bool); void updateUrlHintsModifier(bool); void toggleReverseUrlHints(bool); - void setCursorShape(int); - void autoCursorColor(); - void customCursorColor(); - void customCursorColorChanged(const QColor &); void setDefaultCodec(QTextCodec *); // apply the first previewed changes stored up by delayedPreview() void delayedPreviewActivate(); private: Q_DISABLE_COPY(EditProfileDialog) + enum PageID { + GeneralPage = 0, + TabsPage, + AppearancePage, + ScrollingPage, + KeyboardPage, + MousePage, + AdvancedPage, + + PagesCount, + }; + // initialize various pages of the dialog - void setupGeneralPage(const Profile::Ptr profile); - void setupTabsPage(const Profile::Ptr profile); - void setupAppearancePage(const Profile::Ptr profile); - void setupKeyboardPage(const Profile::Ptr profile); - void setupScrollingPage(const Profile::Ptr profile); - void setupAdvancedPage(const Profile::Ptr profile); - void setupMousePage(const Profile::Ptr info); + void setupGeneralPage(const Profile::Ptr &profile); + void setupTabsPage(const Profile::Ptr &profile); + void setupAppearancePage(const Profile::Ptr &profile); + void setupKeyboardPage(const Profile::Ptr &profile); + void setupScrollingPage(const Profile::Ptr &profile); + void setupAdvancedPage(const Profile::Ptr &profile); + void setupMousePage(const Profile::Ptr &profile); + + int maxSpinBoxWidth(const KPluralHandlingSpinBox *spinBox, const KLocalizedString &suffix); // Returns the name of the colorScheme used in the current profile const QString currentColorSchemeName() const; // select @p selectedColorSchemeName after the changes are saved // in the colorScheme editor void updateColorSchemeList(const QString &selectedColorSchemeName = QString()); void updateColorSchemeButtons(); // Convenience method KeyboardTranslatorManager *_keyManager = KeyboardTranslatorManager::instance(); // Updates the key bindings list widget on the Keyboard tab and selects // @p selectKeyBindingsName void updateKeyBindingsList(const QString &selectKeyBindingsName = QString()); void updateKeyBindingsButtons(); void showKeyBindingEditor(bool isNewTranslator); void showColorSchemeEditor(bool isNewScheme); void closeColorSchemeEditor(); void preview(int property, const QVariant &value); void delayedPreview(int property, const QVariant &value); void unpreview(int property); void unpreviewAll(); void enableIfNonEmptySelection(QWidget *widget, QItemSelectionModel *selectionModel); void updateCaption(const Profile::Ptr profile); void updateTransparencyWarning(); + void updateFontPreview(QFont font); + // Update _tempProfile in a way of respecting the apply button. // When used with some previewed property, this method should // always come after the preview operation. void updateTempProfileProperty(Profile::Property, const QVariant &value); // helper method for creating an empty & hidden profile and assigning // it to _tempProfile. void createTempProfile(); // Enable or disable apply button, used only within // updateTempProfileProperty(). void updateButtonApply(); static QString groupProfileNames(const ProfileGroup::Ptr group, int maxLength = -1); struct RadioOption { QAbstractButton *button; int value; const char *slot; }; void setupRadio(const QVector& possibilities, int actual); struct BooleanOption { QAbstractButton *button; Profile::Property property; const char *slot; }; - void setupCheckBoxes(const QVector& options, const Profile::Ptr profile); + void setupCheckBoxes(const QVector& options, const Profile::Ptr &profile); + + struct ButtonGroupOption { + QAbstractButton *button; + int value; + }; + struct ButtonGroupOptions { + QButtonGroup *group; + Profile::Property profileProperty; + bool preview; + QVector buttons; + }; + void setupButtonGroup(const ButtonGroupOptions &options, const Profile::Ptr &profile); // returns false if: // - the profile name is empty // - the name matches the name of an already existing profile // - the existing profile config file is read-only // otherwise returns true. bool isValidProfileName(); - Ui::EditProfileDialog *_ui; + Ui::EditProfileGeneralPage *_generalUi; + Ui::EditProfileTabsPage *_tabsUi; + Ui::EditProfileAppearancePage *_appearanceUi; + Ui::EditProfileScrollingPage *_scrollingUi; + Ui::EditProfileKeyboardPage *_keyboardUi; + Ui::EditProfileMousePage *_mouseUi; + Ui::EditProfileAdvancedPage *_advancedUi; + + using PageSetupMethod = void (EditProfileDialog::*)(const Profile::Ptr &); + struct Page { + Page(PageSetupMethod setupPage = nullptr, bool needsUpdate = false) + : setupPage(setupPage) + , needsUpdate(needsUpdate) + {} + + PageSetupMethod setupPage; + bool needsUpdate; + }; + + QMap _pages; + Profile::Ptr _tempProfile; Profile::Ptr _profile; - // keeps track of pages which need to be updated to match the current - // profile. all elements in this vector are set to true when the - // profile is changed and individual elements are set to false - // after an update by a call to ensurePageLoaded() - QVector _pageNeedsUpdate; QHash _previewedProperties; QHash _delayedPreviewProperties; QTimer *_delayedPreviewTimer; ColorSchemeEditor *_colorDialog; - QDialogButtonBox *mButtonBox; + QDialogButtonBox *_buttonBox; + FontDialog *_fontDialog; }; /** * A delegate which can display and edit color schemes in a view. */ class ColorSchemeViewDelegate : public QAbstractItemDelegate { Q_OBJECT public: explicit ColorSchemeViewDelegate(QObject *parent = nullptr); // reimplemented void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE; }; + +/** + * An utility class for aligning 0th column in multiple QGridLayouts. + * + * Limitations: + * - a layout can't be nested in another layout + * - reference widget must be an ancestor of all added layouts + * - only 0th column is processed (widgets spanning multiple columns + * are ignored) + */ +class LabelsAligner: public QObject { + Q_OBJECT + +public: + LabelsAligner(QWidget *refWidget): _refWidget(refWidget) {} + + void addLayout(QGridLayout *layout) { _layouts.append(layout); } + void addLayouts(const QVector &layouts) { _layouts.append(layouts); } + void setReferenceWidget(QWidget *refWidget) { _refWidget = refWidget; } + +public Q_SLOTS: + void updateLayouts() { + for (const auto *layout: qAsConst(_layouts)) { + QWidget *widget = layout->parentWidget(); + Q_ASSERT(widget); + do { + QLayout *widgetLayout = widget->layout(); + if (widgetLayout) { + widgetLayout->update(); + widgetLayout->activate(); + } + widget = widget->parentWidget(); + } while (widget != _refWidget && widget != nullptr); + } + } + + void align() { + Q_ASSERT(_refWidget); + + if (_layouts.count() <= 1) { + return; + } + + int maxRight = 0; + for (const auto *layout: qAsConst(_layouts)) { + int left = getLeftMargin(layout); + for (int row = 0; row < layout->rowCount(); ++row) { + QLayoutItem *layoutItem = layout->itemAtPosition(row, LABELS_COLUMN); + if (!layoutItem) { + continue; + } + QWidget *widget = layoutItem->widget(); + if (!widget) { + continue; + } + const int idx = layout->indexOf(widget); + int rows, cols, rowSpan, colSpan; + layout->getItemPosition(idx, &rows, &cols, &rowSpan, &colSpan); + if (colSpan > 1) { + continue; + } + + const int right = left + widget->sizeHint().width(); + if (maxRight < right) { + maxRight = right; + } + } + } + + for (auto *l: qAsConst(_layouts)) { + int left = getLeftMargin(l); + l->setColumnMinimumWidth(LABELS_COLUMN, maxRight - left); + } + } + +private: + int getLeftMargin(const QGridLayout *layout) { + int left = layout->contentsMargins().left(); + + if (layout->parent()->isWidgetType()) { + auto *parentWidget = layout->parentWidget(); + Q_ASSERT(parentWidget); + left += parentWidget->contentsMargins().left(); + } else { + auto *parentLayout = qobject_cast(layout->parent()); + Q_ASSERT(parentLayout); + left += parentLayout->contentsMargins().left(); + } + + QWidget *parent = layout->parentWidget(); + while (parent != _refWidget && parent != nullptr) { + left = parent->mapToParent(QPoint(left, 0)).x(); + parent = parent->parentWidget(); + } + return left; + }; + + static constexpr int LABELS_COLUMN = 0; + + QWidget *_refWidget; + QVector _layouts; +}; + } #endif // EDITPROFILEDIALOG_H diff --git a/src/EditProfileDialog.ui b/src/EditProfileDialog.ui deleted file mode 100644 index d69b3341..00000000 --- a/src/EditProfileDialog.ui +++ /dev/null @@ -1,1591 +0,0 @@ - - - EditProfileDialog - - - - 0 - 0 - 594 - 536 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - 0 - - - true - - - - General - - - - - - General - - - true - - - - - - - - - 0 - 0 - - - - - 64 - 64 - - - - - 0 - 0 - - - - Select the icon displayed on tabs using this profile - - - - - - - 48 - 48 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - Profile name: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - A descriptive name for the profile - - - - - - - - - Command: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - The command to execute when new terminal sessions are created using this profile - - - Qt::LeftToRight - - - - - - - Initial directory: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - The initial working directory for new terminal sessions using this profile - - - Qt::LeftToRight - - - - - - - Choose the initial directory - - - ... - - - - - - - Start in same directory as current tab - - - - - - - - - Environment: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Edit the list of environment variables and associated values - - - Edit... - - - - - - - Qt::Horizontal - - - - 81 - 20 - - - - - - - - - - - - - Terminal Size - - - true - - - - - - Columns - - - - - - - 1 - - - 500 - - - - - - - Rows - - - - - - - 1 - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 40 - 20 - - - - - - - - This will not alter any open windows. - - - - - - - Qt::Horizontal - - - - 81 - 20 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 40 - 20 - - - - - - - - Configure Konsole->General->Use current window size on next startup must be disabled for these entries to work. - - - true - - - - - - - - - - Window - - - true - - - - - - Show terminal size in columns and lines in the center of window after resizing - - - Show hint for terminal size after resizing - - - - - - - Indicate whether the window is active by dimming the colors - - - Dim the colors when the window loses focus - - - - - - - - - - Qt::Vertical - - - - 20 - 20 - - - - - - - - - Tabs - - - - - - Tab Titles - - - true - - - - - - - - - - - - Tab Monitoring - - - true - - - - - - Threshold for continuous silence: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - The threshold for continuous silence to be detected by Konsole - - - 1 - - - 3600 - - - - - - - Qt::Horizontal - - - - 20 - 20 - - - - - - - - - - - Qt::Vertical - - - - 20 - 10 - - - - - - - - - Appearance - - - - - - - 0 - 1 - - - - Color Scheme && Background - - - true - - - - - - Reset the selected color scheme settings to the default values - - - Defaults - - - - - - - Delete the selected color scheme - - - Remove - - - - - - - QAbstractItemView::ScrollPerPixel - - - - - - - Get New... - - - - - - - Create a new color scheme based upon the selected scheme - - - New... - - - - - - - Qt::Vertical - - - - 20 - 20 - - - - - - - - - - - Edit the selected color scheme - - - Edit... - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - - Font - - - true - - - - - - - - Preview: - - - - - - - - 1 - 0 - - - - KSqueezedTextLabel - - - Qt::ElideRight - - - - - - - - - - - Text size: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 1 - - - 4.000000000000000 - - - 999.000000000000000 - - - 1.000000000000000 - - - - - - - Select the font used in this profile - - - Select Font... - - - - - - - Show all fonts instead of the monospaced fonts - - - Show All Fonts - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Smooth fonts - - - - - - - Draw intense colors in bold font - - - - - - - Use the selected font for line characters instead of the builtin code - - - Use line characters contained in font - - - - - - - - - - - Scrolling - - - - - - Scrollback - - - true - - - - - - - - - - - - Scroll Bar - - - true - - - - - - - - - 0 - 0 - - - - Hide the scroll bar - - - Hide - - - - - - - - 0 - 0 - - - - Show the scroll bar on the left side of the terminal window - - - Show on left side - - - - - - - - 0 - 0 - - - - Show the scroll bar on the right side of the terminal window - - - Show on right side - - - - - - - - - - - - Scroll Page Up/Down Amount - - - true - - - - - - Scroll the page the half height of window - - - Half Page Height - - - - - - - Scroll the page the full height of window - - - Full Page Height - - - - - - - - - - Qt::Vertical - - - - 20 - 1 - - - - - - - - - Keyboard - - - - - - Key Bindings - - - true - - - - - - Key bindings control how combinations of keystrokes in the terminal window are converted into the stream of characters that is then sent to the current terminal program. For more information on how to customize the key bindings check the Konsole Handbook. - - - true - - - - - - - - 32 - 32 - - - - - - - - Create a new key bindings scheme based upon the selected bindings - - - New... - - - - - - - Edit the selected key bindings scheme - - - Edit... - - - - - - - Delete the selected key bindings scheme - - - Remove - - - - - - - Qt::Vertical - - - - 20 - 20 - - - - - - - - Reset the selected key bindings scheme to its default values - - - Defaults - - - - - - - - - - - Mouse - - - - - - Select Text - - - true - - - - - - - - Characters considered part of a word when double clicking: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - true - - - - - - - Characters which are considered part of a word when double-clicking to select whole words in the terminal - - - - - - - - - - - Triple-click select: - - - - - - - Which part of current line should be selected with triple click . - - - - The whole current line - - - - - From mouse position to the end of line - - - - - - - - - - - - - Copy && Paste - - - true - - - - - - - - Trim leading spaces in selected text, useful in some instances - - - Trim leading spaces - - - - - - - Trim trailing spaces in selected text, useful in some instances - - - Trim trailing spaces - - - - - - - - - - - Mouse middle button: - - - - - - - Paste from clipboard - - - - - - - Paste from selection - - - - - - - - - - - Automatically copy selected text into clipboard - - - Copy on select - - - - - - - Copy text as HTML (including formatting, font faces, colors... etc) - - - Copy text as HTML - - - - - - - - - - - - Miscellaneous - - - true - - - - - - Text recognized as a file will be underlined when hovered by the mouse pointer. - - - Underline files - - - - - - - Selected text will require control key plus click to drag. - - - Require Ctrl key for drag && drop - - - - - - - Always paste dropped files and URLs as text without offering move, copy and link actions. - - - Disable drag && drop menu for files && URLs - - - - - - - Mouse scroll wheel will emulate up/down key presses in programs that use the Alternate Screen buffer (e.g. less) - - - Enable Alternate Screen buffer scrolling - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 20 - - - - - - - - false - - - - 0 - 0 - - - - Text recognized as a file, link or an email address can be opened by direct mouse click. - - - Open by direct click - - - - - - - - - Text recognized as a link or an email address will be underlined when hovered by the mouse pointer. - - - Underline links - - - - - - - Pressing Ctrl+scrollwheel will increase/decrease the text size. - - - Allow Ctrl+scrollwheel to zoom text size - - - - - - - - - - - Advanced - - - - - - Terminal Features - - - true - - - - - - Show URL hints when these keys are pressed: - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - Shift - - - - - - - Control - - - - - - - Alt - - - - - - - Meta - - - - - - - - - Number URL hints in reverse, starting from the bottom - - - Reverse URL hint numbering - - - - - - - - 0 - 0 - - - - Allow terminal programs to create blinking sections of text - - - Allow blinking text - - - - - - - - 0 - 0 - - - - Allow the output to be suspended by pressing Ctrl+S - - - Enable flow control using Ctrl+S, Ctrl+Q - - - - - - - - 0 - 0 - - - - Enable Bi-Directional display on terminals (valid for Arabic, Farsi or Hebrew only) - - - Enable Bi-Directional text rendering - - - - - - - - - Line Spacing: - - - - - - - The number of pixels between two lines - - - 0 - - - 5 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - Cursor - - - true - - - - - - - 0 - 0 - - - - Make the cursor blink regularly - - - Blinking cursor - - - - - - - - - Cursor shape: - - - - - - - Change the shape of the cursor - - - - Block - - - - - I-Beam - - - - - Underline - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 0 - 0 - - - - Set the cursor to match the color of the character underneath it. - - - Set cursor color to match current character - - - - - - - - - - 0 - 0 - - - - Use a custom, fixed color for the cursor - - - Custom cursor color: - - - - - - - - 0 - 0 - - - - Select the color used to draw the cursor - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - Encoding - - - true - - - - - - Default character encoding: - - - - - - - - 0 - 0 - - - - DEFAULTENCODING - - - - - - - Select - - - - - - - - - - Qt::Vertical - - - - 20 - 20 - - - - - - - - - - - - - KComboBox - QComboBox -
kcombobox.h
-
- - KNS3::Button - QPushButton -
KNS3/Button
-
- - KPluralHandlingSpinBox - QSpinBox -
KPluralHandlingSpinBox
-
- - KColorButton - QPushButton -
kcolorbutton.h
-
- - KSqueezedTextLabel - QLabel -
ksqueezedtextlabel.h
-
- - KMessageWidget - QFrame -
kmessagewidget.h
- 1 -
- - Konsole::RenameTabWidget - QWidget -
RenameTabWidget.h
-
- - Konsole::HistorySizeWidget - QWidget -
HistorySizeWidget.h
-
-
- - -
diff --git a/src/EditProfileGeneralPage.ui b/src/EditProfileGeneralPage.ui new file mode 100644 index 00000000..03dddef9 --- /dev/null +++ b/src/EditProfileGeneralPage.ui @@ -0,0 +1,352 @@ + + + EditProfileGeneralPage + + + + 0 + 0 + 400 + 400 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 6 + + + + + + 0 + 0 + + + + + 48 + 48 + + + + + 0 + 0 + + + + Select the icon displayed on tabs using this profile + + + + + + + 32 + 32 + + + + + + + + A descriptive name for the profile + + + Profile name + + + + + + + + 0 + 0 + + + + Command: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + commandEdit + + + + + + + The command to execute when new terminal sessions are created using this profile + + + Qt::LeftToRight + + + /bin/sh + + + + + + + + 0 + 0 + + + + Initial directory: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + initialDirEdit + + + + + + + The initial working directory for new terminal sessions using this profile + + + Qt::LeftToRight + + + /home/username + + + + + + + Choose the initial directory + + + ... + + + + + + + Start in same directory as current tab + + + + + + + + 0 + 0 + + + + Environment: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + environmentEditButton + + + + + + + 0 + + + + + Edit the list of environment variables and associated values + + + Edit... + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 16 + + + + + + + + + 0 + 0 + + + + Initial terminal size: + + + terminalColumnsEntry + + + + + + + 0 + + + + + 6 + + + + + + 0 + 0 + + + + 1 + + + 999 + + + + + + + + 0 + 0 + + + + 1 + + + 999 + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + <html><head/><body><p><span style=" font-style:italic;">Settings → Configure Konsole → General → Use current window size on next startup</span> must be disabled for these entries to work.</p></body></html> + + + Qt::RichText + + + true + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 0 + + + + + + + + + KPluralHandlingSpinBox + QSpinBox +
KPluralHandlingSpinBox
+
+
+ + environmentEditButton + terminalColumnsEntry + terminalRowsEntry + + + +
\ No newline at end of file diff --git a/src/EditProfileKeyboardPage.ui b/src/EditProfileKeyboardPage.ui new file mode 100644 index 00000000..3ec0d442 --- /dev/null +++ b/src/EditProfileKeyboardPage.ui @@ -0,0 +1,138 @@ + + + EditProfileKeyboardPage + + + + 0 + 0 + 400 + 400 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Key bindings control how combinations of keystrokes in the terminal window are converted into the stream of characters that is then sent to the current terminal program. For more information on how to customize the key bindings check the Konsole Handbook. + + + true + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 32 + 32 + + + + + + + + 6 + + + + + Create a new key bindings scheme based upon the selected bindings + + + New... + + + + + + + Edit the selected key bindings scheme + + + Edit... + + + + + + + Delete the selected key bindings scheme + + + Remove + + + + + + + Reset the selected key bindings scheme to its default values + + + Defaults + + + + + + + + + Qt::Vertical + + + + 20 + 20 + + + + + + + + + + + keyBindingList + newKeyBindingsButton + editKeyBindingsButton + removeKeyBindingsButton + resetKeyBindingsButton + + + + \ No newline at end of file diff --git a/src/EditProfileMousePage.ui b/src/EditProfileMousePage.ui new file mode 100644 index 00000000..889e6d9c --- /dev/null +++ b/src/EditProfileMousePage.ui @@ -0,0 +1,385 @@ + + + EditProfileMousePage + + + + 0 + 0 + 400 + 400 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + Text interaction + + + + 0 + + + + + 6 + + + + + Characters which are considered part of a word when double-clicking to select whole words in the terminal. + + + Word characters: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + wordCharacterEdit + + + + + + + + Monospace + + + + Characters which are considered part of a word when double-clicking to select whole words in the terminal. + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 16 + + + + + + + + Triple-click selects: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + The whole line + + + tripleClickMode + + + + + + + From mouse position to the end of line + + + tripleClickMode + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 16 + + + + + + + + Middle-click pastes: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + From clipboard + + + pasteFrom + + + + + + + From selection + + + pasteFrom + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 16 + + + + + + + + Copy options: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Automatically copy selected text into clipboard + + + Copy on select + + + + + + + Copy text as HTML (including formatting, font faces, colors... etc) + + + Copy text as HTML + + + + + + + Trim leading spaces in selected text, useful in some instances + + + Trim leading spaces + + + + + + + Trim trailing spaces in selected text, useful in some instances + + + Trim trailing spaces + + + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + + Miscellaneous + + + + 0 + + + + + 6 + + + + + Text recognized as a link or an email address will be underlined when hovered by the mouse pointer. + + + Underline links + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 16 + 20 + + + + + + + + false + + + + 0 + 0 + + + + Text recognized as a file, link or an email address can be opened by direct mouse click. + + + Open by direct click + + + + + + + Text recognized as a file will be underlined when hovered by the mouse pointer. + + + Underline files + + + + + + + Selected text will require control key plus click to drag. + + + Require Ctrl key for drag && drop + + + + + + + Always paste dropped files and URLs as text without offering move, copy and link actions. + + + Disable drag && drop menu for files && URLs + + + + + + + Pressing Ctrl+scrollwheel will increase/decrease the text size. + + + Allow Ctrl+scrollwheel to zoom text size + + + + + + + Mouse scroll wheel will emulate up/down key presses in programs that use the Alternate Screen buffer (e.g. less) + + + Enable Alternate Screen buffer scrolling + + + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + + + + + tabWidget + + + + + + + + \ No newline at end of file diff --git a/src/EditProfileScrollingPage.ui b/src/EditProfileScrollingPage.ui new file mode 100644 index 00000000..7a8e0bed --- /dev/null +++ b/src/EditProfileScrollingPage.ui @@ -0,0 +1,222 @@ + + + EditProfileScrollingPage + + + + 0 + 0 + 400 + 400 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 6 + + + + + + 0 + 0 + + + + Scrollback: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 16 + + + + + + + + + 0 + 0 + + + + Scroll Page Up/Down: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + Scroll the page the half height of window + + + Half screen height + + + scrollAmount + + + + + + + Scroll the page the full height of window + + + Full screen height + + + scrollAmount + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 16 + + + + + + + + + 0 + 0 + + + + Scrollbar position: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Show the scroll bar on the right side of the terminal window + + + Right side + + + scrollBarPosition + + + + + + + Show the scroll bar on the left side of the terminal window + + + Left side + + + scrollBarPosition + + + + + + + Hidden + + + scrollBarPosition + + + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + + Konsole::HistorySizeWidget + QWidget +
HistorySizeWidget.h
+
+
+ + + + + + +
\ No newline at end of file diff --git a/src/EditProfileTabsPage.ui b/src/EditProfileTabsPage.ui new file mode 100644 index 00000000..340011f1 --- /dev/null +++ b/src/EditProfileTabsPage.ui @@ -0,0 +1,147 @@ + + + EditProfileTabsPage + + + + 0 + 0 + 400 + 400 + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 6 + + + + + Tab Titles + + + + + + + 0 + 0 + + + + + + + + + + + Tab Monitoring + + + + + + + 0 + 0 + + + + Threshold for continuous silence: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + silenceSecondsSpinner + + + + + + + The threshold for continuous silence to be detected by Konsole + + + 1 + + + 3600 + + + + + + + Qt::Horizontal + + + + 0 + 20 + + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 0 + + + + + + + + + Konsole::RenameTabWidget + QWidget +
RenameTabWidget.h
+
+ + KPluralHandlingSpinBox + QSpinBox +
KPluralHandlingSpinBox
+
+
+ + +
\ No newline at end of file diff --git a/src/FontDialog.cpp b/src/FontDialog.cpp new file mode 100644 index 00000000..88586d3c --- /dev/null +++ b/src/FontDialog.cpp @@ -0,0 +1,85 @@ +/* + Copyright 2018 by Mariusz Glebocki + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. +*/ + +// Own +#include "FontDialog.h" + +// Qt +#include +#include + +// KDE +#include +#include + +using namespace Konsole; + +FontDialog::FontDialog(QWidget *parent) : + QDialog(parent) + , _fontChooser(nullptr) + , _showAllFonts(nullptr) + , _buttonBox(nullptr) +{ + setWindowTitle(i18nc("@title:window", "Select font")); + + _fontChooser = new KFontChooser(this, KFontChooser::FixedFontsOnly); + _showAllFonts = new QCheckBox(i18n("Show all fonts"), this); + _showAllFontsWarningButton = new QToolButton(this); + _buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | + QDialogButtonBox::Cancel, + Qt::Horizontal, this); + + _fontChooser->setSampleText(QStringLiteral( + "0OQ 1Il!| 5S 8B rnm :; ,. \"'` ~-= ({[<>]})\n" + "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\n" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789\n" + "abcdefghijklmnopqrstuvwxyz" + )); + _showAllFontsWarningButton->setIcon(QIcon::fromTheme(QStringLiteral("emblem-warning"))); + _showAllFontsWarningButton->setAutoRaise(true); + + connect(_fontChooser, &KFontChooser::fontSelected, this, &FontDialog::fontChanged); + connect(_showAllFonts, &QCheckBox::toggled, this, [this](bool enable) { + _fontChooser->setFont(_fontChooser->font(), !enable); + }); + connect(_showAllFontsWarningButton, &QToolButton::clicked, this, [this](bool) { + const QString message = i18n("By its very nature, a terminal program requires font characters that are equal width (monospace). Any non monospaced font may cause display issues. This should not be necessary except in rare cases."); + const QPoint pos = QPoint(_showAllFonts->width() / 2, _showAllFonts->height()); + QWhatsThis::showText(_showAllFonts->mapToGlobal(pos), message, _showAllFonts); + }); + connect(_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + + auto *showAllFontsLayout = new QHBoxLayout(); + showAllFontsLayout->addWidget(_showAllFonts); + showAllFontsLayout->addWidget(_showAllFontsWarningButton); + showAllFontsLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding)); + showAllFontsLayout->setContentsMargins(0, 0, 0, 0); + showAllFontsLayout->setSpacing(0); + + auto *layout = new QVBoxLayout(this); + layout->addWidget(_fontChooser, 1); + layout->addLayout(showAllFontsLayout); + layout->addWidget(_buttonBox); +} + +void FontDialog::setFont(const QFont &font) +{ + _fontChooser->setFont(font, !_showAllFonts->isChecked()); +} diff --git a/src/FontDialog.h b/src/FontDialog.h new file mode 100644 index 00000000..f1eee057 --- /dev/null +++ b/src/FontDialog.h @@ -0,0 +1,33 @@ +#ifndef FONTDIALOG_H +#define FONTDIALOG_H + +// Qt +#include +#include +#include +#include +#include + +namespace Konsole { +class FontDialog: public QDialog +{ + Q_OBJECT + +public: + explicit FontDialog(QWidget *parent = nullptr); + + QFont font() const { return _fontChooser->font(); } + void setFont(const QFont &font); + +Q_SIGNALS: + void fontChanged(QFont font); + +private: + KFontChooser *_fontChooser; + QCheckBox *_showAllFonts; + QToolButton *_showAllFontsWarningButton; + QDialogButtonBox *_buttonBox; +}; +} + +#endif // FONTDIALOG_H diff --git a/src/HistorySizeDialog.cpp b/src/HistorySizeDialog.cpp index 17ab1fcb..afc9856a 100644 --- a/src/HistorySizeDialog.cpp +++ b/src/HistorySizeDialog.cpp @@ -1,87 +1,92 @@ /* Copyright 2007-2008 by Robert Knight Copyright 2012 by Kurt Hindenburg This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ // Own #include "HistorySizeDialog.h" // Konsole #include "ui_HistorySizeDialog.h" #include "Shortcut_p.h" #include #include #include #include using namespace Konsole; HistorySizeDialog::HistorySizeDialog(QWidget *parent) : QDialog(parent), _ui(nullptr) { setWindowTitle(i18nc("@title:window", "Adjust Scrollback")); auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); auto mainWidget = new QWidget(this); auto mainLayout = new QVBoxLayout; setLayout(mainLayout); mainLayout->addWidget(mainWidget); QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); connect(buttonBox, &QDialogButtonBox::accepted, this, &HistorySizeDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &HistorySizeDialog::reject); mainLayout->addWidget(buttonBox); setWindowModality(Qt::WindowModal); _ui = new Ui::HistorySizeDialog(); _ui->setupUi(mainWidget); _ui->tempWarningWidget->setVisible(true); - _ui->tempWarningWidget->setWordWrap(true); + _ui->tempWarningWidget->setWordWrap(false); _ui->tempWarningWidget->setCloseButtonVisible(false); _ui->tempWarningWidget->setMessageType(KMessageWidget::Information); _ui->tempWarningWidget->setText(i18nc("@info:status", "Any adjustments are only temporary to this session.")); } HistorySizeDialog::~HistorySizeDialog() { delete _ui; } void HistorySizeDialog::setMode(Enum::HistoryModeEnum aMode) { _ui->historySizeWidget->setMode(aMode); } Enum::HistoryModeEnum HistorySizeDialog::mode() const { return _ui->historySizeWidget->mode(); } int HistorySizeDialog::lineCount() const { return _ui->historySizeWidget->lineCount(); } void HistorySizeDialog::setLineCount(int lines) { _ui->historySizeWidget->setLineCount(lines); } + +QSize HistorySizeDialog::sizeHint() const { + return QSize(_ui->tempWarningWidget->sizeHint().width(), 0); +} + diff --git a/src/HistorySizeDialog.h b/src/HistorySizeDialog.h index db2b4cae..8750cb45 100644 --- a/src/HistorySizeDialog.h +++ b/src/HistorySizeDialog.h @@ -1,60 +1,62 @@ /* Copyright 2007-2008 by Robert Knight Copyright 2012 by Kurt Hindenburg This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef HISTORYSIZEDIALOG_H #define HISTORYSIZEDIALOG_H // KDE #include // Konsole #include "Enumeration.h" namespace Ui { class HistorySizeDialog; } namespace Konsole { class HistorySizeDialog : public QDialog { Q_OBJECT public: explicit HistorySizeDialog(QWidget *parent = nullptr); ~HistorySizeDialog() Q_DECL_OVERRIDE; /** See HistorySizeWidget::setMode. */ void setMode(Enum::HistoryModeEnum aMode); /** See HistorySizeWidget::mode. */ Enum::HistoryModeEnum mode() const; /** See HistorySizeWidget::setLineCount. */ void setLineCount(int lines); /** See HistorySizeWidget::lineCount. */ int lineCount() const; + QSize sizeHint() const override; + private: Ui::HistorySizeDialog *_ui; }; } #endif // HISTORYSIZEDIALOG_H diff --git a/src/HistorySizeDialog.ui b/src/HistorySizeDialog.ui index cd10286a..7be4ac67 100644 --- a/src/HistorySizeDialog.ui +++ b/src/HistorySizeDialog.ui @@ -1,57 +1,79 @@ HistorySizeDialog 0 0 - 325 - 47 + 400 + 48 - + + + 0 + + + 0 + + + 0 + + + 0 + - + 0 0 - + + + + 0 + 0 + + + - + Qt::Vertical + + QSizePolicy::MinimumExpanding + 20 - 18 + 16 KMessageWidget QFrame
kmessagewidget.h
1
Konsole::HistorySizeWidget QWidget
HistorySizeWidget.h
- - -
+ + + \ No newline at end of file diff --git a/src/HistorySizeWidget.cpp b/src/HistorySizeWidget.cpp index 3db17112..22972d17 100644 --- a/src/HistorySizeWidget.cpp +++ b/src/HistorySizeWidget.cpp @@ -1,133 +1,149 @@ /* Copyright 2007-2008 by Robert Knight Copyright 2012 by Jekyll Wu This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ // Own #include "HistorySizeWidget.h" // Qt #include #include +#include +#include #include // Konsole #include "ui_HistorySizeWidget.h" using namespace Konsole; HistorySizeWidget::HistorySizeWidget(QWidget *parent) : QWidget(parent), _ui(nullptr) { _ui = new Ui::HistorySizeWidget(); _ui->setupUi(this); - _ui->fixedSizeWarningWidget->setVisible(false); - _ui->fixedSizeWarningWidget->setWordWrap(true); - _ui->fixedSizeWarningWidget->setCloseButtonVisible(false); - _ui->fixedSizeWarningWidget->setMessageType(KMessageWidget::Information); - _ui->fixedSizeWarningWidget->setText(i18nc("@info:status", - "When using this option, the scrollback data will be saved " - "to RAM. If you choose a huge value, your system may run out " - "of free RAM and cause serious issues with your system.")); - - _ui->unlimitedWarningWidget->setVisible(false); - _ui->unlimitedWarningWidget->setWordWrap(true); - _ui->unlimitedWarningWidget->setCloseButtonVisible(false); - _ui->unlimitedWarningWidget->setMessageType(KMessageWidget::Information); - _ui->unlimitedWarningWidget->setText(i18nc("@info:status", - "When using this option, the scrollback data will be written " - "unencrypted to temporary files. Those temporary files will be " - "deleted automatically when Konsole is closed in a normal manner.\n" - "Use Settings->Configure Konsole->File Location to select the " - "location of the temporary files.")); - // focus and select the spinner automatically when appropriate _ui->fixedSizeHistoryButton->setFocusProxy(_ui->historyLineSpinner); connect(_ui->fixedSizeHistoryButton, &QRadioButton::clicked, _ui->historyLineSpinner, &KPluralHandlingSpinBox::selectAll); auto modeGroup = new QButtonGroup(this); modeGroup->addButton(_ui->noHistoryButton); modeGroup->addButton(_ui->fixedSizeHistoryButton); modeGroup->addButton(_ui->unlimitedHistoryButton); connect(modeGroup, static_cast(&QButtonGroup::buttonClicked), this, &Konsole::HistorySizeWidget::buttonClicked); _ui->historyLineSpinner->setSuffix(ki18ncp("@label:textbox Unit of scrollback", " line", " lines")); setLineCount(HistorySizeWidget::DefaultLineCount); connect(_ui->historyLineSpinner, static_cast(&KPluralHandlingSpinBox::valueChanged), this, &Konsole::HistorySizeWidget::historySizeChanged); + + auto warningButtonSizePolicy = _ui->fixedSizeHistoryWarningButton->sizePolicy(); + warningButtonSizePolicy.setRetainSizeWhenHidden(true); + + _ui->fixedSizeHistoryWarningButton->setSizePolicy(warningButtonSizePolicy); + _ui->fixedSizeHistoryWarningButton->hide(); + connect(_ui->fixedSizeHistoryButton, &QAbstractButton::toggled, _ui->historyLineSpinner, &QWidget::setEnabled); + connect(_ui->fixedSizeHistoryButton, &QAbstractButton::toggled, _ui->fixedSizeHistoryWarningButton, &QWidget::setVisible); + connect(_ui->fixedSizeHistoryWarningButton, &QToolButton::clicked, this, [this](bool) { + const QString message = i18nc("@info:whatsthis", "When using this option, the scrollback data will be saved to RAM. If you choose a huge value, your system may run out of free RAM and cause serious issues with your system."); + const QPoint pos = QPoint(_ui->fixedSizeHistoryWrapper->width() / 2, _ui->fixedSizeHistoryWrapper->height()); + QWhatsThis::showText(_ui->fixedSizeHistoryWrapper->mapToGlobal(pos), message, _ui->fixedSizeHistoryWrapper); + }); + + _ui->unlimitedHistoryWarningButton->setSizePolicy(warningButtonSizePolicy); + _ui->unlimitedHistoryWarningButton->hide(); + connect(_ui->unlimitedHistoryButton, &QAbstractButton::toggled, _ui->unlimitedHistoryWarningButton, &QWidget::setVisible); + connect(_ui->unlimitedHistoryWarningButton, &QToolButton::clicked, this, [this](bool) { + const auto message = i18nc("@info:whatsthis", "When using this option, the scrollback data will be written unencrypted to temporary files. Those temporary files will be deleted automatically when Konsole is closed in a normal manner.
Use Settings → Configure Konsole → File Location to select the location of the temporary files."); + const QPoint pos = QPoint(_ui->unlimitedHistoryWrapper->width() / 2, _ui->unlimitedHistoryWrapper->height()); + QWhatsThis::showText(_ui->unlimitedHistoryWrapper->mapToGlobal(pos), message, _ui->unlimitedHistoryWrapper); + }); + + // Make radio buttons height equal + // fixedSizeHistoryWrapper contains radio + spinbox + toolbutton, so it + // has height always equal to or larger than single radio button, and + // radio + toolbutton + const int radioButtonHeight = _ui->fixedSizeHistoryWrapper->sizeHint().height(); + _ui->noHistoryButton->setMinimumHeight(radioButtonHeight); + _ui->unlimitedHistoryButton->setMinimumHeight(radioButtonHeight); } HistorySizeWidget::~HistorySizeWidget() { delete _ui; } void HistorySizeWidget::buttonClicked(QAbstractButton *) { Enum::HistoryModeEnum selectedMode = mode(); - _ui->fixedSizeWarningWidget->setVisible(Enum::FixedSizeHistory == selectedMode); - _ui->unlimitedWarningWidget->setVisible(Enum::UnlimitedHistory == selectedMode); emit historyModeChanged(selectedMode); } void HistorySizeWidget::setMode(Enum::HistoryModeEnum aMode) { if (aMode == Enum::NoHistory) { _ui->noHistoryButton->setChecked(true); } else if (aMode == Enum::FixedSizeHistory) { _ui->fixedSizeHistoryButton->setChecked(true); } else if (aMode == Enum::UnlimitedHistory) { _ui->unlimitedHistoryButton->setChecked(true); } - _ui->fixedSizeWarningWidget->setVisible(Enum::FixedSizeHistory == aMode); - _ui->unlimitedWarningWidget->setVisible(Enum::UnlimitedHistory == aMode); } Enum::HistoryModeEnum HistorySizeWidget::mode() const { if (_ui->noHistoryButton->isChecked()) { return Enum::NoHistory; } else if (_ui->fixedSizeHistoryButton->isChecked()) { return Enum::FixedSizeHistory; } else if (_ui->unlimitedHistoryButton->isChecked()) { return Enum::UnlimitedHistory; } Q_ASSERT(false); return Enum::NoHistory; } void HistorySizeWidget::setLineCount(int lines) { _ui->historyLineSpinner->setValue(lines); _ui->historyLineSpinner->setSingleStep(lines / 10); } int HistorySizeWidget::lineCount() const { return _ui->historyLineSpinner->value(); } + +int HistorySizeWidget::preferredLabelHeight() +{ + Q_ASSERT(_ui); + Q_ASSERT(_ui->noHistoryButton); + + return _ui->fixedSizeHistoryWrapper->sizeHint().height(); +} diff --git a/src/HistorySizeWidget.h b/src/HistorySizeWidget.h index d3e82738..66515263 100644 --- a/src/HistorySizeWidget.h +++ b/src/HistorySizeWidget.h @@ -1,82 +1,88 @@ /* Copyright 2007-2008 by Robert Knight Copyright 2012 by Jekyll Wu This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef HISTORYSIZEWIDGET_H #define HISTORYSIZEWIDGET_H // Qt #include // Konsole #include "Enumeration.h" class QAbstractButton; namespace Ui { class HistorySizeWidget; } namespace Konsole { /** * A widget for controlling history related options */ class HistorySizeWidget : public QWidget { Q_OBJECT public: explicit HistorySizeWidget(QWidget *parent); ~HistorySizeWidget() Q_DECL_OVERRIDE; /** Specifies the history mode. */ void setMode(Enum::HistoryModeEnum aMode); /** Returns the history mode chosen by the user. */ Enum::HistoryModeEnum mode() const; /** Sets the number of lines for the fixed size history mode. */ void setLineCount(int lines); /** * Returns the number of lines of history to remember. * This is only valid when mode() == FixedSizeHistory, * and returns 0 otherwise. */ int lineCount() const; + /** + * Return height which should be set on the widget's label + * to align with the first widget's item + */ + int preferredLabelHeight(); + Q_SIGNALS: /** Emitted when the history mode is changed. */ void historyModeChanged(Enum::HistoryModeEnum); /** Emitted when the history size is changed. */ void historySizeChanged(int); private Q_SLOTS: void buttonClicked(QAbstractButton *); private: Ui::HistorySizeWidget *_ui; // 1000 lines was the default in the KDE3 series static const int DefaultLineCount = 1000; }; } #endif // HISTORYSIZEWIDGET_H diff --git a/src/HistorySizeWidget.ui b/src/HistorySizeWidget.ui index 5504e9b7..0554bbaf 100644 --- a/src/HistorySizeWidget.ui +++ b/src/HistorySizeWidget.ui @@ -1,138 +1,194 @@ HistorySizeWidget 0 0 - 400 - 143 + 320 + 84 - + 0 0 + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + - - - - 0 - 0 - - - - Do not remember previous output - - - No scrollback - - - - - - - QLayout::SetFixedSize - + - - - - 0 - 0 - - - - Limit the remembered output to a fixed number of lines - - - Fixed size scrollback: + + + 0 - + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Limit the remembered output to a fixed number of lines + + + Fixed size: + + + + + + + false + + + Number of lines of output to remember + + + 1 + + + 1000000 + + + + + + + + .. + + + true + + + + + + + + + + Qt::Horizontal + + + + 0 + 20 + + + + + - - - Number of lines of output to remember - - - 1 + + + 0 - - 1000000 - - + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Remember all output produced by the terminal + + + Unlimited + + + + + + + + .. + + + true + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - - - Qt::Horizontal + + + Do not remember previous output - - - 20 - 20 - + + None - + - - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - Remember all output produced by the terminal - - - Unlimited scrollback - - - - - - - - 0 - 0 - - - - KPluralHandlingSpinBox QSpinBox
KPluralHandlingSpinBox
- - KMessageWidget - QFrame -
kmessagewidget.h
- 1 -
- - -
+ + + \ No newline at end of file diff --git a/src/RenameTabDialog.ui b/src/RenameTabDialog.ui index 41f7f5c5..56f8db2c 100644 --- a/src/RenameTabDialog.ui +++ b/src/RenameTabDialog.ui @@ -1,28 +1,28 @@ RenameTabDialog 0 0 325 110 - + - + Konsole::RenameTabWidget QWidget
RenameTabWidget.h
- - -
+ + + \ No newline at end of file diff --git a/src/RenameTabWidget.ui b/src/RenameTabWidget.ui index 856ebdef..797c1edf 100644 --- a/src/RenameTabWidget.ui +++ b/src/RenameTabWidget.ui @@ -1,77 +1,119 @@ RenameTabWidget 0 0 - 325 - 110 + 400 + 50 - - - - - + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + Tab title format: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + tabTitleEdit + + + + + + + + 0 + 0 + - - true + + Normal tab title format - - - - - Tab title format: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Normal tab title format - - - - - - - - - - Remote tab title format: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Tab title format used when a remote command (e.g. connection to another computer via SSH) is being executed - - - - - - - + + + + + + + + 0 + 0 + + + + Remote tab title format: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + remoteTabTitleEdit + + + + + + + + 0 + 0 + + + + Tab title format used when a remote command (e.g. connection to another computer via SSH) is being executed + + + + + + Konsole::TabTitleFormatButton QPushButton
TabTitleFormatButton.h
- - -
+ + tabTitleEdit + tabTitleFormatButton + remoteTabTitleEdit + remoteTabTitleFormatButton + + + + \ No newline at end of file