diff --git a/debian/.gitignore b/.gitignore similarity index 100% rename from debian/.gitignore rename to .gitignore diff --git a/CHANGELOG b/CHANGELOG index 7a03b26..bc00be6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,53 @@ -qterminal-0.8.0 / 2017-10-21 +qterminal-0.9.0 / 2018-05-21 ============================ + * Bump version to 0.9.0 + * Spanish translation update + * Now building out-of-source is mandatory + * Fix tab texts, especially for vertical tabs + * CMake: Prevent in-source builds + * Fixed some lxde mentions + * Sort color schemes alphabetically + * Support modifying $TERM and use xterm-256color by default + * Convert connect to the new syntax - termwidgetholder.cpp + * Convert connect to the new syntax - termwidget.cpp + * Convert connect to the new syntax - tabwidget.cpp + * Convert connect to the new syntax - propertiesdialog.cpp + * Convert connect to the new syntax - mainwindow.cpp, part 1 + * Convert connect to the new syntax - fontdialog.cpp + * Convert connect to the new syntax - bookmarkswidget.cpp + * Fix tabbar + * Close tab on middle clicking + * A real shortcut editor + * Allow to change tab title color + * Make tab closing button configurable + * Make active tab text bold to make it more visible + * Fix a typo + * Fixes an error in the d3fa804 fix of #304 + * new config: show terminal size on resize + * Fixes #304 + * Fix bracket paste + * Fixes tabAt() when tabBar is not at north position + * Fix terminal menubar + * Drop Qt foreach + * Set QTERMWIDGET_MINIMUM_VERSION + * Fix a typo in qterminal_drop.desktop + * Fix tab icon display in proxy style. + * Switch tab eliding to ElideMiddle. + * Adjust default tab width to 500 and enable limit by default. + * Forward declare TabBar. + * Add option for configuring tab width limit. + * Add maximum tab width and proper text eliding. + * Enable bidi by default + * Fix UI + * Add RTL support button + * Update Catalan translation + +0.8.0 / 2017-10-21 +================== + + * Release 0.8.0: Update changelog * Set version to 0.8.0 * Update information on distribution package * Added legacy font setting support diff --git a/CMakeLists.txt b/CMakeLists.txt index b4de731..6e45aa1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,9 @@ project(qterminal) include(GNUInstallDirs) # qterminal version -set(STR_VERSION "0.8.0") -set(LXQTBT_MINIMUM_VERSION "0.4.0") +set(STR_VERSION "0.9.0") +set(LXQTBT_MINIMUM_VERSION "0.5.0") +set(QTERMWIDGET_MINIMUM_VERSION "0.9.0") option(UPDATE_TRANSLATIONS "Update source translation translations/*.ts files" OFF) @@ -23,8 +24,10 @@ elseif(UNIX) find_package(Qt5X11Extras REQUIRED) find_package(Qt5DBus) endif() -find_package(QTermWidget5 REQUIRED) +find_package(QTermWidget5 ${QTERMWIDGET_MINIMUM_VERSION} REQUIRED) find_package(lxqt-build-tools ${LXQTBT_MINIMUM_VERSION} REQUIRED) + +include(LXQtPreventInSourceBuilds) include(LXQtTranslateTs) include(LXQtCompilerSettings NO_POLICY_SCOPE) message(STATUS "Qt version: ${Qt5Core_VERSION}") @@ -42,13 +45,17 @@ elseif(UNIX) message(STATUS "X11_X11_LIB: ${X11_X11_LIB}") endif() -add_definitions(-DSTR_VERSION=\"${STR_VERSION}\") +add_definitions( + -DSTR_VERSION=\"${STR_VERSION}\" + -DQT_NO_FOREACH +) set(EXE_NAME qterminal) set(QTERM_SRC src/main.cpp src/mainwindow.cpp + src/tabbar.cpp src/tabwidget.cpp src/termwidget.cpp src/termwidgetholder.cpp @@ -63,6 +70,7 @@ set(QTERM_SRC set(QTERM_MOC_SRC src/qterminalapp.h src/mainwindow.h + src/tabbar.h src/tabwidget.h src/termwidget.h src/termwidgetholder.h diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 14c7cf8..fb6604c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,10 +1,10 @@ # Bug reports Please file bugs on the qterminal github tracker: - https://github.com/lxde/qterminal/issues + https://github.com/lxqt/qterminal/issues Please file qtermwidget-related bugs on the qtermwidget github tracker: - https://github.com/lxde/qtermwidget/issues + https://github.com/lxqt/qtermwidget/issues # Code contributions diff --git a/README.md b/README.md index bcb713b..e3e5389 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ ## Overview -QTerminal is a lightweight Qt terminal emulator based on [QTermWidget](https://github.com/lxde/qtermwidget). +QTerminal is a lightweight Qt terminal emulator based on [QTermWidget](https://github.com/lxqt/qtermwidget). -It is maintained by the LXQt project but can be used independently from this desktop environment. The only bonds are [lxqt-build-tools](https://github.com/lxde/lxqt-build-tools) representing a build dependency and the localization files which were outsourced to LXQt repository [lxqt-l10n](https://github.com/lxde/lxqt-l10n). +It is maintained by the LXQt project but can be used independently from this desktop environment. The only bonds are [lxqt-build-tools](https://github.com/lxqt/lxqt-build-tools) representing a build dependency and the localization files which were outsourced to LXQt repository [lxqt-l10n](https://github.com/lxqt/lxqt-l10n). This project is licensed under the terms of the [GPLv2](https://www.gnu.org/licenses/gpl-2.0.en.html) or any later version. See the LICENSE file for the full text of the license. @@ -12,10 +12,10 @@ This project is licensed under the terms of the [GPLv2](https://www.gnu.org/lice ### Compiling sources -Dependencies are qtx11extras ≥ 5.2 and [QTermWidget](https://github.com/lxde/qtermwidget). -In order to build CMake ≥ 3.0.2 and [lxqt-build-tools](https://github.com/lxde/lxqt-build-tools) are needed as well as optionally Git to pull latest VCS checkouts. The localization files were outsourced to repository [lxqt-l10n](https://github.com/lxde/lxqt-l10n) so the corresponding dependencies are needed, too. Please refer to this repository's `README.md` for further information. +Dependencies are qtx11extras ≥ 5.2 and [QTermWidget](https://github.com/lxqt/qtermwidget). +In order to build CMake ≥ 3.0.2 and [lxqt-build-tools](https://github.com/lxqt/lxqt-build-tools) are needed as well as optionally Git to pull latest VCS checkouts. The localization files were outsourced to repository [lxqt-l10n](https://github.com/lxqt/lxqt-l10n) so the corresponding dependencies are needed, too. Please refer to this repository's `README.md` for further information. -Code configuration is handled by CMake. Building out of source is strongly recommended. CMake variable `CMAKE_INSTALL_PREFIX` will normally have to be set to `/usr`. +Code configuration is handled by CMake. Building out of source is required. CMake variable `CMAKE_INSTALL_PREFIX` will normally have to be set to `/usr`. To build run `make`, to install `make install` which accepts variable `DESTDIR` as usual. diff --git a/debian/changelog b/debian/changelog index 7a60c11..ad87ae9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,13 @@ +qterminal (0.9.0-1) unstable; urgency=medium + + * Cherry-picking upstream version 0.9.0. + * Bumped build dependency libqtermwidget5-0-dev to >= 0.9.0~ + * Bumped build dependency lxqt-build-tools to >= 0.5.0~ + * Removed not needed build dependency qtbase5-private-dev + * Refreshed metadata patch + + -- Alf Gaida Thu, 24 May 2018 01:56:48 +0200 + qterminal (0.8.0-5) unstable; urgency=medium * Bumped compat to 11 diff --git a/debian/control b/debian/control index 38abb85..01585d6 100644 --- a/debian/control +++ b/debian/control @@ -7,13 +7,12 @@ Section: x11 Priority: optional Build-Depends: debhelper (>= 11~), libkf5windowsystem-dev, - libqtermwidget5-0-dev (>= 0.8.0), + libqtermwidget5-0-dev (>= 0.9.0~), libqt5svg5-dev, libqt5x11extras5-dev, libutf8proc-dev, libx11-dev, - lxqt-build-tools (>= 0.4.0), - qtbase5-private-dev + lxqt-build-tools (>= 0.5.0~), Standards-Version: 4.1.4 Vcs-Browser: https://salsa.debian.org/lxqt-team/qterminal Vcs-Git: https://salsa.debian.org/lxqt-team/qterminal.git diff --git a/debian/patches/appdata-metainfo.patch b/debian/patches/appdata.patch similarity index 71% rename from debian/patches/appdata-metainfo.patch rename to debian/patches/appdata.patch index fc0c3cb..d73fc6a 100644 --- a/debian/patches/appdata-metainfo.patch +++ b/debian/patches/appdata.patch @@ -1,12 +1,10 @@ -Description: Fixed appdata and path - * should be pushed to upstream soon - +Description: Author: Alf Gaida -Last-Update: 2017-11-05 +Last-Update: 2018-05-23 ---- qterminal-0.8.0.orig/CMakeLists.txt -+++ qterminal-0.8.0/CMakeLists.txt -@@ -205,7 +205,7 @@ install(FILES +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -213,7 +213,7 @@ install(FILES qterminal.appdata.xml @@ -15,8 +13,8 @@ Last-Update: 2017-11-05 ) if(NOT APPLEBUNDLE) ---- qterminal-0.8.0.orig/qterminal.appdata.xml -+++ qterminal-0.8.0/qterminal.appdata.xml +--- a/qterminal.appdata.xml ++++ b/qterminal.appdata.xml @@ -1,6 +1,6 @@ - @@ -30,10 +28,11 @@ Last-Update: 2017-11-05 Find bar and highlighted match. +- https://github.com/lxqt/qterminal +- + + LXQt Team - https://github.com/lxde/qterminal -- ++ https://github.com/lxde/qterminal + https://github.com/qterminal/issues + https://github.com/lxde/lxqt/wiki + http://github.com/lxde/lxqt-l10n diff --git a/debian/patches/series b/debian/patches/series index 9c68bf6..28aed43 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1 +1 @@ -appdata-metainfo.patch +appdata.patch diff --git a/qterminal.appdata.xml b/qterminal.appdata.xml index 61e8fb5..706d539 100644 --- a/qterminal.appdata.xml +++ b/qterminal.appdata.xml @@ -39,5 +39,5 @@ Find bar and highlighted match. - https://github.com/lxde/qterminal + https://github.com/lxqt/qterminal diff --git a/qterminal.desktop b/qterminal.desktop index ca5ce8a..f0f9a5a 100644 --- a/qterminal.desktop +++ b/qterminal.desktop @@ -2,10 +2,13 @@ Name=QTerminal Type=Application GenericName=Terminal emulator +GenericName[es]=Emulador de terminal Comment=Terminal emulator +Comment[ca]=Emulador de terminal Comment[de]=Befehlszeile verwenden Comment[el]=Προσομοιωτής τερματικού +Comment[es]=Emulador de terminal Comment[fr]=Terminal Comment[lt]=Terminalo emuliatorius Comment[pl]=Emulator terminala @@ -33,7 +36,7 @@ Name[cs]=Vysouvací terminál Name[da]=Terminal der ruller ned Name[de]=Aufklapp-Terminal Name[el]=Αναπτυσσόμενο τερματικό -Name[es]=Terminal de menú desplegable +Name[es]=Terminal desplegable Name[et]=Lahtikeriv terminal Name[fr]=Terminal déroulant Name[hr]=Spuštajući terminal diff --git a/qterminal.pro b/qterminal.pro index 29cfc0d..1f3d0bf 100644 --- a/qterminal.pro +++ b/qterminal.pro @@ -8,7 +8,7 @@ CONFIG += link_pkgconfig \ PKGCONFIG += qtermwidget5 -DEFINES += STR_VERSION=\\\"0.7.0\\\" +DEFINES += STR_VERSION=\\\"0.9.0\\\" SOURCES += $$files(src/*.cpp) HEADERS += $$files(src/*.h) diff --git a/qterminal_drop.desktop b/qterminal_drop.desktop index 5654540..08aeb87 100644 --- a/qterminal_drop.desktop +++ b/qterminal_drop.desktop @@ -6,8 +6,10 @@ Categories=Qt;System;TerminalEmulator; Icon=utilities-terminal Name=QTerminal drop down +Name[ca]=QTerminal desplegable Name[de]=QTerminal herabhängend Name[el]=QTerminal αναπτυσσόμενο +Name[es]=QTerminal desplegable Name[lt]=QTerminal išskleidžiamasis Name[pl]=QTerminal (tryb rozwijany) Name[pt]=QTerminal suspenso @@ -23,7 +25,7 @@ GenericName[da]=Terminal der ruller ned GenericName[de]=Aufklapp-Terminal GenericName[el]=Αναπτυσσόμενο τερματικό GenericName[en_GB]=Drop-down Terminal -GenericName[es]=Terminal de menú desplegable +GenericName[es]=Terminal desplegable GenericName[et]=Lahtikeriv terminal GenericName[fr]=Terminal déroulant GenericName[hr]=Spuštajući terminal @@ -52,11 +54,13 @@ GenericName[zh_CN]=拉幕式终端 GenericName[zh_TW]=下拉式終端機 Comment=A drop-down terminal emulator. +Comment[ca]=Un emulador de terminal desplegable. Comment[de]=Ein Ausklapp-Terminalemulator. Comment[el]=Ένας αναπτυσσόμενος προσομοιωτής τερματικού. +Comment[es]=Un emulador de terminal desplegable. Comment[lt]=Išskleidžiamasis terminalo emuliatorius. Comment[pt]=Um emulador de terminal suspenso. Comment[pt_BR]=Um emulador de terminal suspenso. -Comment[ru]=Вападающий эмулятор терминала. +Comment[ru]=Выпадающий эмулятор терминала. Comment[ja]=ドロップダウン式 ターミナルエミュレータ diff --git a/src/bookmarkswidget.cpp b/src/bookmarkswidget.cpp index c7f46d1..2834760 100644 --- a/src/bookmarkswidget.cpp +++ b/src/bookmarkswidget.cpp @@ -123,7 +123,7 @@ public: QDir d; // standard $HOME subdirs - foreach (QStandardPaths::StandardLocation i, locations) + for (const QStandardPaths::StandardLocation i : qAsConst(locations)) { path = QStandardPaths::writableLocation(i); if (!d.exists(path)) @@ -140,7 +140,8 @@ public: // system env - include dirs in the tree QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - foreach (const QString &i, env.keys()) + const auto keys = env.keys(); + for (const QString &i : keys) { path = env.value(i); if (!d.exists(path) || !QFileInfo(path).isDir()) @@ -369,8 +370,8 @@ BookmarksWidget::BookmarksWidget(QWidget *parent) treeView->setModel(m_model); treeView->header()->hide(); - connect(treeView, SIGNAL(doubleClicked(QModelIndex)), - this, SLOT(handleCommand(QModelIndex))); + connect(treeView, &QTreeView::doubleClicked, + this, &BookmarksWidget::handleCommand); } BookmarksWidget::~BookmarksWidget() diff --git a/src/fontdialog.cpp b/src/fontdialog.cpp index 30fc914..fe6b6f1 100644 --- a/src/fontdialog.cpp +++ b/src/fontdialog.cpp @@ -32,12 +32,12 @@ FontDialog::FontDialog(const QFont &f) sizeSpinBox->setValue(f.pointSize()); - setFontSample(); + setFontSample(f); - connect(fontComboBox, SIGNAL(currentFontChanged(QFont)), - this, SLOT(setFontSample())); - connect(sizeSpinBox, SIGNAL(valueChanged(int)), - this, SLOT(setFontSample())); + connect(fontComboBox, &QFontComboBox::currentFontChanged, + this, &FontDialog::setFontSample); + connect(sizeSpinBox, static_cast(&QSpinBox::valueChanged), + this, &FontDialog::setFontSize); } QFont FontDialog::getFont() @@ -47,9 +47,16 @@ QFont FontDialog::getFont() return f; } -void FontDialog::setFontSample() +void FontDialog::setFontSample(const QFont &f) { - QFont f = getFont(); + previewLabel->setFont(f); + QString sample("%1 %2 pt"); + previewLabel->setText(sample.arg(f.family()).arg(f.pointSize())); +} + +void FontDialog::setFontSize() +{ + const QFont &f = getFont(); previewLabel->setFont(f); QString sample("%1 %2 pt"); previewLabel->setText(sample.arg(f.family()).arg(f.pointSize())); diff --git a/src/fontdialog.h b/src/fontdialog.h index 9441e3f..19dc67c 100644 --- a/src/fontdialog.h +++ b/src/fontdialog.h @@ -32,7 +32,8 @@ public: QFont getFont(); private slots: - void setFontSample(); + void setFontSample(const QFont &f); + void setFontSize(); }; diff --git a/src/forms/propertiesdialog.ui b/src/forms/propertiesdialog.ui index 759549f..a7b0c35 100644 --- a/src/forms/propertiesdialog.ui +++ b/src/forms/propertiesdialog.ui @@ -6,8 +6,8 @@ 0 0 - 746 - 634 + 952 + 947 @@ -114,7 +114,7 @@ - + Start with preset: @@ -130,14 +130,14 @@ - + Show a border around the current terminal - + Terminal transparency @@ -147,7 +147,7 @@ - + Application transparency @@ -157,7 +157,7 @@ - + @@ -181,7 +181,7 @@ - + % @@ -274,7 +274,7 @@ - + % @@ -300,7 +300,7 @@ - + Qt::Vertical @@ -330,28 +330,35 @@ - + Change window title based on current terminal - + Change window icon based on current terminal - + + + + Enable bi-directional text support + + + + Background image: - + @@ -365,6 +372,43 @@ + + + + Show terminal size on resize + + + + + + + Limit tab width: + + + + + + + false + + + px + + + 1000 + + + + + + + Show close button on each tab + + + false + + + @@ -450,7 +494,7 @@ - + Qt::Vertical @@ -508,6 +552,33 @@ + + + + Default $TERM + + + + + + + true + + + 1 + + + + xterm + + + + + xterm-256color + + + + @@ -727,6 +798,7 @@ highlightCurrentCheckBox changeWindowTitleCheckBox changeWindowIconCheckBox + enabledBidiSupportCheckBox appTransparencyBox termTransparencyBox backgroundImageLineEdit @@ -801,5 +873,21 @@ + + limitTabWidthCheckBox + toggled(bool) + limitTabWidthSpinBox + setEnabled(bool) + + + 350 + 275 + + + 618 + 275 + + + diff --git a/src/forms/qterminal.ui b/src/forms/qterminal.ui index 3e06edb..2ecb45b 100644 --- a/src/forms/qterminal.ui +++ b/src/forms/qterminal.ui @@ -13,9 +13,6 @@ MainWindow - - true - @@ -57,9 +54,6 @@ 26 - - true - &File diff --git a/src/main.cpp b/src/main.cpp index 42cf62e..170b9af 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -60,8 +60,8 @@ void print_usage_and_exit(int code) puts(" -p, --profile Load qterminal with specific options"); puts(" -v, --version Prints application version and exits"); puts(" -w, --workdir Start session with specified work directory"); - puts("\nHomepage: "); - puts("Report bugs to "); + puts("\nHomepage: "); + puts("Report bugs to "); exit(code); } @@ -111,8 +111,6 @@ void parse_args(int argc, char* argv[], QString& workdir, QString & shell_comman int main(int argc, char *argv[]) { - setenv("TERM", "xterm", 1); // TODO/FIXME: why? - QApplication::setApplicationName("qterminal"); QApplication::setApplicationVersion(STR_VERSION); QApplication::setOrganizationDomain("qterminal.org"); @@ -131,6 +129,11 @@ int main(int argc, char *argv[]) bool dropMode; parse_args(argc, argv, workdir, shell_command, dropMode); + Properties::Instance()->migrate_settings(); + Properties::Instance()->loadSettings(); + + qputenv("TERM", Properties::Instance()->term.toLatin1()); + if (workdir.isEmpty()) workdir = QDir::currentPath(); app->setWorkingDirectory(workdir); @@ -267,7 +270,7 @@ void QTerminalApp::registerOnDbus() QList QTerminalApp::getWindows() { QList windows; - foreach (MainWindow *wnd, m_windowList) + for (MainWindow *wnd : qAsConst(m_windowList)) { windows.push_back(wnd->getDbusPath()); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f1790a2..b96fbe1 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -65,13 +65,16 @@ MainWindow::MainWindow(TerminalConfig &cfg, #ifdef HAVE_QDBUS registerAdapter(this); #endif + m_removeFinished = false; QTerminalApp::Instance()->addWindow(this); + // We want terminal translucency... setAttribute(Qt::WA_TranslucentBackground); + // ... but neither a fully transparent nor a flat menubar + // with styles that have translucency and/or gradient. + setAttribute(Qt::WA_NoSystemBackground, false); setAttribute(Qt::WA_DeleteOnClose); setupUi(this); - Properties::Instance()->migrate_settings(); - Properties::Instance()->loadSettings(); m_bookmarksDock = new QDockWidget(tr("Bookmarks"), this); m_bookmarksDock->setObjectName("BookmarksDockWidget"); @@ -80,15 +83,15 @@ MainWindow::MainWindow(TerminalConfig &cfg, bookmarksWidget->setAutoFillBackground(true); m_bookmarksDock->setWidget(bookmarksWidget); addDockWidget(Qt::LeftDockWidgetArea, m_bookmarksDock); - connect(bookmarksWidget, SIGNAL(callCommand(QString)), - this, SLOT(bookmarksWidget_callCommand(QString))); + connect(bookmarksWidget, &BookmarksWidget::callCommand, + this, &MainWindow::bookmarksWidget_callCommand); - connect(m_bookmarksDock, SIGNAL(visibilityChanged(bool)), - this, SLOT(bookmarksDock_visibilityChanged(bool))); + connect(m_bookmarksDock, &QDockWidget::visibilityChanged, + this, &MainWindow::bookmarksDock_visibilityChanged); - connect(actAbout, SIGNAL(triggered()), SLOT(actAbout_triggered())); - connect(actAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt())); - connect(&m_dropShortcut, SIGNAL(activated()), SLOT(showHide())); + connect(actAbout, &QAction::triggered, this, &MainWindow::actAbout_triggered); + connect(actAboutQt, &QAction::triggered, qApp, &QApplication::aboutQt); + connect(&m_dropShortcut, &QxtGlobalShortcut::activated, this, &MainWindow::showHide); setContentsMargins(0, 0, 0, 0); if (m_dropMode) { @@ -106,7 +109,7 @@ MainWindow::MainWindow(TerminalConfig &cfg, } consoleTabulator->setAutoFillBackground(true); - connect(consoleTabulator, SIGNAL(closeTabNotification()), SLOT(close())); + connect(consoleTabulator, &TabWidget::closeTabNotification, this, &MainWindow::testClose); consoleTabulator->setTabPosition((QTabWidget::TabPosition)Properties::Instance()->tabsPos); //consoleTabulator->setShellProgram(command); @@ -116,7 +119,7 @@ MainWindow::MainWindow(TerminalConfig &cfg, setupCustomDirs(); connect(consoleTabulator, &TabWidget::currentTitleChanged, this, &MainWindow::onCurrentTitleChanged); - connect(menu_Actions, SIGNAL(aboutToShow()), this, SLOT(updateDisabledActions())); + connect(menu_Actions, &QMenu::aboutToShow, this, &MainWindow::updateDisabledActions); /* The tab should be added after all changes are made to the main window; otherwise, the initial prompt might @@ -149,7 +152,7 @@ void MainWindow::enableDropMode() m_dropLockButton = new QToolButton(this); consoleTabulator->setCornerWidget(m_dropLockButton, Qt::BottomRightCorner); m_dropLockButton->setCheckable(true); - m_dropLockButton->connect(m_dropLockButton, SIGNAL(clicked(bool)), this, SLOT(setKeepOpen(bool))); + m_dropLockButton->connect(m_dropLockButton, &QToolButton::clicked, this, &MainWindow::setKeepOpen); setKeepOpen(Properties::Instance()->dropKeepOpen); m_dropLockButton->setAutoRaise(true); @@ -178,7 +181,8 @@ void MainWindow::setup_Action(const char *name, QAction *action, const char *def QList shortcuts; actions[name] = action; - foreach (const QString &sequenceString, settings.value(name, defaultShortcut).toString().split('|')) + const auto sequences = settings.value(name, defaultShortcut).toString().split('|'); + for (const QString &sequenceString : sequences) shortcuts.append(QKeySequence::fromString(sequenceString)); actions[name]->setShortcuts(shortcuts); @@ -391,8 +395,8 @@ void MainWindow::setup_ViewMenu_Actions() if( tabPosition->actions().count() > Properties::Instance()->tabsPos ) tabPosition->actions().at(Properties::Instance()->tabsPos)->setChecked(true); - connect(tabPosition, SIGNAL(triggered(QAction *)), - consoleTabulator, SLOT(changeTabPosition(QAction *)) ); + connect(tabPosition, &QActionGroup::triggered, + consoleTabulator, &TabWidget::changeTabPosition); if (tabPosMenu == NULL) { tabPosMenu = new QMenu(tr("&Tabs Layout"), menu_Window); @@ -402,8 +406,8 @@ void MainWindow::setup_ViewMenu_Actions() tabPosMenu->addAction(tabPosition->actions().at(i)); } - connect(menu_Window, SIGNAL(hovered(QAction *)), - this, SLOT(updateActionGroup(QAction *))); + connect(menu_Window, &QMenu::hovered, + this, &MainWindow::updateActionGroup); } menu_Window->addMenu(tabPosMenu); /* */ @@ -424,8 +428,8 @@ void MainWindow::setup_ViewMenu_Actions() if( Properties::Instance()->scrollBarPos < scrollBarPosition->actions().size() ) scrollBarPosition->actions().at(Properties::Instance()->scrollBarPos)->setChecked(true); - connect(scrollBarPosition, SIGNAL(triggered(QAction *)), - consoleTabulator, SLOT(changeScrollPosition(QAction *)) ); + connect(scrollBarPosition, &QActionGroup::triggered, + consoleTabulator, &TabWidget::changeScrollPosition); } if (scrollPosMenu == NULL) { @@ -456,8 +460,8 @@ void MainWindow::setup_ViewMenu_Actions() if( Properties::Instance()->keyboardCursorShape < keyboardCursorShape->actions().size() ) keyboardCursorShape->actions().at(Properties::Instance()->keyboardCursorShape)->setChecked(true); - connect(keyboardCursorShape, SIGNAL(triggered(QAction *)), - consoleTabulator, SLOT(changeKeyboardCursorShape(QAction *)) ); + connect(keyboardCursorShape, &QActionGroup::triggered, + consoleTabulator, &TabWidget::changeKeyboardCursorShape); } if (keyboardCursorShapeMenu == NULL) { @@ -513,6 +517,12 @@ void MainWindow::showFullscreen(bool fullscreen) setWindowState(windowState() & ~Qt::WindowFullScreen); } +void MainWindow::testClose(bool removeFinished) +{ + + m_removeFinished = removeFinished; + close(); +} void MainWindow::toggleBookmarks() { m_bookmarksDock->toggleViewAction()->trigger(); @@ -551,8 +561,8 @@ void MainWindow::closeEvent(QCloseEvent *ev) QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Yes | QDialogButtonBox::No, Qt::Horizontal, dia); buttonBox->button(QDialogButtonBox::Yes)->setDefault(true); - connect(buttonBox, SIGNAL(accepted()), dia, SLOT(accept())); - connect(buttonBox, SIGNAL(rejected()), dia, SLOT(reject())); + connect(buttonBox, &QDialogButtonBox::accepted, dia, &QDialog::accept); + connect(buttonBox, &QDialogButtonBox::rejected, dia, &QDialog::reject); QVBoxLayout * lay = new QVBoxLayout(); lay->addWidget(new QLabel(tr("Are you sure you want to exit?"))); @@ -571,6 +581,12 @@ void MainWindow::closeEvent(QCloseEvent *ev) } ev->accept(); } else { + if(m_removeFinished) { + QWidget *w = consoleTabulator->widget(consoleTabulator->count()-1); + consoleTabulator->removeTab(consoleTabulator->count()-1); + delete w; // delete the widget because the window isn't closed + m_removeFinished = false; + } ev->ignore(); } @@ -585,7 +601,7 @@ void MainWindow::actAbout_triggered() void MainWindow::actProperties_triggered() { PropertiesDialog *p = new PropertiesDialog(this); - connect(p, SIGNAL(propertiesChanged()), this, SLOT(propertiesChanged())); + connect(p, &PropertiesDialog::propertiesChanged, this, &MainWindow::propertiesChanged); p->exec(); } diff --git a/src/mainwindow.h b/src/mainwindow.h index 21b5067..1432d77 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -63,7 +63,7 @@ private: QWidget *settingOwner; QMenu *presetsMenu; - + bool m_removeFinished; TerminalConfig m_config; QDockWidget *m_bookmarksDock; @@ -102,7 +102,7 @@ private slots: void actAbout_triggered(); void actProperties_triggered(); void updateActionGroup(QAction *); - + void testClose(bool removeFinished); void toggleBookmarks(); void toggleBorderless(); void toggleTabBar(); diff --git a/src/properties.cpp b/src/properties.cpp index b904634..3ed1cff 100644 --- a/src/properties.cpp +++ b/src/properties.cpp @@ -69,6 +69,7 @@ void Properties::loadSettings() colorScheme = m_settings->value("colorScheme", "Linux").toString(); highlightCurrentTerminal = m_settings->value("highlightCurrentTerminal", true).toBool(); + showTerminalSizeHint = m_settings->value("showTerminalSizeHint", true).toBool(); font = QFont(qvariant_cast(m_settings->value("fontFamily", defaultFont().family())), qvariant_cast(m_settings->value("fontSize", defaultFont().pointSize()))); @@ -109,6 +110,11 @@ void Properties::loadSettings() hideTabBarWithOneTab = m_settings->value("HideTabBarWithOneTab", false).toBool(); m_motionAfterPaste = m_settings->value("MotionAfterPaste", 0).toInt(); + /* tab width limit */ + limitTabWidth = m_settings->value("LimitTabWidth", true).toBool(); + limitTabWidthValue = m_settings->value("LimitTabWidthValue", 500).toInt(); + showCloseTabButton = m_settings->value("ShowCloseTabButton", true).toBool(); + /* toggles */ borderless = m_settings->value("Borderless", false).toBool(); tabBarless = m_settings->value("TabBarless", false).toBool(); @@ -117,6 +123,7 @@ void Properties::loadSettings() saveSizeOnExit = m_settings->value("SaveSizeOnExit", true).toBool(); savePosOnExit = m_settings->value("SavePosOnExit", true).toBool(); useCWD = m_settings->value("UseCWD", false).toBool(); + term = m_settings->value("Term", "xterm-256color").toString(); // bookmarks useBookmarks = m_settings->value("UseBookmarks", false).toBool(); @@ -136,6 +143,7 @@ void Properties::loadSettings() changeWindowTitle = m_settings->value("ChangeWindowTitle", true).toBool(); changeWindowIcon = m_settings->value("ChangeWindowIcon", true).toBool(); + enabledBidiSupport = m_settings->value("enabledBidiSupport", true).toBool(); confirmMultilinePaste = m_settings->value("ConfirmMultilinePaste", false).toBool(); trimPastedTrailingNewlines = m_settings->value("TrimPastedTrailingNewlines", false).toBool(); @@ -146,6 +154,7 @@ void Properties::saveSettings() m_settings->setValue("guiStyle", guiStyle); m_settings->setValue("colorScheme", colorScheme); m_settings->setValue("highlightCurrentTerminal", highlightCurrentTerminal); + m_settings->setValue("showTerminalSizeHint", showTerminalSizeHint); m_settings->setValue("fontFamily", font.family()); m_settings->setValue("fontSize", font.pointSize()); //Clobber legacy setting @@ -160,7 +169,8 @@ void Properties::saveSettings() { it.next(); QStringList sequenceStrings; - foreach (const QKeySequence &shortcut, it.value()->shortcuts()) + const auto shortcuts = it.value()->shortcuts(); + for (const QKeySequence &shortcut : shortcuts) sequenceStrings.append(shortcut.toString()); m_settings->setValue(it.key(), sequenceStrings.join('|')); } @@ -197,6 +207,11 @@ void Properties::saveSettings() m_settings->setValue("KeyboardCursorShape", keyboardCursorShape); m_settings->setValue("HideTabBarWithOneTab", hideTabBarWithOneTab); m_settings->setValue("MotionAfterPaste", m_motionAfterPaste); + + m_settings->setValue("LimitTabWidth", limitTabWidth); + m_settings->setValue("LimitTabWidthValue", limitTabWidthValue); + m_settings->setValue("ShowCloseTabButton", showCloseTabButton); + m_settings->setValue("Borderless", borderless); m_settings->setValue("TabBarless", tabBarless); m_settings->setValue("MenuVisible", menuVisible); @@ -204,6 +219,7 @@ void Properties::saveSettings() m_settings->setValue("SavePosOnExit", savePosOnExit); m_settings->setValue("SaveSizeOnExit", saveSizeOnExit); m_settings->setValue("UseCWD", useCWD); + m_settings->setValue("Term", term); // bookmarks m_settings->setValue("UseBookmarks", useBookmarks); @@ -222,6 +238,7 @@ void Properties::saveSettings() m_settings->setValue("ChangeWindowTitle", changeWindowTitle); m_settings->setValue("ChangeWindowIcon", changeWindowIcon); + m_settings->setValue("enabledBidiSupport", enabledBidiSupport); m_settings->setValue("ConfirmMultilinePaste", confirmMultilinePaste); diff --git a/src/properties.h b/src/properties.h index c448a19..872ab2e 100644 --- a/src/properties.h +++ b/src/properties.h @@ -50,6 +50,7 @@ class Properties QString colorScheme; QString guiStyle; bool highlightCurrentTerminal; + bool showTerminalSizeHint; bool historyLimited; unsigned historyLimitedTo; @@ -68,6 +69,11 @@ class Properties bool hideTabBarWithOneTab; int m_motionAfterPaste; + bool limitTabWidth; + int limitTabWidthValue; + + bool showCloseTabButton; + bool borderless; bool tabBarless; bool menuVisible; @@ -79,6 +85,8 @@ class Properties bool useCWD; + QString term; + bool useBookmarks; bool bookmarksVisible; QString bookmarksFile; @@ -93,6 +101,7 @@ class Properties bool changeWindowTitle; bool changeWindowIcon; + bool enabledBidiSupport; bool confirmMultilinePaste; bool trimPastedTrailingNewlines; diff --git a/src/propertiesdialog.cpp b/src/propertiesdialog.cpp index 2c039f9..388e8d5 100644 --- a/src/propertiesdialog.cpp +++ b/src/propertiesdialog.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include "propertiesdialog.h" #include "properties.h" @@ -28,21 +29,47 @@ #include "config.h" #include "qterminalapp.h" +Delegate::Delegate (QObject *parent) + : QStyledItemDelegate (parent) +{ +} + +QWidget* Delegate::createEditor(QWidget *parent, + const QStyleOptionViewItem& /*option*/, + const QModelIndex& /*index*/) const +{ + return new QKeySequenceEdit (parent); +} + +bool Delegate::eventFilter(QObject *object, QEvent *event) +{ + QWidget *editor = qobject_cast(object); + if (editor && event->type() == QEvent::KeyPress) { + int k = static_cast(event)->key(); + if (k == Qt::Key_Return || k == Qt::Key_Enter) { + emit QAbstractItemDelegate::commitData(editor); + emit QAbstractItemDelegate::closeEditor(editor); + return true; + } + } + return QStyledItemDelegate::eventFilter (object, event); +} PropertiesDialog::PropertiesDialog(QWidget *parent) : QDialog(parent) { setupUi(this); - connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), - this, SLOT(apply())); - connect(changeFontButton, SIGNAL(clicked()), - this, SLOT(changeFontButton_clicked())); + connect(buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked, + this, &PropertiesDialog::apply); + connect(changeFontButton, &QPushButton::clicked, + this, &PropertiesDialog::changeFontButton_clicked); connect(chooseBackgroundImageButton, &QPushButton::clicked, this, &PropertiesDialog::chooseBackgroundImageButton_clicked); QStringList emulations = QTermWidget::availableKeyBindings(); QStringList colorSchemes = QTermWidget::availableColorSchemes(); + colorSchemes.sort(Qt::CaseInsensitive); listWidget->setCurrentRow(0); listWidget->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow); @@ -58,7 +85,10 @@ PropertiesDialog::PropertiesDialog(QWidget *parent) int eix = emulationComboBox->findText(Properties::Instance()->emulation); emulationComboBox->setCurrentIndex(eix != -1 ? eix : 0 ); - /* shortcuts */ + /* set the delegate of shortcut widget as well as its contents */ + Delegate *del = new Delegate(shortcutsWidget); + shortcutsWidget->setItemDelegate(del); + shortcutsWidget->sortByColumn(0, Qt::AscendingOrder); setupShortcuts(); /* scrollbar position */ @@ -73,6 +103,11 @@ PropertiesDialog::PropertiesDialog(QWidget *parent) tabsPos_comboBox->addItems(tabsPosList); tabsPos_comboBox->setCurrentIndex(Properties::Instance()->tabsPos); + /* tab width */ + limitTabWidthCheckBox->setChecked(Properties::Instance()->limitTabWidth); + limitTabWidthSpinBox->setValue(Properties::Instance()->limitTabWidthValue); + closeTabButtonCheckBox->setChecked(Properties::Instance()->showCloseTabButton); + /* keyboard cursor shape */ QStringList keyboardCursorShapeList; keyboardCursorShapeList << tr("BlockCursor") << tr("UnderlineCursor") << tr("IBeamCursor"); @@ -107,6 +142,8 @@ PropertiesDialog::PropertiesDialog(QWidget *parent) highlightCurrentCheckBox->setChecked(Properties::Instance()->highlightCurrentTerminal); + showTerminalSizeHintCheckBox->setChecked(Properties::Instance()->showTerminalSizeHint); + askOnExitCheckBox->setChecked(Properties::Instance()->askOnExit); savePosOnExitCheckBox->setChecked(Properties::Instance()->savePosOnExit); @@ -114,6 +151,8 @@ PropertiesDialog::PropertiesDialog(QWidget *parent) useCwdCheckBox->setChecked(Properties::Instance()->useCWD); + termComboBox->setCurrentText(Properties::Instance()->term); + historyLimited->setChecked(Properties::Instance()->historyLimited); historyUnlimited->setChecked(!Properties::Instance()->historyLimited); historyLimitedTo->setValue(Properties::Instance()->historyLimitedTo); @@ -130,17 +169,17 @@ PropertiesDialog::PropertiesDialog(QWidget *parent) useBookmarksCheckBox->setChecked(Properties::Instance()->useBookmarks); bookmarksLineEdit->setText(Properties::Instance()->bookmarksFile); openBookmarksFile(Properties::Instance()->bookmarksFile); - connect(bookmarksButton, SIGNAL(clicked()), - this, SLOT(bookmarksButton_clicked())); + connect(bookmarksButton, &QPushButton::clicked, + this, &PropertiesDialog::bookmarksButton_clicked); terminalPresetComboBox->setCurrentIndex(Properties::Instance()->terminalsPreset); changeWindowTitleCheckBox->setChecked(Properties::Instance()->changeWindowTitle); changeWindowIconCheckBox->setChecked(Properties::Instance()->changeWindowIcon); + enabledBidiSupportCheckBox->setChecked(Properties::Instance()->enabledBidiSupport); trimPastedTrailingNewlinesCheckBox->setChecked(Properties::Instance()->trimPastedTrailingNewlines); confirmMultilinePasteCheckBox->setChecked(Properties::Instance()->confirmMultilinePaste); - } @@ -171,6 +210,7 @@ void PropertiesDialog::apply() Properties::Instance()->termTransparency = termTransparencyBox->value(); Properties::Instance()->highlightCurrentTerminal = highlightCurrentCheckBox->isChecked(); + Properties::Instance()->showTerminalSizeHint = showTerminalSizeHintCheckBox->isChecked(); Properties::Instance()->backgroundImage = backgroundImageLineEdit->text(); Properties::Instance()->askOnExit = askOnExitCheckBox->isChecked(); @@ -180,9 +220,14 @@ void PropertiesDialog::apply() Properties::Instance()->useCWD = useCwdCheckBox->isChecked(); + Properties::Instance()->term = termComboBox->currentText(); + Properties::Instance()->scrollBarPos = scrollBarPos_comboBox->currentIndex(); Properties::Instance()->tabsPos = tabsPos_comboBox->currentIndex(); + Properties::Instance()->limitTabWidth = limitTabWidthCheckBox->isChecked(); + Properties::Instance()->limitTabWidthValue = limitTabWidthSpinBox->value(); Properties::Instance()->keyboardCursorShape = keybCursorShape_comboBox->currentIndex(); + Properties::Instance()->showCloseTabButton = closeTabButtonCheckBox->isChecked(); Properties::Instance()->hideTabBarWithOneTab = hideTabBarCheckBox->isChecked(); Properties::Instance()->menuVisible = showMenuCheckBox->isChecked(); Properties::Instance()->m_motionAfterPaste = motionAfterPasting_comboBox->currentIndex(); @@ -207,6 +252,7 @@ void PropertiesDialog::apply() Properties::Instance()->changeWindowTitle = changeWindowTitleCheckBox->isChecked(); Properties::Instance()->changeWindowIcon = changeWindowIconCheckBox->isChecked(); + Properties::Instance()->enabledBidiSupport = enabledBidiSupportCheckBox->isChecked(); Properties::Instance()->trimPastedTrailingNewlines = trimPastedTrailingNewlinesCheckBox->isChecked(); Properties::Instance()->confirmMultilinePaste = confirmMultilinePasteCheckBox->isChecked(); @@ -258,7 +304,8 @@ void PropertiesDialog::saveShortcuts() QString sequenceString = sequence.toString(); QList shortcuts; - foreach (sequenceString, item->text().split('|')) + const auto sequences = item->text().split('|'); + for (const QKeySequence& sequenceString : sequences) shortcuts.append(QKeySequence(sequenceString)); keyAction->setShortcuts(shortcuts); } @@ -279,41 +326,22 @@ void PropertiesDialog::setupShortcuts() QAction *keyAction = actions[keyValue]; QStringList sequenceStrings; - foreach (const QKeySequence &shortcut, keyAction->shortcuts()) + const auto shortcuts = keyAction->shortcuts(); + for (const QKeySequence &shortcut : shortcuts) sequenceStrings.append(shortcut.toString()); QTableWidgetItem *itemName = new QTableWidgetItem( tr(keyValue.toStdString().c_str()) ); QTableWidgetItem *itemShortcut = new QTableWidgetItem( sequenceStrings.join('|') ); - itemName->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled ); + itemName->setFlags( itemName->flags() & ~Qt::ItemIsEditable & ~Qt::ItemIsSelectable ); shortcutsWidget->setItem(x, 0, itemName); shortcutsWidget->setItem(x, 1, itemShortcut); } shortcutsWidget->resizeColumnsToContents(); -/* - connect(shortcutsWidget, SIGNAL(currentChanged(int, int)), - this, SLOT(recordAction(int, int))); - connect(shortcutsWidget, SIGNAL(valueChanged(int, int)), - this, SLOT(validateAction(int, int))); -*/ -} -void PropertiesDialog::recordAction(int row, int column) -{ - oldAccelText = shortcutsWidget->item(row, column)->text(); -} - -void PropertiesDialog::validateAction(int row, int column) -{ - QTableWidgetItem *item = shortcutsWidget->item(row, column); - QString accelText = QKeySequence(item->text()).toString(); - - if (accelText.isEmpty() && !item->text().isEmpty()) - item->setText(oldAccelText); - else - item->setText(accelText); + // No shortcut validation is needed with QKeySequenceEdit. } void PropertiesDialog::bookmarksButton_clicked() diff --git a/src/propertiesdialog.h b/src/propertiesdialog.h index 4304d19..0ab78b9 100644 --- a/src/propertiesdialog.h +++ b/src/propertiesdialog.h @@ -19,8 +19,22 @@ #ifndef PROPERTIESDIALOG_H #define PROPERTIESDIALOG_H +#include #include "ui_propertiesdialog.h" +class Delegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + Delegate (QObject *parent = 0); + + virtual QWidget* createEditor(QWidget *parent, + const QStyleOptionViewItem&, + const QModelIndex&) const; + virtual bool eventFilter(QObject *object, QEvent *event); +}; + class PropertiesDialog : public QDialog, Ui::PropertiesDialog { Q_OBJECT @@ -50,8 +64,6 @@ class PropertiesDialog : public QDialog, Ui::PropertiesDialog protected: void setupShortcuts(); void saveShortcuts(); - void recordAction(int row, int column); - void validateAction(int row, int column); }; diff --git a/src/tabbar.cpp b/src/tabbar.cpp new file mode 100644 index 0000000..2dc4945 --- /dev/null +++ b/src/tabbar.cpp @@ -0,0 +1,68 @@ +/*************************************************************************** + * Copyright (C) 2017 by Nathan Osman * + * nathan@quickmediasolutions.com * + * * + * 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, see . * + ***************************************************************************/ + +#include "tabbar.h" + +TabBar::TabBar(QWidget *parent) + : QTabBar(parent), + mLimitWidth(false), + mLimitWidthValue(0) +{ + // To make the selected tab text bold, first give a bold font to the tabbar + // for QStyle::sizeFromContents(QStyle::CT_TabBarTab, ...) to make room + // for the bold text, and then, set the non-selected tab text to normal. + QFont f = font(); + f.setBold(true); + setFont(f); + setStyleSheet("QTabBar::tab:!selected { font-weight: normal; }"); +} + +void TabBar::setLimitWidth(bool limitWidth) +{ + mLimitWidth = limitWidth; +} + +void TabBar::setLimitWidthValue(int value) +{ + mLimitWidthValue = value; +} + +void TabBar::updateWidth() +{ + // This seems to be the only way to trigger an update + setIconSize(iconSize()); + setElideMode(Qt::ElideMiddle); +} + +QSize TabBar::tabSizeHint(int index) const +{ + QSize size = QTabBar::tabSizeHint(index); + + // If the width is limited, use that for the width hint + if (mLimitWidth) { + if (shape() == QTabBar::RoundedEast || shape() == QTabBar::TriangularEast + || shape() == QTabBar::RoundedWest || shape() == QTabBar::TriangularWest) { + size.setHeight(mLimitWidthValue); + } + else { + size.setWidth(mLimitWidthValue); + } + } + + return size; +} diff --git a/src/tabbar.h b/src/tabbar.h new file mode 100644 index 0000000..91567e7 --- /dev/null +++ b/src/tabbar.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2017 by Nathan Osman * + * nathan@quickmediasolutions.com * + * * + * 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, see . * + ***************************************************************************/ + +#ifndef TABBAR_H +#define TABBAR_H + +#include +#include + +class TabBar : public QTabBar +{ + Q_OBJECT + +public: + + explicit TabBar(QWidget *parent); + + void setLimitWidth(bool limitWidth); + void setLimitWidthValue(int value); + void updateWidth(); + +protected: + + virtual QSize tabSizeHint(int index) const; + +private: + + bool mLimitWidth; + int mLimitWidthValue; +}; + +#endif // TABBAR_H diff --git a/src/tabwidget.cpp b/src/tabwidget.cpp index e0a815e..b71283d 100644 --- a/src/tabwidget.cpp +++ b/src/tabwidget.cpp @@ -18,11 +18,13 @@ #include #include +#include #include #include #include "mainwindow.h" #include "termwidgetholder.h" +#include "tabbar.h" #include "tabwidget.h" #include "config.h" #include "properties.h" @@ -33,8 +35,11 @@ #define TAB_CUSTOM_NAME_PROPERTY "custom_name" -TabWidget::TabWidget(QWidget* parent) : QTabWidget(parent), tabNumerator(0) +TabWidget::TabWidget(QWidget* parent) : QTabWidget(parent), tabNumerator(0), mTabBar(new TabBar(this)) { + // Insert our own tab bar which overrides tab width and eliding + setTabBar(mTabBar); + setFocusPolicy(Qt::NoFocus); /* On Mac OS X this will look similar to @@ -45,15 +50,15 @@ TabWidget::TabWidget(QWidget* parent) : QTabWidget(parent), tabNumerator(0) tabBar()->setUsesScrollButtons(true); - setTabsClosable(true); setMovable(true); setUsesScrollButtons(true); tabBar()->installEventFilter(this); - connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(removeTab(int))); - connect(tabBar(), SIGNAL(tabMoved(int,int)), this, SLOT(updateTabIndices())); - connect(this, SIGNAL(tabRenameRequested(int)), this, SLOT(renameSession(int))); + connect(this, &TabWidget::tabCloseRequested, this, &TabWidget::removeTab); + connect(tabBar(), &QTabBar::tabMoved, this, &TabWidget::updateTabIndices); + connect(this, &TabWidget::tabRenameRequested, this, &TabWidget::renameSession); + connect(this, &TabWidget::tabTitleColorChangeRequested, this, &TabWidget::setTitleColor); } TermWidgetHolder * TabWidget::terminalHolder() @@ -73,8 +78,8 @@ int TabWidget::addNewTab(TerminalConfig config) TermWidgetHolder *console = new TermWidgetHolder(config, this); console->setWindowTitle(label); - connect(console, SIGNAL(finished()), SLOT(removeFinished())); - connect(console, SIGNAL(lastTerminalClosed()), this, SLOT(removeFinished())); + connect(console, &TermWidgetHolder::finished, this, &TabWidget::removeFinished); + connect(console, &TermWidgetHolder::lastTerminalClosed, this, &TabWidget::removeFinished); connect(console, &TermWidgetHolder::termTitleChanged, this, &TabWidget::onTermTitleChanged); connect(this, &QTabWidget::currentChanged, this, &TabWidget::currentTitleChanged); @@ -197,6 +202,15 @@ void TabWidget::renameCurrentSession() renameSession(currentIndex()); } +void TabWidget::setTitleColor(int index) +{ + QColor current = tabBar()->tabTextColor(index); + QColor color = QColorDialog::getColor(current, this, tr("Select new tab title color")); + + if (color.isValid()) + tabBar()->setTabTextColor(index, color); +} + void TabWidget::renameTabsAfterRemove() { // it breaks custom names - it replaces original/custom title with shell no # @@ -214,23 +228,36 @@ void TabWidget::contextMenuEvent(QContextMenuEvent *event) QAction *close = menu.addAction(QIcon::fromTheme("document-close"), tr("Close session")); QAction *rename = menu.addAction(actions[RENAME_SESSION]->text()); + QAction *changeColor = menu.addAction(QIcon::fromTheme("color-management"), tr("Change title color")); rename->setShortcut(actions[RENAME_SESSION]->shortcut()); rename->blockSignals(true); - int tabIndex = tabBar()->tabAt(event->pos()); + int tabIndex = tabBar()->tabAt(tabBar()->mapFrom(this,event->pos())); QAction *action = menu.exec(event->globalPos()); if (action == close) { emit tabCloseRequested(tabIndex); } else if (action == rename) { emit tabRenameRequested(tabIndex); + } else if (action == changeColor) { + emit tabTitleColorChangeRequested(tabIndex); } } bool TabWidget::eventFilter(QObject *obj, QEvent *event) { - if (event->type() == QEvent::MouseButtonDblClick) + QMouseEvent *e = reinterpret_cast(event); + if (e->button() == Qt::MidButton) { + if (event->type() == QEvent::MouseButtonRelease) { + // close the tab on middle clicking + int index = tabBar()->tabAt(e->pos()); + if (index > -1){ + removeTab(index); + return true; + } + } + } + else if (event->type() == QEvent::MouseButtonDblClick) { - QMouseEvent *e = reinterpret_cast(event); // if user doubleclicks on tab button - rename it. If user // clicks on free space - open new tab int index = tabBar()->tabAt(e->pos()); @@ -278,7 +305,7 @@ void TabWidget::removeTab(int index) // tabNumerator--; setUpdatesEnabled(true); } else { - emit closeTabNotification(); + emit closeTabNotification(true); } renameTabsAfterRemove(); @@ -296,7 +323,7 @@ void TabWidget::removeCurrentTab() if (count() > 1) { removeTab(currentIndex()); } else { - emit closeTabNotification(); + emit closeTabNotification(false); } } @@ -416,6 +443,13 @@ void TabWidget::propertiesChanged() console->propertiesChanged(); } showHideTabBar(); + + setTabsClosable(Properties::Instance()->showCloseTabButton); + + // Update the tab widths + mTabBar->setLimitWidth(Properties::Instance()->limitTabWidth); + mTabBar->setLimitWidthValue(Properties::Instance()->limitTabWidthValue); + mTabBar->updateWidth(); } void TabWidget::clearActiveTerminal() diff --git a/src/tabwidget.h b/src/tabwidget.h index 46def80..930d4ab 100644 --- a/src/tabwidget.h +++ b/src/tabwidget.h @@ -31,6 +31,7 @@ #include "terminalconfig.h" #include "properties.h" +class TabBar; class TermWidgetHolder; class QAction; class QActionGroup; @@ -57,6 +58,7 @@ public slots: void moveRight(); void renameSession(int); void renameCurrentSession(); + void setTitleColor(int); void switchLeftSubterminal(); void switchRightSubterminal(); @@ -89,8 +91,9 @@ public slots: void preset4Terminals(); signals: - void closeTabNotification(); + void closeTabNotification(bool); void tabRenameRequested(int); + void tabTitleColorChangeRequested(int); void currentTitleChanged(int); protected: @@ -111,6 +114,8 @@ private: int tabNumerator; /* re-order naming of the tabs then removeCurrentTab() */ void renameTabsAfterRemove(); + + TabBar *mTabBar; }; #endif diff --git a/src/termwidget.cpp b/src/termwidget.cpp index 6ffd7cb..d43821d 100644 --- a/src/termwidget.cpp +++ b/src/termwidget.cpp @@ -72,8 +72,8 @@ TermWidgetImpl::TermWidgetImpl(TerminalConfig &cfg, QWidget * parent) setMotionAfterPasting(Properties::Instance()->m_motionAfterPaste); setContextMenuPolicy(Qt::CustomContextMenu); - connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), - this, SLOT(customContextMenuCall(const QPoint &))); + connect(this, &QWidget::customContextMenuRequested, + this, &TermWidgetImpl::customContextMenuCall); connect(this, &QTermWidget::urlActivated, this, &TermWidgetImpl::activateUrl); @@ -85,6 +85,7 @@ void TermWidgetImpl::propertiesChanged() setColorScheme(Properties::Instance()->colorScheme); setTerminalFont(Properties::Instance()->font); setMotionAfterPasting(Properties::Instance()->m_motionAfterPaste); + setTerminalSizeHint(Properties::Instance()->showTerminalSizeHint); if (Properties::Instance()->historyLimited) { @@ -99,6 +100,7 @@ void TermWidgetImpl::propertiesChanged() setKeyBindings(Properties::Instance()->emulation); setTerminalOpacity(1.0 - Properties::Instance()->termTransparency/100.0); setTerminalBackgroundImage(Properties::Instance()->backgroundImage); + setBidiEnabled(Properties::Instance()->enabledBidiSupport); /* be consequent with qtermwidget.h here */ switch(Properties::Instance()->scrollBarPos) { @@ -229,7 +231,8 @@ void TermWidgetImpl::paste(QClipboard::Mode mode) confirmation.setDetailedText(text); confirmation.setStandardButtons(QMessageBox::Yes | QMessageBox::No); // Click "Show details..." to show those by default - foreach( QAbstractButton * btn, confirmation.buttons() ) + const auto buttons = confirmation.buttons(); + for( QAbstractButton * btn : buttons ) { if (confirmation.buttonRole(btn) == QMessageBox::ActionRole && btn->text() == QMessageBox::tr("Show Details...")) { @@ -246,12 +249,7 @@ void TermWidgetImpl::paste(QClipboard::Mode mode) } } - /* TODO: Support bracketedPasteMode - if (bracketedPasteMode()) - { - text.prepend("\e[200~"); - text.append("\e[201~"); - }*/ + bracketText(text); sendText(text); } } @@ -286,7 +284,8 @@ TermWidget::TermWidget(TerminalConfig &cfg, QWidget * parent) setLayout(m_layout); m_layout->addWidget(m_term); - foreach (QObject *o, m_term->children()) + const auto objs = m_term->children(); + for (QObject *o : objs) { // Find TerminalDisplay if (!o->isWidgetType() || qobject_cast(o)->isHidden()) @@ -297,9 +296,9 @@ TermWidget::TermWidget(TerminalConfig &cfg, QWidget * parent) propertiesChanged(); - connect(m_term, SIGNAL(finished()), this, SIGNAL(finished())); - connect(m_term, SIGNAL(termGetFocus()), this, SLOT(term_termGetFocus())); - connect(m_term, SIGNAL(termLostFocus()), this, SLOT(term_termLostFocus())); + connect(m_term, &QTermWidget::finished, this, &TermWidget::finished); + connect(m_term, &QTermWidget::termGetFocus, this, &TermWidget::term_termGetFocus); + connect(m_term, &QTermWidget::termLostFocus, this, &TermWidget::term_termLostFocus); connect(m_term, &QTermWidget::titleChanged, this, [this] { emit termTitleChanged(m_term->title(), m_term->icon()); }); } diff --git a/src/termwidgetholder.cpp b/src/termwidgetholder.cpp index b103859..5fa6116 100644 --- a/src/termwidgetholder.cpp +++ b/src/termwidgetholder.cpp @@ -118,10 +118,12 @@ void TermWidgetHolder::saveSession(const QString & name) { Session dump; QString num("%1"); - foreach(QSplitter *w, findChildren()) + const auto ws = findChildren(); + for(QSplitter *w : ws) { dump += '|' + num.arg(w->orientation()); - foreach (int i, w->sizes()) + const auto sizes = w->sizes(); + for (const int i : sizes) dump += ',' + num.arg(i); } Properties::Instance()->sessions[name] = dump; @@ -198,7 +200,7 @@ void TermWidgetHolder::directionalNavigation(NavigationDirection dir) { // Find an active widget QList l = findChildren(); int ix = -1; - foreach (TermWidget * w, l) + for (TermWidget * w : qAsConst(l)) { ++ix; if (w->impl()->hasFocus()) @@ -230,7 +232,7 @@ void TermWidgetHolder::directionalNavigation(NavigationDirection dir) { int lowestX = INT_MAX; int lowestMidpointDistance = INT_MAX; TermWidget *fittest = NULL; - foreach (TermWidget * w, l) + for (TermWidget * w : qAsConst(l)) { NavigationData contenderDims = getNormalizedDimensions(w, dir); int midpointDistance = std::min( @@ -260,7 +262,8 @@ void TermWidgetHolder::clearActiveTerminal() void TermWidgetHolder::propertiesChanged() { - foreach(TermWidget *w, findChildren()) + const auto ws = findChildren(); + for(TermWidget *w : ws) w->propertiesChanged(); } @@ -357,19 +360,17 @@ TermWidget *TermWidgetHolder::newTerm(TerminalConfig &cfg) { TermWidget *w = new TermWidget(cfg, this); // proxy signals - connect(w, SIGNAL(renameSession()), this, SIGNAL(renameSession())); - connect(w, SIGNAL(removeCurrentSession()), this, SIGNAL(lastTerminalClosed())); - connect(w, SIGNAL(finished()), this, SLOT(handle_finished())); + connect(w, &TermWidget::renameSession, this, &TermWidgetHolder::renameSession); + connect(w, &TermWidget::removeCurrentSession, this, &TermWidgetHolder::lastTerminalClosed); + connect(w, &TermWidget::finished, this, &TermWidgetHolder::handle_finished); // consume signals - connect(w, SIGNAL(splitHorizontal(TermWidget *)), - this, SLOT(splitHorizontal(TermWidget *))); - connect(w, SIGNAL(splitVertical(TermWidget *)), - this, SLOT(splitVertical(TermWidget *))); - connect(w, SIGNAL(splitCollapse(TermWidget *)), - this, SLOT(splitCollapse(TermWidget *))); - connect(w, SIGNAL(termGetFocus(TermWidget *)), - this, SLOT(setCurrentTerminal(TermWidget *))); + connect(w, static_cast(&TermWidget::splitHorizontal), + this, &TermWidgetHolder::splitHorizontal); + connect(w, static_cast(&TermWidget::splitVertical), + this, &TermWidgetHolder::splitVertical); + connect(w, &TermWidget::splitCollapse, this, &TermWidgetHolder::splitCollapse); + connect(w, &TermWidget::termGetFocus, this, &TermWidgetHolder::setCurrentTerminal); connect(w, &TermWidget::termTitleChanged, this, &TermWidgetHolder::onTermTitleChanged); return w; @@ -423,7 +424,8 @@ QDBusObjectPath TermWidgetHolder::getActiveTerminal() QList TermWidgetHolder::getTerminals() { QList terminals; - foreach (TermWidget* w, findChildren()) + const auto ws = findChildren(); + for (TermWidget* w : ws) { terminals.push_back(w->getDbusPath()); } diff --git a/src/third-party/qxtglobalshortcut_x11.cpp b/src/third-party/qxtglobalshortcut_x11.cpp index 60969ac..ae70602 100644 --- a/src/third-party/qxtglobalshortcut_x11.cpp +++ b/src/third-party/qxtglobalshortcut_x11.cpp @@ -134,7 +134,7 @@ public: { QxtX11ErrorHandler errorHandler; - foreach (quint32 maskMods, maskModifiers) { + for (const quint32& maskMods : qAsConst(maskModifiers)) { XUngrabKey(display(), keycode, modifiers | maskMods, window); }