Select a folder or a file - qt

Is there a way in Qt to use just one dialog in order to select either a file or a folder?
What I mean is that I'd like to have an option, let's call it select, and by using this user could, from the same dialog, pick either a folder or a file.

There isn't a built in widget, but it is easy enough to connect a QDirModel to a QTreeView and get the selection signals.
Here is an example to get you started:
test.cpp
#include <QtGui>
#include "print.h"
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QDirModel mdl;
QTreeView view;
Print print(&mdl);
view.setModel(&mdl);
QObject::connect(
view.selectionModel(),
SIGNAL(currentChanged(const QModelIndex&,const QModelIndex&)),
&print,
SLOT(currentChanged(const QModelIndex&,const QModelIndex&)));
view.show();
return app.exec();
}
print.h
#ifndef _PRINT_H_
#define _PRINT_H_
#include <QtGui>
class Print : public QObject
{
Q_OBJECT
public:
Print(QDirModel* mdl);
~Print();
public slots:
void currentChanged(const QModelIndex& current, const QModelIndex&);
private:
QDirModel* mModel;
Q_DISABLE_COPY(Print)
};
#endif
print.cpp
#include "print.h"
Print::Print(QDirModel* mdl) : QObject(0), mModel(mdl) {}
Print::~Print() {}
void Print::currentChanged(const QModelIndex& current, const QModelIndex&)
{
qDebug() << mModel->filePath(current);
}

Related

Qt widget does not receive keyPressEvent

My child widget does not get keyPressEvents, while if I put the same widget as top level window, it does. I try to set it get focus, but it has no effect on this. Code is below, showing what I try to get to work.
#include <QApplication>
#include <QKeyEvent>
#include <QLCDNumber>
#include <QLabel>
#include <QVBoxLayout>
class DigitSummer: public QLCDNumber {
Q_OBJECT
public:
DigitSummer(QWidget *parent = nullptr) : QLCDNumber(parent) {
}
protected:
void keyPressEvent(QKeyEvent *event) override {
display(intValue() + event->text().toInt());
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
#if 1 // this version does not work, number does not increase
QWidget widget;
widget.setLayout(new QVBoxLayout());
widget.layout()->addWidget(new QLabel("Press digits!"));
DigitSummer summer; // in stack: must be after widget to avoid child delete
widget.layout()->addWidget(&summer);
widget.setFocusProxy(&summer); // I notice no effect!
widget.show();
#else // this version works, number grows with keypresseas
DigitSummer summer;
summer.show();
#endif
return a.exec();
}
#include "main.moc"
And for completenes, .pro file for the same:
QT += core gui widgets
TARGET = QtMCVE
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
CONFIG += c++11
QMAKE_CXXFLAGS += -Wall -Wextra
SOURCES += main.cpp
How to fix the widget to receive key events?
This related question suggests installing event filter, but I don't want to do that, there must be a self-contained way to fix the widget itself.
I think you need to set the focus policy for the widget before it will accept keyboard input. In your ctor try...
setFocusPolicy(Qt::StrongFocus);
Having said that, I'm really not sure why the behaviour would differ for top-level and non-top-level widgets.
Working version of the question code:
#include <QApplication>
#include <QKeyEvent>
#include <QLCDNumber>
#include <QLabel>
#include <QVBoxLayout>
class DigitSummer: public QLCDNumber {
Q_OBJECT
public:
DigitSummer(QWidget *parent = nullptr) : QLCDNumber(parent) {
setFocusPolicy(Qt::StrongFocus);
}
protected:
void keyPressEvent(QKeyEvent *event) override {
display(intValue() + event->text().toInt());
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget widget;
widget.setLayout(new QVBoxLayout());
widget.layout()->addWidget(new QLabel("Press digits!"));
widget.layout()->addWidget(new DigitSummer);
widget.show();
return a.exec();
}
#include "main.moc"

How to use QMenu signals?

It is very straightforward to connect to QMenu::triggered or QMenu::hovered signals by calling QObject::connect and pass the appropriate QAction.
However, I do not know how to use QMenu::aboutToHide signal, as there is no action passed to that signal.
How to use QMenu::aboutToHide and QMenu::aboutToShow signals or those are just virtual functions that can be overridden?
The signals in the world of Qt are not functions, never invoke them. The signals notify that something has happened with the QObject and send information if necessary.
In the case of triggered and hovered it is necessary to send the QAction because several QActions in a QMenu, then the developer thought that it is necessary to know with which QAction was interacting. On the other hand with aboutToShow and aboutToHide the signal does not send anything because it wants to notify is that if the QMenu was shown or hidden, respectively. Is there any need to know that QMenu was shown or hidden if he did it ? no, because the sender did it, I do not use other properties that we do not have at hand.
Example of use:
#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow w;
QMenu *foo_menu = w.menuBar()->addMenu("Foo Menu");
for(const QString & name: {"action1", "action2", "action3"}){
foo_menu->addAction(name);
}
QObject::connect(foo_menu, &QMenu::aboutToShow, [](){
qDebug()<<"aboutToShow";
});
QObject::connect(foo_menu, &QMenu::aboutToHide, [](){
qDebug()<<"aboutToHide";
});
QObject::connect(foo_menu, &QMenu::triggered, [](QAction *action){
qDebug()<< "triggered: " <<action->text();
});
QObject::connect(foo_menu, &QMenu::hovered, [](QAction *action){
qDebug()<< "hovered: " <<action->text();
});
w.show();
return a.exec();
}
And what happens if you have several QMenu that connect to the same slot? How do I know QMenu was shown or hidden?
The solution is to use sender() which is a method that belongs to the QObject class that returns the object that emitted the signal, in this case the QMenu.
Example:
#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QDebug>
class MainWindow: public QMainWindow{
public:
MainWindow(QWidget *parent=nullptr):
QMainWindow(parent)
{
for(const QString & name_of_menubar: {"bar1", "bar2", "bar3"}){
QMenu *menu = menuBar()->addMenu(name_of_menubar);
connect(menu, &QMenu::aboutToShow, this, &MainWindow::on_aboutToShow);
connect(menu, &QMenu::aboutToHide, this, &MainWindow::on_aboutToHide);
for(const QString & name: {"action1", "action2", "action3"}){
menu->addAction(name);
}
}
}
private slots:
void on_aboutToShow(){
if(QMenu *menu = qobject_cast<QMenu *>(sender()))
qDebug()<<"aboutToShow" << menu->title();
}
void on_aboutToHide(){
if(QMenu *menu = qobject_cast<QMenu *>(sender()))
qDebug()<<"aboutToHide" << menu->title();
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

The line edit widget shows nothing

I've recently started learning Qt and I'm a beginner of it now. So as first example for myself I wrote the following simple example.
The example is named Calculator. It now only has two buttons an a line edit. It's here:
:
My Calculator.h is this:
#ifndef CALCULATOR_H
#define CALCULATOR_H
#include<QDialog>
#include "ui_Calculator.h"
class Calculator : public QDialog, public Ui::Calculator
{
Q_OBJECT
public:
Calculator(QWidget* parent = 0);
private slots:
void myslot();
};
#endif // CALCULATOR_H
And the Calculator.cpp is this:
#include <QtWidgets>
#include "calculator.h"
Calculator::Calculator(QWidget *parent)
:QDialog(parent)
{
setupUi(this);
connect(oneButton,SIGNAL(clicked(bool)), this, SLOT(myslot()));
}
void Calculator::myslot(){
lineEdit -> setText("1");
}
And this is the main.cpp:
#include <QApplication>
#include <QDialog>
#include "ui_Calculator.h"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
Ui::Calculator ui;
QDialog* dialog = new QDialog;
ui.setupUi(dialog);
dialog -> show();
return app.exec();
}
The program runs fine without any error. But when I click on 1 button, nothing will be printed/shown in the line edit. Why please?
And what part of my program should I change to solve the issue please?
You are setting up the wrong class in your main.
You should use your custom Calculator class and not QDialog.
setupUi only initializes your elements but your code in Calculator never gets called. Your main should look like this:
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
Calculator calc; //using your Calculator class.
calc.show();
return app.exec();
}
And don't include ui_calculator.h but calculator.h

Qt - How to get real size of maximized window that I have pointer to?

I have a method that get pointer to widget where should be setted some other widgets. I have to resize the main window, where that widget is placed and then I should get the real size of that widget.
I’ve tried to do this like:
void MyClass::setWidgets(QList<QWidget*> list, QWidget *parentWidget)
{
QWidget* mainWindow = parentWidget->window();
mainWindow->showMaximized();
int width = parentWidget->size().width();
int height = parentWidget->size().height();
/*... rest of method...*/
}
That method is call from other class.
But I read that I should wait for resizeEvent. Could anyone explain me how I should do this or if there is any option to get that size differently?
If you want to get events for a different object, you can install an event filter using QObject::installEventFilter.
A simple example for ResizeEvent is:
filter.hpp
#ifndef FILTER_HPP
#define FILTER_HPP
#include <QtGui>
class ResizeFilter : public QObject
{
Q_OBJECT
public:
ResizeFilter();
protected:
bool eventFilter(QObject *obj, QEvent *event);
};
#endif
filter.cpp
#include "filter.hpp"
ResizeFilter::ResizeFilter() : QObject() {}
bool ResizeFilter::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::Resize)
{
QResizeEvent* resizeEv = static_cast<QResizeEvent*>(event);
qDebug() << resizeEv->size();
}
return QObject::eventFilter(obj, event);
}
main.cpp
#include <QtGui>
#include "filter.hpp"
int main(int argc, char** argv)
{
QApplication app(argc, argv);
ResizeFilter filter;
QWidget window;
window.installEventFilter(&filter);
window.showMaximized();
return app.exec();
}
filter.pro
TEMPLATE = app
HEADERS = filter.hpp
SOURCES = main.cpp filter.cpp
When testing this on my PC it gave the output:
QSize(840, 420)
QSize(1280, 952)

QListView with checkboxes for viewing of filesystem

It is necessary to list of directories by given path in QListView whith icons and checkboxes, then transmit names of marked folders to the program. For list directories i use code:
#include <QtGui/QApplication>
#include <QFileSystemModel>
#include <QListView>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFileSystemModel model;
QListView listView;
listView.setModel(&model);
listView.setRootIndex(model.setRootPath("C:\\Program Files"));
listView.show();
return a.exec();
}
How to add checkboxes and transmit it after pushing button?
Thanks.
There's nothing you can do that would fit in just a few lines. You can either derive from QFileSystemModel and add a checkbox column, or create a proxy model that will do the same.
Note that you can use built-in selection mechanism to Ctrl-click/⌘-click to expand the selection to multiple items:
//main.cpp
#include <QApplication>
#include <QFileSystemModel>
#include <QGridLayout>
#include <QListView>
#include <QPushButton>
#include <QMessageBox>
class Win : public QWidget
{
Q_OBJECT
QListView * view;
QPushButton * button;
public:
Win(QAbstractItemModel * model, const QModelIndex & idx) :
view(new QListView(this)), button(new QPushButton("List Selection", this))
{
QGridLayout * lay = new QGridLayout;
lay->addWidget(view, 0, 0, 1, 2);
lay->addWidget(button, 1, 0);
setLayout(lay);
view->setSelectionMode(QAbstractItemView::MultiSelection);
view->setModel(model);
view->setRootIndex(idx);
connect(button, SIGNAL(clicked()), SLOT(showSelection()));
}
public slots:
void showSelection() {
QString str;
foreach (QModelIndex i, view->selectionModel()->selectedIndexes()) {
str.append(i.data().toString());
str.append("\n");
}
QMessageBox::information(this, "Selected items", str);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFileSystemModel model;
Win v(&model, model.setRootPath("/"));
v.show();
return a.exec();
}
#include "main.moc"

Resources