Название: QTreeView + QFileSystemModel - редактируемое имя папки в качестве имени виджета
Отправлено: Serega от Апрель 10, 2015, 06:50
Установить редактируемое имя папки/файла в качестве имени заголовка.Думал не заводить новый топик. Однако, все таки это разные задачи, соответственно разные темы и проще найти ответ при решении подобных задач. Казалось бы простая задачка. Однако бился день прежде чем обратиться к профи. Надеюсь, что для профи она действительно не составит труда. Этот код работает и для файлов, но что бы не путать, ограничился пояснением с каталогами. C++ (Qt) connect( treeView, SIGNAL( clicked( QModelIndex ) ), this, SLOT( setNameTree( QModelIndex ) ) ); connect( cFileSystemModel, SIGNAL( fileRenamed( QString, QString, QString ) ), this, SLOT( changeCurrentIndex() ) ); } ... ... cFileSystemModel->mkdir(index, newNameFolder); index = cFileSystemModel->index(newFullNameFolder); treeView->setCurrentIndex(index); treeView->edit(index); setWindowTitle(newNameFolder); } void MainWindow::setNameTree(const QModelIndex &index) { setWindowTitle( cFileSystemModel->fileInfo(index).baseName() ); } void MainWindow::changeCurrentIndex() { setNameTree( treeView->currentIndex() ); }
Два слота: - Один просто устанавливает заголовок окна при клике мыши на каталог. В качестве имени окна - имя каталога. - Второй слот срабатывает если пользователь меняет имя каталога или просто создает новый каталог и при этом меняет имя каталога предлагаемого по умолчанию. Этот слот просто отправляет текущий индекс, но уже с новым именем на смену заголовка окна. Все бы хорошо. Имя окна меняется в соответствии с каталогом/файлом на котором стоит курсор. Так и надо. И с конечной точки зрения код работает как положенно. Есть один неприятный момент:Если пользователь меняет имя каталога (дважды кликнув) или создает новый каталог и меняет его имя, но при этом кликает на другой каталог, как и положенно имя этого каталога идет в заголовок. Но при этом в заголовке окна мелькает имя которое ввел пользователь, а затем уже устанавливается текущее. Это хорошо видно если поменять имя каталога и кликнуть на любом другом каталоге, удерживая кнопку мыши. В этот момент имя заголовка сменится на то, что ввел пользователь. В данном случае это лишний момент. Отпускаем кнопку, ставится имя текущего каталога, как и положенно. Соответсвенно вопрос. Как избавиться от этого мелькания - от промежуточной ненужной смены имени окна? Тестовый код с воспроизведенной проблемой прилагается.
Название: Re: QTreeView + QFileSystemModel - редактируемое имя папки в качестве имени виджета
Отправлено: Serega от Апрель 11, 2015, 08:04
Понимаю, задача кажется простенькой, что и браться за нее не стоит. Так же думал и оставил на последок. Однако с этой стороны подойти не удается. Сигналы идут в порядке: сначала закончено редактирование, затем слик мыши. И с этим поделать ничего не могу. Ладно пытаемся подойти с другой стороны и переопределяем события: C++ (Qt) void MainWindow::keyReleaseEvent(QKeyEvent *event) { if(event->key() == Qt::Key_Return) { setNameTree( treeView->currentIndex() ); } } void MainWindow::mouseReleaseEvent(QMouseEvent *event) { if(event->button() == Qt::LeftButton) { setNameTree( treeView->currentIndex() ); } } Enter работает как надо. К сожалению чего не скажешь о клитке мыши. Клик работает если нажать на виджет. Что и понятно в нем это событие и переопредлено. При клике в дереве, событие уже не срабатывает, хотя оно и находится в виджете. Можно ли как то простым способом это подправить?
Название: Re: QTreeView + QFileSystemModel - редактируемое имя папки в качестве имени виджета
Отправлено: Serega от Апрель 12, 2015, 08:56
Все таки пришлось создать класс унаследованный от QTreeView (может и к лучшему) и для него уже переопределить событие mouseReleaseEvent. Вроде как работает все. Хотя вдруг начинает тормозить переставая переключать ветки дерева. Видимо еще осознать надо как делать это правильно. Однако пытаюсь разобраться с фильтрами событий и решить задачку через них. Тут тоже пришлось определить класс фильтра и вроде как установил для treeView. Однако не срабатывает. Понимаю, что что то недопонимаю :). Может кто опытным взглядом оценит и скажет, что не так? C++ (Qt) #include <QDebug> #include "MainWindow.h" #include "ui_MainWindow.h" CFileSystemView::CFileSystemView(QWidget *parent) : QTreeView(parent) {} CFileSystemView::~CFileSystemView() {} MouseFilter::MouseFilter(QObject *object) : QObject(object) {} MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); treeView = new CFileSystemView; cFileSystemModel = new CFileSystemModel; treeMouseFilter = new MouseFilter(treeView); treeView->installEventFilter(treeMouseFilter); treeView->setModel(cFileSystemModel); setCentralWidget(treeView); treeView->setSelectionMode( QAbstractItemView::ExtendedSelection ); treeView->setDragEnabled(true); treeView->setAcceptDrops(true); treeView->setDropIndicatorShown(true); treeView->setDragDropMode( QAbstractItemView::InternalMove ); treeView->setContextMenuPolicy( Qt::CustomContextMenu ); connect( treeView, SIGNAL( customContextMenuRequested( const QPoint & ) ), this, SLOT( showCustomMenu( const QPoint & ) ) ); } MainWindow::~MainWindow() { delete ui; } void MainWindow::createNewFolder() { QModelIndex index = treeView->currentIndex(); QString rootForNewFolder; if(!index.isValid()) { index = treeView->rootIndex(); rootForNewFolder = cFileSystemModel->fileInfo(index).absoluteDir().absolutePath(); } else if(cFileSystemModel->fileInfo(index).isFile()) { rootForNewFolder = cFileSystemModel->fileInfo(index).absoluteDir().absolutePath(); } else { rootForNewFolder = cFileSystemModel->filePath(index); } index = cFileSystemModel->index(rootForNewFolder); QString newNameFolder = "FOLDER"; QString newFullNameFolder = cFileSystemModel->filePath(index) + "/FOLDER"; int nName = 0; while( QDir( newFullNameFolder ).exists() ) { newNameFolder = "FOLDER" + QString::number(++nName); newFullNameFolder = cFileSystemModel->filePath(index) + "/" + newNameFolder; } cFileSystemModel->mkdir(index, newNameFolder); index = cFileSystemModel->index(newFullNameFolder); treeView->setCurrentIndex(index); treeView->edit(index); setWindowTitle(newNameFolder); } void MainWindow::setNameTree() { setWindowTitle( cFileSystemModel->fileInfo(treeView->currentIndex()).baseName() ); } void MainWindow::keyReleaseEvent(QKeyEvent *event) { if(event->key() == Qt::Key_Return) setNameTree(); } void MainWindow::showCustomMenu(QPoint const & pos) { m_managerMenu = new QMenu( treeView ); m_managerMenu->addAction( tr( "New Folder" ), this, SLOT(createNewFolder()) ); m_managerMenu->exec( treeView->mapToGlobal( pos ) ); } bool MouseFilter::eventFilter(QObject* object, QEvent* event) { if( event->type() == QEvent::MouseButtonPress ) { QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); if(mouseEvent->button() == Qt::LeftButton) { qDebug() << "FILTER"; return true; } else return false; } return false; }
Название: Re: QTreeView + QFileSystemModel - редактируемое имя папки в качестве имени виджета
Отправлено: Serega от Апрель 12, 2015, 17:12
Работающий код на основе переопределения события клика мыши. Отрабатывается отпускание левой кнопки после клика. Если отрабатывать момент нажатия, код не работает. Видимо переопределять функцию в этом случае надо полностью. C++ (Qt) #include <QDebug> #include "MainWindow.h" #include "ui_MainWindow.h" CFileSystemView::CFileSystemView(QWidget *parent) : QTreeView(parent) {} CFileSystemView::~CFileSystemView() {} MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); treeView = new CFileSystemView(this); cFileSystemModel = new CFileSystemModel(this); treeView->setModel(cFileSystemModel); setCentralWidget(treeView); treeView->setSelectionMode( QAbstractItemView::ExtendedSelection ); treeView->setDragEnabled(true); treeView->setAcceptDrops(true); treeView->setDropIndicatorShown(true); treeView->setDragDropMode( QAbstractItemView::InternalMove ); treeView->setContextMenuPolicy( Qt::CustomContextMenu ); connect( treeView, SIGNAL( customContextMenuRequested( const QPoint & ) ), this, SLOT( showCustomMenu( const QPoint & ) ) ); connect( treeView, SIGNAL( clicked( QModelIndex ) ), this, SLOT( setNameTree() ) );; connect( treeView, SIGNAL( reName() ), this, SLOT( setNameTree() ) ); } MainWindow::~MainWindow() { delete ui; } void MainWindow::createNewFolder() { QModelIndex index = treeView->currentIndex(); QString rootForNewFolder; if(!index.isValid()) { index = treeView->rootIndex(); rootForNewFolder = cFileSystemModel->fileInfo(index).absoluteDir().absolutePath(); } else if(cFileSystemModel->fileInfo(index).isFile()) { rootForNewFolder = cFileSystemModel->fileInfo(index).absoluteDir().absolutePath(); } else { rootForNewFolder = cFileSystemModel->filePath(index); } index = cFileSystemModel->index(rootForNewFolder); QString newNameFolder = "FOLDER"; QString newFullNameFolder = cFileSystemModel->filePath(index) + "/FOLDER"; int nName = 0; while( QDir( newFullNameFolder ).exists() ) { newNameFolder = "FOLDER" + QString::number(++nName); newFullNameFolder = cFileSystemModel->filePath(index) + "/" + newNameFolder; } cFileSystemModel->mkdir(index, newNameFolder); index = cFileSystemModel->index(newFullNameFolder); treeView->setCurrentIndex(index); treeView->edit(index); setWindowTitle(newNameFolder); } void MainWindow::setNameTree() { setWindowTitle( cFileSystemModel->fileInfo(treeView->currentIndex()).baseName() ); } void MainWindow::keyReleaseEvent(QKeyEvent *event) { if(event->key() == Qt::Key_Return) { qDebug() << "NAME" << cFileSystemModel->fileInfo(treeView->currentIndex()).baseName(); setNameTree(); } } void MainWindow::showCustomMenu(QPoint const & pos) { m_managerMenu = new QMenu( treeView ); m_managerMenu->addAction( tr( "New Folder" ), this, SLOT(createNewFolder()) ); m_managerMenu->exec( treeView->mapToGlobal( pos ) ); } void CFileSystemView::mouseReleaseEvent(QMouseEvent *event) { if(event->button() == Qt::LeftButton) { qDebug() << "NAME" << currentIndex(); emit reName(); } else QTreeView::mouseReleaseEvent(event); }
Если быстро нажимать по пунктам файлового дерева, то в какой то момент курсор останавливается на одном месте. Может в этот раз кто нибудь даст совет, что подправить? Событие клавиши ENTER отлавливается в виджете окна, може стоит ее так же ловить в самом дереве? Во вложении рабочий тестовый вариант.
Название: Re: QTreeView + QFileSystemModel - редактируемое имя папки в качестве имени виджета
Отправлено: Serega от Апрель 13, 2015, 04:08
Утро вечера мудреннее: C++ (Qt) void CFileSystemView::mousePressEvent(QMouseEvent *event) { QTreeView::mousePressEvent(event); emit reName(); }
Пока во всех отношениях устраивает, во всяком случае в тестовом коде.
Название: Re: QTreeView + QFileSystemModel - редактируемое имя папки в качестве имени виджета
Отправлено: Serega от Апрель 14, 2015, 04:23
Переписал код в оригинальную программу, где менеджер встроен в окошке. После создания нового файла имя файла уходит в заголовок. После этого происходит пересортировка дерева. И все работает как положенно, но только если пользователь рабоатет в пределах окошка дерва. Но если пользователь ввел новое имя файла, но при этом кликнул мышкой в пределах приложения, но за окном виджета дерева то в этом случае имя окна меняется, но дальше уже не срабатывает клик мыши и пересортировки не происходит. Могу принудительно вызвать слот сортировки после окончания редактирования, но тут свои проблемы, связанные с тем что если пользователь ввел имя и нажал иной пункт дерва, то после сортировки курсор встает не на нажатый пункт, а на соседний, если введенное имя оказалось выше. Как то не очень интуитивно, хотя и каприз.
Хочу попробовать эмуляию нажатия клавиши ENTER (вместо сортировки). Вопрос как это делается? Т.е. как вообще эмулируется нажатие клавиши в пределах приложения или окошка?
Название: Re: QTreeView + QFileSystemModel - редактируемое имя папки в качестве имени виджета
Отправлено: Serega от Апрель 15, 2015, 03:27
В конечном итоге в случае если пользователь при смене имени словаря ткнул курсор мыши на другой словарь, курсор автоматом ставится на место переименнованного словаря после пересортировки. Это осуществить оказалось намного проще, да и пожалуй более логично и полностью рабочую/сортируемую модель сделать не составило труда.
Название: Re: QTreeView + QFileSystemModel - редактируемое имя папки в качестве имени виджета
Отправлено: Serega от Апрель 16, 2015, 15:33
Вычищаю код. Немного запутался. Ситуация такова: Создается виджет дерева. Курсор ставится автоматом на определенную позицию, т.е. файл. Информация из этого файла должна поступить в другой виджет. Для этого фактически из конструктора виджета дерева необходимо выслать сигнал, что как я понял нельзя. Как быть? Может подскажет кто?
|