-
-
Notifications
You must be signed in to change notification settings - Fork 557
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Context Menu operations on Folder as Workspace tree #556
base: master
Are you sure you want to change the base?
Changes from 4 commits
882066c
08a04c9
45fcfcb
fe945df
58dbd4c
135b880
799ad73
c936ab4
5885f46
0ed5f25
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,20 +18,27 @@ | |
|
||
|
||
#include "FolderAsWorkspaceDock.h" | ||
|
||
#include <QFileSystemModel> | ||
#include <QMessageBox> | ||
|
||
#include "ApplicationSettings.h" | ||
#include "MainWindow.h" | ||
#include "ui_FolderAsWorkspaceDock.h" | ||
|
||
#include <QFileSystemModel> | ||
QString NEW_DIR_TEMPLATE("dir_%1"); | ||
|
||
ApplicationSetting<QString> rootPathSetting{"FolderAsWorkspace/RootPath"}; | ||
|
||
FolderAsWorkspaceDock::FolderAsWorkspaceDock(QWidget *parent) : | ||
FolderAsWorkspaceDock::FolderAsWorkspaceDock(MainWindow *parent) : | ||
QDockWidget(parent), | ||
ui(new Ui::FolderAsWorkspaceDock), | ||
model(new QFileSystemModel(this)) | ||
window(parent) | ||
{ | ||
ui = new Ui::FolderAsWorkspaceDock; | ||
model = new QFileSystemModel(this); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any particular reason these couldn't be kept in the initializer list? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was warning about |
||
ui->setupUi(this); | ||
|
||
model->setReadOnly(false); | ||
ui->treeView->setModel(model); | ||
ui->treeView->header()->hideSection(1); | ||
ui->treeView->header()->hideSection(2); | ||
|
@@ -42,6 +49,8 @@ FolderAsWorkspaceDock::FolderAsWorkspaceDock(QWidget *parent) : | |
emit fileDoubleClicked(model->filePath(index)); | ||
} | ||
}); | ||
connect(ui->treeView, &QTreeView::customContextMenuRequested, this, &FolderAsWorkspaceDock::onCustomContextMenu); | ||
connect(model, &QFileSystemModel::fileRenamed, this, &FolderAsWorkspaceDock::onFileRenamed); | ||
|
||
ApplicationSettings settings; | ||
setRootPath(settings.get(rootPathSetting)); | ||
|
@@ -65,3 +74,95 @@ QString FolderAsWorkspaceDock::rootPath() const | |
{ | ||
return model->rootPath(); | ||
} | ||
|
||
void FolderAsWorkspaceDock::onCustomContextMenu(const QPoint &point) | ||
{ | ||
QModelIndex index = ui->treeView->indexAt(point); | ||
if (!index.isValid()) { | ||
lastSelectedItem = model->index(rootPath()); | ||
ui->menuEmpty->exec(ui->treeView->viewport()->mapToGlobal(point)); | ||
return; | ||
} | ||
lastSelectedItem = index; | ||
if (model->isDir(index)) { | ||
ui->menuDirectory->exec(ui->treeView->viewport()->mapToGlobal(point)); | ||
} | ||
else { | ||
ui->menuFile->exec(ui->treeView->viewport()->mapToGlobal(point)); | ||
} | ||
} | ||
|
||
void FolderAsWorkspaceDock::on_actionSaveHere_triggered() | ||
{ | ||
QDir parentDir(model->filePath(lastSelectedItem)); | ||
auto doc = window->currentEditor(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To keep consistent with the rest of the code base, rename There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
QString dstName(parentDir.absoluteFilePath(doc->getName())); | ||
|
||
if (doc->saveAs(dstName) != QFileDevice::NoError) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In most cases I prefer the "happy path" to be the first part (e.g. switching this to Also, this is a bit of a code 'smell' that the FolderAsWorkspace is messing with the lower editor API. Might be possible to use something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I separate UI questions inside MainWindow and use them here instead. |
||
{ | ||
qWarning("Unable to save %s", dstName.toUtf8().constData()); | ||
} | ||
else | ||
{ | ||
auto newItem = model->index(dstName); | ||
if (!doc->isFile()) { | ||
doc->setFileInfo(dstName); | ||
} | ||
ui->treeView->setCurrentIndex(newItem); | ||
ui->treeView->edit(newItem); | ||
} | ||
} | ||
|
||
void FolderAsWorkspaceDock::on_actionNewFolder_triggered() | ||
{ | ||
QDir parentDir(model->filePath(lastSelectedItem)); | ||
int i = 1; | ||
|
||
for (;parentDir.exists(NEW_DIR_TEMPLATE.arg(i)); i++) { | ||
// Intentional | ||
} | ||
QString dstName = NEW_DIR_TEMPLATE.arg(i); | ||
|
||
auto newItem = model->mkdir(lastSelectedItem, dstName); | ||
if (!newItem.isValid()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Switch this condition as well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
qWarning("Unable to create %s", dstName.toUtf8().constData()); | ||
} | ||
else { | ||
ui->treeView->setCurrentIndex(newItem); | ||
ui->treeView->edit(newItem); | ||
} | ||
} | ||
|
||
void FolderAsWorkspaceDock::on_actionRename_triggered() | ||
{ | ||
ui->treeView->setCurrentIndex(lastSelectedItem); | ||
ui->treeView->edit(lastSelectedItem); | ||
} | ||
|
||
void FolderAsWorkspaceDock::onFileRenamed(const QString &path, const QString &oldName, const QString &newName) | ||
{ | ||
QDir dir(path); | ||
QString fileName = dir.absoluteFilePath(oldName); | ||
for(auto &&editor : window->editors()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might also leverage something in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is some mess between There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved parts into |
||
{ | ||
if (editor->isFile() && (editor->getFilePath() == fileName)) | ||
{ | ||
editor->setName(newName); | ||
} | ||
} | ||
} | ||
|
||
void FolderAsWorkspaceDock::on_actionDelete_triggered() | ||
{ | ||
QString path(model->filePath(lastSelectedItem)); | ||
QMessageBox::StandardButton reply = QMessageBox::question(this, tr("Delete Item"), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Implemented both options but I have no windows box nearby to test on windows. |
||
tr("Are you sure you want to delete <b>%1</b>?").arg(path)); | ||
|
||
if (reply == QMessageBox::Yes) | ||
{ | ||
if (!model->remove(lastSelectedItem)) | ||
{ | ||
qWarning("Unable to delete %s", path.toUtf8().constData()); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,19 +21,21 @@ | |
#define FOLDERASWORKSPACEDOCK_H | ||
|
||
#include <QDockWidget> | ||
#include <QModelIndex> | ||
|
||
namespace Ui { | ||
class FolderAsWorkspaceDock; | ||
} | ||
|
||
class QFileSystemModel; | ||
class MainWindow; | ||
|
||
class FolderAsWorkspaceDock : public QDockWidget | ||
{ | ||
Q_OBJECT | ||
|
||
public: | ||
explicit FolderAsWorkspaceDock(QWidget *parent = nullptr); | ||
explicit FolderAsWorkspaceDock(MainWindow *parent = nullptr); | ||
~FolderAsWorkspaceDock(); | ||
|
||
void setRootPath(const QString dir); | ||
|
@@ -42,10 +44,22 @@ class FolderAsWorkspaceDock : public QDockWidget | |
signals: | ||
void fileDoubleClicked(const QString &filePath); | ||
|
||
private slots: | ||
void on_actionSaveHere_triggered(); | ||
void on_actionNewFolder_triggered(); | ||
void on_actionRename_triggered(); | ||
void on_actionDelete_triggered(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Qt doesn't recommend the auto connect slots and I haven't used them elsewhere throughout the codebase, but for now it is fine. It can be cleaned up later. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. M.. why/where? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is good scripting usage to automate creation of all these boilerplate as a lua script inside NotepadNext. local luaxml = require 'LuaXML'
local file_name = nn.activeEditor.path:gsub('.ui$')
local cpp_editor = nn.findEditorByPath(file_name .. '.cpp')
local h_editor = nn.findEditorByPath(file_name .. '.h')
assert(cpp_editor and h_editor, 'Please open corresponding .cpp and .h')
local cpp_bookmark = cpp_editor:findNamedBookmark('ctor signals')
local h_bookmark = cpp_editor:findNamedBookmark('slots')
assert(cpp_bookmark and h_bookmark, 'Please set "ctor signals" and "slots" bookmarks')
local items = {}
local tree = xml.load(file_name .. '.ui')
tree:iterate(function(el)
table.insert(items, el.name)
end, 'action', nil, nil, true)
local class_name = find_class_name(cpp_bookmark) -- TODO
for i,name in ipairs(items) do
local method_name = 'on'.. name:gsub('^[a-z]', function(s) return s:upper() end) .. 'Triggered'
local full_method = 'void '..method_name..'()'
if not h_editor:findText(full_method) then
h_bookmark:appendText(full_method .. ';\n');
cpp_bookmark:append('connect(ui->'..name..', &QAction::triggered, this, &'.. class_name.. '::'..method_name..');')
cpp_editor:append(full_method..'\n{\n}\n')
end
end There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting idea, though I don't see Lua as a long-term solution. It was originally just added for debugging/testing purposes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see lua as very good "Glue language" to customize and script stuff. I am going to use NotepadNext as very customizable light editor (instead of NotepadQQ and ZeroBraneStudio) on projects where I don't need big IDE like PyCharm |
||
|
||
void onCustomContextMenu(const QPoint &point); | ||
void onFileRenamed(const QString &path, const QString &oldName, const QString &newName); | ||
|
||
private: | ||
Ui::FolderAsWorkspaceDock *ui; | ||
|
||
MainWindow *window; | ||
QFileSystemModel *model; | ||
|
||
QModelIndex lastSelectedItem; | ||
}; | ||
|
||
#endif // FOLDERASWORKSPACEDOCK_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,19 +27,77 @@ | |
<property name="bottomMargin"> | ||
<number>0</number> | ||
</property> | ||
<item> | ||
<widget class="QMenu" name="menuFile"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can QtCreator create a QMenu in the ui file? or some other method (e.g. manually)? I'm just interested since I've never seen this done before :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It can't. I googled for it but at least Qt 5 can't. For me it looks like minor inconvenience everyone accustomed to. |
||
<property name="title"> | ||
<string>File Menu</string> | ||
</property> | ||
<addaction name="actionRename"/> | ||
<addaction name="actionDelete"/> | ||
</widget> | ||
</item> | ||
<item> | ||
<widget class="QMenu" name="menuDirectory"> | ||
<property name="title"> | ||
<string>Folder Menu</string> | ||
</property> | ||
<addaction name="actionRename"/> | ||
<addaction name="actionDelete"/> | ||
<addaction name="separator"/> | ||
<addaction name="actionNewFolder"/> | ||
<addaction name="actionSaveHere"/> | ||
</widget> | ||
</item> | ||
<item> | ||
<widget class="QMenu" name="menuEmpty"> | ||
<property name="title"> | ||
<string>Space Menu</string> | ||
</property> | ||
<addaction name="actionNewFolder"/> | ||
<addaction name="actionSaveHere"/> | ||
</widget> | ||
</item> | ||
<item> | ||
<widget class="QTreeView" name="treeView"> | ||
<property name="contextMenuPolicy"> | ||
<enum>Qt::CustomContextMenu</enum> | ||
</property> | ||
<property name="frameShape"> | ||
<enum>QFrame::NoFrame</enum> | ||
</property> | ||
<property name="editTriggers"> | ||
<set>QAbstractItemView::EditKeyPressed</set> | ||
</property> | ||
<attribute name="headerVisible"> | ||
<bool>false</bool> | ||
</attribute> | ||
</widget> | ||
</item> | ||
</layout> | ||
</widget> | ||
<action name="actionSaveHere"> | ||
<property name="text"> | ||
<string>&Save Here</string> | ||
</property> | ||
</action> | ||
<action name="actionNewFolder"> | ||
<property name="text"> | ||
<string>New &Folder</string> | ||
</property> | ||
</action> | ||
<action name="actionRename"> | ||
<property name="text"> | ||
<string>&Rename</string> | ||
</property> | ||
</action> | ||
<action name="actionDelete"> | ||
<property name="text"> | ||
<string>&Delete</string> | ||
</property> | ||
</action> | ||
</widget> | ||
<resources/> | ||
<resources> | ||
<include location="../resources.qrc"/> | ||
</resources> | ||
<connections/> | ||
</ui> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd have to look deeper how this is used but might make sense to keep it inside the class so this can be translated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done