I am trying to implement Custom File Explorer that fetches metadata of the specific(in house file system) file and displays all these data along with files. For this task I have implemented custom QFileSystemModel that takes care of this.
Now, I understand that loading of file is asynchronous in QFileSystemModel but display is not. Qt holds display job till all the files are loaded. As i have included metadata extraction logic in each display call, it makes display of folder with more than 100 file really slow(even after caching). During whole this time display is completely blocked. How can I display results asynchronously. To be precise display list partly and then refresh it when updates are available.
Files are displayed through QTableView UI widget.
1.You can put your extraction logic in a different thread. Look here how to do that:http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
If you use a shared data don't forget to use a mutex. Also you can send new meta from the new thread to GUI via signals with an argument containing the meta info. In this way you'll need to register a new class with qRegisterMetaType and Q_DECLARE_METATYPE to make it possible to convert it to QVariant and back:
http://qt-project.org/doc/qt-4.8/qmetatype.html
2.Also you can make the files load much faster if you disable loading of icons. For example, if you have only one type of files you can provide an icon preloaded from the resources.
This is how to disable loading of icons:
a) Create a fake icons provider:
class FakeIconProvider : public QFileIconProvider
{
public:
FakeIconProvider();
virtual QIcon icon(IconType) const override
{
return QIcon();
}
virtual QIcon icon(const QFileInfo&) const override
{
return QIcon();
}
};
b) Create an instance of the fake icons provider and install it to the model:
model->setIconProvider(m_fakeIconProvider);
Related
I am trying to design a preferences panel for my multidocument app. When a given pref changes – font size, say – all of the document windows should immediately update to reflect the new pref value. I don't want to construct the preferences panel up front, for all the document windows to connect to, because it contains a QFontComboBox that takes more than a second to set itself up (ouch); that's not a price I want to pay at startup. So then, my question is: what is an elegant design for the prefs panel to let all the document windows know about the change? In Cocoa, which I'm more used to, I'd use NSNotification to broadcast a notification from the prefs panel that all the document windows could observe; that provides the loose coupling required (since objects can add themselves as observers before the broadcaster exists).
Two approaches occur to me so far:
Loop through topLevelWidgets, do a dynamic cast to my document window class, and for all the document windows I thereby find, just call a hard-coded method on them directly.
Make a second class, PreferencesNotifier, that is separate from the UI object that takes so long to load, and construct a singleton object of this class at startup that all of the document windows can connect themselves to. When the preferences panel eventually gets created, it can send signals to slots in PreferencesNotifier, which will then call its own signals to notify the connected document windows.
Neither seems quite as elegant as NSNotification, and I'm wondering if I'm missing something. Thanks for any tips.
First thing, do not try to copy patterns, like Cocoa's NSNotification/NotificationCenter, to other frameworks (or languages, or...). There are various ways to send messages and generally each framework has picked one. Trying to use the one method that was picked by the framework you are using will lead to the most elegant solutions.
If you really want to, you could implement your own set of classes that will do exactly what NSNotification does. It will feel more elegant to you, but only because you are used to using Cocoa. It will feel odd to every other Qt developer. Also, this solution will require you to write a lot of code as you will not be able to leverage all the features of Qt.
The first solution you are suggesting is a bit ugly and looks more like a hack than anything.
What I do, when I have to handle preferences in a program, is something similar to your solution 2. I create a class that is responsible for handling all settings: read/write setting file, change setting, set default values, etc. Generally this class is a singleton. This class has very limited access to other parts of the program, and generally no access at all to the UI. Each components that needs to access the preferences will use this class. If you do it properly (e.g. use Q_PROPERTY), this class can even be accessed by QML, if you ever need to use Qt Quick.
class Settings: public QObject {
Q_OBJECT
Q_PROERTY(bool showX READ showX WRITE setShowX NOTIFY showXChanged)
public:
bool showX() const { return m_showX; }
void setShowX(bool show) {
if (show == m_showX)
return;
m_showX = show;
emit showXChanged(m_showX);
}
signals:
void showXChanged(bool);
public slots:
void save() const; // Save to disk
void load(); // Load from disk
private:
QSettings m_settings; // Handle load/save from/to disk
bool m_showX;
};
class Window {
Window() {
...
m_widgetX->setVisible(settings->showX());
connect(settings, &Settings::showXChanged,
this, [this](bool show) { m_widgetX->setVisible(show); }
);
...
}
};
class PrefWindow {
PrefWindow () {
...
ui->checkBoxShowX->setChecked(settings->showX());
...
}
private slots:
void on_saveButton_clicked() {
settings->setShowX(ui->checkBoxShowX->checked()):
settings->save();
}
};
What is an optimal and an appropriate way to save the state of a Qt GUI so I get the same state I had back when I closed the application ?
By state I mean : current indexes (for combo box ...), color palette, widgets positions... right before closing the application
You can use the QSettings class.
Simple use of QSettings class (code inspired from Qt's documentation):
In the main-window of your application code member functions that saves and restore the settings:
void MainWindow::writeSettings()
{
QSettings settings("reaffer Soft", "reafferApp");
settings.beginGroup("MainWindow");
settings.setValue("size", size());
settings.setValue("pos", pos());
settings.endGroup();
}
void MainWindow::readSettings()
{
QSettings settings("reaffer Soft", "reafferApp");
settings.beginGroup("MainWindow");
resize(settings.value("size", QSize(400, 400)).toSize());
move(settings.value("pos", QPoint(200, 200)).toPoint());
settings.endGroup();
}
Call those 2 functions from the MainWindow constructor and from the closeEvent override, like this:
MainWindow::MainWindow()
{
// code from constructor
//...
readSettings();
}
void MainWindow::closeEvent(QCloseEvent *event)
{
//optional check if the user really want to quit
// and/or if the user want to save settings
writeSettings();
event->accept();
}
The direct answer requires specific elaborated design for your code and not really a short Qt question or even the question specific to Qt. That is about C++ which is not the VM-based language that assists with serializing the state of program code to data. Having all objects serializable we can then attempt to apply certain C++/Qt classes/techniques.
This task is much easier to accomplish with languages like Java, though. And with C++/Qt you have to routinely make serialize-able / serialize / restore everything that is running in your code and still no guarantee that works as long as the context is not fully captured. This task is not easy for sure and makes sense only in specific application.
The most you can get directly from Qt is to save/restore QMainWindow and other independent widgets geometry (position/size):
saveGeometry
restoreGeometry
... and that solution is still somewhat incomplete or you may/not use QSettings for the storage.
I use QSettings for this. With routines similar to Zlatomir's.
For each window I have in the project I use a different section in QSettings and have readSettings() and writeSettings() in the source for each window.
Anything on the form that I want to persist I have to explicitly save and recall. In the case of a QComboBox it would be something like:
QSettings settings("Organisation", "MySoftware");
settings.beginGroup("WindowNumberTwo");
settings.setValue("ComboIndex", combobox->currentIndex());
// save more values here
// ...
settings.endGroup();
I don't know of a built in way to persist your window states - it has to be don't value by value.
The documentation for QWidget::winId states (among other things) "If a widget is non-native (alien) and winId is invoked on it, that widget will be provided a native handle."
I'm not sure what 'alien' means in that context, but I'm choosing to ignore it for now. :)
So assuming that my widget now has a valid native handle associated with it, can I then pass that native handle to another process and into QWidget::find and get a valid QWidget object back within that second process?
I probably don't need to do too much else to the widget in the second process other than show/hide it and attach it to a parent widget. (It is guaranteed to not be attached to any parent widgets in the first process and never visible in the context of the first process).
If all the above works:
How much control will the second process have over that widget?
Will the first process receive user input events as if it were attached
to the first process's UI, and will the first process be able to update the widget as normal?
James
Let's take a look at Qt sources.
QWidget *QWidget::find(WId id)
{
return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(id, 0) : 0;
}
find() can find a widget only if mapper contains it. The mapper is a static QHash<WId, QWidget *> variable. Items are inserted in this hash only in the QWidgetPrivate::setWinId method.
So, if a widget with a WId was created in another process, you can't find it using QWidget::find. This function doesn't use any native OS functions to find widgets.
Also see general description of alien widgets in Qt documentation:
Introduced in Qt 4.4, alien widgets are widgets unknown to the
windowing system. They do not have a native window handle associated
with them. This feature significantly speeds up widget painting,
resizing, and removes flicker.
I'm trying to prepare QML plugin to play video on embedded device in a way that other developers can use it without much hassle. However the way it is currently proposed requires almost always writing some C++ wrapper around your QML application. I'm refering to this example:
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/qt-gstreamer/html/examples_2qmlplayer_2main_8cpp-example.html
I would like to be able to have plugin and simply write:
import AwesomeVideoPlugin 1.0
Rect
{
AwesomeVideo
{
width: 320
height: 240
url: "./myvideo.avi"
// ... some minor stuff like mouse click handling, controls, etc.
}
}
Currently QtGStreamer requires to provide videoSurface property to VideoItem. The only way to do this is to create and set context for additional property in rootContext(). And to create GraphicsVideoSurface I need QGraphicsView (QDeclarativeView fills this role).
Is it possible to:
Get QDeclarativeView from within QDeclarativeItem (to which I have only access from QML plugin) in a way that it can be later used to feed GraphicsVideoSurface? My guess is no - however I've found path QFraphicsItem::scene() ==> QGraphScene ==> QGraphScene::views() ==> QList of QGraphicsView - it looks like VERY bad programming but maybe somebody got it to work (I'm getting segfault)
Is there other way to provide video sink for QtGStreamer from within QDeclarativeItem ?
Greetz
Yatsa
I had the same question, but haven't come up with an elegant solution.
However, one thought would be to make the videosurface available via an accessor function from a sub-classed QApplication object.
This would, of course, mean that your plug-in depends on the application subclass having a getVideoSurface method, but it does remove the ugliness from the QML code.
class MyApp : public QApplication
{
....
QGst::Ui::GraphicsVideoSurface *getVideoSurface() { return m_videosurface; }
}
...
int MyApp::init()
{
m_viewer = new QDeclarativeView();
m_viewer->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
m_videosurface = new QGst::Ui::GraphicsVideoSurface(m_viewer);
}
MyVideoPlugin::MyVideoPlugin(QDeclarativeItem *parent) : QDeclarativeItem(parent)
{
QGst::Ui::GraphicsVideoSurface *surface = ((MyApp*)qApp)->getVideoSurface();
}
...
Now the MyVideoPlugin element may be used without referencing an exported videosurface context item.
I'm trying to write a script for an application developed with Qt, using javascript for the business logic and a .ui file for the GUI, but I'm facing two problems.
In the ui I declared a QComboBox, to which I successfully connect javascript functions to handle
signals such as editTextChanged, etc. I was wondering I cannot populate the combobox from within
javascript code, because the addItem function is not exposed to script-side code.
combobox.editTextChanged[action](ComboBoxChanged); // OK (action is "connect" or "disconnect")
combobox.addItem("element 1"); // Error!
Is there any (other) way to do this?
I need to show a set of items (strings) in a table-like component. I tried using a QTableView and
QTableWidget but I cannot insert or get items. For example, from javascript I cannot access the
setModel function of a QTableView (if at least I could create a QAbstractItemModel from
script...), neither I can access the item(row,col) function of a QTableWidget class, to set an
item's text. Is there any way to show a table of strings to the user, let edit them and retrieve
the modified contents?
Thanks in advance.
Antonio
Because the addItem() function isn't a slot, you'll need an intermediate public slot to handle the transaction. It'll be the same with the other functions you are trying to get at as well.