Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ qt_add_executable(NotepadNext
widgets/StatusLabel.h
Sorter.h Sorter.cpp
ScintillaSorter.h ScintillaSorter.cpp
widgets/TabsQuickActionsBar.cpp
widgets/TabsQuickActionsBar.h
)

set_target_properties(NotepadNext PROPERTIES
Expand Down
1 change: 1 addition & 0 deletions src/DockedEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ DockedEditor::DockedEditor(QWidget *parent) : QObject(parent)
ads::CDockManager::setConfigFlag(ads::CDockManager::FocusHighlighting, true);
ads::CDockManager::setConfigFlag(ads::CDockManager::EqualSplitOnInsertion, true);
ads::CDockManager::setConfigFlag(ads::CDockManager::MiddleMouseButtonClosesTab, true);
ads::CDockManager::setConfigFlag(ads::CDockManager::DockAreaHasTabsMenuButton, false);

dockManager = new ads::CDockManager(parent);
dockManager->setStyleSheet("");
Expand Down
26 changes: 25 additions & 1 deletion src/dialogs/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
#include <QScreen>
#include <QFontDatabase>


#ifdef Q_OS_WIN
#include <QSimpleUpdater.h>
#include <Windows.h>
Expand Down Expand Up @@ -74,6 +73,8 @@
#include "PreferencesDialog.h"
#include "ColumnEditorDialog.h"

#include "TabsQuickActionsBar.h"

#include "QuickFindWidget.h"

#include "EditorPrintPreviewRenderer.h"
Expand Down Expand Up @@ -850,6 +851,29 @@ MainWindow::MainWindow(NotepadNextApplication *app) :
mb.exec();
});

tabsQuickActionsBar = new TabsQuickActionsBar(ui->menuBar);
ui->menuBar->setCornerWidget(tabsQuickActionsBar, Qt::TopRightCorner);
connect(tabsQuickActionsBar, &TabsQuickActionsBar::createNewTabClicked, this, &MainWindow::newFile);
connect(tabsQuickActionsBar, &TabsQuickActionsBar::closeCurrentTabClicked, this, &MainWindow::closeCurrentFile);
connect(tabsQuickActionsBar, &TabsQuickActionsBar::tabsMenuAboutToShow, this, [this](QMenu *editorsMenu) {
const auto editorsList = editors();

editorsMenu->clear();

for (const auto editor : editorsList) {
const auto iconPath = editor->isSavedToDisk() ? ":/icons/saved.png" : ":/icons/unsaved.png";
const auto action = editorsMenu->addAction(QIcon(iconPath), editor->getName());

if (editor->isActiveWindow()) {
auto font = action->font();
font.setBold(true);
action->setFont(font);
}

connect(action, &QAction::triggered, this, [this, editor]() { switchToEditor(editor); });
}
});

#ifdef Q_OS_WIN
connect(ui->actionShowInExplorer, &QAction::triggered, this, [=]() {
QString filePath = QDir::toNativeSeparators(currentEditor()->getFileInfo().canonicalFilePath());
Expand Down
3 changes: 3 additions & 0 deletions src/dialogs/MainWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class QuickFindWidget;
class ZoomEventWatcher;
class Converter;
class DefaultDirectoryManager;
class TabsQuickActionsBar;

class MainWindow : public QMainWindow
{
Expand Down Expand Up @@ -167,6 +168,8 @@ private slots:

QActionGroup *languageActionGroup;

TabsQuickActionsBar *tabsQuickActionsBar = Q_NULLPTR;

//NppImporter *npp;

MacroManager macroManager;
Expand Down
1 change: 1 addition & 0 deletions src/icons/cross.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/icons/list_with_icons.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/icons/plus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/resources.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,8 @@
<file>icons/application_osx_terminal.png</file>
<file>icons/folder_go.png</file>
<file>icons/wrapindicator.png</file>
<file>icons/cross.svg</file>
<file>icons/plus.svg</file>
<file>icons/list_with_icons.svg</file>
</qresource>
</RCC>
95 changes: 95 additions & 0 deletions src/widgets/TabsQuickActionsBar.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* This file is part of Notepad Next.
* Copyright 2026 Justin Dailey
*
* Notepad Next 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 3 of the License, or
* (at your option) any later version.
*
* Notepad Next 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 Notepad Next. If not, see <https://www.gnu.org/licenses/>.
*/


#include <QApplication>
#include <QToolButton>
#include <QStyle>
#include <QMenu>

#include <map>

#include "TabsQuickActionsBar.h"

namespace
{
constexpr QLatin1StringView IconPlusPath(":/icons/plus.svg");
constexpr QLatin1StringView IconListPath(":/icons/list_with_icons.svg");
constexpr QLatin1StringView IconCrossPath(":/icons/cross.svg");
}

TabsQuickActionsBar::TabsQuickActionsBar(const Buttons &visibileButtons, QWidget *parent)
: QToolBar(parent)
{
createNewTabAction = addAction(QIcon(IconPlusPath), "");
createNewTabAction->setToolTip(tr("Create a new file"));

showTabsMenuAction = addAction(QIcon(IconListPath), "");
showTabsMenuAction->setToolTip(tr("Show opened files list"));

const auto tabsMenu = new QMenu(this);
showTabsMenuAction->setMenu(tabsMenu);

closeCurrentTabAction = addAction(QIcon(IconCrossPath), "");
closeCurrentTabAction->setToolTip(tr("Close the current file"));

const auto iconSize = qApp->style()->pixelMetric(QStyle::PM_SmallIconSize);
setIconSize({ iconSize, iconSize });
setStyleSheet(
"QToolBar { padding: 0px; margin: 0px; }"
"QToolButton::menu-indicator { image: none; }"
);

// Trick, cause addWidget will lose some style things
const auto toolButton = qobject_cast<QToolButton*>(widgetForAction(showTabsMenuAction));
if (toolButton) toolButton->setPopupMode(QToolButton::InstantPopup);

connect(createNewTabAction, &QAction::triggered, this, &TabsQuickActionsBar::createNewTabClicked);
connect(tabsMenu, &QMenu::aboutToShow, this, [this, tabsMenu]() { emit tabsMenuAboutToShow(tabsMenu); });
connect(closeCurrentTabAction, &QAction::triggered, this, &TabsQuickActionsBar::closeCurrentTabClicked);

setVisibileButtons(visibileButtons);
}

void TabsQuickActionsBar::setVisibileButtons(const Buttons &buttons)
{
if (visibileButtons == buttons)
return;

visibileButtons = buttons;

const std::map<QAction*, Button> mapping {
{ createNewTabAction, CreateNewTab },
{ showTabsMenuAction, ShowTabsMenu },
{ closeCurrentTabAction, CloseCurrentTab }
};

for (const auto &pair : mapping)
pair.first->setVisible(buttons.testFlag(pair.second));

emit visibileButtonsChanged(buttons);
}

void TabsQuickActionsBar::setVisibileButton(Button button, bool on)
{
const auto &currentOptions = visibileButtons;
setVisibileButtons(
on ? (currentOptions | button)
: (currentOptions & ~button)
);
}
78 changes: 78 additions & 0 deletions src/widgets/TabsQuickActionsBar.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* This file is part of Notepad Next.
* Copyright 2026 Justin Dailey
*
* Notepad Next 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 3 of the License, or
* (at your option) any later version.
*
* Notepad Next 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 Notepad Next. If not, see <https://www.gnu.org/licenses/>.
*/


#ifndef TABSQUICKACTIONSBAR_H
#define TABSQUICKACTIONSBAR_H

#include <QToolBar>

class TabsQuickActionsBar : public QToolBar
{
Q_OBJECT

Q_PROPERTY(
Buttons visibileButtons
READ getVisibileButtons
WRITE setVisibileButtons
NOTIFY visibileButtonsChanged
)

public:
enum Button {
None = 0x00,
CreateNewTab = 0x01,
ShowTabsMenu = 0x02,
CloseCurrentTab = 0x04,

All = CreateNewTab |
ShowTabsMenu |
CloseCurrentTab
};

Q_FLAG(Button)
Q_DECLARE_FLAGS(Buttons, Button)

signals:
void createNewTabClicked();
// Tabs menu must be filled with actual data from outside
void tabsMenuAboutToShow(QMenu *menu);
void closeCurrentTabClicked();

void visibileButtonsChanged(const TabsQuickActionsBar::Buttons &visibileButtons);

public:
inline TabsQuickActionsBar(QWidget *parent = nullptr) : TabsQuickActionsBar(Button::All, parent) { }
explicit TabsQuickActionsBar(const Buttons &visibileButtons = Button::All, QWidget *parent = nullptr);
virtual ~TabsQuickActionsBar() = default;

inline Buttons getVisibileButtons() const { return visibileButtons; }
void setVisibileButtons(const Buttons &buttons);
void setVisibileButton(Button button, bool on = true);

private:
Buttons visibileButtons = TabsQuickActionsBar::All;

QAction *createNewTabAction = nullptr;
QAction *showTabsMenuAction = nullptr;
QAction *closeCurrentTabAction = nullptr;
};

Q_DECLARE_OPERATORS_FOR_FLAGS(TabsQuickActionsBar::Buttons);

#endif // TABSQUICKACTIONSBAR_H