diff options
188 files changed, 3371 insertions, 1740 deletions
diff --git a/demos/spreadsheet/spreadsheet.cpp b/demos/spreadsheet/spreadsheet.cpp index 742855e..d740aee 100644 --- a/demos/spreadsheet/spreadsheet.cpp +++ b/demos/spreadsheet/spreadsheet.cpp @@ -481,7 +481,7 @@ void SpreadSheet::setupContents() table->setItem(3, 0, new SpreadSheetItem("Lunch")); table->setItem(4, 0, new SpreadSheetItem("Flight (LA)")); table->setItem(5, 0, new SpreadSheetItem("Taxi")); - table->setItem(6, 0, new SpreadSheetItem("Diinner")); + table->setItem(6, 0, new SpreadSheetItem("Dinner")); table->setItem(7, 0, new SpreadSheetItem("Hotel")); table->setItem(8, 0, new SpreadSheetItem("Flight (Oslo)")); table->setItem(9, 0, new SpreadSheetItem("Total:")); diff --git a/doc/src/examples/fancybrowser.qdoc b/doc/src/examples/fancybrowser.qdoc index 9001c20..631aff9 100644 --- a/doc/src/examples/fancybrowser.qdoc +++ b/doc/src/examples/fancybrowser.qdoc @@ -40,12 +40,109 @@ ****************************************************************************/ /*! - \example webkit/fancybrowser - \title Fancy Browser Example + \example webkit/fancybrowser + \title Fancy Browser Example The Fancy Browser example shows how to use jQuery with QtWebKit to - make a web browser with some special effects and content manipulation. + create a web browser with special effects and content + manipulation. \image fancybrowser-example.png + The application makes use of QWebFrame::evaluateJavaScript to + evaluate the jQuery JavaScript code. A QMainWindow with a QWebView + as central widget builds up the browser itself. + + \section1 MainWindow Class Definition + + The \c MainWindow class inherits QMainWindow. It implements a number of + slots to perform actions on both the application and on the web content. + + \snippet examples/webkit/fancybrowser/mainwindow.h 1 + + We also declare a QString that contains the jQuery, a QWebView + that displays the web content, and a QLineEdit that acts as the + address bar. + + \section1 MainWindow Class Implementation + + We start by implementing the constructor. + + \snippet examples/webkit/fancybrowser/mainwindow.cpp 1 + + The first part of the constructor sets the value of \c progress to + 0. This value will be used later in the code to visualize the + loading of a webpage. + + Next, the jQuery library is loaded using a QFile and reading the file + content. The jQuery library is a JavaScript library that provides different + functions for manipulating HTML. + + \snippet examples/webkit/fancybrowser/mainwindow.cpp 2 + + The second part of the constructor creates a QWebView and connects + slots to the views signals. Furthermore, we create a QLineEdit as + the browsers address bar. We then set the horizontal QSizePolicy + to fill the available area in the browser at all times. We add the + QLineEdit to a QToolbar together with a set of navigation actions + from QWebView::pageAction. + + \snippet examples/webkit/fancybrowser/mainwindow.cpp 3 + + The third and last part of the constructor implements two QMenus and assigns + a set of actions to them. The last line sets the QWebView as the central + widget in the QMainWindow. + + \snippet examples/webkit/fancybrowser/mainwindow.cpp 4 + + When the page is loaded, \c adjustLocation() updates the address + bar; \c adjustLocation() is triggered by the \c loadFinished() + signal in QWebView. In \c changeLocation() we create a QUrl + object, and then use it to load the page into the QWebView. When + the new web page has finished loading, \c adjustLocation() will be + run once more to update the address bar. + + \snippet examples/webkit/fancybrowser/mainwindow.cpp 5 + + \c adjustTitle() sets the window title and displays the loading + progress. This slot is triggered by the \c titleChanged() signal + in QWebView. + + \snippet examples/webkit/fancybrowser/mainwindow.cpp 6 + + When a web page has loaded, \c finishLoading() is triggered by the + \c loadFinished() signal in QWebView. \c finishLoading() then updates the + progress in the title bar and calls \c evaluateJavaScript() to evaluate the + jQuery library. This evaluates the JavaScript against the current web page. + What that means is that the JavaScript can be viewed as part of the content + loaded into the QWebView, and therefore needs to be loaded every time a new + page is loaded. Once the jQuery library is loaded, we can start executing + the different jQuery functions in the browser. + + \snippet examples/webkit/fancybrowser/mainwindow.cpp 7 + + The first jQuery-based function, \c highlightAllLinks(), is designed to + highlight all links in the current webpage. The JavaScript code looks + for web elements named \e {a}, which is the tag for a hyperlink. + For each such element, the background color is set to be yellow by + using CSS. + + \snippet examples/webkit/fancybrowser/mainwindow.cpp 8 + + The \c rotateImages() function rotates the images on the current + web page. Webkit supports CSS transforms and this JavaScript code + looks up all \e {img} elements and rotates the images 180 degrees + and then back again. + + \snippet examples/webkit/fancybrowser/mainwindow.cpp 9 + + The remaining four methods remove different elements from the current web + page. \c removeGifImages() removes all Gif images on the page by looking up + the \e {src} attribute of all the elements on the web page. Any element with + a \e {gif} file as its source is removed. \c removeInlineFrames() removes all + \e {iframe} or inline elements. \c removeObjectElements() removes all + \e {object} elements, and \c removeEmbeddedElements() removes any elements + such as plugins embedded on the page using the \e {embed} tag. + */ + diff --git a/doc/src/qset.qdoc b/doc/src/qset.qdoc index 9795123..2d12661 100644 --- a/doc/src/qset.qdoc +++ b/doc/src/qset.qdoc @@ -447,7 +447,7 @@ \fn QSet::const_iterator QSet::insert(const T &value) Inserts item \a value into the set, if \a value isn't already - in the set, and returns an iterator positioned at the inserted + in the set, and returns an iterator pointing at the inserted item. \sa operator<<(), remove(), contains() diff --git a/doc/src/snippets/sqldatabase/sqldatabase.cpp b/doc/src/snippets/sqldatabase/sqldatabase.cpp index ae176ac..06afa0c 100644 --- a/doc/src/snippets/sqldatabase/sqldatabase.cpp +++ b/doc/src/snippets/sqldatabase/sqldatabase.cpp @@ -524,7 +524,7 @@ protected: bool fetchLast() { return false; } int size() { return 0; } int numRowsAffected() { return 0; } - QSqlRecord record() { return QSqlRecord(); } + QSqlRecord record() const { return QSqlRecord(); } }; //! [47] diff --git a/examples/assistant/simpletextviewer/mainwindow.cpp b/examples/assistant/simpletextviewer/mainwindow.cpp index cc2f3c0..f7c7098 100644 --- a/examples/assistant/simpletextviewer/mainwindow.cpp +++ b/examples/assistant/simpletextviewer/mainwindow.cpp @@ -101,11 +101,11 @@ void MainWindow::open() void MainWindow::createActions() { assistantAct = new QAction(tr("Help Contents"), this); - assistantAct->setShortcut(tr("F1")); + assistantAct->setShortcuts(QKeySequence::HelpContents); connect(assistantAct, SIGNAL(triggered()), this, SLOT(assistant())); openAct = new QAction(tr("&Open..."), this); - openAct->setShortcut(tr("Ctrl+O")); + openAct->setShortcuts(QKeySequence::Open); connect(openAct, SIGNAL(triggered()), this, SLOT(open())); clearAct = new QAction(tr("&Clear"), this); @@ -113,7 +113,7 @@ void MainWindow::createActions() connect(clearAct, SIGNAL(triggered()), textViewer, SLOT(clear())); exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); aboutAct = new QAction(tr("&About"), this); diff --git a/examples/draganddrop/puzzle/mainwindow.cpp b/examples/draganddrop/puzzle/mainwindow.cpp index f998882..9035442 100644 --- a/examples/draganddrop/puzzle/mainwindow.cpp +++ b/examples/draganddrop/puzzle/mainwindow.cpp @@ -120,10 +120,10 @@ void MainWindow::setupMenus() QMenu *fileMenu = menuBar()->addMenu(tr("&File")); QAction *openAction = fileMenu->addAction(tr("&Open...")); - openAction->setShortcut(QKeySequence(tr("Ctrl+O"))); + openAction->setShortcuts(QKeySequence::Open); QAction *exitAction = fileMenu->addAction(tr("E&xit")); - exitAction->setShortcut(QKeySequence(tr("Ctrl+Q"))); + exitAction->setShortcuts(QKeySequence::Quit); QMenu *gameMenu = menuBar()->addMenu(tr("&Game")); diff --git a/examples/graphicsview/diagramscene/mainwindow.cpp b/examples/graphicsview/diagramscene/mainwindow.cpp index b536a7a..78fac30 100644 --- a/examples/graphicsview/diagramscene/mainwindow.cpp +++ b/examples/graphicsview/diagramscene/mainwindow.cpp @@ -401,7 +401,7 @@ void MainWindow::createActions() this, SLOT(deleteItem())); exitAction = new QAction(tr("E&xit"), this); - exitAction->setShortcut(tr("Ctrl+X")); + exitAction->setShortcuts(QKeySequence::Quit); exitAction->setStatusTip(tr("Quit Scenediagram example")); connect(exitAction, SIGNAL(triggered()), this, SLOT(close())); diff --git a/examples/help/simpletextviewer/mainwindow.cpp b/examples/help/simpletextviewer/mainwindow.cpp index fc9af58..33092ca 100644 --- a/examples/help/simpletextviewer/mainwindow.cpp +++ b/examples/help/simpletextviewer/mainwindow.cpp @@ -102,12 +102,12 @@ void MainWindow::open() void MainWindow::createActions() { assistantAct = new QAction(tr("Help Contents"), this); - assistantAct->setShortcut(tr("F1")); + assistantAct->setShortcut(QKeySequence::HelpContents); connect(assistantAct, SIGNAL(triggered()), this, SLOT(showDocumentation())); //! [4] openAct = new QAction(tr("&Open..."), this); - openAct->setShortcut(tr("Ctrl+O")); + openAct->setShortcut(QKeySequence::Open); connect(openAct, SIGNAL(triggered()), this, SLOT(open())); clearAct = new QAction(tr("&Clear"), this); @@ -115,7 +115,7 @@ void MainWindow::createActions() connect(clearAct, SIGNAL(triggered()), textViewer, SLOT(clear())); exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); aboutAct = new QAction(tr("&About"), this); diff --git a/examples/itemviews/chart/mainwindow.cpp b/examples/itemviews/chart/mainwindow.cpp index 208a465..d065558 100644 --- a/examples/itemviews/chart/mainwindow.cpp +++ b/examples/itemviews/chart/mainwindow.cpp @@ -48,11 +48,11 @@ MainWindow::MainWindow() { QMenu *fileMenu = new QMenu(tr("&File"), this); QAction *openAction = fileMenu->addAction(tr("&Open...")); - openAction->setShortcut(QKeySequence(tr("Ctrl+O"))); + openAction->setShortcuts(QKeySequence::Open); QAction *saveAction = fileMenu->addAction(tr("&Save As...")); - saveAction->setShortcut(QKeySequence(tr("Ctrl+S"))); + saveAction->setShortcuts(QKeySequence::SaveAs); QAction *quitAction = fileMenu->addAction(tr("E&xit")); - quitAction->setShortcut(QKeySequence(tr("Ctrl+Q"))); + quitAction->setShortcuts(QKeySequence::Quit); setupModel(); setupViews(); diff --git a/examples/itemviews/pixelator/mainwindow.cpp b/examples/itemviews/pixelator/mainwindow.cpp index a2b98cf..80cfc5c 100644 --- a/examples/itemviews/pixelator/mainwindow.cpp +++ b/examples/itemviews/pixelator/mainwindow.cpp @@ -79,14 +79,14 @@ MainWindow::MainWindow() QMenu *fileMenu = new QMenu(tr("&File"), this); QAction *openAction = fileMenu->addAction(tr("&Open...")); - openAction->setShortcut(QKeySequence(tr("Ctrl+O"))); + openAction->setShortcuts(QKeySequence::Open); printAction = fileMenu->addAction(tr("&Print...")); printAction->setEnabled(false); - printAction->setShortcut(QKeySequence(tr("Ctrl+P"))); + printAction->setShortcut(QKeySequence::Print); QAction *quitAction = fileMenu->addAction(tr("E&xit")); - quitAction->setShortcut(QKeySequence(tr("Ctrl+Q"))); + quitAction->setShortcuts(QKeySequence::Quit); QMenu *helpMenu = new QMenu(tr("&Help"), this); QAction *aboutAction = helpMenu->addAction(tr("&About")); diff --git a/examples/itemviews/puzzle/mainwindow.cpp b/examples/itemviews/puzzle/mainwindow.cpp index c6088f6..a5ba236 100644 --- a/examples/itemviews/puzzle/mainwindow.cpp +++ b/examples/itemviews/puzzle/mainwindow.cpp @@ -107,10 +107,10 @@ void MainWindow::setupMenus() QMenu *fileMenu = menuBar()->addMenu(tr("&File")); QAction *openAction = fileMenu->addAction(tr("&Open...")); - openAction->setShortcut(QKeySequence(tr("Ctrl+O"))); + openAction->setShortcuts(QKeySequence::Open); QAction *exitAction = fileMenu->addAction(tr("E&xit")); - exitAction->setShortcut(QKeySequence(tr("Ctrl+Q"))); + exitAction->setShortcuts(QKeySequence::Quit); QMenu *gameMenu = menuBar()->addMenu(tr("&Game")); diff --git a/examples/itemviews/simpledommodel/mainwindow.cpp b/examples/itemviews/simpledommodel/mainwindow.cpp index ac96899..73626b1 100644 --- a/examples/itemviews/simpledommodel/mainwindow.cpp +++ b/examples/itemviews/simpledommodel/mainwindow.cpp @@ -50,9 +50,9 @@ MainWindow::MainWindow() : QMainWindow(), model(0) { fileMenu = menuBar()->addMenu(tr("&File")); fileMenu->addAction(tr("&Open..."), this, SLOT(openFile()), - QKeySequence(tr("Ctrl+O"))); + QKeySequence::Open); fileMenu->addAction(tr("E&xit"), this, SLOT(close()), - QKeySequence(tr("Ctrl+Q"))); + QKeySequence::Quit); model = new DomModel(QDomDocument(), this); view = new QTreeView(this); diff --git a/examples/linguist/arrowpad/mainwindow.cpp b/examples/linguist/arrowpad/mainwindow.cpp index a167cc2..37b9362 100644 --- a/examples/linguist/arrowpad/mainwindow.cpp +++ b/examples/linguist/arrowpad/mainwindow.cpp @@ -53,7 +53,7 @@ MainWindow::MainWindow() //! [1] exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); //! [1] diff --git a/examples/mainwindows/application/mainwindow.cpp b/examples/mainwindows/application/mainwindow.cpp index 9a22254..cf36332 100644 --- a/examples/mainwindows/application/mainwindow.cpp +++ b/examples/mainwindows/application/mainwindow.cpp @@ -174,7 +174,7 @@ void MainWindow::createActions() //! [20] exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); //! [20] exitAct->setStatusTip(tr("Exit the application")); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); diff --git a/examples/mainwindows/dockwidgets/mainwindow.cpp b/examples/mainwindows/dockwidgets/mainwindow.cpp index 1683034..4ccd2f1 100644 --- a/examples/mainwindows/dockwidgets/mainwindow.cpp +++ b/examples/mainwindows/dockwidgets/mainwindow.cpp @@ -242,7 +242,7 @@ void MainWindow::createActions() connect(undoAct, SIGNAL(triggered()), this, SLOT(undo())); quitAct = new QAction(tr("&Quit"), this); - quitAct->setShortcut(tr("Ctrl+Q")); + quitAct->setShortcuts(QKeySequence::Quit); quitAct->setStatusTip(tr("Quit the application")); connect(quitAct, SIGNAL(triggered()), this, SLOT(close())); diff --git a/examples/mainwindows/mdi/mainwindow.cpp b/examples/mainwindows/mdi/mainwindow.cpp index 49f9b21..e6e3e6e 100644 --- a/examples/mainwindows/mdi/mainwindow.cpp +++ b/examples/mainwindows/mdi/mainwindow.cpp @@ -235,7 +235,7 @@ void MainWindow::createActions() //! [0] exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); exitAct->setStatusTip(tr("Exit the application")); connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows())); //! [0] diff --git a/examples/mainwindows/menus/mainwindow.cpp b/examples/mainwindows/menus/mainwindow.cpp index 4c10f73..08a3c31 100644 --- a/examples/mainwindows/menus/mainwindow.cpp +++ b/examples/mainwindows/menus/mainwindow.cpp @@ -219,7 +219,7 @@ void MainWindow::createActions() connect(printAct, SIGNAL(triggered()), this, SLOT(print())); exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); exitAct->setStatusTip(tr("Exit the application")); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); @@ -240,7 +240,7 @@ void MainWindow::createActions() connect(cutAct, SIGNAL(triggered()), this, SLOT(cut())); copyAct = new QAction(tr("&Copy"), this); - copyAct->setShortcut(tr("Ctrl+C")); + copyAct->setShortcuts(QKeySequence::Copy); copyAct->setStatusTip(tr("Copy the current selection's contents to the " "clipboard")); connect(copyAct, SIGNAL(triggered()), this, SLOT(copy())); @@ -253,7 +253,7 @@ void MainWindow::createActions() boldAct = new QAction(tr("&Bold"), this); boldAct->setCheckable(true); - boldAct->setShortcut(tr("Ctrl+B")); + boldAct->setShortcut(QKeySequence::Bold); boldAct->setStatusTip(tr("Make the text bold")); connect(boldAct, SIGNAL(triggered()), this, SLOT(bold())); @@ -263,7 +263,7 @@ void MainWindow::createActions() italicAct = new QAction(tr("&Italic"), this); italicAct->setCheckable(true); - italicAct->setShortcut(tr("Ctrl+I")); + italicAct->setShortcut(QKeySequence::Italic); italicAct->setStatusTip(tr("Make the text italic")); connect(italicAct, SIGNAL(triggered()), this, SLOT(italic())); diff --git a/examples/mainwindows/recentfiles/mainwindow.cpp b/examples/mainwindows/recentfiles/mainwindow.cpp index c8c2f88..5746863 100644 --- a/examples/mainwindows/recentfiles/mainwindow.cpp +++ b/examples/mainwindows/recentfiles/mainwindow.cpp @@ -132,7 +132,7 @@ void MainWindow::createActions() } exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); exitAct->setStatusTip(tr("Exit the application")); connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows())); diff --git a/examples/mainwindows/sdi/mainwindow.cpp b/examples/mainwindows/sdi/mainwindow.cpp index 61d63b3..e7e05ee 100644 --- a/examples/mainwindows/sdi/mainwindow.cpp +++ b/examples/mainwindows/sdi/mainwindow.cpp @@ -180,7 +180,7 @@ void MainWindow::createActions() connect(closeAct, SIGNAL(triggered()), this, SLOT(close())); exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); exitAct->setStatusTip(tr("Exit the application")); connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows())); diff --git a/examples/opengl/grabber/mainwindow.cpp b/examples/opengl/grabber/mainwindow.cpp index 7e878f9..9e27023 100644 --- a/examples/opengl/grabber/mainwindow.cpp +++ b/examples/opengl/grabber/mainwindow.cpp @@ -136,7 +136,7 @@ void MainWindow::createActions() connect(clearPixmapAct, SIGNAL(triggered()), this, SLOT(clearPixmap())); exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); aboutAct = new QAction(tr("&About"), this); diff --git a/examples/painting/svgviewer/mainwindow.cpp b/examples/painting/svgviewer/mainwindow.cpp index 22393eb..64f35ed 100644 --- a/examples/painting/svgviewer/mainwindow.cpp +++ b/examples/painting/svgviewer/mainwindow.cpp @@ -53,7 +53,7 @@ MainWindow::MainWindow() QAction *openAction = fileMenu->addAction(tr("&Open...")); openAction->setShortcut(QKeySequence(tr("Ctrl+O"))); QAction *quitAction = fileMenu->addAction(tr("E&xit")); - quitAction->setShortcut(QKeySequence(tr("Ctrl+Q"))); + quitAction->setShortcuts(QKeySequence::Quit); menuBar()->addMenu(fileMenu); diff --git a/examples/phonon/musicplayer/mainwindow.cpp b/examples/phonon/musicplayer/mainwindow.cpp index f50a2bd..30c6d05 100644 --- a/examples/phonon/musicplayer/mainwindow.cpp +++ b/examples/phonon/musicplayer/mainwindow.cpp @@ -261,7 +261,7 @@ void MainWindow::setupActions() addFilesAction = new QAction(tr("Add &Files"), this); addFilesAction->setShortcut(tr("Ctrl+F")); exitAction = new QAction(tr("E&xit"), this); - exitAction->setShortcut(tr("Ctrl+X")); + exitAction->setShortcuts(QKeySequence::Quit); aboutAction = new QAction(tr("A&bout"), this); aboutAction->setShortcut(tr("Ctrl+B")); aboutQtAction = new QAction(tr("About &Qt"), this); diff --git a/examples/richtext/orderform/mainwindow.cpp b/examples/richtext/orderform/mainwindow.cpp index e5cffe3..7e460b7 100644 --- a/examples/richtext/orderform/mainwindow.cpp +++ b/examples/richtext/orderform/mainwindow.cpp @@ -49,12 +49,12 @@ MainWindow::MainWindow() { QMenu *fileMenu = new QMenu(tr("&File"), this); QAction *newAction = fileMenu->addAction(tr("&New...")); - newAction->setShortcut(tr("Ctrl+N")); + newAction->setShortcuts(QKeySequence::New); printAction = fileMenu->addAction(tr("&Print..."), this, SLOT(printFile())); - printAction->setShortcut(tr("Ctrl+P")); + printAction->setShortcuts(QKeySequence::Print); printAction->setEnabled(false); QAction *quitAction = fileMenu->addAction(tr("E&xit")); - quitAction->setShortcut(tr("Ctrl+Q")); + quitAction->setShortcuts(QKeySequence::Quit); menuBar()->addMenu(fileMenu); letters = new QTabWidget; diff --git a/examples/richtext/syntaxhighlighter/mainwindow.cpp b/examples/richtext/syntaxhighlighter/mainwindow.cpp index a6312f9..0d1b41f 100644 --- a/examples/richtext/syntaxhighlighter/mainwindow.cpp +++ b/examples/richtext/syntaxhighlighter/mainwindow.cpp @@ -110,14 +110,13 @@ void MainWindow::setupFileMenu() menuBar()->addMenu(fileMenu); fileMenu->addAction(tr("&New"), this, SLOT(newFile()), - QKeySequence(tr("Ctrl+N", - "File|New"))); + QKeySequence::New); + fileMenu->addAction(tr("&Open..."), this, SLOT(openFile()), - QKeySequence(tr("Ctrl+O", - "File|Open"))); + QKeySequence::Open); + fileMenu->addAction(tr("E&xit"), qApp, SLOT(quit()), - QKeySequence(tr("Ctrl+Q", - "File|Exit"))); + QKeySequence::Quit); } void MainWindow::setupHelpMenu() diff --git a/examples/sql/masterdetail/mainwindow.cpp b/examples/sql/masterdetail/mainwindow.cpp index 67825d6..5bf4cb9 100644 --- a/examples/sql/masterdetail/mainwindow.cpp +++ b/examples/sql/masterdetail/mainwindow.cpp @@ -362,7 +362,7 @@ void MainWindow::createMenuBar() addAction->setShortcut(tr("Ctrl+A")); deleteAction->setShortcut(tr("Ctrl+D")); - quitAction->setShortcut(tr("Ctrl+Q")); + quitAction->setShortcuts(QKeySequence::Quit); QMenu *fileMenu = menuBar()->addMenu(tr("&File")); fileMenu->addAction(addAction); diff --git a/examples/tools/codecs/mainwindow.cpp b/examples/tools/codecs/mainwindow.cpp index 1e6fa69..5d3b7ac 100644 --- a/examples/tools/codecs/mainwindow.cpp +++ b/examples/tools/codecs/mainwindow.cpp @@ -156,7 +156,7 @@ void MainWindow::findCodecs() void MainWindow::createActions() { openAct = new QAction(tr("&Open..."), this); - openAct->setShortcut(tr("Ctrl+O")); + openAct->setShortcuts(QKeySequence::Open); connect(openAct, SIGNAL(triggered()), this, SLOT(open())); foreach (QTextCodec *codec, codecs) { @@ -169,7 +169,7 @@ void MainWindow::createActions() } exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); aboutAct = new QAction(tr("&About"), this); diff --git a/examples/tools/plugandpaint/mainwindow.cpp b/examples/tools/plugandpaint/mainwindow.cpp index 224bc71..f61359b 100644 --- a/examples/tools/plugandpaint/mainwindow.cpp +++ b/examples/tools/plugandpaint/mainwindow.cpp @@ -179,15 +179,15 @@ void MainWindow::aboutPlugins() void MainWindow::createActions() { openAct = new QAction(tr("&Open..."), this); - openAct->setShortcut(tr("Ctrl+O")); + openAct->setShortcuts(QKeySequence::Open); connect(openAct, SIGNAL(triggered()), this, SLOT(open())); saveAsAct = new QAction(tr("&Save As..."), this); - saveAsAct->setShortcut(tr("Ctrl+S")); + saveAsAct->setShortcuts(QKeySequence::SaveAs); connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); brushColorAct = new QAction(tr("&Brush Color..."), this); diff --git a/examples/tools/settingseditor/mainwindow.cpp b/examples/tools/settingseditor/mainwindow.cpp index 0f48a5c..0321b55 100644 --- a/examples/tools/settingseditor/mainwindow.cpp +++ b/examples/tools/settingseditor/mainwindow.cpp @@ -122,7 +122,7 @@ void MainWindow::about() void MainWindow::createActions() { openSettingsAct = new QAction(tr("&Open Application Settings..."), this); - openSettingsAct->setShortcut(tr("Ctrl+O")); + openSettingsAct->setShortcuts(QKeySequence::Open); connect(openSettingsAct, SIGNAL(triggered()), this, SLOT(openSettings())); openIniFileAct = new QAction(tr("Open I&NI File..."), this); @@ -146,7 +146,7 @@ void MainWindow::createActions() connect(refreshAct, SIGNAL(triggered()), settingsTree, SLOT(refresh())); exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); autoRefreshAct = new QAction(tr("&Auto-Refresh"), this); diff --git a/examples/tools/undoframework/mainwindow.cpp b/examples/tools/undoframework/mainwindow.cpp index f912ff2..bf0aa41 100644 --- a/examples/tools/undoframework/mainwindow.cpp +++ b/examples/tools/undoframework/mainwindow.cpp @@ -101,16 +101,14 @@ void MainWindow::createActions() //! [5] undoAction = undoStack->createUndoAction(this, tr("&Undo")); - undoAction->setShortcut(tr("Ctrl+Z")); + undoAction->setShortcuts(QKeySequence::Undo); redoAction = undoStack->createRedoAction(this, tr("&Redo")); - QList<QKeySequence> redoShortcuts; - redoShortcuts << tr("Ctrl+Y") << tr("Shift+Ctrl+Z"); - redoAction->setShortcuts(redoShortcuts); + redoAction->setShortcuts(QKeySequence::Redo); //! [5] exitAction = new QAction(tr("E&xit"), this); - exitAction->setShortcut(tr("Ctrl+Q")); + exitAction->setShortcuts(QKeySequence::Quit); connect(exitAction, SIGNAL(triggered()), this, SLOT(close())); aboutAction = new QAction(tr("&About"), this); diff --git a/examples/webkit/fancybrowser/mainwindow.cpp b/examples/webkit/fancybrowser/mainwindow.cpp index bf61f9c..e24f6cf 100644 --- a/examples/webkit/fancybrowser/mainwindow.cpp +++ b/examples/webkit/fancybrowser/mainwindow.cpp @@ -43,6 +43,8 @@ #include <QtWebKit> #include "mainwindow.h" +//! [1] + MainWindow::MainWindow() { progress = 0; @@ -52,7 +54,9 @@ MainWindow::MainWindow() file.open(QIODevice::ReadOnly); jQuery = file.readAll(); file.close(); +//! [1] +//! [2] view = new QWebView(this); view->load(QUrl("http://www.google.com/ncr")); connect(view, SIGNAL(loadFinished(bool)), SLOT(adjustLocation())); @@ -70,7 +74,9 @@ MainWindow::MainWindow() toolBar->addAction(view->pageAction(QWebPage::Reload)); toolBar->addAction(view->pageAction(QWebPage::Stop)); toolBar->addWidget(locationEdit); +//! [2] +//! [3] QMenu *effectMenu = menuBar()->addMenu(tr("&Effect")); effectMenu->addAction("Highlight all links", this, SLOT(highlightAllLinks())); @@ -89,7 +95,9 @@ MainWindow::MainWindow() setCentralWidget(view); } +//! [3] +//! [4] void MainWindow::adjustLocation() { locationEdit->setText(view->url().toString()); @@ -98,11 +106,12 @@ void MainWindow::adjustLocation() void MainWindow::changeLocation() { QUrl url = QUrl(locationEdit->text()); - locationEdit->setText(url.toString()); view->load(url); view->setFocus(); } +//! [4] +//! [5] void MainWindow::adjustTitle() { if (progress <= 0 || progress >= 100) @@ -116,20 +125,26 @@ void MainWindow::setProgress(int p) progress = p; adjustTitle(); } +//! [5] +//! [6] void MainWindow::finishLoading(bool) { progress = 100; adjustTitle(); view->page()->mainFrame()->evaluateJavaScript(jQuery); } +//! [6] +//! [7] void MainWindow::highlightAllLinks() { QString code = "$('a').each( function () { $(this).css('background-color', 'yellow') } )"; view->page()->mainFrame()->evaluateJavaScript(code); } +//! [7] +//! [8] void MainWindow::rotateImages(bool toggle) { QString code = "$('img').each( function () { $(this).css('-webkit-transition', '-webkit-transform 2s') } )"; @@ -140,7 +155,9 @@ void MainWindow::rotateImages(bool toggle) code = "$('img').each( function () { $(this).css('-webkit-transform', 'rotate(0deg)') } )"; view->page()->mainFrame()->evaluateJavaScript(code); } +//! [8] +//! [9] void MainWindow::removeGifImages() { QString code = "$('[src*=gif]').remove()"; @@ -164,4 +181,5 @@ void MainWindow::removeEmbeddedElements() QString code = "$('embed').remove()"; view->page()->mainFrame()->evaluateJavaScript(code); } +//! [9] diff --git a/examples/webkit/fancybrowser/mainwindow.h b/examples/webkit/fancybrowser/mainwindow.h index 9362ca7..2e1068c 100644 --- a/examples/webkit/fancybrowser/mainwindow.h +++ b/examples/webkit/fancybrowser/mainwindow.h @@ -39,13 +39,14 @@ ** ****************************************************************************/ -#include <QMainWindow> +#include <QtGui> QT_BEGIN_NAMESPACE class QWebView; class QLineEdit; QT_END_NAMESPACE +//! [1] class MainWindow : public QMainWindow { Q_OBJECT @@ -73,4 +74,5 @@ private: QWebView *view; QLineEdit *locationEdit; int progress; +//! [1] }; diff --git a/examples/webkit/formextractor/mainwindow.cpp b/examples/webkit/formextractor/mainwindow.cpp index 222d9b2..ec4d043 100644 --- a/examples/webkit/formextractor/mainwindow.cpp +++ b/examples/webkit/formextractor/mainwindow.cpp @@ -54,7 +54,7 @@ void MainWindow::createActions() { exitAct = new QAction(tr("E&xit"), this); exitAct->setStatusTip(tr("Exit the application")); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); aboutAct = new QAction(tr("&About"), this); diff --git a/examples/webkit/previewer/mainwindow.cpp b/examples/webkit/previewer/mainwindow.cpp index abe7941..1e20ed3 100644 --- a/examples/webkit/previewer/mainwindow.cpp +++ b/examples/webkit/previewer/mainwindow.cpp @@ -61,7 +61,7 @@ MainWindow::MainWindow() void MainWindow::createActions() { openAct = new QAction(tr("&Open..."), this); - openAct->setShortcut(tr("Ctrl+O")); + openAct->setShortcuts(QKeySequence::Open); openAct->setStatusTip(tr("Open an existing HTML file")); connect(openAct, SIGNAL(triggered()), this, SLOT(open())); @@ -72,13 +72,13 @@ void MainWindow::createActions() //! [1] saveAct = new QAction(tr("&Save"), this); - saveAct->setShortcut(tr("Ctrl+S")); + saveAct->setShortcuts(QKeySequence::Save); saveAct->setStatusTip(tr("Save the HTML file to disk")); connect(saveAct, SIGNAL(triggered()), this, SLOT(save())); exitAct = new QAction(tr("E&xit"), this); exitAct->setStatusTip(tr("Exit the application")); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); aboutAct = new QAction(tr("&About"), this); diff --git a/examples/widgets/icons/mainwindow.cpp b/examples/widgets/icons/mainwindow.cpp index 00ce8b0..db42710 100644 --- a/examples/widgets/icons/mainwindow.cpp +++ b/examples/widgets/icons/mainwindow.cpp @@ -369,7 +369,7 @@ void MainWindow::createActions() this, SLOT(removeAllImages())); exitAct = new QAction(tr("&Quit"), this); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); styleActionGroup = new QActionGroup(this); diff --git a/examples/widgets/scribble/mainwindow.cpp b/examples/widgets/scribble/mainwindow.cpp index ad1a837..c4b05fe 100644 --- a/examples/widgets/scribble/mainwindow.cpp +++ b/examples/widgets/scribble/mainwindow.cpp @@ -141,7 +141,7 @@ void MainWindow::createActions() //! [13] //! [14] { openAct = new QAction(tr("&Open..."), this); - openAct->setShortcut(tr("Ctrl+O")); + openAct->setShortcuts(QKeySequence::Open); connect(openAct, SIGNAL(triggered()), this, SLOT(open())); foreach (QByteArray format, QImageWriter::supportedImageFormats()) { @@ -157,7 +157,7 @@ void MainWindow::createActions() connect(printAct, SIGNAL(triggered()), scribbleArea, SLOT(print())); exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); penColorAct = new QAction(tr("&Pen Color..."), this); diff --git a/examples/widgets/tablet/mainwindow.cpp b/examples/widgets/tablet/mainwindow.cpp index 56a10cd..10490bf 100644 --- a/examples/widgets/tablet/mainwindow.cpp +++ b/examples/widgets/tablet/mainwindow.cpp @@ -212,17 +212,17 @@ void MainWindow::createActions() this, SLOT(lineWidthActionTriggered(QAction *))); exitAction = new QAction(tr("E&xit"), this); - exitAction->setShortcut(tr("Ctrl+X")); + exitAction->setShortcuts(QKeySequence::Quit); connect(exitAction, SIGNAL(triggered()), this, SLOT(close())); loadAction = new QAction(tr("&Open..."), this); - loadAction->setShortcut(tr("Ctrl+O")); + loadAction->setShortcuts(QKeySequence::Open); connect(loadAction, SIGNAL(triggered()), this, SLOT(loadAct())); saveAction = new QAction(tr("&Save As..."), this); - saveAction->setShortcut(tr("Ctrl+S")); + saveAction->setShortcuts(QKeySequence::SaveAs); connect(saveAction, SIGNAL(triggered()), this, SLOT(saveAct())); diff --git a/examples/xml/dombookmarks/mainwindow.cpp b/examples/xml/dombookmarks/mainwindow.cpp index 6b0c101..7efe6ff 100644 --- a/examples/xml/dombookmarks/mainwindow.cpp +++ b/examples/xml/dombookmarks/mainwindow.cpp @@ -113,15 +113,15 @@ void MainWindow::about() void MainWindow::createActions() { openAct = new QAction(tr("&Open..."), this); - openAct->setShortcut(tr("Ctrl+O")); + openAct->setShortcuts(QKeySequence::Open); connect(openAct, SIGNAL(triggered()), this, SLOT(open())); saveAsAct = new QAction(tr("&Save As..."), this); - saveAsAct->setShortcut(tr("Ctrl+S")); + saveAsAct->setShortcuts(QKeySequence::SaveAs); connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); aboutAct = new QAction(tr("&About"), this); diff --git a/examples/xml/saxbookmarks/mainwindow.cpp b/examples/xml/saxbookmarks/mainwindow.cpp index 2cba559..9247eb7 100644 --- a/examples/xml/saxbookmarks/mainwindow.cpp +++ b/examples/xml/saxbookmarks/mainwindow.cpp @@ -128,15 +128,15 @@ void MainWindow::about() void MainWindow::createActions() { openAct = new QAction(tr("&Open..."), this); - openAct->setShortcut(tr("Ctrl+O")); + openAct->setShortcuts(QKeySequence::Open); connect(openAct, SIGNAL(triggered()), this, SLOT(open())); saveAsAct = new QAction(tr("&Save As..."), this); - saveAsAct->setShortcut(tr("Ctrl+S")); + saveAsAct->setShortcuts(QKeySequence::SaveAs); connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); aboutAct = new QAction(tr("&About"), this); diff --git a/examples/xml/streambookmarks/mainwindow.cpp b/examples/xml/streambookmarks/mainwindow.cpp index 2136b4b..c6f991b 100644 --- a/examples/xml/streambookmarks/mainwindow.cpp +++ b/examples/xml/streambookmarks/mainwindow.cpp @@ -141,15 +141,15 @@ void MainWindow::about() void MainWindow::createActions() { openAct = new QAction(tr("&Open..."), this); - openAct->setShortcut(tr("Ctrl+O")); + openAct->setShortcuts(QKeySequence::Open); connect(openAct, SIGNAL(triggered()), this, SLOT(open())); saveAsAct = new QAction(tr("&Save As..."), this); - saveAsAct->setShortcut(tr("Ctrl+S")); + saveAsAct->setShortcuts(QKeySequence::SaveAs); connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setShortcuts(QKeySequence::Quit); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); aboutAct = new QAction(tr("&About"), this); diff --git a/examples/xmlpatterns/trafficinfo/mainwindow.cpp b/examples/xmlpatterns/trafficinfo/mainwindow.cpp index 1f754d5..393e33c 100644 --- a/examples/xmlpatterns/trafficinfo/mainwindow.cpp +++ b/examples/xmlpatterns/trafficinfo/mainwindow.cpp @@ -55,7 +55,7 @@ MainWindow::MainWindow() : QWidget(0, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint) { QAction *quitAction = new QAction(tr("E&xit"), this); - quitAction->setShortcut(tr("Ctrl+Q")); + quitAction->setShortcuts(QKeySequence::Quit); connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); QAction *configAction = new QAction(tr("&Select station..."), this); diff --git a/qmake/qmake.pri b/qmake/qmake.pri index 02ff38e..9147ee8 100644 --- a/qmake/qmake.pri +++ b/qmake/qmake.pri @@ -79,7 +79,6 @@ bootstrap { #Qt code qfile.h \ qabstractfileengine.h \ qfileinfo.h \ - qfileinfo_p.h \ qglobal.h \ qnumeric.h \ qhash.h \ diff --git a/src/corelib/arch/qatomic_mips.h b/src/corelib/arch/qatomic_mips.h index b263aab..ea9954b 100644 --- a/src/corelib/arch/qatomic_mips.h +++ b/src/corelib/arch/qatomic_mips.h @@ -103,16 +103,25 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() #if defined(Q_CC_GNU) && !defined(Q_OS_IRIX) +#if _MIPS_SIM == _ABIO32 +#define SET_MIPS2 ".set mips2\n\t" +#else +#define SET_MIPS2 +#endif + inline bool QBasicAtomicInt::ref() { register int originalValue; register int newValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" "ll %[originalValue], %[_q_value]\n" "addiu %[newValue], %[originalValue], %[one]\n" "sc %[newValue], %[_q_value]\n" "beqz %[newValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [_q_value] "+m" (_q_value), [newValue] "=&r" (newValue) @@ -125,12 +134,15 @@ inline bool QBasicAtomicInt::deref() { register int originalValue; register int newValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" "ll %[originalValue], %[_q_value]\n" "addiu %[newValue], %[originalValue], %[minusOne]\n" "sc %[newValue], %[_q_value]\n" "beqz %[newValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [_q_value] "+m" (_q_value), [newValue] "=&r" (newValue) @@ -143,7 +155,9 @@ inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) { register int result; register int tempValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" "ll %[result], %[_q_value]\n" "xor %[result], %[result], %[expectedValue]\n" "bnez %[result], 0f\n" @@ -153,6 +167,7 @@ inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) "beqz %[tempValue], 0b\n" "nop\n" "0:\n" + ".set pop\n" : [result] "=&r" (result), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -166,7 +181,9 @@ inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) { register int result; register int tempValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" "ll %[result], %[_q_value]\n" "xor %[result], %[result], %[expectedValue]\n" "bnez %[result], 0f\n" @@ -177,6 +194,7 @@ inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) "nop\n" "sync\n" "0:\n" + ".set pop\n" : [result] "=&r" (result), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -190,7 +208,9 @@ inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) { register int result; register int tempValue; - asm volatile("sync\n" + asm volatile(".set push\n" + SET_MIPS2 + "sync\n" "0:\n" "ll %[result], %[_q_value]\n" "xor %[result], %[result], %[expectedValue]\n" @@ -201,6 +221,7 @@ inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) "beqz %[tempValue], 0b\n" "nop\n" "0:\n" + ".set pop\n" : [result] "=&r" (result), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -219,12 +240,15 @@ inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) { register int originalValue; register int tempValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" "ll %[originalValue], %[_q_value]\n" "move %[tempValue], %[newValue]\n" "sc %[tempValue], %[_q_value]\n" "beqz %[tempValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -237,13 +261,16 @@ inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) { register int originalValue; register int tempValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" "ll %[originalValue], %[_q_value]\n" "move %[tempValue], %[newValue]\n" "sc %[tempValue], %[_q_value]\n" "beqz %[tempValue], 0b\n" "nop\n" "sync\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -256,13 +283,16 @@ inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) { register int originalValue; register int tempValue; - asm volatile("sync\n" + asm volatile(".set push\n" + SET_MIPS2 + "sync\n" "0:\n" "ll %[originalValue], %[_q_value]\n" "move %[tempValue], %[newValue]\n" "sc %[tempValue], %[_q_value]\n" "beqz %[tempValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -280,12 +310,15 @@ inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) { register int originalValue; register int newValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" "ll %[originalValue], %[_q_value]\n" "addu %[newValue], %[originalValue], %[valueToAdd]\n" "sc %[newValue], %[_q_value]\n" "beqz %[newValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [_q_value] "+m" (_q_value), [newValue] "=&r" (newValue) @@ -298,13 +331,16 @@ inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) { register int originalValue; register int newValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" "ll %[originalValue], %[_q_value]\n" "addu %[newValue], %[originalValue], %[valueToAdd]\n" "sc %[newValue], %[_q_value]\n" "beqz %[newValue], 0b\n" "nop\n" "sync\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [_q_value] "+m" (_q_value), [newValue] "=&r" (newValue) @@ -317,13 +353,16 @@ inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) { register int originalValue; register int newValue; - asm volatile("sync\n" + asm volatile(".set push\n" + SET_MIPS2 + "sync\n" "0:\n" "ll %[originalValue], %[_q_value]\n" "addu %[newValue], %[originalValue], %[valueToAdd]\n" "sc %[newValue], %[_q_value]\n" "beqz %[newValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [_q_value] "+m" (_q_value), [newValue] "=&r" (newValue) @@ -350,7 +389,9 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValu { register T *result; register T *tempValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" LLP" %[result], %[_q_value]\n" "xor %[result], %[result], %[expectedValue]\n" "bnez %[result], 0f\n" @@ -360,6 +401,7 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValu "beqz %[tempValue], 0b\n" "nop\n" "0:\n" + ".set pop\n" : [result] "=&r" (result), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -374,7 +416,9 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValu { register T *result; register T *tempValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" LLP" %[result], %[_q_value]\n" "xor %[result], %[result], %[expectedValue]\n" "bnez %[result], 0f\n" @@ -385,6 +429,7 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValu "nop\n" "sync\n" "0:\n" + ".set pop\n" : [result] "=&r" (result), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -399,7 +444,9 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValu { register T *result; register T *tempValue; - asm volatile("sync\n" + asm volatile(".set push\n" + SET_MIPS2 + "sync\n" "0:\n" LLP" %[result], %[_q_value]\n" "xor %[result], %[result], %[expectedValue]\n" @@ -410,6 +457,7 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValu "beqz %[tempValue], 0b\n" "nop\n" "0:\n" + ".set pop\n" : [result] "=&r" (result), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -430,12 +478,15 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) { register T *originalValue; register T *tempValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" LLP" %[originalValue], %[_q_value]\n" "move %[tempValue], %[newValue]\n" SCP" %[tempValue], %[_q_value]\n" "beqz %[tempValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -449,13 +500,16 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) { register T *originalValue; register T *tempValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" LLP" %[originalValue], %[_q_value]\n" "move %[tempValue], %[newValue]\n" SCP" %[tempValue], %[_q_value]\n" "beqz %[tempValue], 0b\n" "nop\n" "sync\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -469,13 +523,16 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) { register T *originalValue; register T *tempValue; - asm volatile("sync\n" + asm volatile(".set push\n" + SET_MIPS2 + "sync\n" "0:\n" LLP" %[originalValue], %[_q_value]\n" "move %[tempValue], %[newValue]\n" SCP" %[tempValue], %[_q_value]\n" "beqz %[tempValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -495,12 +552,15 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueTo { register T *originalValue; register T *newValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" LLP" %[originalValue], %[_q_value]\n" "addu %[newValue], %[originalValue], %[valueToAdd]\n" SCP" %[newValue], %[_q_value]\n" "beqz %[newValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [_q_value] "+m" (_q_value), [newValue] "=&r" (newValue) @@ -514,13 +574,16 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueTo { register T *originalValue; register T *newValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" LLP" %[originalValue], %[_q_value]\n" "addu %[newValue], %[originalValue], %[valueToAdd]\n" SCP" %[newValue], %[_q_value]\n" "beqz %[newValue], 0b\n" "nop\n" "sync\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [_q_value] "+m" (_q_value), [newValue] "=&r" (newValue) @@ -534,13 +597,16 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueTo { register T *originalValue; register T *newValue; - asm volatile("sync\n" + asm volatile(".set push\n" + SET_MIPS2 + "sync\n" "0:\n" LLP" %[originalValue], %[_q_value]\n" "addu %[newValue], %[originalValue], %[valueToAdd]\n" SCP" %[newValue], %[_q_value]\n" "beqz %[newValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [_q_value] "+m" (_q_value), [newValue] "=&r" (newValue) diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 3690d4b..8f37e25 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -10,9 +10,9 @@ HEADERS += \ io/qdiriterator.h \ io/qfile.h \ io/qfileinfo.h \ - io/qfileinfo_p.h \ io/qiodevice.h \ io/qiodevice_p.h \ + io/qnoncontiguousbytedevice_p.h \ io/qprocess.h \ io/qprocess_p.h \ io/qtextstream.h \ @@ -38,6 +38,7 @@ SOURCES += \ io/qfile.cpp \ io/qfileinfo.cpp \ io/qiodevice.cpp \ + io/qnoncontiguousbytedevice.cpp \ io/qprocess.cpp \ io/qtextstream.cpp \ io/qtemporaryfile.cpp \ diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h deleted file mode 100644 index 7d66581..0000000 --- a/src/corelib/io/qfileinfo_p.h +++ /dev/null @@ -1,145 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QFILEINFO_P_H -#define QFILEINFO_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of QIODevice. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qfileinfo.h" - -QT_BEGIN_NAMESPACE - -class QFileInfoPrivate -{ -public: - QFileInfoPrivate(const QFileInfo *copy=0); - ~QFileInfoPrivate(); - - void initFileEngine(const QString &); - - enum Access { - ReadAccess, - WriteAccess, - ExecuteAccess - }; - bool hasAccess(Access access) const; - - uint getFileFlags(QAbstractFileEngine::FileFlags) const; - QDateTime &getFileTime(QAbstractFileEngine::FileTime) const; - QString getFileName(QAbstractFileEngine::FileName) const; - - enum { - CachedFileFlags = 0x01, - CachedLinkTypeFlag = 0x02, - CachedBundleTypeFlag= 0x04, - CachedMTime = 0x10, - CachedCTime = 0x20, - CachedATime = 0x40, - CachedSize = 0x08 - }; - - struct Data - { - inline Data() - : ref(1), fileEngine(0), cache_enabled(1) - { - clear(); - } - - inline Data(const Data ©) - : ref(1), fileEngine(QAbstractFileEngine::create(copy.fileName)), - fileName(copy.fileName), cache_enabled(copy.cache_enabled) - { - clear(); - } - - inline ~Data() - { - delete fileEngine; - } - - inline void clear() - { - fileNames.clear(); - fileFlags = 0; - cachedFlags = 0; - } - - mutable QAtomicInt ref; - - QAbstractFileEngine *fileEngine; - mutable QString fileName; - mutable QHash<int, QString> fileNames; - mutable uint cachedFlags : 31; - mutable uint cache_enabled : 1; - mutable uint fileFlags; - mutable qint64 fileSize; - mutable QDateTime fileTimes[3]; - - inline bool getCachedFlag(uint c) const - { return cache_enabled ? (cachedFlags & c) : 0; } - - inline void setCachedFlag(uint c) - { if (cache_enabled) cachedFlags |= c; } - } *data; - - inline void reset() { - detach(); - data->clear(); - } - - void detach(); -}; - - -QT_END_NAMESPACE -#endif - diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 8a0a3f5..7a6a85b 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -780,7 +780,7 @@ QString QFSFileEngine::fileName(FileName file) const #endif if (len > 0) { QString ret; - if (S_ISDIR(d->st.st_mode) && s[0] != '/') { + if (d->doStat() && S_ISDIR(d->st.st_mode) && s[0] != '/') { QDir parent(d->filePath); parent.cdUp(); ret = parent.path(); diff --git a/src/corelib/io/qnoncontiguousbytedevice.cpp b/src/corelib/io/qnoncontiguousbytedevice.cpp new file mode 100644 index 0000000..6233fde --- /dev/null +++ b/src/corelib/io/qnoncontiguousbytedevice.cpp @@ -0,0 +1,542 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnoncontiguousbytedevice_p.h" +#include <QObject> +#include <QBuffer> +#include <QDebug> +#include <QFile> + +QT_BEGIN_NAMESPACE + +/*! + \class QNonContiguousByteDevice + \brief A QNonContiguousByteDevice is a representation of a + file, array or buffer that allows access with a read pointer. + \since 4.6 + + \inmodule QtCore + + The goal of this class is to have a data representation that + allows us to avoid doing a memcpy as we have to do with QIODevice. + + \sa QNonContiguousByteDeviceFactory + + \internal +*/ +/*! + \fn virtual const char* QNonContiguousByteDevice::readPointer(qint64 maximumLength, qint64 &len) + + Return a byte pointer for at most \a maximumLength bytes of that device. + if \a maximumLength is -1, the caller does not care about the length and + the device may return what it desires to. + The actual number of bytes the pointer is valid for is returned in + the \a len variable. + \a len will be -1 if EOF or an error occurs. + If it was really EOF can then afterwards be checked with atEnd() + Returns 0 if it is not possible to read at that position. + + \sa atEnd() + + \internal +*/ +/*! + \fn virtual bool QNonContiguousByteDevice::advanceReadPointer(qint64 amount) + + will advance the internal read pointer by \a amount bytes. + The old readPointer is invalid after this call. + + \sa readPointer() + + \internal +*/ +/*! + \fn virtual bool QNonContiguousByteDevice::atEnd() + + Returns true if everything has been read and the read + pointer cannot be advanced anymore. + + \sa readPointer(), advanceReadPointer(), reset() + + \internal +*/ +/*! + \fn virtual bool QNonContiguousByteDevice::reset() + + Moves the internal read pointer back to the beginning. + Returns false if this was not possible. + + \sa atEnd(), disableReset() + + \internal +*/ +/*! + \fn void QNonContiguousByteDevice::disableReset() + + Disable the reset() call, e.g. it will always + do nothing and return false. + + \sa reset() + + \internal +*/ +/*! + \fn virtual qint64 QNonContiguousByteDevice::size() + + Returns the size of the complete device or -1 if unknown. + May also return less/more than what can be actually read with readPointer() + + \internal +*/ +/*! + \fn void QNonContiguousByteDevice::readyRead() + + Emitted when there is data available + + \internal +*/ +/*! + \fn void QNonContiguousByteDevice::readProgress(qint64 current, qint64 total) + + Emitted when data has been "read" by advancing the read pointer + + \internal +*/ + +QNonContiguousByteDevice::QNonContiguousByteDevice() : QObject((QObject*)0), resetDisabled(false) +{ +}; + +QNonContiguousByteDevice::~QNonContiguousByteDevice() +{ +}; + +void QNonContiguousByteDevice::disableReset() +{ + resetDisabled = true; +} + +QNonContiguousByteDeviceBufferImpl::QNonContiguousByteDeviceBufferImpl(QBuffer *b) : QNonContiguousByteDevice() +{ + buffer = b; + byteArray = QByteArray::fromRawData(buffer->buffer().constData() + buffer->pos(), buffer->size() - buffer->pos()); + arrayImpl = new QNonContiguousByteDeviceByteArrayImpl(&byteArray); + arrayImpl->setParent(this); + connect(arrayImpl, SIGNAL(readyRead()), SIGNAL(readyRead())); + connect(arrayImpl, SIGNAL(readProgress(qint64,qint64)), SIGNAL(readProgress(qint64,qint64))); +} + +QNonContiguousByteDeviceBufferImpl::~QNonContiguousByteDeviceBufferImpl() +{ +} + +const char* QNonContiguousByteDeviceBufferImpl::readPointer(qint64 maximumLength, qint64 &len) +{ + return arrayImpl->readPointer(maximumLength, len); +} + +bool QNonContiguousByteDeviceBufferImpl::advanceReadPointer(qint64 amount) +{ + return arrayImpl->advanceReadPointer(amount); +} + +bool QNonContiguousByteDeviceBufferImpl::atEnd() +{ + return arrayImpl->atEnd(); +} + +bool QNonContiguousByteDeviceBufferImpl::reset() +{ + if (resetDisabled) + return false; + return arrayImpl->reset(); +} + +qint64 QNonContiguousByteDeviceBufferImpl::size() +{ + return arrayImpl->size(); +} + +QNonContiguousByteDeviceByteArrayImpl::QNonContiguousByteDeviceByteArrayImpl(QByteArray *ba) : QNonContiguousByteDevice(), currentPosition(0) +{ + byteArray = ba; +} + +QNonContiguousByteDeviceByteArrayImpl::~QNonContiguousByteDeviceByteArrayImpl() +{ +} + +const char* QNonContiguousByteDeviceByteArrayImpl::readPointer(qint64 maximumLength, qint64 &len) +{ + if (atEnd()) { + len = -1; + return 0; + } + + if (maximumLength != -1) + len = qMin(maximumLength, size() - currentPosition); + else + len = size() - currentPosition; + + return byteArray->constData() + currentPosition; +} + +bool QNonContiguousByteDeviceByteArrayImpl::advanceReadPointer(qint64 amount) +{ + currentPosition += amount; + emit readProgress(currentPosition, size()); + return true; +} + +bool QNonContiguousByteDeviceByteArrayImpl::atEnd() +{ + return currentPosition >= size(); +} + +bool QNonContiguousByteDeviceByteArrayImpl::reset() +{ + if (resetDisabled) + return false; + + currentPosition = 0; + return true; +} + +qint64 QNonContiguousByteDeviceByteArrayImpl::size() +{ + return byteArray->size(); +} + +QNonContiguousByteDeviceRingBufferImpl::QNonContiguousByteDeviceRingBufferImpl(QRingBuffer *rb) + : QNonContiguousByteDevice(), currentPosition(0) +{ + ringBuffer = rb; +} + +QNonContiguousByteDeviceRingBufferImpl::~QNonContiguousByteDeviceRingBufferImpl() +{ +}; + +const char* QNonContiguousByteDeviceRingBufferImpl::readPointer(qint64 maximumLength, qint64 &len) +{ + if (atEnd()) { + len = -1; + return 0; + } + + const char *returnValue = ringBuffer->readPointerAtPosition(currentPosition, len); + + if (maximumLength != -1) + len = qMin(len, maximumLength); + + return returnValue; +}; + +bool QNonContiguousByteDeviceRingBufferImpl::advanceReadPointer(qint64 amount) +{ + currentPosition += amount; + emit readProgress(currentPosition, size()); + return true; +}; + +bool QNonContiguousByteDeviceRingBufferImpl::atEnd() +{ + return currentPosition >= size(); +}; + +bool QNonContiguousByteDeviceRingBufferImpl::reset() +{ + if (resetDisabled) + return false; + + currentPosition = 0; + return true; +}; + +qint64 QNonContiguousByteDeviceRingBufferImpl::size() +{ + return ringBuffer->size(); +}; + +QNonContiguousByteDeviceIoDeviceImpl::QNonContiguousByteDeviceIoDeviceImpl(QIODevice *d) + : QNonContiguousByteDevice(), + currentReadBuffer(0), currentReadBufferSize(16*1024), + currentReadBufferAmount(0), currentReadBufferPosition(0), totalAdvancements(0), + eof(false) +{ + device = d; + initialPosition = d->pos(); + connect(device, SIGNAL(readyRead()), this, SIGNAL(readyRead()), Qt::QueuedConnection); + connect(device, SIGNAL(readChannelFinished()), this, SIGNAL(readyRead()), Qt::QueuedConnection); +}; + +QNonContiguousByteDeviceIoDeviceImpl::~QNonContiguousByteDeviceIoDeviceImpl() +{ + delete currentReadBuffer; +}; + +const char* QNonContiguousByteDeviceIoDeviceImpl::readPointer(qint64 maximumLength, qint64 &len) +{ + if (eof == true) { + len = -1; + return 0; + } + + if (currentReadBuffer == 0) + currentReadBuffer = new QByteArray(currentReadBufferSize, '\0'); // lazy alloc + + if (maximumLength == -1) + maximumLength = currentReadBufferSize; + + if (currentReadBufferAmount - currentReadBufferPosition > 0) { + len = currentReadBufferAmount - currentReadBufferPosition; + return currentReadBuffer->data() + currentReadBufferPosition; + } + + qint64 haveRead = device->read(currentReadBuffer->data(), qMin(maximumLength, currentReadBufferSize)); + + if ((haveRead == -1) || (haveRead == 0 && device->atEnd() && !device->isSequential())) { + eof = true; + len = -1; + // size was unknown before, emit a readProgress with the final size + if (size() == -1) + emit readProgress(totalAdvancements, totalAdvancements); + return 0; + } + + currentReadBufferAmount = haveRead; + currentReadBufferPosition = 0; + + len = haveRead; + return currentReadBuffer->data(); +}; + +bool QNonContiguousByteDeviceIoDeviceImpl::advanceReadPointer(qint64 amount) +{ + totalAdvancements += amount; + + // normal advancement + currentReadBufferPosition += amount; + + // advancing over that what has actually been read before + if (currentReadBufferPosition > currentReadBufferAmount) { + qint64 i = currentReadBufferPosition - currentReadBufferAmount; + while (i > 0) { + if (device->getChar(0) == false) { + emit readProgress(totalAdvancements - i, size()); + return false; // ### FIXME handle eof + } + i--; + } + + currentReadBufferPosition = 0; + currentReadBufferAmount = 0; + } + + if (size() == -1) + emit readProgress(totalAdvancements, totalAdvancements); + else + emit readProgress(totalAdvancements, size()); + + return true; +}; + +bool QNonContiguousByteDeviceIoDeviceImpl::atEnd() +{ + return eof == true; +}; + +bool QNonContiguousByteDeviceIoDeviceImpl::reset() +{ + if (resetDisabled) + return false; + + if (device->seek(initialPosition)) { + eof = false; // assume eof is false, it will be true after a read has been attempted + return true; + } + + return false; +}; + +qint64 QNonContiguousByteDeviceIoDeviceImpl::size() +{ + // note that this is different from the size() implementation of QIODevice! + + if (device->isSequential()) + return -1; + + return device->size() - initialPosition; +}; + +QByteDeviceWrappingIoDevice::QByteDeviceWrappingIoDevice(QNonContiguousByteDevice *bd) : QIODevice((QObject*)0) +{ + byteDevice = bd; + connect(bd, SIGNAL(readyRead()), SIGNAL(readyRead())); + + open(ReadOnly); +} + +QByteDeviceWrappingIoDevice::~QByteDeviceWrappingIoDevice() +{ + +} + +bool QByteDeviceWrappingIoDevice::isSequential() const +{ + return (byteDevice->size() == -1); +} + +bool QByteDeviceWrappingIoDevice::atEnd() const +{ + return byteDevice->atEnd(); +} + +bool QByteDeviceWrappingIoDevice::reset() +{ + return byteDevice->reset(); +} + +qint64 QByteDeviceWrappingIoDevice::size() const +{ + if (isSequential()) + return 0; + + return byteDevice->size(); +} + + +qint64 QByteDeviceWrappingIoDevice::readData( char * data, qint64 maxSize) +{ + qint64 len; + const char *readPointer = byteDevice->readPointer(maxSize, len); + if (len == -1) + return -1; + + memcpy(data, readPointer, len); + byteDevice->advanceReadPointer(len); + return len; +} + +qint64 QByteDeviceWrappingIoDevice::writeData( const char* data, qint64 maxSize) +{ + return -1; +} + +/*! + \class QNonContiguousByteDeviceFactory + \since 4.6 + + \inmodule QtCore + + Creates a QNonContiguousByteDevice out of a QIODevice, + QByteArray etc. + + \sa QNonContiguousByteDevice + + \internal +*/ + +/*! + \fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QIODevice *device); + + Create a QNonContiguousByteDevice out of a QIODevice. + For QFile, QBuffer and all other QIoDevice, sequential or not. + + \internal +*/ +QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QIODevice *device) +{ + // shortcut if it is a QBuffer + if (QBuffer* buffer = qobject_cast<QBuffer*>(device)) { + return new QNonContiguousByteDeviceBufferImpl(buffer); + } + + // ### FIXME special case if device is a QFile that supports map() + // then we can actually deal with the file without using read/peek + + // generic QIODevice + return new QNonContiguousByteDeviceIoDeviceImpl(device); // FIXME +}; + +/*! + \fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QRingBuffer *ringBuffer); + + Create a QNonContiguousByteDevice out of a QRingBuffer. + + \internal +*/ +QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QRingBuffer *ringBuffer) +{ + return new QNonContiguousByteDeviceRingBufferImpl(ringBuffer); +}; + +/*! + \fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QByteArray *byteArray); + + Create a QNonContiguousByteDevice out of a QByteArray. + + \internal +*/ +QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QByteArray *byteArray) +{ + return new QNonContiguousByteDeviceByteArrayImpl(byteArray); +}; + +/*! + \fn static QIODevice* QNonContiguousByteDeviceFactory::wrap(QNonContiguousByteDevice* byteDevice); + + Wrap the \a byteDevice (possibly again) into a QIODevice. + + \internal +*/ +QIODevice* QNonContiguousByteDeviceFactory::wrap(QNonContiguousByteDevice* byteDevice) +{ + // ### FIXME if it already has been based on QIoDevice, we could that one out again + // and save some calling + + // needed for FTP backend + + return new QByteDeviceWrappingIoDevice(byteDevice); +} + +QT_END_NAMESPACE + diff --git a/src/corelib/io/qnoncontiguousbytedevice_p.h b/src/corelib/io/qnoncontiguousbytedevice_p.h new file mode 100644 index 0000000..2a7e40b --- /dev/null +++ b/src/corelib/io/qnoncontiguousbytedevice_p.h @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNONCONTIGUOUSBYTEDEVICE_H +#define QNONCONTIGUOUSBYTEDEVICE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of a number of Qt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include <QObject> +#include <QtCore/qbytearray.h> +#include <QtCore/qbuffer.h> +#include <QtCore/qiodevice.h> +#include "private/qringbuffer_p.h" + +QT_BEGIN_NAMESPACE + +class Q_CORE_EXPORT QNonContiguousByteDevice : public QObject +{ + Q_OBJECT +public: + virtual const char* readPointer(qint64 maximumLength, qint64 &len) = 0; + virtual bool advanceReadPointer(qint64 amount) = 0; + virtual bool atEnd() = 0; + virtual bool reset() = 0; + void disableReset(); + virtual qint64 size() = 0; + +protected: + QNonContiguousByteDevice(); + virtual ~QNonContiguousByteDevice(); + + bool resetDisabled; +signals: + void readyRead(); + void readProgress(qint64 current, qint64 total); +}; + +class Q_CORE_EXPORT QNonContiguousByteDeviceFactory +{ +public: + static QNonContiguousByteDevice* create(QIODevice *device); + static QNonContiguousByteDevice* create(QByteArray *byteArray); + static QNonContiguousByteDevice* create(QRingBuffer *ringBuffer); + static QIODevice* wrap(QNonContiguousByteDevice* byteDevice); +}; + +// the actual implementations +// + +class QNonContiguousByteDeviceByteArrayImpl : public QNonContiguousByteDevice +{ + Q_OBJECT +public: + QNonContiguousByteDeviceByteArrayImpl(QByteArray *ba); + ~QNonContiguousByteDeviceByteArrayImpl(); + const char* readPointer(qint64 maximumLength, qint64 &len); + bool advanceReadPointer(qint64 amount); + bool atEnd(); + bool reset(); + qint64 size(); +protected: + QByteArray* byteArray; + qint64 currentPosition; +}; + +class QNonContiguousByteDeviceRingBufferImpl : public QNonContiguousByteDevice +{ + Q_OBJECT +public: + QNonContiguousByteDeviceRingBufferImpl(QRingBuffer *rb); + ~QNonContiguousByteDeviceRingBufferImpl(); + const char* readPointer(qint64 maximumLength, qint64 &len); + bool advanceReadPointer(qint64 amount); + bool atEnd(); + bool reset(); + qint64 size(); +protected: + QRingBuffer* ringBuffer; + qint64 currentPosition; +}; + + +class QNonContiguousByteDeviceIoDeviceImpl : public QNonContiguousByteDevice +{ + Q_OBJECT +public: + QNonContiguousByteDeviceIoDeviceImpl(QIODevice *d); + ~QNonContiguousByteDeviceIoDeviceImpl(); + const char* readPointer(qint64 maximumLength, qint64 &len); + bool advanceReadPointer(qint64 amount); + bool atEnd(); + bool reset(); + qint64 size(); +protected: + QIODevice* device; + QByteArray* currentReadBuffer; + qint64 currentReadBufferSize; + qint64 currentReadBufferAmount; + qint64 currentReadBufferPosition; + qint64 totalAdvancements; + bool eof; + qint64 initialPosition; +}; + +class QNonContiguousByteDeviceBufferImpl : public QNonContiguousByteDevice +{ + Q_OBJECT +public: + QNonContiguousByteDeviceBufferImpl(QBuffer *b); + ~QNonContiguousByteDeviceBufferImpl(); + const char* readPointer(qint64 maximumLength, qint64 &len); + bool advanceReadPointer(qint64 amount); + bool atEnd(); + bool reset(); + qint64 size(); +protected: + QBuffer* buffer; + QByteArray byteArray; + QNonContiguousByteDeviceByteArrayImpl* arrayImpl; +}; + +// ... and the reverse thing +class QByteDeviceWrappingIoDevice : public QIODevice +{ + Q_OBJECT +public: + QByteDeviceWrappingIoDevice (QNonContiguousByteDevice *bd); + ~QByteDeviceWrappingIoDevice (); + virtual bool isSequential () const; + virtual bool atEnd () const; + virtual bool reset (); + virtual qint64 size () const; +protected: + virtual qint64 readData ( char * data, qint64 maxSize ); + virtual qint64 writeData ( const char * data, qint64 maxSize ); + + QNonContiguousByteDevice *byteDevice; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index 21d98b5..2313e0e 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -379,6 +379,107 @@ void QHashData::checkSanity() #endif /*! + \fn uint qHash(const QPair<T1, T2> &key) + \since 4.3 + \relates QHash + + Returns the hash value for the \a key. + + Types \c T1 and \c T2 must be supported by qHash(). +*/ + +/*! \fn uint qHash(char key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(uchar key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(signed char key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(ushort key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(short key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(uint key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(int key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(ulong key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(long key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(quint64 key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(qint64 key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(QChar key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(const QByteArray &key) + \fn uint qHash(const QBitArray &key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(const QString &key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(const T *key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \class QHash \brief The QHash class is a template class that provides a hash-table-based dictionary. @@ -401,7 +502,8 @@ void QHashData::checkSanity() key. With QHash, the items are arbitrarily ordered. \i The key type of a QMap must provide operator<(). The key type of a QHash must provide operator==() and a global - \l{qHash()}{qHash}(Key) function. + hash function called qHash() (see the related non-member + functions). \endlist Here's an example QHash with QString keys and \c int values: @@ -732,7 +834,6 @@ void QHashData::checkSanity() */ /*! \fn const T QHash::value(const Key &key, const T &defaultValue) const - \overload If the hash contains no item with the given \a key, the function returns @@ -1490,121 +1591,6 @@ void QHashData::checkSanity() \sa operator+=(), operator-() */ -/*! \fn uint qHash(char key) - \relates QHash - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(uchar key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(signed char key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(ushort key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(short key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(uint key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(int key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(ulong key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(long key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(quint64 key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(qint64 key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(QChar key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(const QByteArray &key) - \fn uint qHash(const QBitArray &key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(const QString &key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(const T *key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! - \fn uint qHash(const QPair<T1, T2> &key) - \relates QHash - \since 4.3 - - Returns the hash value for the \a key. - - Types \c T1 and \c T2 must be supported by qHash(). -*/ - /*! \fn QDataStream &operator<<(QDataStream &out, const QHash<Key, T>& hash) \relates QHash diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h index eed4ba9..02cc497 100644 --- a/src/corelib/tools/qringbuffer_p.h +++ b/src/corelib/tools/qringbuffer_p.h @@ -74,6 +74,52 @@ public: return buffers.isEmpty() ? 0 : (buffers.first().constData() + head); } + // access the bytes at a specified position + // the out-variable length will contain the amount of bytes readable + // from there, e.g. the amount still the same QByteArray + inline const char *readPointerAtPosition(qint64 pos, qint64 &length) const { + if (buffers.isEmpty()) { + length = 0; + return 0; + } + + if (pos >= bufferSize) { + length = 0; + return 0; + } + + // special case: it is in the first buffer + int nextDataBlockSizeValue = nextDataBlockSize(); + if (pos - head < nextDataBlockSizeValue) { + length = nextDataBlockSizeValue - pos; + return buffers.at(0).constData() + head + pos; + } + + // special case: we only had one buffer and tried to read over it + if (buffers.length() == 1) { + length = 0; + return 0; + } + + // skip the first + pos -= nextDataBlockSizeValue; + + // normal case: it is somewhere in the second to the-one-before-the-tailBuffer + for (int i = 1; i < tailBuffer; i++) { + if (pos >= buffers[i].size()) { + pos -= buffers[i].size(); + continue; + } + + length = buffers[i].length() - pos; + return buffers[i].constData() + pos; + } + + // it is in the tail buffer + length = tail - pos; + return buffers[tailBuffer].constData() + pos; + } + inline void free(int bytes) { bufferSize -= bytes; if (bufferSize < 0) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 375d672..c3649e3 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -743,7 +743,9 @@ int QString::grow(int size) /*! \since 4.2 - Returns a copy of the \a string string encoded in ucs4. + Returns a copy of the \a string, where the encoding of \a string depends on + the size of wchar. If wchar is 4 bytes, the \a string is interpreted as ucs-4, + if wchar is 2 bytes it is interpreted as ucs-2. If \a size is -1 (default), the \a string has to be 0 terminated. diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 1d801cd..2d2113c 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -1717,6 +1717,7 @@ void QGraphicsView::setScene(QGraphicsScene *scene) disconnect(d->scene, SIGNAL(sceneRectChanged(QRectF)), this, SLOT(updateSceneRect(QRectF))); d->scene->d_func()->removeView(this); + d->connectedToScene = false; } // Assign the new scene and update the contents (scrollbars, etc.)). diff --git a/src/gui/graphicsview/qgridlayoutengine.cpp b/src/gui/graphicsview/qgridlayoutengine.cpp index dc5ca21..c150b0e 100644 --- a/src/gui/graphicsview/qgridlayoutengine.cpp +++ b/src/gui/graphicsview/qgridlayoutengine.cpp @@ -275,7 +275,7 @@ void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSiz if (hasIgnoreFlag) { factors[i] = (stretch < 0) ? 1.0 : 0.0; } else { - factors[i] = (stretch < 0) ? sizes[i] : 0.0; + factors[i] = (stretch < 0) ? sizes[i] : 0.0; } } else if (stretch == sumStretches) { factors[i] = 1.0; @@ -615,7 +615,7 @@ QRectF QGridLayoutItem::geometryWithin(qreal x, qreal y, qreal width, qreal heig QSizeF size = effectiveMaxSize().boundedTo(QSizeF(cellWidth, cellHeight)); width = size.width(); height = size.height(); - + Qt::Alignment align = q_engine->effectiveAlignment(this); switch (align & Qt::AlignHorizontal_Mask) { case Qt::AlignHCenter: @@ -717,7 +717,7 @@ void QGridLayoutItem::dump(int indent) const void QGridLayoutRowInfo::insertOrRemoveRows(int row, int delta) { count += delta; - + insertOrRemoveItems(stretches, row, delta); insertOrRemoveItems(spacings, row, delta); insertOrRemoveItems(alignments, row, delta); @@ -1076,7 +1076,7 @@ QSizeF QGridLayoutEngine::sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHi break; } return QSizeF(); -} +} QSizePolicy::ControlTypes QGridLayoutEngine::controlTypes(LayoutSide side) const { @@ -1150,16 +1150,16 @@ void QGridLayoutEngine::dump(int indent) const q_rowData.dump(indent + 2); qDebug("%*s Geometries output", indent, ""); + QVector<qreal> *cellPos = &q_yy; for (int pass = 0; pass < 2; ++pass) { - QVector<qreal> &cellPos = q_yy; QString message; - for (i = 0; i < cellPos.count(); ++i) { + for (i = 0; i < cellPos->count(); ++i) { message += QLatin1String((message.isEmpty() ? "[" : ", ")); - message += QString::number(cellPos.at(i)); + message += QString::number(cellPos->at(i)); } message += QLatin1String("]"); qDebug("%*s %s %s", indent, "", (pass == 0 ? "rows:" : "columns:"), qPrintable(message)); - cellPos = q_xx; + cellPos = &q_xx; } } #endif @@ -1538,5 +1538,5 @@ void QGridLayoutEngine::ensureGeometries(const QLayoutStyleInfo &styleInfo, } QT_END_NAMESPACE - + #endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index 0514567..b2b8c13 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -856,6 +856,9 @@ void QIcon::addPixmap(const QPixmap &pixmap, Mode mode, State state) QImageWriter::supportedImageFormats() functions to retrieve a complete list of the supported file formats. + Note: When you add a non-empty filename to a QIcon, the icon becomes + non-null, even if the file doesn't exist or points to a corrupt file. + \sa addPixmap() */ void QIcon::addFile(const QString &fileName, const QSize &size, Mode mode, State state) diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp index 20bed02..d4ebef7 100644 --- a/src/gui/image/qpixmap_win.cpp +++ b/src/gui/image/qpixmap_win.cpp @@ -319,6 +319,7 @@ static QImage qt_fromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h) } else { qWarning("qt_fromWinHBITMAP(), failed to get bitmap bits"); } + qFree(data); return image; } diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 4c1f7fc..90c38ca 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -2845,9 +2845,9 @@ void QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget d->persistent.insert(widget); d->addEditor(index, widget, true); widget->show(); + dataChanged(index, index); // update the geometry if (!d->delayedPendingLayout) widget->setGeometry(visualRect(index)); - dataChanged(index, index); // update the geometry } } diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index 3e00cd0..1071c1d 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -1608,6 +1608,10 @@ QRegion QListView::visualRegionForSelection(const QItemSelection &selection) con if (!selection.at(i).isValid()) continue; QModelIndex parent = selection.at(i).topLeft().parent(); + //we only display the children of the root in a listview + //we're not interested in the other model indexes + if (parent != d->root) + continue; int t = selection.at(i).topLeft().row(); int b = selection.at(i).bottomRight().row(); if (d->viewMode == IconMode || d->isWrapping()) { // in non-static mode, we have to go through all selected items @@ -1616,8 +1620,8 @@ QRegion QListView::visualRegionForSelection(const QItemSelection &selection) con } else { // in static mode, we can optimize a bit while (t <= b && d->isHidden(t)) ++t; while (b >= t && d->isHidden(b)) --b; - const QModelIndex top = d->model->index(t, c, d->root); - const QModelIndex bottom = d->model->index(b, c, d->root); + const QModelIndex top = d->model->index(t, c, parent); + const QModelIndex bottom = d->model->index(b, c, parent); QRect rect(visualRect(top).topLeft(), visualRect(bottom).bottomRight()); selectionRegion += QRegion(rect); diff --git a/src/gui/kernel/qdnd_x11.cpp b/src/gui/kernel/qdnd_x11.cpp index ed93b34..9b2305d 100644 --- a/src/gui/kernel/qdnd_x11.cpp +++ b/src/gui/kernel/qdnd_x11.cpp @@ -543,7 +543,7 @@ bool QX11Data::xdndMimeDataForAtom(Atom a, QMimeData *mimeData, QByteArray *data (dm->xdndMimeTransferedPixmapIndex + 1) % 2; } } else { - DEBUG("QClipboard: xdndMimeDataForAtom(): converting to type '%s' is not supported", atomName); + DEBUG("QClipboard: xdndMimeDataForAtom(): converting to type '%s' is not supported", qPrintable(atomName)); } } return data; @@ -624,7 +624,6 @@ QVariant QX11Data::xdndMimeConvertToFormat(Atom a, const QByteArray &data, const if (format == QLatin1String("image/ppm")) { if (a == XA_PIXMAP && data.size() == sizeof(Pixmap)) { Pixmap xpm = *((Pixmap*)data.data()); - Display *dpy = display; if (!xpm) return QByteArray(); QPixmap qpm = QPixmap::fromX11Pixmap(xpm); diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 35fe6a3..d616e5e 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -677,12 +677,13 @@ QWheelEvent::QWheelEvent(const QPoint &pos, const QPoint& globalPos, int delta, The \a type parameter must be QEvent::KeyPress, QEvent::KeyRelease, or QEvent::ShortcutOverride. - If \a key is 0, the event is not a result of - a known key; for example, it may be the result of a compose - sequence or keyboard macro. The \a modifiers holds the keyboard - modifiers, and the given \a text is the Unicode text that the - key generated. If \a autorep is true, isAutoRepeat() will be - true. \a count is the number of keys involved in the event. + Int \a key is the code for the Qt::Key that the event loop should listen + for. If \a key is 0, the event is not a result of a known key; for + example, it may be the result of a compose sequence or keyboard macro. + The \a modifiers holds the keyboard modifiers, and the given \a text + is the Unicode text that the key generated. If \a autorep is true, + isAutoRepeat() will be true. \a count is the number of keys involved + in the event. */ QKeyEvent::QKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers, const QString& text, bool autorep, ushort count) diff --git a/src/gui/kernel/qlayoutitem.cpp b/src/gui/kernel/qlayoutitem.cpp index 0fd73b8..c70ab2d 100644 --- a/src/gui/kernel/qlayoutitem.cpp +++ b/src/gui/kernel/qlayoutitem.cpp @@ -54,7 +54,8 @@ QT_BEGIN_NAMESPACE inline static QRect fromLayoutItemRect(QWidgetPrivate *priv, const QRect &rect) { - return priv->fromOrToLayoutItemRect(rect, -1); + return rect.adjusted(priv->leftLayoutItemMargin, priv->topLayoutItemMargin, + -priv->rightLayoutItemMargin, -priv->bottomLayoutItemMargin); } inline static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size) @@ -64,7 +65,8 @@ inline static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size) inline static QRect toLayoutItemRect(QWidgetPrivate *priv, const QRect &rect) { - return priv->fromOrToLayoutItemRect(rect, +1); + return rect.adjusted(-priv->leftLayoutItemMargin, -priv->topLayoutItemMargin, + priv->rightLayoutItemMargin, priv->bottomLayoutItemMargin); } inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size) diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp index b6703e2..f998bb2 100644 --- a/src/gui/kernel/qshortcutmap.cpp +++ b/src/gui/kernel/qshortcutmap.cpp @@ -751,6 +751,7 @@ bool QShortcutMap::correctGraphicsWidgetContext(Qt::ShortcutContext context, QGr tw = tw->parentWidget(); return tw == w; } + return false; } // Below is Qt::WindowShortcut context diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 7d06d3f..3a146e5 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -170,39 +170,48 @@ static inline bool bypassGraphicsProxyWidget(QWidget *p) extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp -QWidgetPrivate::QWidgetPrivate(int version) : - QObjectPrivate(version), extra(0), focus_child(0) - ,layout(0), widgetItem(0) - ,leftmargin(0), topmargin(0), rightmargin(0), bottommargin(0) - ,leftLayoutItemMargin(0), topLayoutItemMargin(0), rightLayoutItemMargin(0) - ,bottomLayoutItemMargin(0) - ,fg_role(QPalette::NoRole) - ,bg_role(QPalette::NoRole) - ,hd(0) - ,dirty(0) - ,needsFlush(0) - ,dirtyOpaqueChildren(1) - ,isOpaque(0) - ,inDirtyList(0) - ,isScrolled(0) - ,isMoved(0) - ,usesDoubleBufferedGLContext(0) -#ifdef Q_WS_WIN - ,noPaintOnScreen(0) -#endif - ,inheritedFontResolveMask(0) - ,inheritedPaletteResolveMask(0) +QWidgetPrivate::QWidgetPrivate(int version) + : QObjectPrivate(version) + , extra(0) + , focus_next(0) + , focus_prev(0) + , focus_child(0) + , layout(0) + , needsFlush(0) + , redirectDev(0) + , widgetItem(0) + , extraPaintEngine(0) + , polished(0) + , inheritedFontResolveMask(0) + , inheritedPaletteResolveMask(0) + , leftmargin(0) + , topmargin(0) + , rightmargin(0) + , bottommargin(0) + , leftLayoutItemMargin(0) + , topLayoutItemMargin(0) + , rightLayoutItemMargin(0) + , bottomLayoutItemMargin(0) + , hd(0) + , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred) + , fg_role(QPalette::NoRole) + , bg_role(QPalette::NoRole) + , dirtyOpaqueChildren(1) + , isOpaque(0) + , inDirtyList(0) + , isScrolled(0) + , isMoved(0) + , usesDoubleBufferedGLContext(0) #if defined(Q_WS_X11) - ,picture(0) + , picture(0) +#elif defined(Q_WS_WIN) + , noPaintOnScreen(0) +#elif defined(Q_WS_MAC) + , needWindowChange(0) + , isGLWidget(0) + , window_event(0) + , qd_hd(0) #endif -#ifdef Q_WS_MAC - ,needWindowChange(0) - ,isGLWidget(0) -#endif - ,polished(0) - - , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred) - , redirectDev(0) { if (!qApp) { qFatal("QWidget: Must construct a QApplication before a QPaintDevice"); @@ -1348,7 +1357,7 @@ QWidget::~QWidget() d->setDirtyOpaqueRegion(); if (isWindow() && isVisible() && internalWinId()) - hide(); + d->close_helper(QWidgetPrivate::CloseNoEvent); #if defined(Q_WS_WIN) || defined(Q_WS_X11) else if (!internalWinId() && isVisible()) qApp->d_func()->sendSyntheticEnterLeave(this); @@ -1415,36 +1424,26 @@ void QWidgetPrivate::createTLExtra() createExtra(); if (!extra->topextra) { QTLWExtra* x = extra->topextra = new QTLWExtra; + x->icon = 0; + x->iconPixmap = 0; + x->backingStore = 0; x->windowSurface = 0; + x->sharedPainter = 0; + x->incw = x->inch = 0; + x->basew = x->baseh = 0; + x->frameStrut.setCoords(0, 0, 0, 0); + x->normalGeometry = QRect(0,0,-1,-1); + x->savedFlags = 0; x->opacity = 255; x->posFromMove = false; x->sizeAdjusted = false; x->inTopLevelResize = false; x->inRepaint = false; - x->backingStore = 0; - x->icon = 0; - x->iconPixmap = 0; - x->frameStrut.setCoords(0, 0, 0, 0); - x->incw = x->inch = 0; - x->basew = x->baseh = 0; - x->normalGeometry = QRect(0,0,-1,-1); -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_MAC) x->embedded = 0; -#endif -#if defined(Q_WS_X11) - x->parentWinId = 0; - x->spont_unmapped = 0; - x->dnd = 0; -#endif - x->savedFlags = 0; -#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER) - x->qwsManager = 0; -#endif - x->sharedPainter = 0; createTLSysExtra(); #ifdef QWIDGET_EXTRA_DEBUG - static int count = 0; - qDebug() << "tlextra" << ++count; + static int count = 0; + qDebug() << "tlextra" << ++count; #endif } } @@ -1458,27 +1457,28 @@ void QWidgetPrivate::createExtra() { if (!extra) { // if not exists extra = new QWExtra; - extra->minw = extra->minh = 0; - extra->maxw = extra->maxh = QWIDGETSIZE_MAX; + extra->glContext = 0; + extra->topextra = 0; + extra->proxyWidget = 0; +#ifndef QT_NO_CURSOR + extra->curs = 0; +#endif + extra->minw = 0; + extra->minh = 0; + extra->maxw = QWIDGETSIZE_MAX; + extra->maxh = QWIDGETSIZE_MAX; + extra->customDpiX = 0; + extra->customDpiY = 0; extra->explicitMinSize = 0; extra->explicitMaxSize = 0; extra->autoFillBackground = 0; extra->nativeChildrenForced = 0; extra->inRenderWithPainter = 0; extra->hasMask = 0; -#ifndef QT_NO_CURSOR - extra->curs = 0; -#endif - extra->style = 0; - extra->topextra = 0; - extra->proxyWidget = 0; - extra->glContext = 0; - extra->customDpiX = 0; - extra->customDpiY = 0; createSysExtra(); #ifdef QWIDGET_EXTRA_DEBUG - static int count = 0; - qDebug() << "extra" << ++count; + static int count = 0; + qDebug() << "extra" << ++count; #endif } } @@ -1519,45 +1519,6 @@ void QWidgetPrivate::deleteExtra() } /* - Returns true if the background is inherited; otherwise returns - false. - - Mainly used in the paintOnScreen case. -*/ - -bool QWidgetPrivate::isBackgroundInherited() const -{ - Q_Q(const QWidget); - - // windows do not inherit their background - if (q->isWindow() || q->windowType() == Qt::SubWindow) - return false; - - if (q->testAttribute(Qt::WA_NoSystemBackground) || q->testAttribute(Qt::WA_OpaquePaintEvent)) - return false; - - const QPalette &pal = q->palette(); - QPalette::ColorRole bg = q->backgroundRole(); - QBrush brush = pal.brush(bg); - - // non opaque brushes leaves us no choice, we must inherit - if (!q->autoFillBackground() || !brush.isOpaque()) - return true; - - if (brush.style() == Qt::SolidPattern) { - // the background is just a solid color. If there is no - // propagated contents, then we claim as performance - // optimization that it was not inheritet. This is the normal - // case in standard Windows or Motif style. - const QWidget *w = q->parentWidget(); - if (!w->d_func()->isBackgroundInherited()) - return false; - } - - return true; -} - -/* Returns true if there are widgets above this which overlap with \a rect, which is in parent's coordinate system (same as crect). */ @@ -1903,24 +1864,6 @@ void QWidgetPrivate::clipToEffectiveMask(QRegion ®ion) const } } -bool QWidgetPrivate::hasBackground() const -{ - Q_Q(const QWidget); - if (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_PaintOnScreen)) - return true; - if (q->testAttribute(Qt::WA_PaintOnScreen)) - return true; - if (!q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) { - const QPalette &pal = q->palette(); - QPalette::ColorRole bg = q->backgroundRole(); - QBrush bgBrush = pal.brush(bg); - return (bgBrush.style() != Qt::NoBrush && - ((q->isWindow() || q->windowType() == Qt::SubWindow) - || (QPalette::ColorRole(bg_role) != QPalette::NoRole || (pal.resolve() & (1<<bg))))); - } - return false; -} - bool QWidgetPrivate::paintOnScreen() const { #if defined(Q_WS_QWS) @@ -6160,14 +6103,6 @@ int QWidgetPrivate::pointToRect(const QPoint &p, const QRect &r) return dx + dy; } -QRect QWidgetPrivate::fromOrToLayoutItemRect(const QRect &rect, int sign) const -{ - QRect r = rect; - r.adjust(-sign * leftLayoutItemMargin, -sign * topLayoutItemMargin, - +sign * rightLayoutItemMargin, +sign * bottomLayoutItemMargin); - return r; -} - /*! \property QWidget::frameSize \brief the size of the widget including any window frame diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 1896b97..6524bc9 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -728,6 +728,7 @@ static OSWindowRef qt_mac_create_window(QWidget *, WindowClass wclass, WindowAtt static EventTypeSpec window_events[] = { { kEventClassWindow, kEventWindowClose }, { kEventClassWindow, kEventWindowExpanded }, + { kEventClassWindow, kEventWindowHidden }, { kEventClassWindow, kEventWindowZoomed }, { kEventClassWindow, kEventWindowCollapsed }, { kEventClassWindow, kEventWindowToolbarSwitchMode }, @@ -997,6 +998,19 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, } } } + } else if (ekind == kEventWindowHidden) { + // Make sure that we also hide any visible sheets on our window. + // Cocoa does the right thing for us. + const QObjectList children = widget->children(); + const int childCount = children.count(); + for (int i = 0; i < childCount; ++i) { + QObject *obj = children.at(i); + if (obj->isWidgetType()) { + QWidget *widget = static_cast<QWidget *>(obj); + if (qt_mac_is_macsheet(widget) && widget->isVisible()) + widget->hide(); + } + } } else { handled_event = false; } @@ -1599,24 +1613,6 @@ bool QWidgetPrivate::qt_create_root_win() return true; } -bool QWidgetPrivate::qt_recreate_root_win() -{ - if(!qt_root_win) //sanity check - return false; - //store old - OSWindowRef old_root_win = qt_root_win; - //recreate - qt_root_win = 0; - qt_create_root_win(); - //cleanup old window -#ifdef QT_MAC_USE_COCOA - [old_root_win release]; -#else - CFRelease(old_root_win); -#endif - return true; -} - bool QWidgetPrivate::qt_widget_rgn(QWidget *widget, short wcode, RgnHandle rgn, bool force = false) { bool ret = false; @@ -4438,11 +4434,13 @@ void QWidgetPrivate::deleteSysExtra() void QWidgetPrivate::createTLSysExtra() { + extra->topextra->resizer = 0; + extra->topextra->isSetGeometry = 0; + extra->topextra->isMove = 0; + extra->topextra->wattr = 0; extra->topextra->wclass = 0; extra->topextra->group = 0; extra->topextra->windowIcon = 0; - extra->topextra->resizer = 0; - extra->topextra->isSetGeometry = 0; extra->topextra->savedWindowAttributesFromMaximized = 0; } diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index d1f3acb..a603b44 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -101,88 +101,92 @@ class QWidgetItemV2; class QStyle; struct QTLWExtra { + // *************************** Cross-platform variables ***************************** + + // Regular pointers (keep them together to avoid gaps on 64 bits architectures). + QIcon *icon; // widget icon + QPixmap *iconPixmap; + QWidgetBackingStore *backingStore; + QWindowSurface *windowSurface; + QPainter *sharedPainter; + + // Implicit pointers (shared_null). QString caption; // widget caption QString iconText; // widget icon text QString role; // widget role QString filePath; // widget file path - QIcon *icon; // widget icon - QPixmap *iconPixmap; + + // Other variables. short incw, inch; // size increments + short basew, baseh; // base sizes // frame strut, don't use these directly, use QWidgetPrivate::frameStrut() instead. QRect frameStrut; + QRect normalGeometry; // used by showMin/maximized/FullScreen + Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen + + // *************************** Cross-platform bit fields **************************** uint opacity : 8; uint posFromMove : 1; uint sizeAdjusted : 1; uint inTopLevelResize : 1; uint inRepaint : 1; - QWidgetBackingStore *backingStore; -#if defined(Q_WS_WIN) - ulong savedFlags; // Save window flags while showing fullscreen - uint embedded : 1; // window is embedded in another application -#else - Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen -#endif - short basew, baseh; // base sizes -#if defined(Q_WS_X11) - WId parentWinId; // parent window Id (valid after reparenting) - uint embedded : 1; // window is embedded in another Qt application + uint embedded : 1; + + // *************************** Platform specific values (bit fields first) ********** +#if defined(Q_WS_X11) // <----------------------------------------------------------- X11 uint spont_unmapped: 1; // window was spontaneously unmapped uint dnd : 1; // DND properties installed uint validWMState : 1; // is WM_STATE valid? uint waitingForMapNotify : 1; // show() has been called, haven't got the MapNotify yet + WId parentWinId; // parent window Id (valid after reparenting) WId userTimeWindow; // window id that contains user-time timestamp when WM supports a _NET_WM_USER_TIME_WINDOW atom QPoint fullScreenOffset; -#endif -#if defined(Q_WS_MAC) +#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN + HICON winIconBig; // internal big Windows icon + HICON winIconSmall; // internal small Windows icon +#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC + uint resizer : 4; + uint isSetGeometry : 1; + uint isMove : 1; quint32 wattr; quint32 wclass; WindowGroupRef group; IconRef windowIcon; // the current window icon, if set with setWindowIcon_sys. quint32 savedWindowAttributesFromMaximized; // Saved attributes from when the calling updateMaximizeButton_sys() - uint resizer : 4; - uint isSetGeometry : 1; - uint isMove : 1; - uint embedded : 1; -#endif -#if defined(Q_WS_QWS) && !defined (QT_NO_QWS_MANAGER) +#elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS +#ifndef QT_NO_QWS_MANAGER QWSManager *qwsManager; #endif -#if defined(Q_WS_WIN) - HICON winIconBig; // internal big Windows icon - HICON winIconSmall; // internal small Windows icon #endif - QRect normalGeometry; // used by showMin/maximized/FullScreen - QWindowSurface *windowSurface; - QPainter *sharedPainter; }; struct QWExtra { - qint32 minw, minh; // minimum size - qint32 maxw, maxh; // maximum size - QPointer<QWidget> focus_proxy; -#ifndef QT_NO_CURSOR - QCursor *curs; -#endif + // *************************** Cross-platform variables ***************************** + + // Regular pointers (keep them together to avoid gaps on 64 bits architectures). + void *glContext; // if the widget is hijacked by QGLWindowSurface QTLWExtra *topextra; // only useful for TLWs QGraphicsProxyWidget *proxyWidget; // if the widget is embedded - void *glContext; // if the widget is hijacked by QGLWindowSurface -#if defined(Q_WS_WIN) && !defined(QT_NO_DRAGANDDROP) - QOleDropTarget *dropTarget; // drop target - QList<QPointer<QWidget> > oleDropWidgets; -#endif -#if defined(Q_WS_X11) - WId xDndProxy; // XDND forwarding to embedded windows +#ifndef QT_NO_CURSOR + QCursor *curs; #endif + QPointer<QStyle> style; + QPointer<QWidget> focus_proxy; + + // Implicit pointers (shared_empty/shared_null). QRegion mask; // widget mask + QString styleSheet; + + // Other variables. + qint32 minw; + qint32 minh; // minimum size + qint32 maxw; + qint32 maxh; // maximum size + quint16 customDpiX; + quint16 customDpiY; QSize staticContentsSize; -//bit flags at the end to improve packing -#if defined(Q_WS_WIN) - uint shown_mode : 8; // widget show mode -#endif -#if defined(Q_WS_X11) - uint compress_events : 1; -#endif + // *************************** Cross-platform bit fields **************************** uint explicitMinSize : 2; uint explicitMaxSize : 2; uint autoFillBackground : 1; @@ -190,16 +194,22 @@ struct QWExtra { uint inRenderWithPainter : 1; uint hasMask : 1; - QPointer<QStyle> style; - QString styleSheet; - - quint16 customDpiX; - quint16 customDpiY; -#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA) + // *************************** Platform specific values (bit fields first) ********** +#if defined(Q_WS_WIN) // <----------------------------------------------------------- WIN +#ifndef QT_NO_DRAGANDDROP + QOleDropTarget *dropTarget; // drop target + QList<QPointer<QWidget> > oleDropWidgets; +#endif +#elif defined(Q_WS_X11) // <--------------------------------------------------------- X11 + uint compress_events : 1; + WId xDndProxy; // XDND forwarding to embedded windows +#elif defined(Q_WS_MAC) // <------------------------------------------------------ MAC +#ifdef QT_MAC_USE_COCOA // Cocoa Mask stuff QImage maskBits; CGImageRef imageMask; #endif +#endif }; class Q_GUI_EXPORT QWidgetPrivate : public QObjectPrivate @@ -207,6 +217,24 @@ class Q_GUI_EXPORT QWidgetPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QWidget) public: + // *************************** Cross-platform *************************************** + enum DrawWidgetFlags { + DrawAsRoot = 0x01, + DrawPaintOnScreen = 0x02, + DrawRecursive = 0x04, + DrawInvisible = 0x08, + DontSubtractOpaqueChildren = 0x10, + DontSetCompositionMode = 0x20, + DontDrawOpaqueChildren = 0x40 + }; + + enum CloseMode { + CloseNoEvent, + CloseWithEvent, + CloseWithSpontaneousEvent + }; + + // Functions. explicit QWidgetPrivate(int version = QObjectPrivateVersion); ~QWidgetPrivate(); @@ -216,10 +244,6 @@ public: QPainter *sharedPainter() const; void setSharedPainter(QPainter *painter); QWidgetBackingStore *maybeBackingStore() const; -#ifdef Q_WS_QWS - void setMaxWindowState_helper(); - void setFullScreenSize_helper(); -#endif void init(QWidget *desktopWidget, Qt::WindowFlags f); void create_sys(WId window, bool initializeWindow, bool destroyOldWindow); void createRecursively(); @@ -240,24 +264,6 @@ public: QPalette naturalWidgetPalette(uint inheritedMask) const; void setMask_sys(const QRegion &); -#ifdef Q_WS_WIN - bool shouldShowMaximizeButton(); - void winUpdateIsOpaque(); -#endif - -#ifdef Q_WS_MAC - void macUpdateSizeAttribute(); - void macUpdateHideOnSuspend(); - void macUpdateOpaqueSizeGrip(); - void macUpdateIgnoreMouseEvents(); - void macUpdateMetalAttribute(); - void macUpdateIsOpaque(); - void setEnabled_helper_sys(bool enable); - bool isRealWindow() const; - void adjustWithinMaxAndMinSize(int &w, int &h); - void applyMaxAndMinSizeOnWindow(); -#endif - void raise_sys(); void lower_sys(); void stackUnder_sys(QWidget *); @@ -282,20 +288,9 @@ public: void setStyle_helper(QStyle *newStyle, bool propagate, bool metalHack = false); void inheritStyle(); - bool isBackgroundInherited() const; - void setUpdatesEnabled_helper(bool ); void paintBackground(QPainter *, const QRegion &, const QPoint & = QPoint(), int flags = DrawAsRoot) const; - enum DrawWidgetFlags { - DrawAsRoot = 0x01, - DrawPaintOnScreen = 0x02, - DrawRecursive = 0x04, - DrawInvisible = 0x08, - DontSubtractOpaqueChildren = 0x10, - DontSetCompositionMode = 0x20, - DontDrawOpaqueChildren = 0x40 - }; bool isAboutToShow() const; QRegion prepareToRender(const QRegion ®ion, QWidget::RenderFlags renderFlags); void render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &sourceRegion, @@ -318,10 +313,6 @@ public: QWindowSurface *createDefaultWindowSurface(); QWindowSurface *createDefaultWindowSurface_sys(); void repaint_sys(const QRegion &rgn); -#ifdef Q_WS_MAC - void update_sys(const QRect &rect); - void update_sys(const QRegion &rgn); -#endif QRect clipRect() const; QRegion clipRegion() const; @@ -332,42 +323,20 @@ public: void updateIsOpaque(); void setOpaque(bool opaque); void updateIsTranslucent(); - bool hasBackground() const; bool paintOnScreen() const; QRegion getOpaqueRegion() const; const QRegion &getOpaqueChildren() const; void setDirtyOpaqueRegion(); - QRegion opaqueChildren; - - enum CloseMode { - CloseNoEvent, - CloseWithEvent, - CloseWithSpontaneousEvent - }; bool close_helper(CloseMode mode); - bool compositeEvent(QEvent *e); void setWindowIcon_helper(); void setWindowIcon_sys(bool forceReset = false); void setWindowOpacity_sys(qreal opacity); - void adjustQuitOnCloseAttribute(); -#if defined(Q_WS_X11) - void setWindowRole(); - void sendStartupMessage(const char *message) const; - void setNetWmWindowTypes(); - void x11UpdateIsOpaque(); -#endif - -#if defined (Q_WS_WIN) - void reparentChildren(); -#endif - void scrollChildren(int dx, int dy); - void moveRect(const QRect &, int dx, int dy); void scrollRect(const QRect &, int dx, int dy); void invalidateBuffer_resizeHelper(const QPoint &oldPos, const QSize &oldSize); @@ -381,7 +350,6 @@ public: void reparentFocusWidgets(QWidget *oldtlw); static int pointToRect(const QPoint &p, const QRect &r); - QRect fromOrToLayoutItemRect(const QRect &rect, int sign) const; void setWinId(WId); void showChildren(bool spontaneous); @@ -391,9 +359,6 @@ public: void scroll_sys(int dx, int dy, const QRect &r); void deactivateWidgetCleanup(); void setGeometry_sys(int, int, int, int, bool); -#ifdef Q_WS_MAC - void setGeometry_sys_helper(int, int, int, int, bool); -#endif void sendPendingMoveAndResizeEvents(bool recursive = false, bool disableUpdates = false); void activateChildLayoutsRecursively(); void show_recursive(); @@ -405,10 +370,6 @@ public: void setEnabled_helper(bool); void registerDropSite(bool); -#if defined(Q_WS_WIN) && !defined(QT_NO_DRAGANDDROP) - QOleDropTarget *registerOleDnd(QWidget *widget); - void unregisterOleDnd(QWidget *widget, QOleDropTarget *target); -#endif static void adjustFlags(Qt::WindowFlags &flags, QWidget *w = 0); void updateFrameStrut(); @@ -418,32 +379,11 @@ public: void setWindowIconText_helper(const QString &cap); void setWindowTitle_sys(const QString &cap); -#ifdef Q_OS_WIN - void grabMouseWhileInWindow(); -#endif - #ifndef QT_NO_CURSOR void setCursor_sys(const QCursor &cursor); void unsetCursor_sys(); #endif -#ifdef Q_WS_MAC - void setWindowModified_sys(bool b); - void updateMaximizeButton_sys(); - void setWindowFilePath_sys(const QString &filePath); - void createWindow_sys(); - void recreateMacWindow(); -#ifndef QT_MAC_USE_COCOA - void initWindowPtr(); - void finishCreateWindow_sys_Carbon(OSWindowRef windowRef); -#else - void finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ windowRef); - void syncCocoaMask(); - void finishCocoaMaskSetup(); -#endif - void determineWindowClass(); - void transferChildren(); -#endif void setWindowTitle_helper(const QString &cap); void setWindowFilePath_helper(const QString &filePath); @@ -459,59 +399,89 @@ public: QInputContext *inputContext() const; -#if defined(Q_WS_QWS) - void moveSurface(QWindowSurface *surface, const QPoint &offset); + void setModal_sys(); - QRegion localRequestedRegion() const; - QRegion localAllocatedRegion() const; + inline void setRedirected(QPaintDevice *replacement, const QPoint &offset) + { + Q_ASSERT(q_func()->testAttribute(Qt::WA_WState_InPaintEvent)); + redirectDev = replacement; + redirectOffset = offset; + } - void blitToScreen(const QRegion &globalrgn); -#ifndef QT_NO_CURSOR - void updateCursor() const; -#endif + inline QPaintDevice *redirected(QPoint *offset) const + { + if (offset) + *offset = redirectDev ? redirectOffset : QPoint(); + return redirectDev; + } - QScreen* getScreen() const; + inline void restoreRedirected() + { redirectDev = 0; } - friend class QWSManager; - friend class QWSManagerPrivate; - friend class QDecoration; -#endif + inline void enforceNativeChildren() + { + if (!extra) + createExtra(); - static int instanceCounter; // Current number of widget instances - static int maxInstances; // Maximum number of widget instances + if (extra->nativeChildrenForced) + return; + extra->nativeChildrenForced = 1; -#ifdef QT_KEYPAD_NAVIGATION - static QPointer<QWidget> editingWidget; -#endif + for (int i = 0; i < children.size(); ++i) { + if (QWidget *child = qobject_cast<QWidget *>(children.at(i))) + child->setAttribute(Qt::WA_NativeWindow); + } + } - QWidgetData data; + inline bool nativeChildrenForced() const + { + return extra ? extra->nativeChildrenForced : false; + } + + QSize adjustedSize() const; + +#ifndef Q_WS_QWS // Almost cross-platform :-) + void setWSGeometry(bool dontShow=false, const QRect &oldRect = QRect()); + + inline QPoint mapToWS(const QPoint &p) const + { return p - data.wrect.topLeft(); } + + inline QPoint mapFromWS(const QPoint &p) const + { return p + data.wrect.topLeft(); } + + inline QRect mapToWS(const QRect &r) const + { QRect rr(r); rr.translate(-data.wrect.topLeft()); return rr; } + inline QRect mapFromWS(const QRect &r) const + { QRect rr(r); rr.translate(data.wrect.topLeft()); return rr; } +#endif + + // Variables. + // Regular pointers (keep them together to avoid gaps on 64 bit architectures). QWExtra *extra; QWidget *focus_next; QWidget *focus_prev; QWidget *focus_child; -#ifndef QT_NO_ACTION - QList<QAction*> actions; -#endif QLayout *layout; + QRegion *needsFlush; + QPaintDevice *redirectDev; QWidgetItemV2 *widgetItem; -#if !defined(QT_NO_IM) - QPointer<QInputContext> ic; -#endif + QPaintEngine *extraPaintEngine; + mutable const QMetaObject *polished; // All widgets are initially added into the uncreatedWidgets set. Once // they receive a window id they are removed and added to the mapper static QWidgetMapper *mapper; static QWidgetSet *uncreatedWidgets; +#if !defined(QT_NO_IM) + QPointer<QInputContext> ic; +#endif +#ifdef QT_KEYPAD_NAVIGATION + static QPointer<QWidget> editingWidget; +#endif - short leftmargin, topmargin, rightmargin, bottommargin; - - signed char leftLayoutItemMargin; - signed char topLayoutItemMargin; - signed char rightLayoutItemMargin; - signed char bottomLayoutItemMargin; - - // ### TODO: reorganize private/extra/topextra to save memory - QPointer<QWidget> compositeChildGrab; + // Implicit pointers (shared_null/shared_empty). + QRegion opaqueChildren; + QRegion dirty; #ifndef QT_NO_TOOLTIP QString toolTip; #endif @@ -521,14 +491,41 @@ public: #ifndef QT_NO_WHATSTHIS QString whatsThis; #endif - QString accessibleName, accessibleDescription; +#ifndef QT_NO_ACCESSIBILITY + QString accessibleName; + QString accessibleDescription; +#endif + + // Other variables. + uint inheritedFontResolveMask; + uint inheritedPaletteResolveMask; + short leftmargin; + short topmargin; + short rightmargin; + short bottommargin; + signed char leftLayoutItemMargin; + signed char topLayoutItemMargin; + signed char rightLayoutItemMargin; + signed char bottomLayoutItemMargin; + static int instanceCounter; // Current number of widget instances + static int maxInstances; // Maximum number of widget instances + Qt::HANDLE hd; + QWidgetData data; + QSizePolicy size_policy; + QLocale locale; + QPoint redirectOffset; +#ifndef QT_NO_ACTION + QList<QAction*> actions; +#endif + + QSet<int> gestures; + int grabGesture(int gestureId); + bool releaseGesture(int gestureId); + // Bit fields. + uint high_attributes[3]; // the low ones are in QWidget::widget_attributes QPalette::ColorRole fg_role : 8; QPalette::ColorRole bg_role : 8; - uint high_attributes[3]; // the low ones are in QWidget::widget_attributes - Qt::HANDLE hd; - QRegion dirty; - QRegion *needsFlush; uint dirtyOpaqueChildren : 1; uint isOpaque : 1; uint inDirtyList : 1; @@ -536,35 +533,33 @@ public: uint isMoved : 1; uint usesDoubleBufferedGLContext : 1; -#ifdef Q_WS_WIN - uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine() -#endif - - uint inheritedFontResolveMask; - uint inheritedPaletteResolveMask; -#if defined(Q_WS_X11) + // *************************** Platform specific ************************************ +#if defined(Q_WS_X11) // <----------------------------------------------------------- X11 QX11Info xinfo; Qt::HANDLE picture; + static QWidget *mouseGrabber; + static QWidget *keyboardGrabber; + + void setWindowRole(); + void sendStartupMessage(const char *message) const; + void setNetWmWindowTypes(); + void x11UpdateIsOpaque(); + bool isBackgroundInherited() const; +#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN + uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine() + + bool shouldShowMaximizeButton(); + void winUpdateIsOpaque(); + void reparentChildren(); +#ifndef QT_NO_DRAGANDDROP + QOleDropTarget *registerOleDnd(QWidget *widget); + void unregisterOleDnd(QWidget *widget, QOleDropTarget *target); #endif -#if defined(Q_WS_MAC) - enum PaintChildrenOPs { - PC_None = 0x00, - PC_Now = 0x01, - PC_NoPaint = 0x04, - PC_Later = 0x10 - }; - EventHandlerRef window_event; - bool qt_mac_dnd_event(uint, DragRef); - void toggleDrawers(bool); - //mac event functions - static bool qt_create_root_win(); - static void qt_clean_root_win(); - static bool qt_recreate_root_win(); - static bool qt_mac_update_sizer(QWidget *, int up = 0); - static OSStatus qt_window_event(EventHandlerCallRef er, EventRef event, void *); - static OSStatus qt_widget_event(EventHandlerCallRef er, EventRef event, void *); - static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool); - static bool qt_widget_shape(QWidget *, short, HIMutableShapeRef, bool); + void grabMouseWhileInWindow(); +#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC + // This is new stuff + uint needWindowChange : 1; + uint isGLWidget : 1; // Each wiget keeps a list of all its child and grandchild OpenGL widgets. // This list is used to update the gl context whenever a parent and a granparent @@ -577,99 +572,70 @@ public: QWidget * widget; QWidget * lastUpdateWidget; }; - QList<GlWidgetInfo> glWidgets; // dirtyOnWidget contains the areas in the widget that needs to be repained, // in the same way as dirtyOnScreen does for the window. Areas are added in // dirtyWidget_sys and cleared in the paint event. In scroll_sys we then use // this information repaint invalid areas when widgets are scrolled. QRegion dirtyOnWidget; + EventHandlerRef window_event; + QList<GlWidgetInfo> glWidgets; //these are here just for code compat (HIViews) Qt::HANDLE qd_hd; - // This is new stuff - uint needWindowChange : 1; - uint isGLWidget : 1; -#endif - - QSet<int> gestures; - int grabGesture(int gestureId); - bool releaseGesture(int gestureId); - -#if defined(Q_WS_X11) || defined (Q_WS_WIN) || defined(Q_WS_MAC) -#ifdef Q_WS_MAC - void setWSGeometry(bool dontShow=false, const QRect &oldRect = QRect()); + void macUpdateSizeAttribute(); + void macUpdateHideOnSuspend(); + void macUpdateOpaqueSizeGrip(); + void macUpdateIgnoreMouseEvents(); + void macUpdateMetalAttribute(); + void macUpdateIsOpaque(); + void setEnabled_helper_sys(bool enable); + bool isRealWindow() const; + void adjustWithinMaxAndMinSize(int &w, int &h); + void applyMaxAndMinSizeOnWindow(); + void update_sys(const QRect &rect); + void update_sys(const QRegion &rgn); + void setGeometry_sys_helper(int, int, int, int, bool); + void setWindowModified_sys(bool b); + void updateMaximizeButton_sys(); + void setWindowFilePath_sys(const QString &filePath); + void createWindow_sys(); + void recreateMacWindow(); +#ifndef QT_MAC_USE_COCOA + void initWindowPtr(); + void finishCreateWindow_sys_Carbon(OSWindowRef windowRef); #else - void setWSGeometry(bool dontShow=false); + void finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ windowRef); + void syncCocoaMask(); + void finishCocoaMaskSetup(); #endif + void determineWindowClass(); + void transferChildren(); + bool qt_mac_dnd_event(uint, DragRef); + void toggleDrawers(bool); + //mac event functions + static bool qt_create_root_win(); + static void qt_clean_root_win(); + static bool qt_mac_update_sizer(QWidget *, int up = 0); + static OSStatus qt_window_event(EventHandlerCallRef er, EventRef event, void *); + static OSStatus qt_widget_event(EventHandlerCallRef er, EventRef event, void *); + static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool); +#elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS + void setMaxWindowState_helper(); + void setFullScreenSize_helper(); + void moveSurface(QWindowSurface *surface, const QPoint &offset); + QRegion localRequestedRegion() const; + QRegion localAllocatedRegion() const; - inline QPoint mapToWS(const QPoint &p) const - { return p - data.wrect.topLeft(); } - - inline QPoint mapFromWS(const QPoint &p) const - { return p + data.wrect.topLeft(); } - - inline QRect mapToWS(const QRect &r) const - { QRect rr(r); rr.translate(-data.wrect.topLeft()); return rr; } - - inline QRect mapFromWS(const QRect &r) const - { QRect rr(r); rr.translate(data.wrect.topLeft()); return rr; } + friend class QWSManager; + friend class QWSManagerPrivate; + friend class QDecoration; +#ifndef QT_NO_CURSOR + void updateCursor() const; #endif - - QPaintEngine *extraPaintEngine; - - mutable const QMetaObject *polished; - - void setModal_sys(); - QSizePolicy size_policy; - QLocale locale; - -#ifdef Q_WS_X11 - static QWidget *mouseGrabber; - static QWidget *keyboardGrabber; + QScreen* getScreen() const; #endif - QPaintDevice *redirectDev; - QPoint redirectOffset; - - inline void setRedirected(QPaintDevice *replacement, const QPoint &offset) - { - Q_ASSERT(q_func()->testAttribute(Qt::WA_WState_InPaintEvent)); - redirectDev = replacement; - redirectOffset = offset; - } - - inline QPaintDevice *redirected(QPoint *offset) const - { - if (offset) - *offset = redirectDev ? redirectOffset : QPoint(); - return redirectDev; - } - - inline void restoreRedirected() - { redirectDev = 0; } - - inline void enforceNativeChildren() - { - if (!extra) - createExtra(); - - if (extra->nativeChildrenForced) - return; - extra->nativeChildrenForced = 1; - - for (int i = 0; i < children.size(); ++i) { - if (QWidget *child = qobject_cast<QWidget *>(children.at(i))) - child->setAttribute(Qt::WA_NativeWindow); - } - } - - inline bool nativeChildrenForced() const - { - return extra ? extra->nativeChildrenForced : false; - } - - QSize adjustedSize() const; }; inline QWExtra *QWidgetPrivate::extraData() const diff --git a/src/gui/kernel/qwidget_qws.cpp b/src/gui/kernel/qwidget_qws.cpp index 1445f57..94bdb85 100644 --- a/src/gui/kernel/qwidget_qws.cpp +++ b/src/gui/kernel/qwidget_qws.cpp @@ -565,20 +565,6 @@ void QWidget::activateWindow() } } -/* - Should we require that q is a toplevel window ??? - - Used by QWSManager - */ -void QWidgetPrivate::blitToScreen(const QRegion &globalrgn) -{ - Q_Q(QWidget); - QWidget *win = q->window(); - QBrush bgBrush = win->palette().brush(win->backgroundRole()); - bool opaque = bgBrush.style() == Qt::NoBrush || bgBrush.isOpaque(); - QWidget::qwsDisplay()->repaintRegion(win->data->winid, win->windowFlags(), opaque, globalrgn); -} - void QWidgetPrivate::show_sys() { Q_Q(QWidget); @@ -1037,6 +1023,9 @@ void QWidgetPrivate::deleteSysExtra() void QWidgetPrivate::createTLSysExtra() { +#ifndef QT_NO_QWS_MANAGER + extra->topextra->qwsManager = 0; +#endif } void QWidgetPrivate::deleteTLSysExtra() diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index f53a3ef..d381cb2 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -1029,13 +1029,13 @@ void QWidget::setWindowState(Qt::WindowStates newstate) if (newstate & Qt::WindowFullScreen) { if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized)) d->topData()->normalGeometry = geometry(); - d->topData()->savedFlags = GetWindowLongA(internalWinId(), GWL_STYLE); + d->topData()->savedFlags = Qt::WindowFlags(GetWindowLongA(internalWinId(), GWL_STYLE)); #ifndef Q_FLATTEN_EXPOSE UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP; #else UINT style = WS_POPUP; #endif - if (d->topData()->savedFlags & WS_SYSMENU) + if (ulong(d->topData()->savedFlags) & WS_SYSMENU) style |= WS_SYSMENU; if (isVisible()) style |= WS_VISIBLE; @@ -1238,7 +1238,7 @@ void QWidgetPrivate::stackUnder_sys(QWidget* w) (In all comments below: s/X/Windows/g) */ -void QWidgetPrivate::setWSGeometry(bool dontShow) +void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &) { Q_Q(QWidget); Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); @@ -1708,7 +1708,6 @@ int QWidget::metric(PaintDeviceMetric m) const return val; } -#ifndef Q_WS_WINCE void QWidgetPrivate::createSysExtra() { #ifndef QT_NO_DRAGANDDROP @@ -1716,6 +1715,7 @@ void QWidgetPrivate::createSysExtra() #endif } +#ifndef Q_WS_WINCE void QWidgetPrivate::deleteSysExtra() { } @@ -1723,8 +1723,9 @@ void QWidgetPrivate::deleteSysExtra() void QWidgetPrivate::createTLSysExtra() { - extra->topextra->winIconSmall = 0; + extra->topextra->savedFlags = 0; extra->topextra->winIconBig = 0; + extra->topextra->winIconSmall = 0; } void QWidgetPrivate::deleteTLSysExtra() diff --git a/src/gui/kernel/qwidget_wince.cpp b/src/gui/kernel/qwidget_wince.cpp index cca928e..435fd31 100644 --- a/src/gui/kernel/qwidget_wince.cpp +++ b/src/gui/kernel/qwidget_wince.cpp @@ -535,7 +535,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) if (newstate & Qt::WindowFullScreen) { if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized)) d->topData()->normalGeometry = geometry(); - d->topData()->savedFlags = GetWindowLongA(internalWinId(), GWL_STYLE); + d->topData()->savedFlags = (Qt::WindowFlags) GetWindowLongA(internalWinId(), GWL_STYLE); UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP; if (isVisible()) style |= WS_VISIBLE; @@ -598,13 +598,6 @@ void QWidget::setWindowState(Qt::WindowStates newstate) QApplication::sendEvent(this, &e); } - -void QWidgetPrivate::createSysExtra() { -#ifndef QT_NO_DRAGANDDROP - extra->dropTarget = 0; -#endif -} - void QWidgetPrivate::deleteSysExtra() { Q_Q(QWidget); diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index 6202b35..b35740a 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -906,6 +906,44 @@ void QWidgetPrivate::x11UpdateIsOpaque() #endif } +/* + Returns true if the background is inherited; otherwise returns + false. + + Mainly used in the paintOnScreen case. +*/ +bool QWidgetPrivate::isBackgroundInherited() const +{ + Q_Q(const QWidget); + + // windows do not inherit their background + if (q->isWindow() || q->windowType() == Qt::SubWindow) + return false; + + if (q->testAttribute(Qt::WA_NoSystemBackground) || q->testAttribute(Qt::WA_OpaquePaintEvent)) + return false; + + const QPalette &pal = q->palette(); + QPalette::ColorRole bg = q->backgroundRole(); + QBrush brush = pal.brush(bg); + + // non opaque brushes leaves us no choice, we must inherit + if (!q->autoFillBackground() || !brush.isOpaque()) + return true; + + if (brush.style() == Qt::SolidPattern) { + // the background is just a solid color. If there is no + // propagated contents, then we claim as performance + // optimization that it was not inheritet. This is the normal + // case in standard Windows or Motif style. + const QWidget *w = q->parentWidget(); + if (!w->d_func()->isBackgroundInherited()) + return false; + } + + return true; +} + void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); @@ -2152,7 +2190,7 @@ static void do_size_hints(QWidget* widget, QWExtra *x) parentWRect is the geometry of the parent's X rect, measured in parent's coord sys */ -void QWidgetPrivate::setWSGeometry(bool dontShow) +void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &) { Q_Q(QWidget); Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); @@ -2610,8 +2648,8 @@ int QWidget::metric(PaintDeviceMetric m) const void QWidgetPrivate::createSysExtra() { - extra->xDndProxy = 0; extra->compress_events = true; + extra->xDndProxy = 0; } void QWidgetPrivate::deleteSysExtra() @@ -2620,8 +2658,11 @@ void QWidgetPrivate::deleteSysExtra() void QWidgetPrivate::createTLSysExtra() { + extra->topextra->spont_unmapped = 0; + extra->topextra->dnd = 0; extra->topextra->validWMState = 0; extra->topextra->waitingForMapNotify = 0; + extra->topextra->parentWinId = 0; extra->topextra->userTimeWindow = 0; } diff --git a/src/gui/painting/qemulationpaintengine.cpp b/src/gui/painting/qemulationpaintengine.cpp index 3397c45..175f1ab 100644 --- a/src/gui/painting/qemulationpaintengine.cpp +++ b/src/gui/painting/qemulationpaintengine.cpp @@ -123,14 +123,30 @@ void QEmulationPaintEngine::stroke(const QVectorPath &path, const QPen &pen) real_engine->stroke(path, bgPen); } - QBrush brush = pen.brush(); + QPen copy = pen; Qt::BrushStyle style = qbrush_style(brush); if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) { const QGradient *g = brush.gradient(); + if (g->coordinateMode() > QGradient::LogicalMode) { - QPaintEngineEx::stroke(path, pen); - return; + if (g->coordinateMode() == QGradient::StretchToDeviceMode) { + QTransform mat = brush.transform(); + mat.scale(real_engine->painter()->device()->width(), real_engine->painter()->device()->height()); + brush.setTransform(mat); + copy.setBrush(brush); + real_engine->stroke(path, copy); + return; + } else if (g->coordinateMode() == QGradient::ObjectBoundingMode) { + QTransform mat = brush.transform(); + QRealRect r = path.controlPointRect(); + mat.translate(r.x1, r.y1); + mat.scale(r.x2 - r.x1, r.y2 - r.y1); + brush.setTransform(mat); + copy.setBrush(brush); + real_engine->stroke(path, copy); + return; + } } } diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 7a236fd..6f5ee1f 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -613,7 +613,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd) subpixelType = Subpixel_None; lcdFilterType = 0; #if defined(FT_LCD_FILTER_H) - lcdFilterType = (int) FT_LCD_FILTER_DEFAULT; + lcdFilterType = (int)((quintptr) FT_LCD_FILTER_DEFAULT); #endif defaultFormat = Format_None; canUploadGlyphsToServer = false; diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 5940fba..d4bf008 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qhttpnetworkconnection_p.h" +#include "private/qnoncontiguousbytedevice_p.h" #include <private/qnetworkrequest_p.h> #include <private/qobject_p.h> #include <private/qauthenticator_p.h> @@ -71,6 +72,7 @@ QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &host #ifndef QT_NO_NETWORKPROXY , networkProxy(QNetworkProxy::NoProxy) #endif + { } @@ -205,12 +207,19 @@ void QHttpNetworkConnectionPrivate::prepareRequest(HttpMessagePair &messagePair) // add missing fields for the request QByteArray value; // check if Content-Length is provided - QIODevice *data = request.data(); - if (data && request.contentLength() == -1) { - if (!data->isSequential()) - request.setContentLength(data->size()); - else - bufferData(messagePair); // ### or do chunked upload + QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice(); + if (uploadByteDevice) { + if (request.contentLength() != -1 && uploadByteDevice->size() != -1) { + // both values known, take the smaller one. + request.setContentLength(qMin(uploadByteDevice->size(), request.contentLength())); + } else if (request.contentLength() == -1 && uploadByteDevice->size() != -1) { + // content length not supplied by user, but the upload device knows it + request.setContentLength(uploadByteDevice->size()); + } else if (request.contentLength() != -1 && uploadByteDevice->size() == -1) { + // everything OK, the user supplied us the contentLength + } else if (request.contentLength() == -1 && uploadByteDevice->size() == -1) { + qFatal("QHttpNetworkConnectionPrivate: Neither content-length nor upload device size were given"); + } } // set the Connection/Proxy-Connection: Keep-Alive headers #ifndef QT_NO_NETWORKPROXY @@ -361,18 +370,12 @@ bool QHttpNetworkConnectionPrivate::sendRequest(QAbstractSocket *socket) false); #endif socket->write(header); - QIODevice *data = channels[i].request.d->data; - QHttpNetworkReply *reply = channels[i].reply; - if (reply && reply->d_func()->requestDataBuffer.size()) - data = &channels[i].reply->d_func()->requestDataBuffer; - if (data && (data->isOpen() || data->open(QIODevice::ReadOnly))) { - if (data->isSequential()) { - channels[i].bytesTotal = -1; - QObject::connect(data, SIGNAL(readyRead()), q, SLOT(_q_dataReadyReadNoBuffer())); - QObject::connect(data, SIGNAL(readChannelFinished()), q, SLOT(_q_dataReadyReadNoBuffer())); - } else { - channels[i].bytesTotal = data->size(); - } + QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice(); + if (uploadByteDevice) { + // connect the signals so this function gets called again + QObject::connect(uploadByteDevice, SIGNAL(readyRead()), q, SLOT(_q_uploadDataReadyRead())); + + channels[i].bytesTotal = channels[i].request.contentLength(); } else { channels[i].state = WaitingState; break; @@ -380,30 +383,81 @@ bool QHttpNetworkConnectionPrivate::sendRequest(QAbstractSocket *socket) // write the initial chunk together with the headers // fall through } - case WritingState: { // write the data - QIODevice *data = channels[i].request.d->data; - if (channels[i].reply->d_func()->requestDataBuffer.size()) - data = &channels[i].reply->d_func()->requestDataBuffer; - if (!data || channels[i].bytesTotal == channels[i].written) { + case WritingState: + { + // write the data + QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice(); + if (!uploadByteDevice || channels[i].bytesTotal == channels[i].written) { + if (uploadByteDevice) + emit channels[i].reply->dataSendProgress(channels[i].written, channels[i].bytesTotal); channels[i].state = WaitingState; // now wait for response + sendRequest(socket); break; } - QByteArray chunk; - chunk.resize(ChunkSize); - qint64 readSize = data->read(chunk.data(), ChunkSize); - if (readSize == -1) { - // source has reached EOF - channels[i].state = WaitingState; // now wait for response - } else if (readSize > 0) { - // source gave us something useful - channels[i].written += socket->write(chunk.data(), readSize); - if (channels[i].reply) - emit channels[i].reply->dataSendProgress(channels[i].written, channels[i].bytesTotal); + // only feed the QTcpSocket buffer when there is less than 32 kB in it + const qint64 socketBufferFill = 32*1024; + const qint64 socketWriteMaxSize = 16*1024; + + +#ifndef QT_NO_OPENSSL + QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket); + while ((sslSocket->encryptedBytesToWrite() + sslSocket->bytesToWrite()) <= socketBufferFill + && channels[i].bytesTotal != channels[i].written) +#else + while (socket->bytesToWrite() <= socketBufferFill + && channels[i].bytesTotal != channels[i].written) +#endif + { + // get pointer to upload data + qint64 currentReadSize; + qint64 desiredReadSize = qMin(socketWriteMaxSize, channels[i].bytesTotal - channels[i].written); + const char *readPointer = uploadByteDevice->readPointer(desiredReadSize, currentReadSize); + + if (currentReadSize == -1) { + // premature eof happened + emitReplyError(socket, channels[i].reply, QNetworkReply::UnknownNetworkError); + return false; + break; + } else if (readPointer == 0 || currentReadSize == 0) { + // nothing to read currently, break the loop + break; + } else { + qint64 currentWriteSize = socket->write(readPointer, currentReadSize); + if (currentWriteSize == -1 || currentWriteSize != currentReadSize) { + // socket broke down + emitReplyError(socket, channels[i].reply, QNetworkReply::UnknownNetworkError); + return false; + } else { + channels[i].written += currentWriteSize; + uploadByteDevice->advanceReadPointer(currentWriteSize); + + emit channels[i].reply->dataSendProgress(channels[i].written, channels[i].bytesTotal); + + if (channels[i].written == channels[i].bytesTotal) { + // make sure this function is called once again + channels[i].state = WaitingState; + sendRequest(socket); + break; + } + } + } } break; } + case WaitingState: + { + QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice(); + if (uploadByteDevice) { + QObject::disconnect(uploadByteDevice, SIGNAL(readyRead()), q, SLOT(_q_uploadDataReadyRead())); + } + // ensure we try to receive a reply in all cases, even if _q_readyRead_ hat not been called + // this is needed if the sends an reply before we have finished sending the request. In that + // case receiveReply had been called before but ignored the server reply + receiveReply(socket, channels[i].reply); + break; + } case ReadingState: case Wait4AuthState: // ignore _q_bytesWritten in these states @@ -479,6 +533,9 @@ bool QHttpNetworkConnectionPrivate::expand(QAbstractSocket *socket, QHttpNetwork // make sure that the reply is valid if (channels[i].reply != reply) return true; + // emit dataReadProgress signal (signal is currently not connected + // to the rest of QNAM) since readProgress of the + // QNonContiguousByteDevice is used emit reply->dataReadProgress(reply->d_func()->totalProgress, 0); // make sure that the reply is valid if (channels[i].reply != reply) @@ -529,10 +586,20 @@ void QHttpNetworkConnectionPrivate::receiveReply(QAbstractSocket *socket, QHttpN QHttpNetworkReplyPrivate::ReplyState state = reply ? reply->d_func()->state : QHttpNetworkReplyPrivate::AllDoneState; switch (state) { case QHttpNetworkReplyPrivate::NothingDoneState: - case QHttpNetworkReplyPrivate::ReadingStatusState: - bytes += reply->d_func()->readStatus(socket); + case QHttpNetworkReplyPrivate::ReadingStatusState: { + qint64 statusBytes = reply->d_func()->readStatus(socket); + if (statusBytes == -1) { + // error reading the status, close the socket and emit error + socket->close(); + reply->d_func()->errorString = errorDetail(QNetworkReply::ProtocolFailure, socket); + emit reply->finishedWithError(QNetworkReply::ProtocolFailure, reply->d_func()->errorString); + QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); + break; + } + bytes += statusBytes; channels[i].lastStatus = reply->d_func()->statusCode; break; + } case QHttpNetworkReplyPrivate::ReadingHeaderState: bytes += reply->d_func()->readHeader(socket); if (reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) { @@ -569,6 +636,9 @@ void QHttpNetworkConnectionPrivate::receiveReply(QAbstractSocket *socket, QHttpN // make sure that the reply is valid if (channels[i].reply != reply) return; + // emit dataReadProgress signal (signal is currently not connected + // to the rest of QNAM) since readProgress of the + // QNonContiguousByteDevice is used emit reply->dataReadProgress(reply->d_func()->totalProgress, reply->d_func()->bodyLength); // make sure that the reply is valid if (channels[i].reply != reply) @@ -635,8 +705,25 @@ void QHttpNetworkConnectionPrivate::handleStatus(QAbstractSocket *socket, QHttpN case 407: handleAuthenticateChallenge(socket, reply, (statusCode == 407), resend); if (resend) { + int i = indexOf(socket); + + QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice(); + if (uploadByteDevice) { + if (uploadByteDevice->reset()) { + channels[i].written = 0; + } else { + emitReplyError(socket, reply, QNetworkReply::ContentReSendError); + break; + } + } + eraseData(reply); - sendRequest(socket); + + // also use async _q_startNextRequest so we dont break with closed + // proxy or server connections.. + channels[i].resendCurrent = true; + QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); + } break; default: @@ -970,6 +1057,7 @@ void QHttpNetworkConnectionPrivate::_q_bytesWritten(qint64 bytes) QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender()); if (!socket) return; // ### error + // bytes have been written to the socket. write even more of them :) if (isSocketWriting(socket)) sendRequest(socket); // otherwise we do nothing @@ -1128,80 +1216,21 @@ void QHttpNetworkConnectionPrivate::_q_proxyAuthenticationRequired(const QNetwor } #endif -void QHttpNetworkConnectionPrivate::_q_dataReadyReadNoBuffer() +void QHttpNetworkConnectionPrivate::_q_uploadDataReadyRead() { Q_Q(QHttpNetworkConnection); - // data emitted either readyRead() + // upload data emitted readyRead() // find out which channel it is for - QIODevice *sender = qobject_cast<QIODevice *>(q->sender()); + QObject *sender = q->sender(); - // won't match anything if the qobject_cast above failed for (int i = 0; i < channelCount; ++i) { - if (sender == channels[i].request.data()) { + if (sender == channels[i].request.uploadByteDevice()) { sendRequest(channels[i].socket); break; } } } -void QHttpNetworkConnectionPrivate::_q_dataReadyReadBuffer() -{ - Q_Q(QHttpNetworkConnection); - QIODevice *sender = qobject_cast<QIODevice *>(q->sender()); - HttpMessagePair *thePair = 0; - for (int i = 0; !thePair && i < lowPriorityQueue.size(); ++i) - if (lowPriorityQueue.at(i).first.data() == sender) - thePair = &lowPriorityQueue[i]; - - for (int i = 0; !thePair && i < highPriorityQueue.size(); ++i) - if (highPriorityQueue.at(i).first.data() == sender) - thePair = &highPriorityQueue[i]; - - if (thePair) { - bufferData(*thePair); - - // are we finished buffering? - if (!thePair->second->d_func()->requestIsBuffering) - _q_startNextRequest(); - } -} - -void QHttpNetworkConnectionPrivate::bufferData(HttpMessagePair &messagePair) -{ - Q_Q(QHttpNetworkConnection); - QHttpNetworkRequest &request = messagePair.first; - QHttpNetworkReply *reply = messagePair.second; - Q_ASSERT(request.data()); - if (!reply->d_func()->requestIsBuffering) { // first time - QObject::connect(request.data(), SIGNAL(readyRead()), q, SLOT(_q_dataReadyReadBuffer())); - QObject::connect(request.data(), SIGNAL(readChannelFinished()), q, SLOT(_q_dataReadyReadBuffer())); - reply->d_func()->requestIsBuffering = true; - reply->d_func()->requestDataBuffer.open(QIODevice::ReadWrite); - } - - // always try to read at least one byte - // ### FIXME! use a QRingBuffer - qint64 bytesToRead = qMax<qint64>(1, request.data()->bytesAvailable()); - QByteArray newData; - newData.resize(bytesToRead); - qint64 bytesActuallyRead = request.data()->read(newData.data(), bytesToRead); - - if (bytesActuallyRead > 0) { - // we read something - newData.chop(bytesToRead - bytesActuallyRead); - reply->d_func()->requestDataBuffer.write(newData); - } else if (bytesActuallyRead == -1) { // last time - QObject::disconnect(request.data(), SIGNAL(readyRead()), q, SLOT(_q_dataReadyReadBuffer())); - QObject::disconnect(request.data(), SIGNAL(readChannelFinished()), q, SLOT(_q_dataReadyReadBuffer())); - - request.setContentLength(reply->d_func()->requestDataBuffer.size()); - reply->d_func()->requestDataBuffer.seek(0); - reply->d_func()->requestIsBuffering = false; - } -} - -// QHttpNetworkConnection - QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, QObject *parent) : QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt)), parent) { diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index 09bd459..9b127dd 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -146,8 +146,7 @@ private: #ifndef QT_NO_NETWORKPROXY Q_PRIVATE_SLOT(d_func(), void _q_proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)) #endif - Q_PRIVATE_SLOT(d_func(), void _q_dataReadyReadBuffer()) - Q_PRIVATE_SLOT(d_func(), void _q_dataReadyReadNoBuffer()) + Q_PRIVATE_SLOT(d_func(), void _q_uploadDataReadyRead()) #ifndef QT_NO_OPENSSL Q_PRIVATE_SLOT(d_func(), void _q_encrypted()) @@ -209,8 +208,8 @@ public: #ifndef QT_NO_NETWORKPROXY void _q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth); // from transparent proxy #endif - void _q_dataReadyReadNoBuffer(); - void _q_dataReadyReadBuffer(); + + void _q_uploadDataReadyRead(); void createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request); bool ensureConnection(QAbstractSocket *socket); @@ -219,7 +218,6 @@ public: #ifndef QT_NO_COMPRESS bool expand(QAbstractSocket *socket, QHttpNetworkReply *reply, bool dataComplete); #endif - void bufferData(HttpMessagePair &request); void removeReply(QHttpNetworkReply *reply); QString hostName; diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index fe3f6af..310994c 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -409,39 +409,62 @@ qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket) if (fragment.endsWith('\r')) { fragment.truncate(fragment.length()-1); } - parseStatus(fragment); + bool ok = parseStatus(fragment); state = ReadingHeaderState; fragment.clear(); // next fragment + + if (!ok) + return -1; break; } else { c = 0; bytes += socket->read(&c, 1); fragment.append(c); } + + // is this a valid reply? + if (fragment.length() >= 5 && !fragment.startsWith("HTTP/")) + return -1; + } + return bytes; } -void QHttpNetworkReplyPrivate::parseStatus(const QByteArray &status) +bool QHttpNetworkReplyPrivate::parseStatus(const QByteArray &status) { - const QByteArrayMatcher sp(" "); - int i = sp.indexIn(status); - const QByteArray version = status.mid(0, i); - int j = sp.indexIn(status, i + 1); + // from RFC 2616: + // Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF + // HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT + // that makes: 'HTTP/n.n xxx Message' + // byte count: 0123456789012 + + static const int minLength = 11; + static const int dotPos = 6; + static const int spacePos = 8; + static const char httpMagic[] = "HTTP/"; + + if (status.length() < minLength + || !status.startsWith(httpMagic) + || status.at(dotPos) != '.' + || status.at(spacePos) != ' ') { + // I don't know how to parse this status line + return false; + } + + // optimize for the valid case: defer checking until the end + majorVersion = status.at(dotPos - 1) - '0'; + minorVersion = status.at(dotPos + 1) - '0'; + + int i = spacePos; + int j = status.indexOf(' ', i + 1); // j == -1 || at(j) == ' ' so j+1 == 0 && j+1 <= length() const QByteArray code = status.mid(i + 1, j - i - 1); - const QByteArray reason = status.mid(j + 1, status.count() - j); - const QByteArrayMatcher slash("/"); - int k = slash.indexIn(version); - const QByteArrayMatcher dot("."); - int l = dot.indexIn(version, k); - const QByteArray major = version.mid(k + 1, l - k - 1); - const QByteArray minor = version.mid(l + 1, version.count() - l); + bool ok; + statusCode = code.toInt(&ok); + reasonPhrase = QString::fromLatin1(status.constData() + j + 1); - majorVersion = QString::fromAscii(major.constData()).toInt(); - minorVersion = QString::fromAscii(minor.constData()).toInt(); - statusCode = QString::fromAscii(code.constData()).toInt(); - reasonPhrase = QString::fromAscii(reason.constData()); + return ok && uint(majorVersion) <= 9 && uint(minorVersion) <= 9; } qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket) @@ -521,13 +544,13 @@ qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QIODevice *ou { qint64 bytes = 0; if (isChunked()) { - bytes += transferChunked(socket, out); // chunked transfer encoding (rfc 2616, sec 3.6) + bytes += readReplyBodyChunked(socket, out); // chunked transfer encoding (rfc 2616, sec 3.6) } else if (bodyLength > 0) { // we have a Content-Length - bytes += transferRaw(socket, out, bodyLength - contentRead); + bytes += readReplyBodyRaw(socket, out, bodyLength - contentRead); if (contentRead + bytes == bodyLength) state = AllDoneState; } else { - bytes += transferRaw(socket, out, socket->bytesAvailable()); + bytes += readReplyBodyRaw(socket, out, socket->bytesAvailable()); } if (state == AllDoneState) socket->readAll(); // Read the rest to clean (CRLF) @@ -535,7 +558,7 @@ qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QIODevice *ou return bytes; } -qint64 QHttpNetworkReplyPrivate::transferRaw(QIODevice *in, QIODevice *out, qint64 size) +qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QIODevice *in, QIODevice *out, qint64 size) { qint64 bytes = 0; Q_ASSERT(in); @@ -561,7 +584,7 @@ qint64 QHttpNetworkReplyPrivate::transferRaw(QIODevice *in, QIODevice *out, qint } -qint64 QHttpNetworkReplyPrivate::transferChunked(QIODevice *in, QIODevice *out) +qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *in, QIODevice *out) { qint64 bytes = 0; while (in->bytesAvailable()) { // while we can read from input @@ -660,4 +683,4 @@ void QHttpNetworkReply::ignoreSslErrors() QT_END_NAMESPACE -#endif // QT_NO_HTTP
\ No newline at end of file +#endif // QT_NO_HTTP diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index c17c65c..cc5cce8 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -139,7 +139,7 @@ Q_SIGNALS: void finishedWithError(QNetworkReply::NetworkError errorCode, const QString &detail = QString()); void headerChanged(); void dataReadProgress(int done, int total); - void dataSendProgress(int done, int total); + void dataSendProgress(qint64 done, qint64 total); private: Q_DECLARE_PRIVATE(QHttpNetworkReply) @@ -154,7 +154,7 @@ public: QHttpNetworkReplyPrivate(const QUrl &newUrl = QUrl()); ~QHttpNetworkReplyPrivate(); qint64 readStatus(QAbstractSocket *socket); - void parseStatus(const QByteArray &status); + bool parseStatus(const QByteArray &status); qint64 readHeader(QAbstractSocket *socket); void parseHeader(const QByteArray &header); qint64 readBody(QAbstractSocket *socket, QIODevice *out); @@ -162,8 +162,8 @@ public: QAuthenticatorPrivate::Method authenticationMethod(bool isProxy) const; void clear(); - qint64 transferRaw(QIODevice *in, QIODevice *out, qint64 size); - qint64 transferChunked(QIODevice *in, QIODevice *out); + qint64 readReplyBodyRaw(QIODevice *in, QIODevice *out, qint64 size); + qint64 readReplyBodyChunked(QIODevice *in, QIODevice *out); qint64 getChunkSize(QIODevice *in, qint64 *chunkSize); qint64 bytesAvailable() const; @@ -206,7 +206,6 @@ public: QByteArray responseData; // uncompressed body QByteArray compressedData; // compressed body (temporary) - QBuffer requestDataBuffer; bool requestIsBuffering; bool requestIsPrepared; }; diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp index 420cb69..7df68fc 100644 --- a/src/network/access/qhttpnetworkrequest.cpp +++ b/src/network/access/qhttpnetworkrequest.cpp @@ -40,12 +40,13 @@ ****************************************************************************/ #include "qhttpnetworkrequest_p.h" +#include "private/qnoncontiguousbytedevice_p.h" QT_BEGIN_NAMESPACE QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op, QHttpNetworkRequest::Priority pri, const QUrl &newUrl) - : QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), data(0), + : QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), uploadByteDevice(0), autoDecompress(false) { } @@ -55,7 +56,7 @@ QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequest { operation = other.operation; priority = other.priority; - data = other.data; + uploadByteDevice = other.uploadByteDevice; autoDecompress = other.autoDecompress; } @@ -67,7 +68,7 @@ bool QHttpNetworkRequestPrivate::operator==(const QHttpNetworkRequestPrivate &ot { return QHttpNetworkHeaderPrivate::operator==(other) && (operation == other.operation) - && (data == other.data); + && (uploadByteDevice == other.uploadByteDevice); } QByteArray QHttpNetworkRequestPrivate::methodName() const @@ -109,7 +110,7 @@ QByteArray QHttpNetworkRequestPrivate::uri(bool throughProxy) const QUrl::FormattingOptions format(QUrl::RemoveFragment); // for POST, query data is send as content - if (operation == QHttpNetworkRequest::Post && !data) + if (operation == QHttpNetworkRequest::Post && !uploadByteDevice) format |= QUrl::RemoveQuery; // for requests through proxy, the Request-URI contains full url if (throughProxy) @@ -140,7 +141,7 @@ QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request // add content type, if not set in the request if (request.headerField("content-type").isEmpty()) ba += "Content-Type: application/x-www-form-urlencoded\r\n"; - if (!request.d->data && request.d->url.hasQuery()) { + if (!request.d->uploadByteDevice && request.d->url.hasQuery()) { QByteArray query = request.d->url.encodedQuery(); ba += "Content-Length: "+ QByteArray::number(query.size()) + "\r\n"; ba += "\r\n"; @@ -236,14 +237,14 @@ void QHttpNetworkRequest::setPriority(Priority priority) d->priority = priority; } -QIODevice *QHttpNetworkRequest::data() const +void QHttpNetworkRequest::setUploadByteDevice(QNonContiguousByteDevice *bd) { - return d->data; + d->uploadByteDevice = bd; } -void QHttpNetworkRequest::setData(QIODevice *data) +QNonContiguousByteDevice* QHttpNetworkRequest::uploadByteDevice() const { - d->data = data; + return d->uploadByteDevice; } int QHttpNetworkRequest::majorVersion() const diff --git a/src/network/access/qhttpnetworkrequest_p.h b/src/network/access/qhttpnetworkrequest_p.h index d18e116..ed4325a 100644 --- a/src/network/access/qhttpnetworkrequest_p.h +++ b/src/network/access/qhttpnetworkrequest_p.h @@ -58,6 +58,8 @@ QT_BEGIN_NAMESPACE +class QNonContiguousByteDevice; + class QHttpNetworkRequestPrivate; class Q_AUTOTEST_EXPORT QHttpNetworkRequest: public QHttpNetworkHeader { @@ -104,8 +106,8 @@ public: Priority priority() const; void setPriority(Priority priority); - QIODevice *data() const; - void setData(QIODevice *data); + void setUploadByteDevice(QNonContiguousByteDevice *bd); + QNonContiguousByteDevice* uploadByteDevice() const; private: QSharedDataPointer<QHttpNetworkRequestPrivate> d; @@ -113,7 +115,6 @@ private: friend class QHttpNetworkConnectionPrivate; }; - class QHttpNetworkRequestPrivate : public QHttpNetworkHeaderPrivate { public: @@ -129,7 +130,7 @@ public: QHttpNetworkRequest::Operation operation; QHttpNetworkRequest::Priority priority; - mutable QIODevice *data; + mutable QNonContiguousByteDevice* uploadByteDevice; bool autoDecompress; }; diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp index df468b8..b9d1b85 100644 --- a/src/network/access/qnetworkaccessbackend.cpp +++ b/src/network/access/qnetworkaccessbackend.cpp @@ -50,6 +50,8 @@ #include "qnetworkaccesscachebackend_p.h" #include "qabstractnetworkcache.h" +#include "private/qnoncontiguousbytedevice_p.h" + QT_BEGIN_NAMESPACE static bool factoryDataShutdown = false; @@ -109,17 +111,43 @@ QNetworkAccessBackend *QNetworkAccessManagerPrivate::findBackend(QNetworkAccessM return 0; } -QNetworkAccessBackend::QNetworkAccessBackend() + +QNonContiguousByteDevice* QNetworkAccessBackend::createUploadByteDevice() { + QNonContiguousByteDevice* device = 0; + + if (reply->outgoingDataBuffer) + device = QNonContiguousByteDeviceFactory::create(reply->outgoingDataBuffer); + else + device = QNonContiguousByteDeviceFactory::create(reply->outgoingData); + + bool bufferDisallowed = + reply->request.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute, + QVariant(false)) == QVariant(true); + if (bufferDisallowed) + device->disableReset(); + + // make sure we delete this later + device->setParent(this); + + connect(device, SIGNAL(readProgress(qint64,qint64)), this, SLOT(emitReplyUploadProgress(qint64,qint64))); + + return device; } -QNetworkAccessBackend::~QNetworkAccessBackend() +// need to have this function since the reply is a private member variable +// and the special backends need to access this. +void QNetworkAccessBackend::emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal) { + reply->emitUploadProgress(bytesSent, bytesTotal); } -void QNetworkAccessBackend::upstreamReadyRead() +QNetworkAccessBackend::QNetworkAccessBackend() +{ +} + +QNetworkAccessBackend::~QNetworkAccessBackend() { - // do nothing } void QNetworkAccessBackend::downstreamReadyWrite() @@ -184,23 +212,6 @@ bool QNetworkAccessBackend::isCachingEnabled() const return reply->isCachingEnabled(); } -qint64 QNetworkAccessBackend::upstreamBytesAvailable() const -{ - return reply->writeBuffer.size(); -} - -void QNetworkAccessBackend::upstreamBytesConsumed(qint64 count) -{ - // remove count bytes from the write buffer - reply->consume(count); -} - -QByteArray QNetworkAccessBackend::readUpstream() -{ - // ### this is expensive. Consider making QRingBuffer::peekAll keep the buffer it returns - return reply->writeBuffer.peek(upstreamBytesAvailable()); -} - qint64 QNetworkAccessBackend::nextDownstreamBlockSize() const { return reply->nextDownstreamBlockSize(); @@ -213,12 +224,12 @@ qint64 QNetworkAccessBackend::downstreamBytesToConsume() const void QNetworkAccessBackend::writeDownstreamData(const QByteArray &data) { - reply->feed(data); + reply->appendDownstreamData(data); } void QNetworkAccessBackend::writeDownstreamData(QIODevice *data) { - reply->feed(data); + reply->appendDownstreamData(data); } QVariant QNetworkAccessBackend::header(QNetworkRequest::KnownHeaders header) const diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h index 9012396..6035f3a 100644 --- a/src/network/access/qnetworkaccessbackend_p.h +++ b/src/network/access/qnetworkaccessbackend_p.h @@ -70,6 +70,8 @@ class QNetworkAccessManagerPrivate; class QNetworkReplyImplPrivate; class QAbstractNetworkCache; class QNetworkCacheMetaData; +class QNetworkAccessBackendUploadIODevice; +class QNonContiguousByteDevice; // Should support direct file upload from disk or download to disk. // @@ -86,14 +88,13 @@ public: // have different names. The Connection has two streams: // // - Upstream: - // Upstream is data that is being written into this connection, - // from the user. Upstream operates in a "pull" mechanism: the - // connection will be notified that there is more data available - // by a call to "upstreamReadyRead". The number of bytes - // available is given by upstreamBytesAvailable(). A call to - // readUpstream() always yields the entire upstream buffer. When - // the connection has processed a certain amount of bytes from - // that buffer, it should call upstreamBytesConsumed(). + // The upstream uses a QNonContiguousByteDevice provided + // by the backend. This device emits the usual readyRead() + // signal when the backend has data available for the connection + // to write. The different backends can listen on this signal + // and then pull upload data from the QNonContiguousByteDevice and + // deal with it. + // // // - Downstream: // Downstream is the data that is being read from this @@ -111,12 +112,9 @@ public: virtual void open() = 0; virtual void closeDownstreamChannel() = 0; - virtual void closeUpstreamChannel() = 0; virtual bool waitForDownstreamReadyRead(int msecs) = 0; - virtual bool waitForUpstreamBytesWritten(int msecs) = 0; // slot-like: - virtual void upstreamReadyRead(); virtual void downstreamReadyWrite(); virtual void copyFinished(QIODevice *); virtual void ignoreSslErrors(); @@ -155,18 +153,24 @@ public: QVariant attribute(QNetworkRequest::Attribute code) const; void setAttribute(QNetworkRequest::Attribute code, const QVariant &value); + // return true if the QNonContiguousByteDevice of the upload + // data needs to support reset(). Currently needed for HTTP. + // This will possibly enable buffering of the upload data. + virtual bool needsResetableUploadData() {return false;}; + protected: - // these functions control the upstream mechanism - // that is, data coming into the backend and out via the connection - qint64 upstreamBytesAvailable() const; - void upstreamBytesConsumed(qint64 count); - QByteArray readUpstream(); + // Create the device used for reading the upload data + QNonContiguousByteDevice* createUploadByteDevice(); + // these functions control the downstream mechanism // that is, data that has come via the connection and is going out the backend qint64 nextDownstreamBlockSize() const; qint64 downstreamBytesToConsume() const; void writeDownstreamData(const QByteArray &data); + +public slots: + // for task 251801, needs to be a slot to be called asynchronously void writeDownstreamData(QIODevice *data); protected slots: @@ -179,10 +183,12 @@ protected slots: void metaDataChanged(); void redirectionRequested(const QUrl &destination); void sslErrors(const QList<QSslError> &errors); + void emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal); private: friend class QNetworkAccessManager; friend class QNetworkAccessManagerPrivate; + friend class QNetworkAccessBackendUploadIODevice; QNetworkAccessManagerPrivate *manager; QNetworkReplyImplPrivate *reply; }; diff --git a/src/network/access/qnetworkaccessdebugpipebackend.cpp b/src/network/access/qnetworkaccessdebugpipebackend.cpp index 2e5f1b1..d4bda9a 100644 --- a/src/network/access/qnetworkaccessdebugpipebackend.cpp +++ b/src/network/access/qnetworkaccessdebugpipebackend.cpp @@ -41,6 +41,8 @@ #include "qnetworkaccessdebugpipebackend_p.h" #include "QtCore/qdatastream.h" +#include <QCoreApplication> +#include "private/qnoncontiguousbytedevice_p.h" QT_BEGIN_NAMESPACE @@ -51,12 +53,6 @@ enum { WriteBufferSize = ReadBufferSize }; -struct QNetworkAccessDebugPipeBackend::DataPacket -{ - QList<QPair<QByteArray, QByteArray> > headers; - QByteArray data; -}; - QNetworkAccessBackend * QNetworkAccessDebugPipeBackendFactory::create(QNetworkAccessManager::Operation op, const QNetworkRequest &request) const @@ -79,12 +75,14 @@ QNetworkAccessDebugPipeBackendFactory::create(QNetworkAccessManager::Operation o } QNetworkAccessDebugPipeBackend::QNetworkAccessDebugPipeBackend() - : incomingPacketSize(0), bareProtocol(false) + : bareProtocol(false), hasUploadFinished(false), hasDownloadFinished(false), + hasEverythingFinished(false), bytesDownloaded(0), bytesUploaded(0) { } QNetworkAccessDebugPipeBackend::~QNetworkAccessDebugPipeBackend() { + // this is signals disconnect, not network! socket.disconnect(this); // we're not interested in the signals at this point } @@ -92,160 +90,150 @@ void QNetworkAccessDebugPipeBackend::open() { socket.connectToHost(url().host(), url().port(12345)); socket.setReadBufferSize(ReadBufferSize); + + // socket ready read -> we can push from socket to downstream connect(&socket, SIGNAL(readyRead()), SLOT(socketReadyRead())); - connect(&socket, SIGNAL(bytesWritten(qint64)), SLOT(socketBytesWritten(qint64))); connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketError())); connect(&socket, SIGNAL(disconnected()), SLOT(socketDisconnected())); + connect(&socket, SIGNAL(connected()), SLOT(socketConnected())); + // socket bytes written -> we can push more from upstream to socket + connect(&socket, SIGNAL(bytesWritten(qint64)), SLOT(socketBytesWritten(qint64))); bareProtocol = url().queryItemValue(QLatin1String("bare")) == QLatin1String("1"); - if (!bareProtocol) { - // "Handshake": - // send outgoing metadata and the URL being requested - DataPacket packet; - //packet.metaData = request().metaData(); - packet.data = url().toEncoded(); - send(packet); + if (operation() == QNetworkAccessManager::PutOperation) { + uploadByteDevice = createUploadByteDevice(); + QObject::connect(uploadByteDevice, SIGNAL(readyRead()), this, SLOT(uploadReadyReadSlot())); + QMetaObject::invokeMethod(this, "uploadReadyReadSlot", Qt::QueuedConnection); } } -void QNetworkAccessDebugPipeBackend::closeDownstreamChannel() +void QNetworkAccessDebugPipeBackend::socketReadyRead() { - if (operation() == QNetworkAccessManager::GetOperation) - socket.disconnectFromHost(); + pushFromSocketToDownstream(); } -void QNetworkAccessDebugPipeBackend::closeUpstreamChannel() +void QNetworkAccessDebugPipeBackend::downstreamReadyWrite() { - if (operation() == QNetworkAccessManager::PutOperation) - socket.disconnectFromHost(); - else if (operation() == QNetworkAccessManager::PostOperation) { - send(DataPacket()); - } + pushFromSocketToDownstream(); } -bool QNetworkAccessDebugPipeBackend::waitForDownstreamReadyRead(int ms) +void QNetworkAccessDebugPipeBackend::socketBytesWritten(qint64) { - readyReadEmitted = false; - if (socket.bytesAvailable()) { - socketReadyRead(); - if (readyReadEmitted) - return true; - } - socket.waitForReadyRead(ms); - return readyReadEmitted; + pushFromUpstreamToSocket(); } -bool QNetworkAccessDebugPipeBackend::waitForUpstreamBytesWritten(int ms) +void QNetworkAccessDebugPipeBackend::uploadReadyReadSlot() { - bytesWrittenEmitted = false; - upstreamReadyRead(); - if (bytesWrittenEmitted) - return true; - - socket.waitForBytesWritten(ms); - return bytesWrittenEmitted; + pushFromUpstreamToSocket(); } -void QNetworkAccessDebugPipeBackend::upstreamReadyRead() +void QNetworkAccessDebugPipeBackend::pushFromSocketToDownstream() { - int maxWrite = WriteBufferSize - socket.bytesToWrite(); - if (maxWrite <= 0) - return; // can't write yet, wait for the socket to write - - if (bareProtocol) { - QByteArray data = readUpstream(); - if (data.isEmpty()) - return; + QByteArray buffer; - socket.write(data); - upstreamBytesConsumed(data.size()); - bytesWrittenEmitted = true; + if (socket.state() == QAbstractSocket::ConnectingState) { return; } - DataPacket packet; - packet.data = readUpstream(); - if (packet.data.isEmpty()) - return; // we'll be called again when there's data - if (packet.data.size() > maxWrite) - packet.data.truncate(maxWrite); - - if (!send(packet)) { - QString msg = QObject::tr("Write error writing to %1: %2") - .arg(url().toString(), socket.errorString()); - error(QNetworkReply::ProtocolFailure, msg); + forever { + if (hasDownloadFinished) + return; - finished(); - return; + buffer.resize(ReadBufferSize); + qint64 haveRead = socket.read(buffer.data(), ReadBufferSize); + + if (haveRead == -1) { + hasDownloadFinished = true; + // this ensures a good last downloadProgress is emitted + setHeader(QNetworkRequest::ContentLengthHeader, QVariant()); + possiblyFinish(); + break; + } else if (haveRead == 0) { + break; + } else { + // have read something + buffer.resize(haveRead); + bytesDownloaded += haveRead; + writeDownstreamData(buffer); + } } - upstreamBytesConsumed(packet.data.size()); - bytesWrittenEmitted = true; } -void QNetworkAccessDebugPipeBackend::downstreamReadyWrite() +void QNetworkAccessDebugPipeBackend::pushFromUpstreamToSocket() { - socketReadyRead(); -} + // FIXME + if (operation() == QNetworkAccessManager::PutOperation) { + if (hasUploadFinished) + return; -void QNetworkAccessDebugPipeBackend::socketReadyRead() -{ - if (bareProtocol) { - qint64 bytesToRead = socket.bytesAvailable(); - if (bytesToRead) { - QByteArray buffer; - buffer.resize(bytesToRead); - qint64 bytesRead = socket.read(buffer.data(), bytesToRead); - if (bytesRead < bytesToRead) - buffer.truncate(bytesRead); - writeDownstreamData(buffer); - readyReadEmitted = true; + forever { + if (socket.bytesToWrite() >= WriteBufferSize) + return; + + qint64 haveRead; + const char *readPointer = uploadByteDevice->readPointer(WriteBufferSize, haveRead); + if (haveRead == -1) { + // EOF + hasUploadFinished = true; + emitReplyUploadProgress(bytesUploaded, bytesUploaded); + possiblyFinish(); + break; + } else if (haveRead == 0 || readPointer == 0) { + // nothing to read right now, we will be called again later + break; + } else { + qint64 haveWritten; + haveWritten = socket.write(readPointer, haveRead); + + if (haveWritten < 0) { + // write error! + QString msg = QCoreApplication::translate("QNetworkAccessDebugPipeBackend", "Write error writing to %1: %2") + .arg(url().toString(), socket.errorString()); + error(QNetworkReply::ProtocolFailure, msg); + finished(); + return; + } else { + uploadByteDevice->advanceReadPointer(haveWritten); + bytesUploaded += haveWritten; + emitReplyUploadProgress(bytesUploaded, -1); + } + + //QCoreApplication::processEvents(); + + } } - return; } +} - while (canReceive() && - (socket.state() == QAbstractSocket::UnconnectedState || nextDownstreamBlockSize())) { - DataPacket packet; - if (receive(packet)) { - if (!packet.headers.isEmpty()) { - QList<QPair<QByteArray, QByteArray> >::ConstIterator - it = packet.headers.constBegin(), - end = packet.headers.constEnd(); - for ( ; it != end; ++it) - setRawHeader(it->first, it->second); - metaDataChanged(); - } +void QNetworkAccessDebugPipeBackend::possiblyFinish() +{ + if (hasEverythingFinished) + return; + hasEverythingFinished = true; - if (!packet.data.isEmpty()) { - writeDownstreamData(packet.data); - readyReadEmitted = true; - } + if ((operation() == QNetworkAccessManager::GetOperation) && hasDownloadFinished) { + socket.close(); + finished(); + } else if ((operation() == QNetworkAccessManager::PutOperation) && hasUploadFinished) { + socket.close(); + finished(); + } - if (packet.headers.isEmpty() && packet.data.isEmpty()) { - // it's an eof - socket.close(); - readyReadEmitted = true; - } - } else { - // got an error - QString msg = QObject::tr("Read error reading from %1: %2") - .arg(url().toString(), socket.errorString()); - error(QNetworkReply::ProtocolFailure, msg); - finished(); - return; - } - } } -void QNetworkAccessDebugPipeBackend::socketBytesWritten(qint64) +void QNetworkAccessDebugPipeBackend::closeDownstreamChannel() { - upstreamReadyRead(); + qWarning() << "QNetworkAccessDebugPipeBackend::closeDownstreamChannel()" << operation(); + //if (operation() == QNetworkAccessManager::GetOperation) + // socket.disconnectFromHost(); } + void QNetworkAccessDebugPipeBackend::socketError() { + qWarning() << "QNetworkAccessDebugPipeBackend::socketError()" << socket.error(); QNetworkReply::NetworkError code; switch (socket.error()) { case QAbstractSocket::RemoteHostClosedError: @@ -269,76 +257,27 @@ void QNetworkAccessDebugPipeBackend::socketError() void QNetworkAccessDebugPipeBackend::socketDisconnected() { - socketReadyRead(); - if (incomingPacketSize == 0 && socket.bytesToWrite() == 0) { + pushFromSocketToDownstream(); + + if (socket.bytesToWrite() == 0) { // normal close - finished(); } else { // abnormal close QString msg = QObject::tr("Remote host closed the connection prematurely on %1") .arg(url().toString()); error(QNetworkReply::RemoteHostClosedError, msg); - finished(); } } -bool QNetworkAccessDebugPipeBackend::send(const DataPacket &packet) -{ - QByteArray ba; - { - QDataStream stream(&ba, QIODevice::WriteOnly); - stream.setVersion(QDataStream::Qt_4_4); - - stream << packet.headers << packet.data; - } - - qint32 outgoingPacketSize = ba.size(); - qint64 written = socket.write((const char*)&outgoingPacketSize, sizeof outgoingPacketSize); - written += socket.write(ba); - return quint64(written) == (outgoingPacketSize + sizeof outgoingPacketSize); -} - -bool QNetworkAccessDebugPipeBackend::receive(DataPacket &packet) +void QNetworkAccessDebugPipeBackend::socketConnected() { - if (!canReceive()) - return false; - - // canReceive() does the setting up for us - Q_ASSERT(socket.bytesAvailable() >= incomingPacketSize); - QByteArray incomingPacket = socket.read(incomingPacketSize); - QDataStream stream(&incomingPacket, QIODevice::ReadOnly); - stream.setVersion(QDataStream::Qt_4_4); - stream >> packet.headers >> packet.data; - - // reset for next packet: - incomingPacketSize = 0; - socket.setReadBufferSize(ReadBufferSize); - return true; } -bool QNetworkAccessDebugPipeBackend::canReceive() +bool QNetworkAccessDebugPipeBackend::waitForDownstreamReadyRead(int ms) { - if (incomingPacketSize == 0) { - // read the packet size - if (quint64(socket.bytesAvailable()) >= sizeof incomingPacketSize) - socket.read((char*)&incomingPacketSize, sizeof incomingPacketSize); - else - return false; - } - - if (incomingPacketSize == 0) { - QString msg = QObject::tr("Protocol error: packet of size 0 received"); - error(QNetworkReply::ProtocolFailure, msg); - finished(); - - socket.blockSignals(true); - socket.abort(); - socket.blockSignals(false); - return false; - } - - return socket.bytesAvailable() >= incomingPacketSize; + qCritical("QNetworkAccess: Debug pipe backend does not support waitForReadyRead()"); + return false; } #endif diff --git a/src/network/access/qnetworkaccessdebugpipebackend_p.h b/src/network/access/qnetworkaccessdebugpipebackend_p.h index 73a35cf..a13edc4 100644 --- a/src/network/access/qnetworkaccessdebugpipebackend_p.h +++ b/src/network/access/qnetworkaccessdebugpipebackend_p.h @@ -66,35 +66,38 @@ class QNetworkAccessDebugPipeBackend: public QNetworkAccessBackend { Q_OBJECT public: - struct DataPacket; QNetworkAccessDebugPipeBackend(); virtual ~QNetworkAccessDebugPipeBackend(); virtual void open(); virtual void closeDownstreamChannel(); - virtual void closeUpstreamChannel(); virtual bool waitForDownstreamReadyRead(int msecs); - virtual bool waitForUpstreamBytesWritten(int msecs); - virtual void upstreamReadyRead(); virtual void downstreamReadyWrite(); +protected: + void pushFromSocketToDownstream(); + void pushFromUpstreamToSocket(); + void possiblyFinish(); + QNonContiguousByteDevice *uploadByteDevice; + private slots: + void uploadReadyReadSlot(); void socketReadyRead(); void socketBytesWritten(qint64 bytes); void socketError(); void socketDisconnected(); + void socketConnected(); private: QTcpSocket socket; - qint32 incomingPacketSize; - bool readyReadEmitted; - bool bytesWrittenEmitted; bool bareProtocol; + bool hasUploadFinished; + bool hasDownloadFinished; + bool hasEverythingFinished; - bool send(const DataPacket &packet); - bool canReceive(); - bool receive(DataPacket &packet); + qint64 bytesDownloaded; + qint64 bytesUploaded; }; class QNetworkAccessDebugPipeBackendFactory: public QNetworkAccessBackendFactory diff --git a/src/network/access/qnetworkaccessfilebackend.cpp b/src/network/access/qnetworkaccessfilebackend.cpp index 8a5a665..6374fde 100644 --- a/src/network/access/qnetworkaccessfilebackend.cpp +++ b/src/network/access/qnetworkaccessfilebackend.cpp @@ -43,6 +43,7 @@ #include "qfileinfo.h" #include "qurlinfo.h" #include "qdir.h" +#include "private/qnoncontiguousbytedevice_p.h" #include <QtCore/QCoreApplication> @@ -77,7 +78,7 @@ QNetworkAccessFileBackendFactory::create(QNetworkAccessManager::Operation op, } QNetworkAccessFileBackend::QNetworkAccessFileBackend() - : totalBytes(0) + : uploadByteDevice(0), totalBytes(0), hasUploadFinished(false) { } @@ -126,6 +127,9 @@ void QNetworkAccessFileBackend::open() break; case QNetworkAccessManager::PutOperation: mode = QIODevice::WriteOnly | QIODevice::Truncate; + uploadByteDevice = createUploadByteDevice(); + QObject::connect(uploadByteDevice, SIGNAL(readyRead()), this, SLOT(uploadReadyReadSlot())); + QMetaObject::invokeMethod(this, "uploadReadyReadSlot", Qt::QueuedConnection); break; default: Q_ASSERT_X(false, "QNetworkAccessFileBackend::open", @@ -152,19 +156,50 @@ void QNetworkAccessFileBackend::open() } } -void QNetworkAccessFileBackend::closeDownstreamChannel() +void QNetworkAccessFileBackend::uploadReadyReadSlot() { - if (operation() == QNetworkAccessManager::GetOperation) { - file.close(); - //downstreamChannelClosed(); + if (hasUploadFinished) + return; + + forever { + qint64 haveRead; + const char *readPointer = uploadByteDevice->readPointer(-1, haveRead); + if (haveRead == -1) { + // EOF + hasUploadFinished = true; + file.flush(); + file.close(); + finished(); + break; + } else if (haveRead == 0 || readPointer == 0) { + // nothing to read right now, we will be called again later + break; + } else { + qint64 haveWritten; + haveWritten = file.write(readPointer, haveRead); + + if (haveWritten < 0) { + // write error! + QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Write error writing to %1: %2") + .arg(url().toString(), file.errorString()); + error(QNetworkReply::ProtocolFailure, msg); + + finished(); + return; + } else { + uploadByteDevice->advanceReadPointer(haveWritten); + } + + + file.flush(); + } } } -void QNetworkAccessFileBackend::closeUpstreamChannel() +void QNetworkAccessFileBackend::closeDownstreamChannel() { - if (operation() == QNetworkAccessManager::PutOperation) { + if (operation() == QNetworkAccessManager::GetOperation) { file.close(); - finished(); } } @@ -174,40 +209,6 @@ bool QNetworkAccessFileBackend::waitForDownstreamReadyRead(int) return readMoreFromFile(); } -bool QNetworkAccessFileBackend::waitForUpstreamBytesWritten(int) -{ - Q_ASSERT_X(false, "QNetworkAccessFileBackend::waitForUpstreamBytesWritten", - "This function should never have been called, since there is never anything " - "left to be written!"); - return false; -} - -void QNetworkAccessFileBackend::upstreamReadyRead() -{ - Q_ASSERT_X(operation() == QNetworkAccessManager::PutOperation, "QNetworkAccessFileBackend", - "We're being told to upload data but operation isn't PUT!"); - - // there's more data to be written to the file - while (upstreamBytesAvailable()) { - // write everything and let QFile handle it - int written = file.write(readUpstream()); - - if (written < 0) { - // write error! - QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Write error writing to %1: %2") - .arg(url().toString(), file.errorString()); - error(QNetworkReply::ProtocolFailure, msg); - - finished(); - return; - } - - // successful write - file.flush(); - upstreamBytesConsumed(written); - } -} - void QNetworkAccessFileBackend::downstreamReadyWrite() { Q_ASSERT_X(operation() == QNetworkAccessManager::GetOperation, "QNetworkAccessFileBackend", diff --git a/src/network/access/qnetworkaccessfilebackend_p.h b/src/network/access/qnetworkaccessfilebackend_p.h index ce7d351..4615c5f 100644 --- a/src/network/access/qnetworkaccessfilebackend_p.h +++ b/src/network/access/qnetworkaccessfilebackend_p.h @@ -62,22 +62,25 @@ QT_BEGIN_NAMESPACE class QNetworkAccessFileBackend: public QNetworkAccessBackend { + Q_OBJECT public: QNetworkAccessFileBackend(); virtual ~QNetworkAccessFileBackend(); virtual void open(); virtual void closeDownstreamChannel(); - virtual void closeUpstreamChannel(); virtual bool waitForDownstreamReadyRead(int msecs); - virtual bool waitForUpstreamBytesWritten(int msecs); - virtual void upstreamReadyRead(); virtual void downstreamReadyWrite(); +public slots: + void uploadReadyReadSlot(); +protected: + QNonContiguousByteDevice *uploadByteDevice; private: QFile file; qint64 totalBytes; + bool hasUploadFinished; bool loadFileInfo(); bool readMoreFromFile(); diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp index ea39dec..ad55b85 100644 --- a/src/network/access/qnetworkaccessftpbackend.cpp +++ b/src/network/access/qnetworkaccessftpbackend.cpp @@ -42,6 +42,7 @@ #include "qnetworkaccessftpbackend_p.h" #include "qnetworkaccessmanager_p.h" #include "QtNetwork/qauthenticator.h" +#include "private/qnoncontiguousbytedevice_p.h" #ifndef QT_NO_FTP @@ -81,41 +82,6 @@ QNetworkAccessFtpBackendFactory::create(QNetworkAccessManager::Operation op, return 0; } -class QNetworkAccessFtpIODevice: public QIODevice -{ - //Q_OBJECT -public: - QNetworkAccessFtpBackend *backend; - bool eof; - - inline QNetworkAccessFtpIODevice(QNetworkAccessFtpBackend *parent) - : QIODevice(parent), backend(parent), eof(false) - { open(ReadOnly); } - - bool isSequential() const { return true; } - bool atEnd() const { return backend->upstreamBytesAvailable() == 0; } - - qint64 bytesAvailable() const { return backend->upstreamBytesAvailable(); } - qint64 bytesToWrite() const { return backend->downstreamBytesToConsume(); } -protected: - qint64 readData(char *data, qint64 maxlen) - { - const QByteArray toSend = backend->readUpstream(); - maxlen = qMin<qint64>(maxlen, toSend.size()); - if (!maxlen) - return eof ? -1 : 0; - - backend->upstreamBytesConsumed(maxlen); - memcpy(data, toSend.constData(), maxlen); - return maxlen; - } - - qint64 writeData(const char *, qint64) - { return -1; } - - friend class QNetworkAccessFtpBackend; -}; - class QNetworkAccessFtpFtp: public QFtp, public QNetworkAccessCache::CacheableObject { // Q_OBJECT @@ -198,7 +164,11 @@ void QNetworkAccessFtpBackend::open() ftpConnectionReady(ftp); } - uploadDevice = new QNetworkAccessFtpIODevice(this); + // Put operation + if (operation() == QNetworkAccessManager::PutOperation) { + uploadDevice = QNonContiguousByteDeviceFactory::wrap(createUploadByteDevice()); + uploadDevice->setParent(this); + } } void QNetworkAccessFtpBackend::closeDownstreamChannel() @@ -212,16 +182,6 @@ void QNetworkAccessFtpBackend::closeDownstreamChannel() #endif } -void QNetworkAccessFtpBackend::closeUpstreamChannel() -{ - if (operation() == QNetworkAccessManager::PutOperation) { - Q_ASSERT(uploadDevice); - uploadDevice->eof = true; - if (!upstreamBytesAvailable()) - emit uploadDevice->readyRead(); - } -} - bool QNetworkAccessFtpBackend::waitForDownstreamReadyRead(int ms) { if (!ftp) @@ -239,18 +199,6 @@ bool QNetworkAccessFtpBackend::waitForDownstreamReadyRead(int ms) return false; } -bool QNetworkAccessFtpBackend::waitForUpstreamBytesWritten(int ms) -{ - Q_UNUSED(ms); - qCritical("QNetworkAccess: FTP backend does not support waitForBytesWritten()"); - return false; -} - -void QNetworkAccessFtpBackend::upstreamReadyRead() -{ - // uh... how does QFtp operate? -} - void QNetworkAccessFtpBackend::downstreamReadyWrite() { if (state == Transferring && ftp && ftp->bytesAvailable()) diff --git a/src/network/access/qnetworkaccessftpbackend_p.h b/src/network/access/qnetworkaccessftpbackend_p.h index 9ec2dd8..1bb7ff2 100644 --- a/src/network/access/qnetworkaccessftpbackend_p.h +++ b/src/network/access/qnetworkaccessftpbackend_p.h @@ -87,11 +87,8 @@ public: virtual void open(); virtual void closeDownstreamChannel(); - virtual void closeUpstreamChannel(); virtual bool waitForDownstreamReadyRead(int msecs); - virtual bool waitForUpstreamBytesWritten(int msecs); - virtual void upstreamReadyRead(); virtual void downstreamReadyWrite(); void disconnectFromFtp(); @@ -105,7 +102,7 @@ public slots: private: friend class QNetworkAccessFtpIODevice; QPointer<QNetworkAccessFtpFtp> ftp; - QNetworkAccessFtpIODevice *uploadDevice; + QIODevice *uploadDevice; qint64 totalBytes; int helpId, sizeId, mdtmId; bool supportsSize, supportsMdtm; diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index a52b5a0..7d0438e 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -286,37 +286,6 @@ public: } }; -class QNetworkAccessHttpBackendIODevice: public QIODevice -{ - // Q_OBJECT -public: - bool eof; - QNetworkAccessHttpBackendIODevice(QNetworkAccessHttpBackend *parent) - : QIODevice(parent), eof(false) - { - setOpenMode(ReadOnly); - } - bool isSequential() const { return true; } - qint64 bytesAvailable() const - { return static_cast<QNetworkAccessHttpBackend *>(parent())->upstreamBytesAvailable(); } - -protected: - virtual qint64 readData(char *buffer, qint64 maxlen) - { - qint64 ret = static_cast<QNetworkAccessHttpBackend *>(parent())->deviceReadData(buffer, maxlen); - if (!ret && eof) - return -1; - return ret; - } - - virtual qint64 writeData(const char *, qint64) - { - return -1; // cannot write - } - - friend class QNetworkAccessHttpBackend; -}; - QNetworkAccessHttpBackend::QNetworkAccessHttpBackend() : QNetworkAccessBackend(), httpReply(0), http(0), uploadDevice(0) #ifndef QT_NO_OPENSSL @@ -507,20 +476,19 @@ void QNetworkAccessHttpBackend::postRequest() case QNetworkAccessManager::PostOperation: invalidateCache(); httpRequest.setOperation(QHttpNetworkRequest::Post); - uploadDevice = new QNetworkAccessHttpBackendIODevice(this); + httpRequest.setUploadByteDevice(createUploadByteDevice()); break; case QNetworkAccessManager::PutOperation: invalidateCache(); httpRequest.setOperation(QHttpNetworkRequest::Put); - uploadDevice = new QNetworkAccessHttpBackendIODevice(this); + httpRequest.setUploadByteDevice(createUploadByteDevice()); break; default: break; // can't happen } - httpRequest.setData(uploadDevice); httpRequest.setUrl(url()); QList<QByteArray> headers = request().rawHeaderList(); @@ -528,7 +496,9 @@ void QNetworkAccessHttpBackend::postRequest() httpRequest.setHeaderField(header, request().rawHeader(header)); if (loadedFromCache) { - QNetworkAccessBackend::finished(); + // commented this out since it will be called later anyway + // by copyFinished() + //QNetworkAccessBackend::finished(); return; // no need to send the request! :) } @@ -624,14 +594,6 @@ void QNetworkAccessHttpBackend::closeDownstreamChannel() // this indicates that the user closed the stream while the reply isn't finished yet } -void QNetworkAccessHttpBackend::closeUpstreamChannel() -{ - // this indicates that the user finished uploading the data for POST - Q_ASSERT(uploadDevice); - uploadDevice->eof = true; - emit uploadDevice->readChannelFinished(); -} - bool QNetworkAccessHttpBackend::waitForDownstreamReadyRead(int msecs) { Q_ASSERT(http); @@ -651,38 +613,6 @@ bool QNetworkAccessHttpBackend::waitForDownstreamReadyRead(int msecs) return false; } -bool QNetworkAccessHttpBackend::waitForUpstreamBytesWritten(int msecs) -{ - - // ### FIXME: not implemented in QHttpNetworkAccess - Q_UNUSED(msecs); - qCritical("QNetworkAccess: HTTP backend does not support waitForBytesWritten()"); - return false; -} - -void QNetworkAccessHttpBackend::upstreamReadyRead() -{ - // There is more data available from the user to be uploaded - // QHttpNetworkAccess implements the upload rate control: - // we simply tell QHttpNetworkAccess that there is more data available - // it'll pull from us when it can (through uploadDevice) - - Q_ASSERT(uploadDevice); - emit uploadDevice->readyRead(); -} - -qint64 QNetworkAccessHttpBackend::deviceReadData(char *buffer, qint64 maxlen) -{ - QByteArray toBeUploaded = readUpstream(); - if (toBeUploaded.isEmpty()) - return 0; // nothing to be uploaded - - maxlen = qMin<qint64>(maxlen, toBeUploaded.length()); - - memcpy(buffer, toBeUploaded.constData(), maxlen); - upstreamBytesConsumed(maxlen); - return maxlen; -} void QNetworkAccessHttpBackend::downstreamReadyWrite() { @@ -904,7 +834,14 @@ bool QNetworkAccessHttpBackend::sendCacheContents(const QNetworkCacheMetaData &m checkForRedirect(status); - writeDownstreamData(contents); + emit metaDataChanged(); + + // invoke this asynchronously, else Arora/QtDemoBrowser don't like cached downloads + // see task 250221 / 251801 + qRegisterMetaType<QIODevice*>("QIODevice*"); + QMetaObject::invokeMethod(this, "writeDownstreamData", Qt::QueuedConnection, Q_ARG(QIODevice*, contents)); + + #if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) qDebug() << "Successfully sent cache:" << url() << contents->size() << "bytes"; #endif diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h index 02915e7..225f944 100644 --- a/src/network/access/qnetworkaccesshttpbackend_p.h +++ b/src/network/access/qnetworkaccesshttpbackend_p.h @@ -79,11 +79,8 @@ public: virtual void open(); virtual void closeDownstreamChannel(); - virtual void closeUpstreamChannel(); virtual bool waitForDownstreamReadyRead(int msecs); - virtual bool waitForUpstreamBytesWritten(int msecs); - virtual void upstreamReadyRead(); virtual void downstreamReadyWrite(); virtual void copyFinished(QIODevice *); #ifndef QT_NO_OPENSSL @@ -96,6 +93,9 @@ public: qint64 deviceReadData(char *buffer, qint64 maxlen); + // we return true since HTTP needs to send PUT/POST data again after having authenticated + bool needsResetableUploadData() {return true;}; + private slots: void replyReadyRead(); void replyFinished(); @@ -108,7 +108,8 @@ private: QHttpNetworkReply *httpReply; QPointer<QNetworkAccessHttpBackendCache> http; QByteArray cacheKey; - QNetworkAccessHttpBackendIODevice *uploadDevice; + QNetworkAccessBackendUploadIODevice *uploadDevice; + #ifndef QT_NO_OPENSSL QSslConfiguration *pendingSslConfiguration; bool pendingIgnoreSslErrors; @@ -122,8 +123,6 @@ private: void postRequest(); void readFromHttp(); void checkForRedirect(const int statusCode); - - friend class QNetworkAccessHttpBackendIODevice; }; class QNetworkAccessHttpBackendFactory : public QNetworkAccessBackendFactory diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index bcbeef1..bf06ede 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -686,7 +686,10 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera priv->urlForLastAuthentication = url; } - // third step: setup the reply + // third step: find a backend + priv->backend = d->findBackend(op, request); + + // fourth step: setup the reply priv->setup(op, request, outgoingData); if (request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt() != QNetworkRequest::AlwaysNetwork) @@ -695,9 +698,6 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera QList<QNetworkProxy> proxyList = d->queryProxy(QNetworkProxyQuery(request.url())); priv->proxyList = proxyList; #endif - - // fourth step: find a backend - priv->backend = d->findBackend(op, request); if (priv->backend) { priv->backend->setParent(reply); priv->backend->reply = priv; diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp index f4dad3c..0990b17 100644 --- a/src/network/access/qnetworkreply.cpp +++ b/src/network/access/qnetworkreply.cpp @@ -151,6 +151,10 @@ QNetworkReplyPrivate::QNetworkReplyPrivate() authentication to serve the content but the credentials provided were not accepted (if any) + \value ContentReSendError the request needed to be sent + again, but this failed for example because the upload data + could not be read a second time. + \value ProtocolUnknownError the Network Access API cannot honor the request because the protocol is not known diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h index 6f763b3..2f864fe 100644 --- a/src/network/access/qnetworkreply.h +++ b/src/network/access/qnetworkreply.h @@ -92,6 +92,7 @@ public: ContentOperationNotPermittedError, ContentNotFoundError, AuthenticationRequiredError, + ContentReSendError, UnknownContentError = 299, // protocol errors diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 79c3d1a..749a462 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -46,13 +46,15 @@ #include "QtCore/qcoreapplication.h" #include "QtCore/qdatetime.h" #include "QtNetwork/qsslconfiguration.h" +#include "qnetworkaccesshttpbackend_p.h" #include <QtCore/QCoreApplication> QT_BEGIN_NAMESPACE inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate() - : copyDevice(0), networkCache(0), + : backend(0), outgoingData(0), outgoingDataBuffer(0), + copyDevice(0), networkCache(0), cacheEnabled(false), cacheSaveDevice(0), bytesDownloaded(0), lastBytesDownloaded(-1), bytesUploaded(-1), state(Idle) @@ -61,8 +63,13 @@ inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate() void QNetworkReplyImplPrivate::_q_startOperation() { - // This function is called exactly once + // ensure this function is only being called once + if (state == Working) { + qDebug("QNetworkReplyImpl::_q_startOperation was called more than once"); + return; + } state = Working; + if (!backend) { error(QNetworkReplyImpl::ProtocolUnknownError, QCoreApplication::translate("QNetworkReply", "Protocol \"%1\" is unknown").arg(url.scheme())); // not really true!; @@ -74,57 +81,11 @@ void QNetworkReplyImplPrivate::_q_startOperation() if (state != Finished) { if (operation == QNetworkAccessManager::GetOperation) pendingNotifications.append(NotifyDownstreamReadyWrite); - if (outgoingData) { - _q_sourceReadyRead(); -#if 0 // ### FIXME - if (outgoingData->atEndOfStream() && writeBuffer.isEmpty()) - // empty upload - emit q->uploadProgress(0, 0); -#endif - } handleNotifications(); } } -void QNetworkReplyImplPrivate::_q_sourceReadyRead() -{ - // read data from the outgoingData QIODevice into our internal buffer - enum { DesiredBufferSize = 32 * 1024 }; - - if (writeBuffer.size() >= DesiredBufferSize) - return; // don't grow the buffer too much - - // read as many bytes are available or up until we fill up the buffer - // but always read at least one byte - qint64 bytesToRead = qBound<qint64>(1, outgoingData->bytesAvailable(), - DesiredBufferSize - writeBuffer.size()); - char *ptr = writeBuffer.reserve(bytesToRead); - qint64 bytesActuallyRead = outgoingData->read(ptr, bytesToRead); - if (bytesActuallyRead == -1) { - // EOF - writeBuffer.chop(bytesToRead); - backendNotify(NotifyCloseUpstreamChannel); - return; - } - - if (bytesActuallyRead < bytesToRead) - writeBuffer.chop(bytesToRead - bytesActuallyRead); - - // if we did read anything, let the backend know and handle it - if (bytesActuallyRead) - backendNotify(NotifyUpstreamReadyRead); - - // check for EOF again - if (!outgoingData->isSequential() && outgoingData->atEnd()) - backendNotify(NotifyCloseUpstreamChannel); -} - -void QNetworkReplyImplPrivate::_q_sourceReadChannelFinished() -{ - _q_sourceReadyRead(); -} - void QNetworkReplyImplPrivate::_q_copyReadyRead() { Q_Q(QNetworkReplyImpl); @@ -143,7 +104,7 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead() if (bytesActuallyRead == -1) { readBuffer.chop(bytesToRead); backendNotify(NotifyCopyFinished); - return; + break; } if (bytesActuallyRead != bytesToRead) @@ -151,6 +112,7 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead() if (!copyDevice->isSequential() && copyDevice->atEnd()) { backendNotify(NotifyCopyFinished); + bytesDownloaded += bytesActuallyRead; break; } @@ -174,6 +136,67 @@ void QNetworkReplyImplPrivate::_q_copyReadChannelFinished() _q_copyReadyRead(); } +void QNetworkReplyImplPrivate::_q_bufferOutgoingDataFinished() +{ + Q_Q(QNetworkReplyImpl); + + // make sure this is only called once, ever. + //_q_bufferOutgoingData may call it or the readChannelFinished emission + if (state != Buffering) + return; + + // disconnect signals + QObject::disconnect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData())); + QObject::disconnect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished())); + + // finally, start the request + QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); +} + +void QNetworkReplyImplPrivate::_q_bufferOutgoingData() +{ + Q_Q(QNetworkReplyImpl); + + if (!outgoingDataBuffer) { + // first call, create our buffer + outgoingDataBuffer = new QRingBuffer(); + + QObject::connect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData())); + QObject::connect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished())); + } + + qint64 bytesBuffered = 0; + qint64 bytesToBuffer = 0; + + // read data into our buffer + forever { + bytesToBuffer = outgoingData->bytesAvailable(); + // unknown? just try 2 kB, this also ensures we always try to read the EOF + if (bytesToBuffer <= 0) + bytesToBuffer = 2*1024; + + char *dst = outgoingDataBuffer->reserve(bytesToBuffer); + bytesBuffered = outgoingData->read(dst, bytesToBuffer); + + if (bytesBuffered == -1) { + // EOF has been reached. + outgoingDataBuffer->chop(bytesToBuffer); + + _q_bufferOutgoingDataFinished(); + break; + } else if (bytesBuffered == 0) { + // nothing read right now, just wait until we get called again + outgoingDataBuffer->chop(bytesToBuffer); + + break; + } else { + // don't break, try to read() again + outgoingDataBuffer->chop(bytesToBuffer - bytesBuffered); + } + } +} + + void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *data) { @@ -184,13 +207,42 @@ void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const url = request.url(); operation = op; - if (outgoingData) { - q->connect(outgoingData, SIGNAL(readyRead()), SLOT(_q_sourceReadyRead())); - q->connect(outgoingData, SIGNAL(readChannelFinished()), SLOT(_q_sourceReadChannelFinished())); + if (outgoingData && backend) { + // there is data to be uploaded, e.g. HTTP POST. + + if (!backend->needsResetableUploadData() || !outgoingData->isSequential()) { + // backend does not need upload buffering or + // fixed size non-sequential + // just start the operation + QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); + } else { + bool bufferingDisallowed = + req.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute, + false).toBool(); + + if (bufferingDisallowed) { + // if a valid content-length header for the request was supplied, we can disable buffering + // if not, we will buffer anyway + if (req.header(QNetworkRequest::ContentLengthHeader).isValid()) { + QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); + } else { + state = Buffering; + QMetaObject::invokeMethod(q, "_q_bufferOutgoingData", Qt::QueuedConnection); + } + } else { + // _q_startOperation will be called when the buffering has finished. + state = Buffering; + QMetaObject::invokeMethod(q, "_q_bufferOutgoingData", Qt::QueuedConnection); + } + } + } else { + // No outgoing data (e.g. HTTP GET request) + // or no backend + // if no backend, _q_startOperation will handle the error of this + QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); } q->QIODevice::open(QIODevice::ReadOnly); - QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); } void QNetworkReplyImplPrivate::setNetworkCache(QAbstractNetworkCache *nc) @@ -226,18 +278,10 @@ void QNetworkReplyImplPrivate::handleNotifications() backend->downstreamReadyWrite(); break; - case NotifyUpstreamReadyRead: - backend->upstreamReadyRead(); - break; - case NotifyCloseDownstreamChannel: backend->closeDownstreamChannel(); break; - case NotifyCloseUpstreamChannel: - backend->closeUpstreamChannel(); - break; - case NotifyCopyFinished: { QIODevice *dev = copyDevice; copyDevice = 0; @@ -299,29 +343,14 @@ void QNetworkReplyImplPrivate::completeCacheSave() cacheEnabled = false; } -void QNetworkReplyImplPrivate::consume(qint64 count) +void QNetworkReplyImplPrivate::emitUploadProgress(qint64 bytesSent, qint64 bytesTotal) { Q_Q(QNetworkReplyImpl); - if (count <= 0) { - qWarning("QNetworkConnection: backend signalled that it consumed %ld bytes", long(count)); - return; - } - - if (outgoingData) - // schedule another read from the source - QMetaObject::invokeMethod(q_func(), "_q_sourceReadyRead", Qt::QueuedConnection); - - writeBuffer.skip(count); - if (bytesUploaded == -1) - bytesUploaded = count; - else - bytesUploaded += count; - - QVariant totalSize = request.header(QNetworkRequest::ContentLengthHeader); - emit q->uploadProgress(bytesUploaded, - totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong()); + bytesUploaded = bytesSent; + emit q->uploadProgress(bytesSent, bytesTotal); } + qint64 QNetworkReplyImplPrivate::nextDownstreamBlockSize() const { enum { DesiredBufferSize = 32 * 1024 }; @@ -331,7 +360,9 @@ qint64 QNetworkReplyImplPrivate::nextDownstreamBlockSize() const return qMax<qint64>(0, readBufferMaxSize - readBuffer.size()); } -void QNetworkReplyImplPrivate::feed(const QByteArray &data) +// we received downstream data and send this to the cache +// and to our readBuffer (which in turn gets read by the user of QNetworkReply) +void QNetworkReplyImplPrivate::appendDownstreamData(const QByteArray &data) { Q_Q(QNetworkReplyImpl); if (!q->isOpen()) @@ -379,7 +410,8 @@ void QNetworkReplyImplPrivate::feed(const QByteArray &data) } } -void QNetworkReplyImplPrivate::feed(QIODevice *data) +// this is used when it was fetched from the cache, right? +void QNetworkReplyImplPrivate::appendDownstreamData(QIODevice *data) { Q_Q(QNetworkReplyImpl); Q_ASSERT(q->isOpen()); @@ -409,9 +441,11 @@ void QNetworkReplyImplPrivate::finished() pendingNotifications.clear(); QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader); - if (bytesDownloaded != lastBytesDownloaded || totalSize.isNull()) + if (totalSize.isNull() || totalSize == -1) { emit q->downloadProgress(bytesDownloaded, bytesDownloaded); - if (bytesUploaded == -1 && outgoingData) + } + + if (bytesUploaded == -1 && (outgoingData || outgoingDataBuffer)) emit q->uploadProgress(0, 0); completeCacheSave(); diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index ad06f78..8d3c90e 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -59,6 +59,7 @@ #include "qnetworkproxy.h" #include "QtCore/qmap.h" #include "QtCore/qqueue.h" +#include "QtCore/qbuffer.h" #include "private/qringbuffer_p.h" QT_BEGIN_NAMESPACE @@ -91,10 +92,10 @@ public: Q_DECLARE_PRIVATE(QNetworkReplyImpl) Q_PRIVATE_SLOT(d_func(), void _q_startOperation()) - Q_PRIVATE_SLOT(d_func(), void _q_sourceReadyRead()) - Q_PRIVATE_SLOT(d_func(), void _q_sourceReadChannelFinished()) Q_PRIVATE_SLOT(d_func(), void _q_copyReadyRead()) Q_PRIVATE_SLOT(d_func(), void _q_copyReadChannelFinished()) + Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingData()) + Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingDataFinished()) }; class QNetworkReplyImplPrivate: public QNetworkReplyPrivate @@ -102,15 +103,13 @@ class QNetworkReplyImplPrivate: public QNetworkReplyPrivate public: enum InternalNotifications { NotifyDownstreamReadyWrite, - NotifyUpstreamReadyRead, NotifyCloseDownstreamChannel, - NotifyCloseUpstreamChannel, NotifyCopyFinished }; enum State { Idle, - Opening, + Buffering, Working, Finished, Aborted @@ -125,6 +124,8 @@ public: void _q_sourceReadChannelFinished(); void _q_copyReadyRead(); void _q_copyReadChannelFinished(); + void _q_bufferOutgoingData(); + void _q_bufferOutgoingDataFinished(); void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData); @@ -138,9 +139,10 @@ public: void setCachingEnabled(bool enable); bool isCachingEnabled() const; void consume(qint64 count); + void emitUploadProgress(qint64 bytesSent, qint64 bytesTotal); qint64 nextDownstreamBlockSize() const; - void feed(const QByteArray &data); - void feed(QIODevice *data); + void appendDownstreamData(const QByteArray &data); + void appendDownstreamData(QIODevice *data); void finished(); void error(QNetworkReply::NetworkError code, const QString &errorString); void metaDataChanged(); @@ -149,6 +151,7 @@ public: QNetworkAccessBackend *backend; QIODevice *outgoingData; + QRingBuffer *outgoingDataBuffer; QIODevice *copyDevice; QAbstractNetworkCache *networkCache; diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index 56b793d..8b1afba 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -162,6 +162,13 @@ QT_BEGIN_NAMESPACE Indicates whether the data was obtained from cache or not. + \value DoNotBufferUploadDataAttribute + Requests only, type: QVariant::Bool (default: false) + Indicates whether the QNetworkAccessManager code is + allowed to buffer the upload data, e.g. when doing a HTTP POST. + When using this flag with sequential upload data, the ContentLengthHeader + header must be set. + \value User Special type. Additional information can be passed in QVariants with types ranging from User to UserMax. The default diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h index 6f34bce..5dea1df 100644 --- a/src/network/access/qnetworkrequest.h +++ b/src/network/access/qnetworkrequest.h @@ -75,6 +75,7 @@ public: CacheLoadControlAttribute, CacheSaveControlAttribute, SourceIsFromCacheAttribute, + DoNotBufferUploadDataAttribute, User = 1000, UserMax = 32767 diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 39ac5da..92054a4 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -113,8 +113,8 @@ readLine(), or getChar() to read decrypted data from QSslSocket's internal buffer, and you can call write() or putChar() to write data back to the peer. QSslSocket will automatically encrypt the - written data for you, and emit bytesWritten() once the data has - been written to the peer. + written data for you, and emit encryptedBytesWritten() once + the data has been written to the peer. As a convenience, QSslSocket supports QTcpSocket's blocking functions waitForConnected(), waitForReadyRead(), diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 827f461..49798e0 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -523,7 +523,7 @@ void QSslSocketBackendPrivate::startClientEncryption() // Start connecting. This will place outgoing data in the BIO, so we // follow up with calling transmit(). - testConnection(); + startHandshake(); transmit(); } @@ -536,7 +536,7 @@ void QSslSocketBackendPrivate::startServerEncryption() // Start connecting. This will place outgoing data in the BIO, so we // follow up with calling transmit(). - testConnection(); + startHandshake(); transmit(); } @@ -624,7 +624,7 @@ void QSslSocketBackendPrivate::transmit() #ifdef QSSLSOCKET_DEBUG qDebug() << "QSslSocketBackendPrivate::transmit: testing encryption"; #endif - if (testConnection()) { + if (startHandshake()) { #ifdef QSSLSOCKET_DEBUG qDebug() << "QSslSocketBackendPrivate::transmit: encryption established"; #endif @@ -643,7 +643,7 @@ void QSslSocketBackendPrivate::transmit() } // If the request is small and the remote host closes the transmission - // after sending, there's a chance that testConnection() will already + // after sending, there's a chance that startHandshake() will already // have triggered a shutdown. if (!ssl) continue; @@ -743,7 +743,7 @@ static QSslError _q_OpenSSL_to_QSslError(int errorCode, const QSslCertificate &c return error; } -bool QSslSocketBackendPrivate::testConnection() +bool QSslSocketBackendPrivate::startHandshake() { Q_Q(QSslSocket); @@ -784,7 +784,7 @@ bool QSslSocketBackendPrivate::testConnection() q->setErrorString(QSslSocket::tr("Error during SSL handshake: %1").arg(SSL_ERRORSTR())); q->setSocketError(QAbstractSocket::SslHandshakeFailedError); #ifdef QSSLSOCKET_DEBUG - qDebug() << "QSslSocketBackendPrivate::testConnection: error!" << q->errorString(); + qDebug() << "QSslSocketBackendPrivate::startHandshake: error!" << q->errorString(); #endif emit q->error(QAbstractSocket::SslHandshakeFailedError); q->abort(); diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h index b3be42a..f53d4e8 100644 --- a/src/network/ssl/qsslsocket_openssl_p.h +++ b/src/network/ssl/qsslsocket_openssl_p.h @@ -102,7 +102,7 @@ public: void startClientEncryption(); void startServerEncryption(); void transmit(); - bool testConnection(); + bool startHandshake(); void disconnectFromHost(); void disconnected(); QSslCipher sessionCipher() const; diff --git a/src/plugins/accessible/widgets/simplewidgets.h b/src/plugins/accessible/widgets/simplewidgets.h index d4552e3..d1fd0da 100644 --- a/src/plugins/accessible/widgets/simplewidgets.h +++ b/src/plugins/accessible/widgets/simplewidgets.h @@ -115,6 +115,7 @@ public: class QAccessibleLineEdit : public QAccessibleWidgetEx, public QAccessibleTextInterface, public QAccessibleSimpleEditableTextInterface { + Q_ACCESSIBLE_OBJECT public: explicit QAccessibleLineEdit(QWidget *o, const QString &name = QString()); diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index 91a60e7..989a37a 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -275,7 +275,6 @@ private: int lastLockedHeight; IDirectFB *fb; - DFBSurfaceDescription fbDescription; int fbWidth; int fbHeight; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index 7297a99..c9b676a 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -271,7 +271,7 @@ void QDirectFBPixmapData::fill(const QColor &color) forceRaster = false; setSerialNumber(++global_ser_no); if (!dfbSurface) { - qWarning("QDirecttFBPixmapData::fill()"); + qWarning("QDirectFBPixmapData::fill()"); invalidate(); return; } diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index f571d1b..98e32ed 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -205,6 +205,7 @@ IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QSize &size, SurfaceCreationOptions options) { DFBSurfaceDescription desc; + memset(&desc, 0, sizeof(DFBSurfaceDescription)); desc.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH|DSDESC_HEIGHT); if (!QDirectFBScreen::initSurfaceDescriptionPixelFormat(&desc, format)) return 0; @@ -213,7 +214,6 @@ IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QSize &size, return createDFBSurface(desc, options); } - IDirectFBSurface *QDirectFBScreen::createDFBSurface(DFBSurfaceDescription desc, SurfaceCreationOptions options) { DFBResult result = DFB_OK; @@ -247,6 +247,7 @@ IDirectFBSurface *QDirectFBScreen::createDFBSurface(DFBSurfaceDescription desc, } desc.caps = DFBSurfaceCapabilities(desc.caps & ~DSCAPS_VIDEOONLY); } + if (d_ptr->directFBFlags & SystemOnly) desc.caps = DFBSurfaceCapabilities(desc.caps | DSCAPS_SYSTEMONLY); @@ -293,14 +294,14 @@ IDirectFBSurface *QDirectFBScreen::copyToDFBSurface(const QImage &img, IDirectFBSurface *dfbSurface = createDFBSurface(image.size(), pixmapFormat, options); if (!dfbSurface) { - qWarning("QDirectFBPixmapData::fromImage() Couldn't create surface"); + qWarning("QDirectFBScreen::copyToDFBSurface() Couldn't create surface"); return 0; } #ifndef QT_NO_DIRECTFB_PREALLOCATED IDirectFBSurface *imgSurface = createDFBSurface(image, DontTrackSurface); if (!imgSurface) { - qWarning("QDirectFBPixmapData::fromImage()"); + qWarning("QDirectFBScreen::copyToDFBSurface()"); QDirectFBScreen::releaseDFBSurface(dfbSurface); return 0; } @@ -315,7 +316,7 @@ IDirectFBSurface *QDirectFBScreen::copyToDFBSurface(const QImage &img, dfbSurface->SetBlittingFlags(dfbSurface, flags); DFBResult result = dfbSurface->Blit(dfbSurface, imgSurface, 0, 0, 0); if (result != DFB_OK) - DirectFBError("QDirectFBPixmapData::fromImage()", result); + DirectFBError("QDirectFBScreen::copyToDFBSurface()", result); dfbSurface->ReleaseSource(dfbSurface); imgSurface->Release(imgSurface); #else // QT_NO_DIRECTFB_PREALLOCATED @@ -445,6 +446,7 @@ QImage::Format QDirectFBScreen::getImageFormat(IDirectFBSurface *surface) DFBSurfaceDescription QDirectFBScreen::getSurfaceDescription(const QImage &image) { DFBSurfaceDescription description; + memset(&description, 0, sizeof(DFBSurfaceDescription)); const DFBSurfacePixelFormat format = getSurfacePixelFormat(image.format()); @@ -479,6 +481,7 @@ DFBSurfaceDescription QDirectFBScreen::getSurfaceDescription(const uint *buffer, int length) { DFBSurfaceDescription description; + memset(&description, 0, sizeof(DFBSurfaceDescription)); description.flags = DFBSurfaceDescriptionFlags(DSDESC_CAPS | DSDESC_WIDTH @@ -917,6 +920,8 @@ bool QDirectFBScreen::connect(const QString &displaySpec) d_ptr->dfb->SetCooperativeLevel(d_ptr->dfb, DFSCL_FULLSCREEN); DFBSurfaceDescription description; + memset(&description, 0, sizeof(DFBSurfaceDescription)); + description.flags = DFBSurfaceDescriptionFlags(DSDESC_CAPS); if (::setIntOption(displayArgs, QLatin1String("width"), &description.width)) description.flags = DFBSurfaceDescriptionFlags(description.flags | DSDESC_WIDTH); diff --git a/src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp b/src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp index c7249d3..3273513 100644 --- a/src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp +++ b/src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp @@ -122,16 +122,10 @@ QSize QSvgIconEngine::actualSize(const QSize &size, QIcon::Mode mode, return size; } - QSvgRenderer renderer; - d->loadDataForModeAndState(&renderer, mode, state); - if (renderer.isValid()) { - QSize defaultSize = renderer.defaultSize(); - if (!defaultSize.isNull()) - defaultSize.scale(size, Qt::KeepAspectRatio); - return defaultSize; - } else { + QPixmap pm = pixmap(size, mode, state); + if (pm.isNull()) return QSize(); - } + return pm.size(); } void QSvgIconEnginePrivate::loadDataForModeAndState(QSvgRenderer *renderer, QIcon::Mode mode, QIcon::State state) diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp index 1f54db7..fbefa0c 100644 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ b/src/sql/drivers/mysql/qsql_mysql.cpp @@ -163,18 +163,21 @@ static inline QVariant qDateTimeFromString(QString &val) #endif } -class QMYSQLResultPrivate +class QMYSQLResultPrivate : public QObject { + Q_OBJECT public: - QMYSQLResultPrivate(QMYSQLDriverPrivate* dp) : d(dp), result(0), + QMYSQLResultPrivate(const QMYSQLDriver* dp) : driver(dp), result(0), rowsAffected(0), hasBlobs(false) #if MYSQL_VERSION_ID >= 40108 , stmt(0), meta(0), inBinds(0), outBinds(0) #endif , precisionPolicy(QSql::HighPrecision) - {} + { + connect(dp, SIGNAL(destroyed()), this, SLOT(driverDestroyed())); + } - QMYSQLDriverPrivate* d; + const QMYSQLDriver* driver; MYSQL_RES *result; MYSQL_ROW row; @@ -207,6 +210,8 @@ public: MYSQL_BIND *outBinds; #endif QSql::NumericalPrecisionPolicy precisionPolicy; +private Q_SLOTS: + void driverDestroyed() { driver = NULL; } }; #ifndef QT_NO_TEXTCODEC @@ -379,7 +384,7 @@ bool QMYSQLResultPrivate::bindInValues() QMYSQLResult::QMYSQLResult(const QMYSQLDriver* db) : QSqlResult(db) { - d = new QMYSQLResultPrivate(db->d); + d = new QMYSQLResultPrivate(db); } QMYSQLResult::~QMYSQLResult() @@ -391,7 +396,7 @@ QMYSQLResult::~QMYSQLResult() QVariant QMYSQLResult::handle() const { #if MYSQL_VERSION_ID >= 40108 - if(d->d->preparedQuerys) + if(d->driver && d->driver->d->preparedQuerys) return d->meta ? qVariantFromValue(d->meta) : qVariantFromValue(d->stmt); else #endif @@ -406,8 +411,8 @@ void QMYSQLResult::cleanup() // must iterate trough leftover result sets from multi-selects or stored procedures // if this isn't done subsequent queries will fail with "Commands out of sync" #if MYSQL_VERSION_ID >= 40100 - while (d->d->mysql && mysql_next_result(d->d->mysql) == 0) { - MYSQL_RES *res = mysql_store_result(d->d->mysql); + while (d->driver && d->driver->d->mysql && mysql_next_result(d->driver->d->mysql) == 0) { + MYSQL_RES *res = mysql_store_result(d->driver->d->mysql); if (res) mysql_free_result(res); } @@ -447,11 +452,14 @@ void QMYSQLResult::cleanup() setAt(-1); setActive(false); - d->d->preparedQuerys = d->d->preparedQuerysEnabled; + if(d->driver) + d->driver->d->preparedQuerys = d->driver->d->preparedQuerysEnabled; } bool QMYSQLResult::fetch(int i) { + if(!d->driver) + return false; if (isForwardOnly()) { // fake a forward seek if (at() < i) { int x = i - at(); @@ -463,7 +471,7 @@ bool QMYSQLResult::fetch(int i) } if (at() == i) return true; - if (d->d->preparedQuerys) { + if (d->driver->d->preparedQuerys) { #if MYSQL_VERSION_ID >= 40108 mysql_stmt_data_seek(d->stmt, i); @@ -494,7 +502,9 @@ bool QMYSQLResult::fetch(int i) bool QMYSQLResult::fetchNext() { - if (d->d->preparedQuerys) { + if(!d->driver) + return false; + if (d->driver->d->preparedQuerys) { #if MYSQL_VERSION_ID >= 40108 if (mysql_stmt_fetch(d->stmt)) return false; @@ -512,6 +522,8 @@ bool QMYSQLResult::fetchNext() bool QMYSQLResult::fetchLast() { + if(!d->driver) + return false; if (isForwardOnly()) { // fake this since MySQL can't seek on forward only queries bool success = fetchNext(); // did we move at all? while (fetchNext()) {}; @@ -519,7 +531,7 @@ bool QMYSQLResult::fetchLast() } my_ulonglong numRows; - if (d->d->preparedQuerys) { + if (d->driver->d->preparedQuerys) { #if MYSQL_VERSION_ID >= 40108 numRows = mysql_stmt_num_rows(d->stmt); #else @@ -553,15 +565,18 @@ QVariant QMYSQLResult::data(int field) return QVariant(); } + if (!d->driver) + return QVariant(); + int fieldLength = 0; const QMYSQLResultPrivate::QMyField &f = d->fields.at(field); QString val; - if (d->d->preparedQuerys) { + if (d->driver->d->preparedQuerys) { if (f.nullIndicator) return QVariant(f.type); if (f.type != QVariant::ByteArray) - val = toUnicode(d->d->tc, f.outField, f.bufLength); + val = toUnicode(d->driver->d->tc, f.outField, f.bufLength); } else { if (d->row[field] == NULL) { // NULL value @@ -569,7 +584,7 @@ QVariant QMYSQLResult::data(int field) } fieldLength = mysql_fetch_lengths(d->result)[field]; if (f.type != QVariant::ByteArray) - val = toUnicode(d->d->tc, d->row[field], fieldLength); + val = toUnicode(d->driver->d->tc, d->row[field], fieldLength); } switch(f.type) { @@ -614,7 +629,7 @@ QVariant QMYSQLResult::data(int field) case QVariant::ByteArray: { QByteArray ba; - if (d->d->preparedQuerys) { + if (d->driver->d->preparedQuerys) { ba = QByteArray(f.outField, f.bufLength); } else { ba = QByteArray(d->row[field], fieldLength); @@ -631,7 +646,7 @@ QVariant QMYSQLResult::data(int field) bool QMYSQLResult::isNull(int field) { - if (d->d->preparedQuerys) + if (d->driver->d->preparedQuerys) return d->fields.at(field).nullIndicator; else return d->row[field] == NULL; @@ -639,31 +654,31 @@ bool QMYSQLResult::isNull(int field) bool QMYSQLResult::reset (const QString& query) { - if (!driver() || !driver()->isOpen() || driver()->isOpenError()) + if (!driver() || !driver()->isOpen() || driver()->isOpenError() || !d->driver) return false; - if(d->d->preparedQuerysEnabled && prepare(query)) { - d->d->preparedQuerys = true; + if(d->driver->d->preparedQuerysEnabled && prepare(query)) { + d->driver->d->preparedQuerys = true; return exec(); } - d->d->preparedQuerys = false; + d->driver->d->preparedQuerys = false; - const QByteArray encQuery(fromUnicode(d->d->tc, query)); - if (mysql_real_query(d->d->mysql, encQuery.data(), encQuery.length())) { + const QByteArray encQuery(fromUnicode(d->driver->d->tc, query)); + if (mysql_real_query(d->driver->d->mysql, encQuery.data(), encQuery.length())) { setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to execute query"), - QSqlError::StatementError, d->d)); + QSqlError::StatementError, d->driver->d)); return false; } - d->result = mysql_store_result(d->d->mysql); - if (!d->result && mysql_field_count(d->d->mysql) > 0) { + d->result = mysql_store_result(d->driver->d->mysql); + if (!d->result && mysql_field_count(d->driver->d->mysql) > 0) { setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to store result"), - QSqlError::StatementError, d->d)); + QSqlError::StatementError, d->driver->d)); return false; } - int numFields = mysql_field_count(d->d->mysql); + int numFields = mysql_field_count(d->driver->d->mysql); setSelect(numFields != 0); d->fields.resize(numFields); - d->rowsAffected = mysql_affected_rows(d->d->mysql); + d->rowsAffected = mysql_affected_rows(d->driver->d->mysql); if (isSelect()) { for(int i = 0; i < numFields; i++) { MYSQL_FIELD* field = mysql_fetch_field_direct(d->result, i); @@ -677,8 +692,8 @@ bool QMYSQLResult::reset (const QString& query) int QMYSQLResult::size() { - if (isSelect()) - if (d->d->preparedQuerys) + if (d->driver && isSelect()) + if (d->driver->d->preparedQuerys) #if MYSQL_VERSION_ID >= 40108 return mysql_stmt_num_rows(d->stmt); #else @@ -697,17 +712,17 @@ int QMYSQLResult::numRowsAffected() QVariant QMYSQLResult::lastInsertId() const { - if (!isActive()) + if (!isActive() || !d->driver) return QVariant(); - if (d->d->preparedQuerys) { + if (d->driver->d->preparedQuerys) { #if MYSQL_VERSION_ID >= 40108 quint64 id = mysql_stmt_insert_id(d->stmt); if (id) return QVariant(id); #endif } else { - quint64 id = mysql_insert_id(d->d->mysql); + quint64 id = mysql_insert_id(d->driver->d->mysql); if (id) return QVariant(id); } @@ -718,20 +733,20 @@ QSqlRecord QMYSQLResult::record() const { QSqlRecord info; MYSQL_RES *res; - if (!isActive() || !isSelect()) + if (!isActive() || !isSelect() || !d->driver) return info; #if MYSQL_VERSION_ID >= 40108 - res = d->d->preparedQuerys ? d->meta : d->result; + res = d->driver->d->preparedQuerys ? d->meta : d->result; #else res = d->result; #endif - if (!mysql_errno(d->d->mysql)) { + if (!mysql_errno(d->driver->d->mysql)) { mysql_field_seek(res, 0); MYSQL_FIELD* field = mysql_fetch_field(res); while(field) { - info.append(qToField(field, d->d->tc)); + info.append(qToField(field, d->driver->d->tc)); field = mysql_fetch_field(res); } } @@ -741,6 +756,8 @@ QSqlRecord QMYSQLResult::record() const bool QMYSQLResult::nextResult() { + if(!d->driver) + return false; #if MYSQL_VERSION_ID >= 40100 setAt(-1); setActive(false); @@ -754,26 +771,26 @@ bool QMYSQLResult::nextResult() delete[] d->fields[i].outField; d->fields.clear(); - int status = mysql_next_result(d->d->mysql); + int status = mysql_next_result(d->driver->d->mysql); if (status > 0) { setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to execute next query"), - QSqlError::StatementError, d->d)); + QSqlError::StatementError, d->driver->d)); return false; } else if (status == -1) { return false; // No more result sets } - d->result = mysql_store_result(d->d->mysql); - int numFields = mysql_field_count(d->d->mysql); + d->result = mysql_store_result(d->driver->d->mysql); + int numFields = mysql_field_count(d->driver->d->mysql); if (!d->result && numFields > 0) { setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to store next result"), - QSqlError::StatementError, d->d)); + QSqlError::StatementError, d->driver->d)); return false; } setSelect(numFields > 0); d->fields.resize(numFields); - d->rowsAffected = mysql_affected_rows(d->d->mysql); + d->rowsAffected = mysql_affected_rows(d->driver->d->mysql); if (isSelect()) { for (int i = 0; i < numFields; i++) { @@ -833,9 +850,11 @@ static MYSQL_TIME *toMySqlDate(QDate date, QTime time, QVariant::Type type) bool QMYSQLResult::prepare(const QString& query) { + if(!d->driver) + return false; #if MYSQL_VERSION_ID >= 40108 cleanup(); - if (!d->d->preparedQuerys) + if (!d->driver->d->preparedQuerys) return QSqlResult::prepare(query); int r; @@ -844,14 +863,14 @@ bool QMYSQLResult::prepare(const QString& query) return false; if (!d->stmt) - d->stmt = mysql_stmt_init(d->d->mysql); + d->stmt = mysql_stmt_init(d->driver->d->mysql); if (!d->stmt) { setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to prepare statement"), - QSqlError::StatementError, d->d)); + QSqlError::StatementError, d->driver->d)); return false; } - const QByteArray encQuery(fromUnicode(d->d->tc, query)); + const QByteArray encQuery(fromUnicode(d->driver->d->tc, query)); r = mysql_stmt_prepare(d->stmt, encQuery.constData(), encQuery.length()); if (r != 0) { setLastError(qMakeStmtError(QCoreApplication::translate("QMYSQLResult", @@ -873,7 +892,9 @@ bool QMYSQLResult::prepare(const QString& query) bool QMYSQLResult::exec() { - if (!d->d->preparedQuerys) + if (!d->driver) + return false; + if (!d->driver->d->preparedQuerys) return QSqlResult::exec(); if (!d->stmt) return false; @@ -963,7 +984,7 @@ bool QMYSQLResult::exec() break; case QVariant::String: default: { - QByteArray ba = fromUnicode(d->d->tc, val.toString()); + QByteArray ba = fromUnicode(d->driver->d->tc, val.toString()); stringVector.append(ba); currBind->buffer_type = MYSQL_TYPE_STRING; currBind->buffer = const_cast<char *>(ba.constData()); @@ -1459,3 +1480,5 @@ bool QMYSQLDriver::isIdentifierEscapedImplementation(const QString &identifier, } QT_END_NAMESPACE + +#include "qsql_mysql.moc"
\ No newline at end of file diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp index 6232452..a270c0e 100644 --- a/src/sql/kernel/qsqldatabase.cpp +++ b/src/sql/kernel/qsqldatabase.cpp @@ -378,7 +378,7 @@ void QSqlDatabasePrivate::disable() the connection name argument, if you don't pass the connection name argument, the default connection is assumed. The following snippet shows how to create and open a default connection to a - MySQL database: + PostgreSQL database: \snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 0 diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 443ee7e..a3a6916 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -238,6 +238,7 @@ SUBDIRS += bic \ qregexpvalidator \ qregion \ qresourceengine \ + qringbuffer \ qscriptable \ qscriptclass \ qscriptcontext \ diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index bb61f90..920cba7 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -204,6 +204,7 @@ private slots: void task239729_noViewUpdate(); void task239047_fitInViewSmallViewport(); void task245469_itemsAtPointWithClip(); + void task253415_reconnectUpdateSceneOnSceneChanged(); }; void tst_QGraphicsView::initTestCase() @@ -3200,5 +3201,28 @@ void tst_QGraphicsView::mouseTracking2() QCOMPARE(spy.count(), 1); } +void tst_QGraphicsView::task253415_reconnectUpdateSceneOnSceneChanged() +{ + QGraphicsView view; + QGraphicsView dummyView; + view.setWindowFlags(view.windowFlags() | Qt::WindowStaysOnTopHint); + view.resize(200, 200); + + QGraphicsScene scene1; + QObject::connect(&scene1, SIGNAL(changed(QList<QRectF>)), &dummyView, SLOT(updateScene(QList<QRectF>))); + view.setScene(&scene1); + + QTest::qWait(125); + + QGraphicsScene scene2; + QObject::connect(&scene2, SIGNAL(changed(QList<QRectF>)), &dummyView, SLOT(updateScene(QList<QRectF>))); + view.setScene(&scene2); + + QTest::qWait(125); + + bool wasConnected2 = QObject::disconnect(&scene2, SIGNAL(changed(QList<QRectF>)), &view, 0); + QVERIFY(wasConnected2); +} + QTEST_MAIN(tst_QGraphicsView) #include "tst_qgraphicsview.moc" diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp index 56737c3..343aac6 100644 --- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp +++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp @@ -50,6 +50,7 @@ #include <qcleanlooksstyle.h> #include <qlineedit.h> #include <qboxlayout.h> +#include <qaction.h> #include "../../shared/util.h" @@ -155,6 +156,7 @@ private slots: // Task fixes void task236127_bspTreeIndexFails(); void task243004_setStyleCrash(); + void task250119_shortcutContext(); }; @@ -2212,6 +2214,89 @@ void tst_QGraphicsWidget::task243004_setStyleCrash() delete item2; } +class GraphicsWidget_task250119 : public QGraphicsWidget +{ +public: + GraphicsWidget_task250119() + : shortcutEvents(0) + { + setFocusPolicy(Qt::StrongFocus); + resize(100, 100); + } + + int shortcutEvents; + +private: + bool event(QEvent *event) + { + if (event->type() == QEvent::Shortcut) + shortcutEvents++; + return QGraphicsWidget::event(event); + } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) + { + if (hasFocus()) { + painter->setPen(QPen(Qt::black, 0, Qt::DashLine)); + painter->drawRect(rect()); + } + painter->setPen(QPen(Qt::black, 0, Qt::SolidLine)); + painter->fillRect(rect().adjusted(2, 2, -2, -2), Qt::yellow); + painter->drawRect(rect().adjusted(2, 2, -2, -2)); + } +}; + +void tst_QGraphicsWidget::task250119_shortcutContext() +{ + QGraphicsScene scene; + QGraphicsView view; + view.setScene(&scene); + view.show(); + QTest::qWait(100); + + + // *** Event: *** + + GraphicsWidget_task250119 w_event; + scene.addItem(&w_event); + + const int id = w_event.grabShortcut(Qt::Key_A, Qt::WidgetWithChildrenShortcut); + w_event.setShortcutEnabled(id, true); + + w_event.setFocus(); + QTest::keyPress(&view, Qt::Key_A); + QCOMPARE(w_event.shortcutEvents, 1); + + w_event.clearFocus(); + QTest::keyPress(&view, Qt::Key_A); + QCOMPARE(w_event.shortcutEvents, 1); + + scene.removeItem(&w_event); + + + // *** Signal: *** + + GraphicsWidget_task250119 w_signal; + scene.addItem(&w_signal); + + QAction action(0); + action.setShortcut(Qt::Key_B); + action.setShortcutContext(Qt::WidgetWithChildrenShortcut); + QSignalSpy spy(&action, SIGNAL(triggered())); + + w_signal.addAction(&action); + + w_signal.setFocus(); + QTest::keyPress(&view, Qt::Key_B); + QCOMPARE(spy.count(), 1); + + w_signal.clearFocus(); + QTest::keyPress(&view, Qt::Key_B); + QCOMPARE(spy.count(), 1); + + scene.removeItem(&w_signal); +} + QTEST_MAIN(tst_QGraphicsWidget) #include "tst_qgraphicswidget.moc" diff --git a/tests/auto/qlistview/tst_qlistview.cpp b/tests/auto/qlistview/tst_qlistview.cpp index 791a472..f70db14 100644 --- a/tests/auto/qlistview/tst_qlistview.cpp +++ b/tests/auto/qlistview/tst_qlistview.cpp @@ -106,6 +106,7 @@ private slots: void task228566_infiniteRelayout(); void task248430_crashWith0SizedItem(); void task250446_scrollChanged(); + void task196118_visualRegionForSelection(); void keyboardSearch(); }; @@ -1556,6 +1557,29 @@ void tst_QListView::task250446_scrollChanged() QCOMPARE(view.currentIndex(), index); } +void tst_QListView::task196118_visualRegionForSelection() +{ + class MyListView : public QListView + { + public: + QRegion visualRegionForSelection() const + { return QListView::visualRegionForSelection( selectionModel()->selection()); } + } view; + + QStandardItemModel model; + QStandardItem top1("top1"); + QStandardItem sub1("sub1"); + top1.appendRow(QList<QStandardItem*>() << &sub1); + model.appendColumn(QList<QStandardItem*>() << &top1); + view.setModel(&model); + view.setRootIndex(top1.index()); + + view.selectionModel()->select(top1.index(), QItemSelectionModel::Select); + + QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QVERIFY(view.visualRegionForSelection().isEmpty()); +} + void tst_QListView::keyboardSearch() { QStringList items; diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index 104b788..6c622f7 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -52,6 +52,7 @@ #include <QtNetwork/QTcpSocket> #include <QtNetwork/QLocalSocket> #include <QtNetwork/QLocalServer> +#include <QtNetwork/QHostInfo> #include <QtNetwork/QFtp> #include <QtNetwork/qauthenticator.h> #include <QtNetwork/qnetworkaccessmanager.h> @@ -91,6 +92,15 @@ class tst_QNetworkReply: public QObject { Q_OBJECT + struct ProxyData { + ProxyData(const QNetworkProxy &p, const QByteArray &t, bool auth) + : tag(t), proxy(p), requiresAuthentication(auth) + { } + QByteArray tag; + QNetworkProxy proxy; + bool requiresAuthentication; + }; + QEventLoop *loop; enum RunSimpleRequestReturn { Timeout = 0, Success, Failure }; int returnCode; @@ -99,6 +109,7 @@ class tst_QNetworkReply: public QObject QString wronlyFileName; #endif QString uniqueExtension; + QList<ProxyData> proxies; QNetworkAccessManager manager; MyCookieJar *cookieJar; #ifndef QT_NO_OPENSSL @@ -172,6 +183,8 @@ private Q_SLOTS: void ioGetFromHttpsWithIgnoreSslErrors(); void ioGetFromHttpsWithSslHandshakeError(); #endif + void ioGetFromHttpBrokenServer_data(); + void ioGetFromHttpBrokenServer(); void ioGetWithManyProxies_data(); void ioGetWithManyProxies(); @@ -190,11 +203,20 @@ private Q_SLOTS: void ioPutToHttpFromFile(); void ioPostToHttpFromFile_data(); void ioPostToHttpFromFile(); + void ioPostToHttpFromSocket_data(); + void ioPostToHttpFromSocket(); + void ioPostToHttpFromMiddleOfFileToEnd(); + void ioPostToHttpFromMiddleOfFileFiveBytes(); + void ioPostToHttpFromMiddleOfQBufferFiveBytes(); + void ioPostToHttpNoBufferFlag(); + void ioPostToHttpUploadProgress(); + void ioPostToHttpEmtpyUploadProgress(); void rateControl_data(); void rateControl(); void downloadPerformance(); void uploadPerformance(); + void httpUploadPerformance(); void performanceControlRate(); void downloadProgress_data(); @@ -364,6 +386,63 @@ public slots: } }; +class FixedSizeDataGenerator : public QIODevice +{ + Q_OBJECT + enum { Idle, Started, Stopped } state; +public: + FixedSizeDataGenerator(qint64 size) : state(Idle) + { open(ReadOnly | Unbuffered); + toBeGeneratedTotalCount = toBeGeneratedCount = size; + } + + virtual qint64 bytesAvailable() const + { + return state == Started ? toBeGeneratedCount + QIODevice::bytesAvailable() : 0; + } + + virtual bool isSequential() const{ + return false; + } + + virtual bool reset() const{ + return false; + } + + qint64 size() const { + return toBeGeneratedTotalCount; + } + +public slots: + void start() { state = Started; emit readyRead(); } + +protected: + virtual qint64 readData(char *data, qint64 maxlen) + { + memset(data, '@', maxlen); + + if (toBeGeneratedCount <= 0) { + return -1; + } + + qint64 n = qMin(maxlen, toBeGeneratedCount); + toBeGeneratedCount -= n; + + if (toBeGeneratedCount <= 0) { + // make sure this is a queued connection! + emit readChannelFinished(); + } + + return n; + } + virtual qint64 writeData(const char *, qint64) + { return -1; } + + qint64 toBeGeneratedCount; + qint64 toBeGeneratedTotalCount; +}; + + class DataGenerator: public QIODevice { Q_OBJECT @@ -384,6 +463,7 @@ protected: { if (state == Stopped) return -1; // EOF + // return as many bytes as are wanted memset(data, '@', maxlen); return maxlen; @@ -392,6 +472,8 @@ protected: { return -1; } }; + + class SocketPair: public QObject { Q_OBJECT @@ -629,7 +711,7 @@ protected: return; transferRate = totalBytes * 1000 / timer.elapsed(); - qDebug() << "receive rate:" << (transferRate / 1024) << "kB/s in" + qDebug() << "TimedSender::run" << "receive rate:" << (transferRate / 1024) << "kB/s in" << timer.elapsed() << "ms"; } @@ -643,12 +725,13 @@ protected: class ThreadedDataReader: public QThread { Q_OBJECT + // used to make the constructor only return after the tcp server started listening QSemaphore ready; QTcpSocket *client; int timeout; int port; public: - int transferRate; + qint64 transferRate; ThreadedDataReader() : port(-1), transferRate(-1) { @@ -676,12 +759,65 @@ protected: QTime timer; timer.start(); eventLoop.exec(); + qint64 elapsed = timer.elapsed(); - transferRate = reader.totalBytes * 1000 / timer.elapsed(); - qDebug() << "send rate:" << (transferRate / 1024) << "kB/s"; + transferRate = reader.totalBytes * 1000 / elapsed; + qDebug() << "ThreadedDataReader::run" << "send rate:" << (transferRate / 1024) << "kB/s in" << elapsed << "msec"; } }; +class ThreadedDataReaderHttpServer: public QThread +{ + Q_OBJECT + // used to make the constructor only return after the tcp server started listening + QSemaphore ready; + QTcpSocket *client; + int timeout; + int port; +public: + qint64 transferRate; + ThreadedDataReaderHttpServer() + : port(-1), transferRate(-1) + { + start(); + ready.acquire(); + } + + inline int serverPort() const { return port; } + +protected: + void run() + { + QTcpServer server; + server.listen(); + port = server.serverPort(); + ready.release(); + + server.waitForNewConnection(-1); + client = server.nextPendingConnection(); + client->write("HTTP/1.0 200 OK\r\n"); + client->write("Content-length: 0\r\n"); + client->write("\r\n"); + client->flush(); + + QCoreApplication::processEvents(); + + QEventLoop eventLoop; + DataReader reader(client, false); + QObject::connect(client, SIGNAL(disconnected()), &eventLoop, SLOT(quit())); + + QTime timer; + timer.start(); + eventLoop.exec(); + qint64 elapsed = timer.elapsed(); + + transferRate = reader.totalBytes * 1000 / elapsed; + qDebug() << "ThreadedDataReaderHttpServer::run" << "send rate:" << (transferRate / 1024) << "kB/s in" << elapsed << "msec"; + } +}; + + + tst_QNetworkReply::tst_QNetworkReply() { testFileName = QDir::currentPath() + "/testfile"; @@ -692,8 +828,28 @@ tst_QNetworkReply::tst_QNetworkReply() #endif cookieJar = new MyCookieJar; manager.setCookieJar(cookieJar); + + QHostInfo hostInfo = QHostInfo::fromName(QtNetworkSettings::serverName()); + + proxies << ProxyData(QNetworkProxy::NoProxy, "", false); + + if (hostInfo.error() == QHostInfo::NoError && !hostInfo.addresses().isEmpty()) { + QString proxyserver = hostInfo.addresses().first().toString(); + proxies << ProxyData(QNetworkProxy(QNetworkProxy::HttpProxy, proxyserver, 3128), "+proxy", false) + << ProxyData(QNetworkProxy(QNetworkProxy::HttpProxy, proxyserver, 3129), "+proxyauth", true) + // currently unsupported + // << ProxyData(QNetworkProxy(QNetworkProxy::HttpProxy, proxyserver, 3130), "+proxyauth-ntlm", true); + << ProxyData(QNetworkProxy(QNetworkProxy::Socks5Proxy, proxyserver, 1080), "+socks", false) + << ProxyData(QNetworkProxy(QNetworkProxy::Socks5Proxy, proxyserver, 1081), "+socksauth", true); + } else { + printf("==================================================================\n"); + printf("Proxy could not be looked up. No proxy will be used while testing!\n"); + printf("==================================================================\n"); + } } + + void tst_QNetworkReply::authenticationRequired(QNetworkReply*, QAuthenticator* auth) { auth->setUser("httptest"); @@ -1887,6 +2043,53 @@ void tst_QNetworkReply::ioGetFromHttpsWithSslHandshakeError() } #endif +void tst_QNetworkReply::ioGetFromHttpBrokenServer_data() +{ + QTest::addColumn<QByteArray>("dataToSend"); + QTest::addColumn<bool>("doDisconnect"); + + QTest::newRow("no-newline") << QByteArray("Hello World") << false; + QTest::newRow("just-newline") << QByteArray("\r\n") << false; + QTest::newRow("just-2newline") << QByteArray("\r\n\r\n") << false; + QTest::newRow("with-newlines") << QByteArray("Long first line\r\nLong second line") << false; + QTest::newRow("with-newlines2") << QByteArray("\r\nSecond line") << false; + QTest::newRow("with-newlines3") << QByteArray("ICY\r\nSecond line") << false; + QTest::newRow("invalid-version") << QByteArray("HTTP/123 200 \r\n") << false; + QTest::newRow("invalid-version2") << QByteArray("HTTP/a.\033 200 \r\n") << false; + QTest::newRow("invalid-reply-code") << QByteArray("HTTP/1.0 fuu \r\n") << false; + + QTest::newRow("empty+disconnect") << QByteArray() << true; + + QTest::newRow("no-newline+disconnect") << QByteArray("Hello World") << true; + QTest::newRow("just-newline+disconnect") << QByteArray("\r\n") << true; + QTest::newRow("just-2newline+disconnect") << QByteArray("\r\n\r\n") << true; + QTest::newRow("with-newlines+disconnect") << QByteArray("Long first line\r\nLong second line") << true; + QTest::newRow("with-newlines2+disconnect") << QByteArray("\r\nSecond line") << true; + QTest::newRow("with-newlines3+disconnect") << QByteArray("ICY\r\nSecond line") << true; + + QTest::newRow("invalid-version+disconnect") << QByteArray("HTTP/123 200 ") << true; + QTest::newRow("invalid-version2+disconnect") << QByteArray("HTTP/a.\033 200 ") << true; + QTest::newRow("invalid-reply-code+disconnect") << QByteArray("HTTP/1.0 fuu ") << true; +} + +void tst_QNetworkReply::ioGetFromHttpBrokenServer() +{ + QFETCH(QByteArray, dataToSend); + QFETCH(bool, doDisconnect); + MiniHttpServer server(dataToSend); + server.doClose = doDisconnect; + + QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort()))); + QNetworkReplyPtr reply = manager.get(request); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(reply->url(), request.url()); + QVERIFY(reply->error() != QNetworkReply::NoError); +} + void tst_QNetworkReply::ioGetWithManyProxies_data() { QTest::addColumn<QList<QNetworkProxy> >("proxyList"); @@ -2452,6 +2655,320 @@ void tst_QNetworkReply::ioPostToHttpFromFile() QCOMPARE(reply->readAll().trimmed(), md5sum(sourceFile.readAll()).toHex()); } +void tst_QNetworkReply::ioPostToHttpFromSocket_data() +{ + QTest::addColumn<QByteArray>("data"); + QTest::addColumn<QByteArray>("md5sum"); + QTest::addColumn<QUrl>("url"); + QTest::addColumn<QNetworkProxy>("proxy"); + QTest::addColumn<int>("authenticationRequiredCount"); + QTest::addColumn<int>("proxyAuthenticationRequiredCount"); + + for (int i = 0; i < proxies.count(); ++i) + for (int auth = 0; auth < 2; ++auth) { + QUrl url; + if (auth) + url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"; + else + url = "http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi"; + + QNetworkProxy proxy = proxies.at(i).proxy; + QByteArray testsuffix = QByteArray(auth ? "+auth" : "") + proxies.at(i).tag; + int proxyauthcount = proxies.at(i).requiresAuthentication; + + QByteArray data; + data = ""; + QTest::newRow("empty" + testsuffix) << data << md5sum(data) << url << proxy << auth << proxyauthcount; + + data = "This is a normal message."; + QTest::newRow("generic" + testsuffix) << data << md5sum(data) << url << proxy << auth << proxyauthcount; + + data = "This is a message to show that Qt rocks!\r\n\n"; + QTest::newRow("small" + testsuffix) << data << md5sum(data) << url << proxy << auth << proxyauthcount; + + data = QByteArray("abcd\0\1\2\abcd",12); + QTest::newRow("with-nul" + testsuffix) << data << md5sum(data) << url << proxy << auth << proxyauthcount; + + data = QByteArray(4097, '\4'); + QTest::newRow("4k+1" + testsuffix) << data << md5sum(data) << url << proxy << auth << proxyauthcount; + + data = QByteArray(128*1024+1, '\177'); + QTest::newRow("128k+1" + testsuffix) << data << md5sum(data) << url << proxy << auth << proxyauthcount; + } +} + +void tst_QNetworkReply::ioPostToHttpFromSocket() +{ + qRegisterMetaType<QNetworkProxy>(); // for QSignalSpy + qRegisterMetaType<QAuthenticator *>(); + qRegisterMetaType<QNetworkReply *>(); + + QFETCH(QByteArray, data); + QFETCH(QUrl, url); + QFETCH(QNetworkProxy, proxy); + SocketPair socketpair; + socketpair.create(); + QVERIFY(socketpair.endPoints[0] && socketpair.endPoints[1]); + + socketpair.endPoints[0]->write(data); + + QNetworkRequest request(url); + manager.setProxy(proxy); + QNetworkReplyPtr reply = manager.post(QNetworkRequest(url), socketpair.endPoints[1]); + socketpair.endPoints[0]->close(); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + connect(&manager, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), + SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*))); + connect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), + SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*))); + + QSignalSpy authenticationRequiredSpy(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*))); + QSignalSpy proxyAuthenticationRequiredSpy(&manager, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*))); + + QTestEventLoop::instance().enterLoop(1); + + disconnect(&manager, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), + this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*))); + disconnect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), + this, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*))); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(reply->url(), url); + QCOMPARE(reply->error(), QNetworkReply::NoError); + // verify that the HTTP status code is 200 Ok + QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); + + QCOMPARE(reply->readAll().trimmed(), md5sum(data).toHex()); + + QTEST(authenticationRequiredSpy.count(), "authenticationRequiredCount"); + QTEST(proxyAuthenticationRequiredSpy.count(), "proxyAuthenticationRequiredCount"); + } + +// this tests checks if rewinding the POST-data to some place in the middle +// worked. +void tst_QNetworkReply::ioPostToHttpFromMiddleOfFileToEnd() +{ + QFile sourceFile(SRCDIR "/rfc3252.txt"); + QVERIFY(sourceFile.open(QIODevice::ReadOnly)); + // seeking to the middle + sourceFile.seek(sourceFile.size() / 2); + + QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"; + QNetworkRequest request(url); + QNetworkReplyPtr reply = manager.post(QNetworkRequest(url), &sourceFile); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + connect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), + SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*))); + + QTestEventLoop::instance().enterLoop(2); + disconnect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), + this, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*))); + QVERIFY(!QTestEventLoop::instance().timeout()); + + // compare half data + sourceFile.seek(sourceFile.size() / 2); + QByteArray data = sourceFile.readAll(); + QCOMPARE(reply->readAll().trimmed(), md5sum(data).toHex()); +} + +void tst_QNetworkReply::ioPostToHttpFromMiddleOfFileFiveBytes() +{ + QFile sourceFile(SRCDIR "/rfc3252.txt"); + QVERIFY(sourceFile.open(QIODevice::ReadOnly)); + // seeking to the middle + sourceFile.seek(sourceFile.size() / 2); + + QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"; + QNetworkRequest request(url); + // only send 5 bytes + request.setHeader(QNetworkRequest::ContentLengthHeader, 5); + QVERIFY(request.header(QNetworkRequest::ContentLengthHeader).isValid()); + QNetworkReplyPtr reply = manager.post(request, &sourceFile); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + connect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), + SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*))); + + QTestEventLoop::instance().enterLoop(2); + disconnect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), + this, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*))); + QVERIFY(!QTestEventLoop::instance().timeout()); + + // compare half data + sourceFile.seek(sourceFile.size() / 2); + QByteArray data = sourceFile.read(5); + QCOMPARE(reply->readAll().trimmed(), md5sum(data).toHex()); +} + +void tst_QNetworkReply::ioPostToHttpFromMiddleOfQBufferFiveBytes() +{ + // test needed since a QBuffer goes with a different codepath than the QFile + // tested in ioPostToHttpFromMiddleOfFileFiveBytes + QBuffer uploadBuffer; + uploadBuffer.open(QIODevice::ReadWrite); + uploadBuffer.write("1234567890"); + uploadBuffer.seek(5); + + QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"; + QNetworkRequest request(url); + QNetworkReplyPtr reply = manager.post(request, &uploadBuffer); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + connect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), + SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*))); + + QTestEventLoop::instance().enterLoop(2); + disconnect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), + this, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*))); + QVERIFY(!QTestEventLoop::instance().timeout()); + + // compare half data + uploadBuffer.seek(5); + QByteArray data = uploadBuffer.read(5); + QCOMPARE(reply->readAll().trimmed(), md5sum(data).toHex()); +} + + +void tst_QNetworkReply::ioPostToHttpNoBufferFlag() +{ + QByteArray data = QByteArray("daaaaaaataaaaaaa"); + // create a sequential QIODevice by feeding the data into a local TCP server + SocketPair socketpair; + socketpair.create(); + QVERIFY(socketpair.endPoints[0] && socketpair.endPoints[1]); + socketpair.endPoints[0]->write(data); + + QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"; + QNetworkRequest request(url); + // disallow buffering + request.setAttribute(QNetworkRequest::DoNotBufferUploadDataAttribute, true); + request.setHeader(QNetworkRequest::ContentLengthHeader, data.size()); + QNetworkReplyPtr reply = manager.post(request, socketpair.endPoints[1]); + socketpair.endPoints[0]->close(); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + connect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), + SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*))); + + QTestEventLoop::instance().enterLoop(2); + disconnect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), + this, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*))); + + // verify: error code is QNetworkReply::ContentReSendError + QCOMPARE(reply->error(), QNetworkReply::ContentReSendError); +} + + +void tst_QNetworkReply::ioPostToHttpUploadProgress() +{ + QFile sourceFile(SRCDIR "/bigfile"); + QVERIFY(sourceFile.open(QIODevice::ReadOnly)); + + // emulate a minimal http server + QTcpServer server; + server.listen(QHostAddress(QHostAddress::LocalHost), 0); + + // create the request + QUrl url = QUrl(QString("http://127.0.0.1:%1/").arg(server.serverPort())); + QNetworkRequest request(url); + QNetworkReplyPtr reply = manager.post(request, &sourceFile); + QSignalSpy spy(reply, SIGNAL(uploadProgress(qint64,qint64))); + connect(&server, SIGNAL(newConnection()), &QTestEventLoop::instance(), SLOT(exitLoop())); + + // get the request started and the incoming socket connected + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + QTcpSocket *incomingSocket = server.nextPendingConnection(); + QVERIFY(incomingSocket); + disconnect(&server, SIGNAL(newConnection()), &QTestEventLoop::instance(), SLOT(exitLoop())); + + incomingSocket->setReadBufferSize(1*1024); + QTestEventLoop::instance().enterLoop(2); + // some progress should have been made + QList<QVariant> args = spy.last(); + QVERIFY(!args.isEmpty()); + QVERIFY(args.at(0).toLongLong() > 0); + + incomingSocket->setReadBufferSize(32*1024); + incomingSocket->read(16*1024); + QTestEventLoop::instance().enterLoop(2); + // some more progress than before + QList<QVariant> args2 = spy.last(); + QVERIFY(!args2.isEmpty()); + QVERIFY(args2.at(0).toLongLong() > args.at(0).toLongLong()); + + // set the read buffer to unlimited + incomingSocket->setReadBufferSize(0); + QTestEventLoop::instance().enterLoop(10); + // progress should be finished + QList<QVariant> args3 = spy.last(); + QVERIFY(!args3.isEmpty()); + QVERIFY(args3.at(0).toLongLong() > args2.at(0).toLongLong()); + QCOMPARE(args3.at(0).toLongLong(), args3.at(1).toLongLong()); + QCOMPARE(args3.at(0).toLongLong(), sourceFile.size()); + + // after sending this, the QNAM should emit finished() + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + incomingSocket->write("HTTP/1.0 200 OK\r\n"); + incomingSocket->write("Content-Length: 0\r\n"); + incomingSocket->write("\r\n"); + QTestEventLoop::instance().enterLoop(10); + // not timeouted -> finished() was emitted + QVERIFY(!QTestEventLoop::instance().timeout()); + + incomingSocket->close(); + server.close(); +} + +void tst_QNetworkReply::ioPostToHttpEmtpyUploadProgress() +{ + QByteArray ba; + ba.resize(0); + QBuffer buffer(&ba,0); + QVERIFY(buffer.open(QIODevice::ReadOnly)); + + // emulate a minimal http server + QTcpServer server; + server.listen(QHostAddress(QHostAddress::LocalHost), 0); + + // create the request + QUrl url = QUrl(QString("http://127.0.0.1:%1/").arg(server.serverPort())); + QNetworkRequest request(url); + QNetworkReplyPtr reply = manager.post(request, &buffer); + QSignalSpy spy(reply, SIGNAL(uploadProgress(qint64,qint64))); + connect(&server, SIGNAL(newConnection()), &QTestEventLoop::instance(), SLOT(exitLoop())); + + + // get the request started and the incoming socket connected + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + QTcpSocket *incomingSocket = server.nextPendingConnection(); + QVERIFY(incomingSocket); + + // after sending this, the QNAM should emit finished() + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + incomingSocket->write("HTTP/1.0 200 OK\r\n"); + incomingSocket->write("Content-Length: 0\r\n"); + incomingSocket->write("\r\n"); + incomingSocket->flush(); + QTestEventLoop::instance().enterLoop(10); + // not timeouted -> finished() was emitted + QVERIFY(!QTestEventLoop::instance().timeout()); + + // final check: only 1 uploadProgress has been emitted + QVERIFY(spy.length() == 1); + QList<QVariant> args = spy.last(); + QVERIFY(!args.isEmpty()); + QCOMPARE(args.at(0).toLongLong(), buffer.size()); + QCOMPARE(args.at(0).toLongLong(), buffer.size()); + + incomingSocket->close(); + server.close(); +} + + void tst_QNetworkReply::rateControl_data() { QTest::addColumn<int>("rate"); @@ -2488,8 +3005,8 @@ void tst_QNetworkReply::rateControl() QTestEventLoop::instance().enterLoop(40); int elapsedTime = loopTime.elapsed(); - qDebug() << "send rate:" << sender.transferRate; - qDebug() << "receive rate:" << reader.totalBytesRead * 1000 / elapsedTime + qDebug() << "tst_QNetworkReply::rateControl" << "send rate:" << sender.transferRate; + qDebug() << "tst_QNetworkReply::rateControl" << "receive rate:" << reader.totalBytesRead * 1000 / elapsedTime << "(it received" << reader.totalBytesRead << "bytes in" << elapsedTime << "ms)"; sender.wait(); @@ -2523,23 +3040,54 @@ void tst_QNetworkReply::downloadPerformance() sender.wait(); qint64 receivedBytes = reader.totalBytes; - qDebug() << "receive rate:" << (receivedBytes * 1000 / elapsedTime / 1024) << "kB/s and" + qDebug() << "tst_QNetworkReply::downloadPerformance" << "receive rate:" << (receivedBytes * 1000 / elapsedTime / 1024) << "kB/s and" << elapsedTime << "ms"; } void tst_QNetworkReply::uploadPerformance() { - ThreadedDataReader reader; - DataGenerator generator; - QNetworkRequest request("debugpipe://127.0.0.1:" + QString::number(reader.serverPort()) + "/?bare=1"); - QNetworkReplyPtr reply = manager.put(request, &generator); + ThreadedDataReader reader; + DataGenerator generator; - connect(&reader, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); - QTimer::singleShot(5000, &generator, SLOT(stop())); - generator.start(); - QTestEventLoop::instance().enterLoop(40); + + QNetworkRequest request("debugpipe://127.0.0.1:" + QString::number(reader.serverPort()) + "/?bare=1"); + QNetworkReplyPtr reply = manager.put(request, &generator); + generator.start(); + connect(&reader, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTimer::singleShot(5000, &generator, SLOT(stop())); + + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); +} + +void tst_QNetworkReply::httpUploadPerformance() +{ + enum {UploadSize = 1000*1024*1024}; // 1000 MB + ThreadedDataReaderHttpServer reader; + FixedSizeDataGenerator generator(UploadSize); + + QNetworkRequest request(QUrl("http://127.0.0.1:" + QString::number(reader.serverPort()) + "/?bare=1")); + request.setHeader(QNetworkRequest::ContentLengthHeader,UploadSize); + + QNetworkReplyPtr reply = manager.put(request, &generator); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + + QTime time; + generator.start(); + time.start(); + QTestEventLoop::instance().enterLoop(40); + QVERIFY(!QTestEventLoop::instance().timeout()); + + qint64 elapsed = time.elapsed(); + qWarning() << "tst_QNetworkReply::httpUploadPerformance" << elapsed << "msec, " + << ((UploadSize/1024.0)/(elapsed/1000.0)) << " kB/sec"; + + reader.exit(); + reader.wait(3000); } + void tst_QNetworkReply::performanceControlRate() { // this is a control comparison for the other two above @@ -2560,7 +3108,7 @@ void tst_QNetworkReply::performanceControlRate() sender.wait(); qint64 receivedBytes = reader.totalBytes; - qDebug() << "receive rate:" << (receivedBytes * 1000 / elapsedTime / 1024) << "kB/s and" + qDebug() << "tst_QNetworkReply::performanceControlRate" << "receive rate:" << (receivedBytes * 1000 / elapsedTime / 1024) << "kB/s and" << elapsedTime << "ms"; } @@ -2592,6 +3140,7 @@ void tst_QNetworkReply::downloadProgress() QByteArray data(128, 'a'); QTcpSocket *sender = server.nextPendingConnection(); + QVERIFY(sender); QFETCH(int, loopCount); for (int i = 1; i <= loopCount; ++i) { diff --git a/tests/auto/qringbuffer/qringbuffer.pro b/tests/auto/qringbuffer/qringbuffer.pro new file mode 100644 index 0000000..91fb0a0 --- /dev/null +++ b/tests/auto/qringbuffer/qringbuffer.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +SOURCES += tst_qringbuffer.cpp + +QT = core + + diff --git a/tests/auto/qringbuffer/tst_qringbuffer.cpp b/tests/auto/qringbuffer/tst_qringbuffer.cpp new file mode 100644 index 0000000..c741c2e --- /dev/null +++ b/tests/auto/qringbuffer/tst_qringbuffer.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> + +#include <private/qringbuffer_p.h> + +class tst_QRingBuffer : public QObject +{ + Q_OBJECT + +public: + tst_QRingBuffer(); + virtual ~tst_QRingBuffer(); +public slots: + void initTestCase(); + void cleanupTestCase(); +private slots: + void readPointerAtPositionWriteRead(); + void readPointerAtPositionEmptyRead(); + void readPointerAtPositionWithHead(); + void readPointerAtPositionReadTooMuch(); + void sizeWhenEmpty(); + void sizeWhenReservedAndChopped(); + void sizeWhenReserved(); +}; + +tst_QRingBuffer::tst_QRingBuffer() +{ +} + +tst_QRingBuffer::~tst_QRingBuffer() +{ +} + +void tst_QRingBuffer::initTestCase() +{ +} + +void tst_QRingBuffer::cleanupTestCase() +{ +} + +void tst_QRingBuffer::sizeWhenReserved() +{ + QRingBuffer ringBuffer; + ringBuffer.reserve(5); + + QCOMPARE(ringBuffer.size(), 5); +} + +void tst_QRingBuffer::sizeWhenReservedAndChopped() +{ + QRingBuffer ringBuffer; + ringBuffer.reserve(31337); + ringBuffer.chop(31337); + + QCOMPARE(ringBuffer.size(), 0); +} + +void tst_QRingBuffer::sizeWhenEmpty() +{ + QRingBuffer ringBuffer; + + QCOMPARE(ringBuffer.size(), 0); +} + +void tst_QRingBuffer::readPointerAtPositionReadTooMuch() +{ + QRingBuffer ringBuffer; + + qint64 length; + const char *buf = ringBuffer.readPointerAtPosition(42, length); + QVERIFY(buf == 0); + QVERIFY(length == 0); +} + +void tst_QRingBuffer::readPointerAtPositionWithHead() +{ + QRingBuffer ringBuffer; + char *buf = ringBuffer.reserve(4); + memcpy (buf, "0123", 4); + ringBuffer.free(2); + + // ringBuffer should have stayed the same except + // its head it had moved to position 2 + qint64 length; + const char* buf2 = ringBuffer.readPointerAtPosition(0, length); + + QCOMPARE(length, qint64(2)); + QVERIFY(*buf2 == '2'); + QVERIFY(*(buf2+1) == '3'); + + // advance 2 more, ringBuffer should be empty then + ringBuffer.free(2); + buf2 = ringBuffer.readPointerAtPosition(0, length); + QCOMPARE(length, qint64(0)); + QVERIFY(buf2 == 0); +} + +void tst_QRingBuffer::readPointerAtPositionEmptyRead() +{ + QRingBuffer ringBuffer; + + qint64 length; + const char *buf = ringBuffer.readPointerAtPosition(0, length); + QVERIFY(buf == 0); + QVERIFY(length == 0); +} + +void tst_QRingBuffer::readPointerAtPositionWriteRead() +{ + //create some data + QBuffer inData; + inData.open(QIODevice::ReadWrite); + inData.putChar(0x42); + inData.putChar(0x23); + inData.write("Qt rocks!"); + for (int i = 0; i < 5000; i++) + inData.write(QString("Number %1").arg(i).toUtf8()); + inData.reset(); + QVERIFY(inData.size() > 0); + + //put the inData in the QRingBuffer + QRingBuffer ringBuffer; + qint64 remaining = inData.size(); + while (remaining > 0) { + // write in chunks of 50 bytes + // this ensures there will be multiple QByteArrays inside the QRingBuffer + // since QRingBuffer is then only using individual arrays of around 4000 bytes + qint64 thisWrite = qMin(remaining, qint64(50)); + char *pos = ringBuffer.reserve(thisWrite); + inData.read(pos, thisWrite); + remaining -= thisWrite; + } + // was data put into it? + QVERIFY(ringBuffer.size() > 0); + QCOMPARE(qint64(ringBuffer.size()), inData.size()); + + //read from the QRingBuffer in loop, put back into another QBuffer + QBuffer outData; + outData.open(QIODevice::ReadWrite); + remaining = ringBuffer.size(); + while (remaining > 0) { + qint64 thisRead; + // always try to read as much as possible + const char *buf = ringBuffer.readPointerAtPosition(ringBuffer.size() - remaining, thisRead); + outData.write(buf, thisRead); + remaining -= thisRead; + } + outData.reset(); + + QVERIFY(outData.size() > 0); + + // was the data read from the QRingBuffer the same as the one written into it? + QCOMPARE(outData.size(), inData.size()); + QVERIFY(outData.buffer().startsWith(inData.buffer())); +} + + +QTEST_APPLESS_MAIN(tst_QRingBuffer) +#include "tst_qringbuffer.moc" diff --git a/tests/auto/qsqlquery/tst_qsqlquery.cpp b/tests/auto/qsqlquery/tst_qsqlquery.cpp index 074f16f..7f97972 100644 --- a/tests/auto/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/qsqlquery/tst_qsqlquery.cpp @@ -178,9 +178,11 @@ private slots: void task_217003_data() { generic_data(); } void task_217003(); #endif - void task_250026_data() { generic_data("QODBC"); } void task_250026(); + void task_205701_data() { generic_data("QMYSQL"); } + void task_205701(); + private: @@ -297,7 +299,7 @@ void tst_QSqlQuery::dropTestTables( QSqlDatabase db ) #ifdef NOT_READY_YET tablenames << qTableName( "Planet" ); #endif - tablenames << qTableName( "task_250026" ); + tablenames << qTableName( "task_250026" ); tst_Databases::safeDropTables( db, tablenames ); } @@ -2711,5 +2713,21 @@ void tst_QSqlQuery::task_250026() QCOMPARE( q.value( 0 ).toString().length(), data1026.length() ); } +void tst_QSqlQuery::task_205701() +{ + QSqlDatabase qsdb = QSqlDatabase::addDatabase("QMYSQL", "atest"); + qsdb.setHostName("test"); + qsdb.setDatabaseName("test"); + qsdb.setUserName("test"); + qsdb.setPassword("test"); + qsdb.open(); + +// { + QSqlQuery query(qsdb); +// } + QSqlDatabase::removeDatabase("atest"); +} + + QTEST_MAIN( tst_QSqlQuery ) #include "tst_qsqlquery.moc" diff --git a/tests/auto/qsslsocket/tst_qsslsocket.cpp b/tests/auto/qsslsocket/tst_qsslsocket.cpp index b9725fd..432092a 100644 --- a/tests/auto/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/qsslsocket/tst_qsslsocket.cpp @@ -1286,6 +1286,8 @@ protected: // delayed start of encryption QTest::qSleep(100); QSslSocket *socket = server.socket; + Q_ASSERT(socket); + Q_ASSERT(socket->isValid()); socket->ignoreSslErrors(); socket->startServerEncryption(); if (!socket->waitForEncrypted(2000)) diff --git a/tests/auto/qtreewidget/tst_qtreewidget.cpp b/tests/auto/qtreewidget/tst_qtreewidget.cpp index c3595c2..906332c 100644 --- a/tests/auto/qtreewidget/tst_qtreewidget.cpp +++ b/tests/auto/qtreewidget/tst_qtreewidget.cpp @@ -136,6 +136,7 @@ private slots: void rootItemFlags(); void task218661_setHeaderData(); void task245280_sortChildren(); + void task253109_itemHeight(); // QTreeWidgetItem void itemOperatorLessThan(); @@ -2879,6 +2880,25 @@ void tst_QTreeWidget::task245280_sortChildren() QCOMPARE(top.child(i)->text(1), QString::number(i)); } +void tst_QTreeWidget::task253109_itemHeight() +{ + QTreeWidget treeWidget; + treeWidget.setColumnCount(1); + treeWidget.show(); + QTest::qWait(200); + + QTreeWidgetItem item(&treeWidget); + class MyWidget : public QWidget + { + virtual QSize sizeHint() const { return QSize(200,100); } + } w; + treeWidget.setItemWidget(&item, 0, &w); + + QTest::qWait(200); + QCOMPARE(w.geometry(), treeWidget.visualItemRect(&item)); + +} + void tst_QTreeWidget::task206367_duplication() { QTreeWidget treeWidget; diff --git a/tools/assistant/tools/assistant/assistant.qch b/tools/assistant/tools/assistant/assistant.qch Binary files differindex 64763f7..99687ed 100644 --- a/tools/assistant/tools/assistant/assistant.qch +++ b/tools/assistant/tools/assistant/assistant.qch diff --git a/tools/assistant/tools/assistant/mainwindow.cpp b/tools/assistant/tools/assistant/mainwindow.cpp index b0c2c6b..cb10e3f 100644 --- a/tools/assistant/tools/assistant/mainwindow.cpp +++ b/tools/assistant/tools/assistant/mainwindow.cpp @@ -412,7 +412,7 @@ void MainWindow::setupActions() m_closeTabAction->setShortcuts(QKeySequence::Close); QAction *tmp = menu->addAction(tr("&Quit"), this, SLOT(close())); - tmp->setShortcut(tr("CTRL+Q")); + tmp->setShortcut(QKeySequence::Quit); tmp->setMenuRole(QAction::QuitRole); menu = menuBar()->addMenu(tr("&Edit")); diff --git a/tools/designer/src/designer/qdesigner_actions.cpp b/tools/designer/src/designer/qdesigner_actions.cpp index 65e5937..d5d01f4 100644 --- a/tools/designer/src/designer/qdesigner_actions.cpp +++ b/tools/designer/src/designer/qdesigner_actions.cpp @@ -280,7 +280,7 @@ QDesignerActions::QDesignerActions(QDesignerWorkbench *workbench) m_fileActions->addAction(createSeparator(this)); - m_quitAction->setShortcut(tr("CTRL+Q")); + m_quitAction->setShortcuts(QKeySequence::Quit); m_quitAction->setMenuRole(QAction::QuitRole); connect(m_quitAction, SIGNAL(triggered()), this, SLOT(shutdown())); m_fileActions->addAction(m_quitAction); diff --git a/tools/designer/src/lib/sdk/abstractformeditor.cpp b/tools/designer/src/lib/sdk/abstractformeditor.cpp index e6debd5..09d6976 100644 --- a/tools/designer/src/lib/sdk/abstractformeditor.cpp +++ b/tools/designer/src/lib/sdk/abstractformeditor.cpp @@ -72,7 +72,6 @@ static void initResources() Q_INIT_RESOURCE(shared); Q_INIT_RESOURCE(ClamshellPhone); Q_INIT_RESOURCE(PDAPhone); - Q_INIT_RESOURCE(pda); Q_INIT_RESOURCE(PortableMedia); Q_INIT_RESOURCE(S60_nHD_Touchscreen); Q_INIT_RESOURCE(S60_QVGA_Candybar); diff --git a/tools/designer/src/lib/shared/shared.pri b/tools/designer/src/lib/shared/shared.pri index 0424a41..8ed051a 100644 --- a/tools/designer/src/lib/shared/shared.pri +++ b/tools/designer/src/lib/shared/shared.pri @@ -186,17 +186,4 @@ SOURCES += \ $$PWD/filterwidget.cpp \ $$PWD/plugindialog.cpp -RESOURCES += $$PWD/shared.qrc \ -$$QT_SOURCE_TREE/tools/qvfb/ClamshellPhone.qrc \ -$$QT_SOURCE_TREE/tools/qvfb/PDAPhone.qrc \ -$$QT_SOURCE_TREE/tools/qvfb/pda.qrc \ -$$QT_SOURCE_TREE/tools/qvfb/PortableMedia.qrc \ -$$QT_SOURCE_TREE/tools/qvfb/qvfb.qrc \ -$$QT_SOURCE_TREE/tools/qvfb/S60-nHD-Touchscreen.qrc \ -$$QT_SOURCE_TREE/tools/qvfb/S60-QVGA-Candybar.qrc \ -$$QT_SOURCE_TREE/tools/qvfb/SmartPhone2.qrc \ -$$QT_SOURCE_TREE/tools/qvfb/SmartPhone.qrc \ -$$QT_SOURCE_TREE/tools/qvfb/SmartPhoneWithButtons.qrc \ -$$QT_SOURCE_TREE/tools/qvfb/TouchscreenPhone.qrc \ -$$QT_SOURCE_TREE/tools/qvfb/Trolltech-Keypad.qrc \ -$$QT_SOURCE_TREE/tools/qvfb/Trolltech-Touchscreen.qrc +RESOURCES += $$PWD/shared.qrc diff --git a/tools/designer/src/uitools/quiloader.cpp b/tools/designer/src/uitools/quiloader.cpp index 67bd29c..2a66095 100644 --- a/tools/designer/src/uitools/quiloader.cpp +++ b/tools/designer/src/uitools/quiloader.cpp @@ -572,53 +572,52 @@ void QUiLoaderPrivate::setupWidgetMap() const \class QUiLoader \inmodule QtUiTools - \brief The QUiLoader class allows standalone applications dynamically - create user interfaces at run-time using the information stored in - .ui files or specified plugin paths. + \brief The QUiLoader class enables standalone applications to + dynamically create user interfaces at run-time using the + information stored in .ui files or specified in plugin paths. - In addition, you can customize of creating an user interface by + In addition, you can customize or create your own user interface by deriving your own loader class. - If you have a custom component or an application that embeds Qt - Designer, you can also use the QFormBuilder class provided by the - QtDesigner module to create user interfaces from .ui files. + If you have a custom component or an application that embeds \QD, you can + also use the QFormBuilder class provided by the QtDesigner module to create + user interfaces from \c{.ui} files. - The QUiLoader class provides a collection of functions that allows - you to create widgets based on the information stored in \c .ui - files (created with Qt Designer) or available in the specified - plugin paths. The specified plugin paths can be retrieved using - the pluginPaths() function. You can retrieve the contents of an \c - .ui file using the load() function. For example: + The QUiLoader class provides a collection of functions allowing you to + create widgets based on the information stored in \c .ui files (created + with \QD) or available in the specified plugin paths. The specified plugin + paths can be retrieved using the pluginPaths() function. Similarly, the + contents of a \c{.ui} file can be retrieved using the load() function. For + example: \snippet doc/src/snippets/quiloader/mywidget.cpp 0 - By including the user interface in the form's resources (\c myform.qrc), - we ensure that it will be present at run-time: + By including the user interface in the form's resources (\c myform.qrc), we + ensure that it will be present at run-time: \quotefile doc/src/snippets/quiloader/mywidget.qrc - The availableWidgets() function returns a QStringList with the - class names of the widgets available in the specified plugin - paths. You can create any of these widgets using the - createWidget() function. For example: + The availableWidgets() function returns a QStringList with the class names + of the widgets available in the specified plugin paths. To create these + widgets, simply use the createWidget() function. For example: \snippet doc/src/snippets/quiloader/main.cpp 0 - You can make a custom widget available to the loader using the - addPluginPath() function, and you can remove all the available widgets - by calling the clearPluginPaths() function. + To make a custom widget available to the loader, you can use the + addPluginPath() function; to remove all available widgets, you can call + the clearPluginPaths() function. - The createAction(), createActionGroup(), createLayout() and - createWidget() functions are used internally by the QUiLoader class - whenever it has to create an action, action group, layout or - widget respectively. For that reason, you can subclass the QUiLoader - class and reimplement these functions to intervene the process of - constructing an user interface. For example, you might want to - create a list of the actions created when loading a form or - creating a custom widget. + The createAction(), createActionGroup(), createLayout(), and createWidget() + functions are used internally by the QUiLoader class whenever it has to + create an action, action group, layout, or widget respectively. For that + reason, you can subclass the QUiLoader class and reimplement these + functions to intervene the process of constructing a user interface. For + example, you might want to have a list of the actions created when loading + a form or creating a custom widget. However, in your reimplementation, you + must call QUiLoader's original implementation of these functions first. - For a complete example using the QUiLoader class, see the \l - {designer/calculatorbuilder}{Calculator Builder} example. + For a complete example using the QUiLoader class, see the + \l{Calculator Builder Example}. \sa QtUiTools, QFormBuilder */ @@ -653,8 +652,8 @@ QUiLoader::~QUiLoader() } /*! - Loads a form from the given \a device and creates a new widget with the given - \a parentWidget to hold its contents. + Loads a form from the given \a device and creates a new widget with the + given \a parentWidget to hold its contents. \sa createWidget() */ @@ -668,8 +667,8 @@ QWidget *QUiLoader::load(QIODevice *device, QWidget *parentWidget) } /*! - Returns a list naming the paths the loader searches when locating - custom widget plugins. + Returns a list naming the paths in which the loader will search when + locating custom widget plugins. \sa addPluginPath(), clearPluginPaths() */ @@ -680,7 +679,7 @@ QStringList QUiLoader::pluginPaths() const } /*! - Clears the list of paths the loader searches when locating + Clears the list of paths in which the loader will search when locating plugins. \sa addPluginPath(), pluginPaths() @@ -692,7 +691,7 @@ void QUiLoader::clearPluginPaths() } /*! - Adds the given \a path to the list of paths the loader searches + Adds the given \a path to the list of paths in which the loader will search when locating plugins. \sa pluginPaths(), clearPluginPaths() @@ -704,17 +703,17 @@ void QUiLoader::addPluginPath(const QString &path) } /*! - Creates a new widget with the given \a parent and \a name - using the class specified by \a className. You can use this - function to create any of the widgets returned by the - availableWidgets() function. + Creates a new widget with the given \a parent and \a name using the class + specified by \a className. You can use this function to create any of the + widgets returned by the availableWidgets() function. - The function is also used internally by the QUiLoader class whenever - it has to create a widget. For that reason, you can subclass the - QUiLoader class and reimplement this function to intervene in the - process of constructing a user interface or widget. + The function is also used internally by the QUiLoader class whenever it + creates a widget. Hence, you can subclass QUiLoader and reimplement this + function to intervene process of constructing a user interface or widget. + However, in your implementation, ensure that you call QUiLoader's version + first. - \sa availableWidgets(), load() + \sa availableWidgets(), load() */ QWidget *QUiLoader::createWidget(const QString &className, QWidget *parent, const QString &name) { @@ -723,13 +722,14 @@ QWidget *QUiLoader::createWidget(const QString &className, QWidget *parent, cons } /*! - Creates a new layout with the given \a parent and \a name - using the class specified by \a className. + Creates a new layout with the given \a parent and \a name using the class + specified by \a className. - The function is used internally by the QUiLoader class whenever it - has to create a layout. For that reason, you can subclass the - QUiLoader class and reimplement this function to intervene the - process of constructing an user interface or widget. + The function is also used internally by the QUiLoader class whenever it + creates a widget. Hence, you can subclass QUiLoader and reimplement this + function to intervene process of constructing a user interface or widget. + However, in your implementation, ensure that you call QUiLoader's version + first. \sa createWidget(), load() */ @@ -742,10 +742,11 @@ QLayout *QUiLoader::createLayout(const QString &className, QObject *parent, cons /*! Creates a new action group with the given \a parent and \a name. - The function is used internally by the QUiLoader class whenever it - has to create an action group. For that reason, you can subclass - the QUiLoader class and reimplement this function to intervene the - process of constructing an user interface or widget. + The function is also used internally by the QUiLoader class whenever it + creates a widget. Hence, you can subclass QUiLoader and reimplement this + function to intervene process of constructing a user interface or widget. + However, in your implementation, ensure that you call QUiLoader's version + first. \sa createAction(), createWidget(), load() */ @@ -758,10 +759,11 @@ QActionGroup *QUiLoader::createActionGroup(QObject *parent, const QString &name) /*! Creates a new action with the given \a parent and \a name. - The function is used internally by the QUiLoader class whenever it - has to create an action. For that reason, you can subclass the - QUiLoader class and reimplement this function to intervene the - process of constructing an user interface or widget. + The function is also used internally by the QUiLoader class whenever it + creates a widget. Hence, you can subclass QUiLoader and reimplement this + function to intervene process of constructing a user interface or widget. + However, in your implementation, ensure that you call QUiLoader's version + first. \sa createActionGroup(), createWidget(), load() */ @@ -772,9 +774,9 @@ QAction *QUiLoader::createAction(QObject *parent, const QString &name) } /*! - Returns a list naming the available widgets that can be built - using the createWidget() function, i.e all the widgets specified - within the given plugin paths. + Returns a list naming all available widgets that can be built using the + createWidget() function, i.e all the widgets specified within the given + plugin paths. \sa pluginPaths(), createWidget() @@ -795,11 +797,11 @@ QStringList QUiLoader::availableWidgets() const /*! - Returns a list naming the available layouts that can be built - using the createLayout() function + \since 4.5 + Returns a list naming all available layouts that can be built using the + createLayout() function \sa createLayout() - \since 4.5 */ QStringList QUiLoader::availableLayouts() const @@ -816,9 +818,9 @@ QStringList QUiLoader::availableLayouts() const } /*! - Sets the working directory of the loader to \a dir. The loader - looks for other resources, such as icons and resource files, - in paths relative to this directory. + Sets the working directory of the loader to \a dir. The loader will look + for other resources, such as icons and resource files, in paths relative to + this directory. \sa workingDirectory() */ @@ -842,9 +844,13 @@ QDir QUiLoader::workingDirectory() const } /*! - Sets whether the execution of scripts is enabled to \a enabled. - \since 4.3 \internal + \since 4.3 + + If \a enabled is true, the loader will be able to execute scripts. + Otherwise, execution of scripts will be disabled. + + \sa isScriptingEnabled() */ void QUiLoader::setScriptingEnabled(bool enabled) @@ -854,10 +860,12 @@ void QUiLoader::setScriptingEnabled(bool enabled) } /*! - Returns whether the execution of scripts is enabled. - \sa setScriptingEnabled() - \since 4.3 - \internal + \internal + \since 4.3 + + Returns true if execution of scripts is enabled; returns false otherwise. + + \sa setScriptingEnabled() */ bool QUiLoader::isScriptingEnabled() const @@ -867,11 +875,13 @@ bool QUiLoader::isScriptingEnabled() const } /*! - Sets whether user interfaces loaded by this loader automatically - retranslate themselves upon receiving a language change event or not, - depending on \a enabled. - \since 4.5 + + If \a enabled is true, user interfaces loaded by this loader will + automatically retranslate themselves upon receiving a language change + event. Otherwise, the user interfaces will not be retranslated. + + \sa isLanguageChangeEnabled() */ void QUiLoader::setLanguageChangeEnabled(bool enabled) @@ -881,9 +891,12 @@ void QUiLoader::setLanguageChangeEnabled(bool enabled) } /*! - Returns whether dynamic retranslation on language change is enabled. - \sa setLanguageChangeEnabled() - \since 4.5 + \since 4.5 + + Returns true if dynamic retranslation on language change is enabled; + returns false otherwise. + + \sa setLanguageChangeEnabled() */ bool QUiLoader::isLanguageChangeEnabled() const @@ -894,11 +907,14 @@ bool QUiLoader::isLanguageChangeEnabled() const /*! \internal + \since 4.5 - Sets whether user interfaces loaded by this loader are translated - at all. Note that this is orthogonal to languageChangeEnabled. + If \a enabled is true, user interfaces loaded by this loader will be + translated. Otherwise, the user interfaces will not be translated. - \since 4.5 + \note This is orthogonal to languageChangeEnabled. + + \sa isLanguageChangeEnabled(), setLanguageChangeEnabled() */ void QUiLoader::setTranslationEnabled(bool enabled) @@ -909,11 +925,11 @@ void QUiLoader::setTranslationEnabled(bool enabled) /*! \internal + \since 4.5 - Returns whether translation is enabled. - \sa setTranslationEnabled() + Returns true if translation is enabled; returns false otherwise. - \since 4.5 + \sa setTranslationEnabled() */ bool QUiLoader::isTranslationEnabled() const diff --git a/tools/qtestlib/chart/chart.pro b/tools/qtestlib/chart/chart.pro index 6f6e6d5..7328e5d 100644 --- a/tools/qtestlib/chart/chart.pro +++ b/tools/qtestlib/chart/chart.pro @@ -4,7 +4,7 @@ SOURCES += main.cpp RESOURCES = $$PWD/chart.qrc QT += sql xml -CONFIG += console release +CONFIG += console CONFIG -= app_bundle diff --git a/tools/qvfb/PDAPhone.skin/pda_up.png b/tools/qvfb/PDAPhone.skin/pda_up.png Binary files differdeleted file mode 100644 index 541e3c4..0000000 --- a/tools/qvfb/PDAPhone.skin/pda_up.png +++ /dev/null diff --git a/tools/qvfb/pda.qrc b/tools/qvfb/pda.qrc deleted file mode 100644 index b14e7b3..0000000 --- a/tools/qvfb/pda.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<!DOCTYPE RCC><RCC version="1.0"> -<qresource prefix="/skins"> - <file>pda.skin</file> -</qresource> -</RCC> diff --git a/tools/qvfb/pda.skin b/tools/qvfb/pda.skin deleted file mode 100644 index 037f750..0000000 --- a/tools/qvfb/pda.skin +++ /dev/null @@ -1,14 +0,0 @@ -pda_up.png pda_down.png -57 81 -240 320 -11 -"Power" 0x0100000a 277 36 302 57 -"F1" 0x01000030 52 439 81 470 -"F2" 0x01000031 101 422 130 451 -"F3" 0x01000032 232 423 260 452 -"F4" 0x01000033 279 445 309 473 -"Left" 0x01000012 155 438 176 472 -"Down" 0x01000015 169 471 203 486 -"Right" 0x01000014 193 448 215 472 -"Up" 0x01000013 166 427 199 451 -"Enter" 0x01000005 177 448 193 468 diff --git a/tools/qvfb/pda_down.png b/tools/qvfb/pda_down.png Binary files differdeleted file mode 100644 index 0ea157d..0000000 --- a/tools/qvfb/pda_down.png +++ /dev/null diff --git a/tools/qvfb/qvfb.pro b/tools/qvfb/qvfb.pro index 85c4d96..247337a 100644 --- a/tools/qvfb/qvfb.pro +++ b/tools/qvfb/qvfb.pro @@ -60,15 +60,4 @@ unix:x11 { LIBS += -lXtst } -RESOURCES += qvfb.qrc \ - ClamshellPhone.qrc \ - PDAPhone.qrc \ - SmartPhone2.qrc \ - SmartPhone.qrc \ - SmartPhoneWithButtons.qrc \ - TouchscreenPhone.qrc \ - Trolltech-Keypad.qrc \ - Trolltech-Touchscreen.qrc \ - PortableMedia.qrc \ - S60-QVGA-Candybar.qrc \ - S60-nHD-Touchscreen.qrc +RESOURCES += qvfb.qrc diff --git a/tools/shared/deviceskin/deviceskin.pri b/tools/shared/deviceskin/deviceskin.pri index e4c9ef7..2552c92 100644 --- a/tools/shared/deviceskin/deviceskin.pri +++ b/tools/shared/deviceskin/deviceskin.pri @@ -1,3 +1,15 @@ INCLUDEPATH += $$PWD HEADERS += $$PWD/deviceskin.h SOURCES += $$PWD/deviceskin.cpp +RESOURCES += $$PWD/skins/ClamshellPhone.qrc \ + $$PWD/skins/PDAPhone.qrc \ + $$PWD/skins/SmartPhone2.qrc \ + $$PWD/skins/SmartPhone.qrc \ + $$PWD/skins/SmartPhoneWithButtons.qrc \ + $$PWD/skins/TouchscreenPhone.qrc \ + $$PWD/skins/Trolltech-Keypad.qrc \ + $$PWD/skins/Trolltech-Touchscreen.qrc \ + $$PWD/skins/PortableMedia.qrc \ + $$PWD/skins/S60-QVGA-Candybar.qrc \ + $$PWD/skins/S60-nHD-Touchscreen.qrc + diff --git a/tools/qvfb/ClamshellPhone.qrc b/tools/shared/deviceskin/skins/ClamshellPhone.qrc index 39cd422..39cd422 100644 --- a/tools/qvfb/ClamshellPhone.qrc +++ b/tools/shared/deviceskin/skins/ClamshellPhone.qrc diff --git a/tools/qvfb/ClamshellPhone.skin/ClamshellPhone.skin b/tools/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone.skin index cb24a8e..cb24a8e 100644 --- a/tools/qvfb/ClamshellPhone.skin/ClamshellPhone.skin +++ b/tools/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone.skin diff --git a/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-closed.png b/tools/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5-closed.png Binary files differindex 88ba3a1..88ba3a1 100644 --- a/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-closed.png +++ b/tools/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5-closed.png diff --git a/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-pressed.png b/tools/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5-pressed.png Binary files differindex 971cdef..971cdef 100644 --- a/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-pressed.png +++ b/tools/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5-pressed.png diff --git a/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5.png b/tools/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5.png Binary files differindex f3550ee..f3550ee 100644 --- a/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5.png +++ b/tools/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5.png diff --git a/tools/qvfb/S60-QVGA-Candybar.skin/defaultbuttons.conf b/tools/shared/deviceskin/skins/ClamshellPhone.skin/defaultbuttons.conf index e349dbc..e349dbc 100644 --- a/tools/qvfb/S60-QVGA-Candybar.skin/defaultbuttons.conf +++ b/tools/shared/deviceskin/skins/ClamshellPhone.skin/defaultbuttons.conf diff --git a/tools/qvfb/DualScreenPhone.skin/DualScreen-pressed.png b/tools/shared/deviceskin/skins/DualScreenPhone.skin/DualScreen-pressed.png Binary files differindex d62ef4a..d62ef4a 100644 --- a/tools/qvfb/DualScreenPhone.skin/DualScreen-pressed.png +++ b/tools/shared/deviceskin/skins/DualScreenPhone.skin/DualScreen-pressed.png diff --git a/tools/qvfb/DualScreenPhone.skin/DualScreen.png b/tools/shared/deviceskin/skins/DualScreenPhone.skin/DualScreen.png Binary files differindex cb3d1a7..cb3d1a7 100644 --- a/tools/qvfb/DualScreenPhone.skin/DualScreen.png +++ b/tools/shared/deviceskin/skins/DualScreenPhone.skin/DualScreen.png diff --git a/tools/qvfb/DualScreenPhone.skin/DualScreenPhone.skin b/tools/shared/deviceskin/skins/DualScreenPhone.skin/DualScreenPhone.skin index a82ef23..a82ef23 100644 --- a/tools/qvfb/DualScreenPhone.skin/DualScreenPhone.skin +++ b/tools/shared/deviceskin/skins/DualScreenPhone.skin/DualScreenPhone.skin diff --git a/tools/qvfb/SmartPhone.skin/defaultbuttons.conf b/tools/shared/deviceskin/skins/DualScreenPhone.skin/defaultbuttons.conf index 1103350..1103350 100644 --- a/tools/qvfb/SmartPhone.skin/defaultbuttons.conf +++ b/tools/shared/deviceskin/skins/DualScreenPhone.skin/defaultbuttons.conf diff --git a/tools/qvfb/PDAPhone.qrc b/tools/shared/deviceskin/skins/PDAPhone.qrc index 1a1c35a..1a1c35a 100644 --- a/tools/qvfb/PDAPhone.qrc +++ b/tools/shared/deviceskin/skins/PDAPhone.qrc diff --git a/tools/qvfb/PDAPhone.skin/PDAPhone.skin b/tools/shared/deviceskin/skins/PDAPhone.skin/PDAPhone.skin index d6a1966..d6a1966 100644 --- a/tools/qvfb/PDAPhone.skin/PDAPhone.skin +++ b/tools/shared/deviceskin/skins/PDAPhone.skin/PDAPhone.skin diff --git a/tools/qvfb/PDAPhone.skin/defaultbuttons.conf b/tools/shared/deviceskin/skins/PDAPhone.skin/defaultbuttons.conf index e3ae813..e3ae813 100644 --- a/tools/qvfb/PDAPhone.skin/defaultbuttons.conf +++ b/tools/shared/deviceskin/skins/PDAPhone.skin/defaultbuttons.conf diff --git a/tools/qvfb/PDAPhone.skin/finger.png b/tools/shared/deviceskin/skins/PDAPhone.skin/finger.png Binary files differindex 24cf0cb..24cf0cb 100644 --- a/tools/qvfb/PDAPhone.skin/finger.png +++ b/tools/shared/deviceskin/skins/PDAPhone.skin/finger.png diff --git a/tools/qvfb/PDAPhone.skin/pda_down.png b/tools/shared/deviceskin/skins/PDAPhone.skin/pda_down.png Binary files differindex f65c059..f65c059 100644 --- a/tools/qvfb/PDAPhone.skin/pda_down.png +++ b/tools/shared/deviceskin/skins/PDAPhone.skin/pda_down.png diff --git a/tools/qvfb/pda_up.png b/tools/shared/deviceskin/skins/PDAPhone.skin/pda_up.png Binary files differindex 541e3c4..541e3c4 100644 --- a/tools/qvfb/pda_up.png +++ b/tools/shared/deviceskin/skins/PDAPhone.skin/pda_up.png diff --git a/tools/qvfb/PortableMedia.qrc b/tools/shared/deviceskin/skins/PortableMedia.qrc index a902f1a..a902f1a 100644 --- a/tools/qvfb/PortableMedia.qrc +++ b/tools/shared/deviceskin/skins/PortableMedia.qrc diff --git a/tools/qvfb/PortableMedia.skin/PortableMedia.skin b/tools/shared/deviceskin/skins/PortableMedia.skin/PortableMedia.skin index b76e5cf..b76e5cf 100644 --- a/tools/qvfb/PortableMedia.skin/PortableMedia.skin +++ b/tools/shared/deviceskin/skins/PortableMedia.skin/PortableMedia.skin diff --git a/tools/qvfb/PortableMedia.skin/defaultbuttons.conf b/tools/shared/deviceskin/skins/PortableMedia.skin/defaultbuttons.conf index 514e881..514e881 100644 --- a/tools/qvfb/PortableMedia.skin/defaultbuttons.conf +++ b/tools/shared/deviceskin/skins/PortableMedia.skin/defaultbuttons.conf diff --git a/tools/qvfb/PortableMedia.skin/portablemedia-pressed.png b/tools/shared/deviceskin/skins/PortableMedia.skin/portablemedia-pressed.png Binary files differindex 730e762..730e762 100644 --- a/tools/qvfb/PortableMedia.skin/portablemedia-pressed.png +++ b/tools/shared/deviceskin/skins/PortableMedia.skin/portablemedia-pressed.png diff --git a/tools/qvfb/PortableMedia.skin/portablemedia.png b/tools/shared/deviceskin/skins/PortableMedia.skin/portablemedia.png Binary files differindex e44cbe1..e44cbe1 100644 --- a/tools/qvfb/PortableMedia.skin/portablemedia.png +++ b/tools/shared/deviceskin/skins/PortableMedia.skin/portablemedia.png diff --git a/tools/qvfb/PortableMedia.skin/portablemedia.xcf b/tools/shared/deviceskin/skins/PortableMedia.skin/portablemedia.xcf Binary files differindex 127e07c..127e07c 100644 --- a/tools/qvfb/PortableMedia.skin/portablemedia.xcf +++ b/tools/shared/deviceskin/skins/PortableMedia.skin/portablemedia.xcf diff --git a/tools/qvfb/S60-QVGA-Candybar.qrc b/tools/shared/deviceskin/skins/S60-QVGA-Candybar.qrc index 8138484..8138484 100644 --- a/tools/qvfb/S60-QVGA-Candybar.qrc +++ b/tools/shared/deviceskin/skins/S60-QVGA-Candybar.qrc diff --git a/tools/qvfb/S60-QVGA-Candybar.skin/S60-QVGA-Candybar-down.png b/tools/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar-down.png Binary files differindex 89d40cb..89d40cb 100644 --- a/tools/qvfb/S60-QVGA-Candybar.skin/S60-QVGA-Candybar-down.png +++ b/tools/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar-down.png diff --git a/tools/qvfb/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.png b/tools/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.png Binary files differindex 0d0e598..0d0e598 100644 --- a/tools/qvfb/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.png +++ b/tools/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.png diff --git a/tools/qvfb/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.skin b/tools/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.skin index 4f8fe5d..4f8fe5d 100644 --- a/tools/qvfb/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.skin +++ b/tools/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.skin diff --git a/tools/qvfb/ClamshellPhone.skin/defaultbuttons.conf b/tools/shared/deviceskin/skins/S60-QVGA-Candybar.skin/defaultbuttons.conf index e349dbc..e349dbc 100644 --- a/tools/qvfb/ClamshellPhone.skin/defaultbuttons.conf +++ b/tools/shared/deviceskin/skins/S60-QVGA-Candybar.skin/defaultbuttons.conf diff --git a/tools/qvfb/S60-nHD-Touchscreen.qrc b/tools/shared/deviceskin/skins/S60-nHD-Touchscreen.qrc index daf0cc3..daf0cc3 100644 --- a/tools/qvfb/S60-nHD-Touchscreen.qrc +++ b/tools/shared/deviceskin/skins/S60-nHD-Touchscreen.qrc diff --git a/tools/qvfb/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen-down.png b/tools/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen-down.png Binary files differindex 7253e38..7253e38 100644 --- a/tools/qvfb/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen-down.png +++ b/tools/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen-down.png diff --git a/tools/qvfb/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.png b/tools/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.png Binary files differindex 675563e..675563e 100644 --- a/tools/qvfb/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.png +++ b/tools/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.png diff --git a/tools/qvfb/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.skin b/tools/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.skin index ed25d0e..ed25d0e 100644 --- a/tools/qvfb/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.skin +++ b/tools/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.skin diff --git a/tools/qvfb/Trolltech-Touchscreen.skin/defaultbuttons.conf b/tools/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/defaultbuttons.conf index 6665125..6665125 100644 --- a/tools/qvfb/Trolltech-Touchscreen.skin/defaultbuttons.conf +++ b/tools/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/defaultbuttons.conf diff --git a/tools/qvfb/SmartPhone.qrc b/tools/shared/deviceskin/skins/SmartPhone.qrc index 8bb5325..8bb5325 100644 --- a/tools/qvfb/SmartPhone.qrc +++ b/tools/shared/deviceskin/skins/SmartPhone.qrc diff --git a/tools/qvfb/SmartPhone.skin/SmartPhone-pressed.png b/tools/shared/deviceskin/skins/SmartPhone.skin/SmartPhone-pressed.png Binary files differindex d0db2ed..d0db2ed 100644 --- a/tools/qvfb/SmartPhone.skin/SmartPhone-pressed.png +++ b/tools/shared/deviceskin/skins/SmartPhone.skin/SmartPhone-pressed.png diff --git a/tools/qvfb/SmartPhone.skin/SmartPhone.png b/tools/shared/deviceskin/skins/SmartPhone.skin/SmartPhone.png Binary files differindex e6ac5a0..e6ac5a0 100644 --- a/tools/qvfb/SmartPhone.skin/SmartPhone.png +++ b/tools/shared/deviceskin/skins/SmartPhone.skin/SmartPhone.png diff --git a/tools/qvfb/SmartPhone.skin/SmartPhone.skin b/tools/shared/deviceskin/skins/SmartPhone.skin/SmartPhone.skin index 2f44c5a..2f44c5a 100644 --- a/tools/qvfb/SmartPhone.skin/SmartPhone.skin +++ b/tools/shared/deviceskin/skins/SmartPhone.skin/SmartPhone.skin diff --git a/tools/qvfb/DualScreenPhone.skin/defaultbuttons.conf b/tools/shared/deviceskin/skins/SmartPhone.skin/defaultbuttons.conf index 1103350..1103350 100644 --- a/tools/qvfb/DualScreenPhone.skin/defaultbuttons.conf +++ b/tools/shared/deviceskin/skins/SmartPhone.skin/defaultbuttons.conf diff --git a/tools/qvfb/SmartPhone2.qrc b/tools/shared/deviceskin/skins/SmartPhone2.qrc index 751e985..751e985 100644 --- a/tools/qvfb/SmartPhone2.qrc +++ b/tools/shared/deviceskin/skins/SmartPhone2.qrc diff --git a/tools/qvfb/SmartPhone2.skin/SmartPhone2-pressed.png b/tools/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2-pressed.png Binary files differindex d4eb5b0..d4eb5b0 100644 --- a/tools/qvfb/SmartPhone2.skin/SmartPhone2-pressed.png +++ b/tools/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2-pressed.png diff --git a/tools/qvfb/SmartPhone2.skin/SmartPhone2.png b/tools/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2.png Binary files differindex 48ccc1c..48ccc1c 100644 --- a/tools/qvfb/SmartPhone2.skin/SmartPhone2.png +++ b/tools/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2.png diff --git a/tools/qvfb/SmartPhone2.skin/SmartPhone2.skin b/tools/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2.skin index 16884bf..16884bf 100644 --- a/tools/qvfb/SmartPhone2.skin/SmartPhone2.skin +++ b/tools/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2.skin diff --git a/tools/qvfb/SmartPhone2.skin/defaultbuttons.conf b/tools/shared/deviceskin/skins/SmartPhone2.skin/defaultbuttons.conf index b083203..b083203 100644 --- a/tools/qvfb/SmartPhone2.skin/defaultbuttons.conf +++ b/tools/shared/deviceskin/skins/SmartPhone2.skin/defaultbuttons.conf diff --git a/tools/qvfb/SmartPhoneWithButtons.qrc b/tools/shared/deviceskin/skins/SmartPhoneWithButtons.qrc index f3393ba..f3393ba 100644 --- a/tools/qvfb/SmartPhoneWithButtons.qrc +++ b/tools/shared/deviceskin/skins/SmartPhoneWithButtons.qrc diff --git a/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons-pressed.png b/tools/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons-pressed.png Binary files differindex 456a068..456a068 100644 --- a/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons-pressed.png +++ b/tools/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons-pressed.png diff --git a/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.png b/tools/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.png Binary files differindex 5ffbd6e..5ffbd6e 100644 --- a/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.png +++ b/tools/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.png diff --git a/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.skin b/tools/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.skin index 9afa67f..9afa67f 100644 --- a/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.skin +++ b/tools/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.skin diff --git a/tools/qvfb/SmartPhoneWithButtons.skin/defaultbuttons.conf b/tools/shared/deviceskin/skins/SmartPhoneWithButtons.skin/defaultbuttons.conf index ebd6926..ebd6926 100644 --- a/tools/qvfb/SmartPhoneWithButtons.skin/defaultbuttons.conf +++ b/tools/shared/deviceskin/skins/SmartPhoneWithButtons.skin/defaultbuttons.conf diff --git a/tools/qvfb/TouchscreenPhone.qrc b/tools/shared/deviceskin/skins/TouchscreenPhone.qrc index 023144d..023144d 100644 --- a/tools/qvfb/TouchscreenPhone.qrc +++ b/tools/shared/deviceskin/skins/TouchscreenPhone.qrc diff --git a/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone-pressed.png b/tools/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone-pressed.png Binary files differindex 01acb86..01acb86 100644 --- a/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone-pressed.png +++ b/tools/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone-pressed.png diff --git a/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.png b/tools/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone.png Binary files differindex e90de0d..e90de0d 100644 --- a/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.png +++ b/tools/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone.png diff --git a/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.skin b/tools/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone.skin index 24316a1..24316a1 100644 --- a/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.skin +++ b/tools/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone.skin diff --git a/tools/qvfb/TouchscreenPhone.skin/defaultbuttons.conf b/tools/shared/deviceskin/skins/TouchscreenPhone.skin/defaultbuttons.conf index a13dfdc..a13dfdc 100644 --- a/tools/qvfb/TouchscreenPhone.skin/defaultbuttons.conf +++ b/tools/shared/deviceskin/skins/TouchscreenPhone.skin/defaultbuttons.conf diff --git a/tools/qvfb/Trolltech-Keypad.qrc b/tools/shared/deviceskin/skins/Trolltech-Keypad.qrc index 4775068..4775068 100644 --- a/tools/qvfb/Trolltech-Keypad.qrc +++ b/tools/shared/deviceskin/skins/Trolltech-Keypad.qrc diff --git a/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-closed.png b/tools/shared/deviceskin/skins/Trolltech-Keypad.skin/Trolltech-Keypad-closed.png Binary files differindex 8dd5719..8dd5719 100644 --- a/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-closed.png +++ b/tools/shared/deviceskin/skins/Trolltech-Keypad.skin/Trolltech-Keypad-closed.png diff --git a/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-down.png b/tools/shared/deviceskin/skins/Trolltech-Keypad.skin/Trolltech-Keypad-down.png Binary files differindex 5e1e6be..5e1e6be 100644 --- a/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-down.png +++ b/tools/shared/deviceskin/skins/Trolltech-Keypad.skin/Trolltech-Keypad-down.png diff --git a/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.png b/tools/shared/deviceskin/skins/Trolltech-Keypad.skin/Trolltech-Keypad.png Binary files differindex fb3d549..fb3d549 100644 --- a/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.png +++ b/tools/shared/deviceskin/skins/Trolltech-Keypad.skin/Trolltech-Keypad.png diff --git a/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.skin b/tools/shared/deviceskin/skins/Trolltech-Keypad.skin/Trolltech-Keypad.skin index 4d90321..4d90321 100644 --- a/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.skin +++ b/tools/shared/deviceskin/skins/Trolltech-Keypad.skin/Trolltech-Keypad.skin diff --git a/tools/qvfb/Trolltech-Keypad.skin/defaultbuttons.conf b/tools/shared/deviceskin/skins/Trolltech-Keypad.skin/defaultbuttons.conf index 6a78e67..6a78e67 100644 --- a/tools/qvfb/Trolltech-Keypad.skin/defaultbuttons.conf +++ b/tools/shared/deviceskin/skins/Trolltech-Keypad.skin/defaultbuttons.conf diff --git a/tools/qvfb/Trolltech-Touchscreen.qrc b/tools/shared/deviceskin/skins/Trolltech-Touchscreen.qrc index 40fafeb..40fafeb 100644 --- a/tools/qvfb/Trolltech-Touchscreen.qrc +++ b/tools/shared/deviceskin/skins/Trolltech-Touchscreen.qrc diff --git a/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen-down.png b/tools/shared/deviceskin/skins/Trolltech-Touchscreen.skin/Trolltech-Touchscreen-down.png Binary files differindex c1a422f..c1a422f 100644 --- a/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen-down.png +++ b/tools/shared/deviceskin/skins/Trolltech-Touchscreen.skin/Trolltech-Touchscreen-down.png diff --git a/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.png b/tools/shared/deviceskin/skins/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.png Binary files differindex 544a425..544a425 100644 --- a/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.png +++ b/tools/shared/deviceskin/skins/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.png diff --git a/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.skin b/tools/shared/deviceskin/skins/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.skin index 5de882e..5de882e 100644 --- a/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.skin +++ b/tools/shared/deviceskin/skins/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.skin diff --git a/tools/qvfb/S60-nHD-Touchscreen.skin/defaultbuttons.conf b/tools/shared/deviceskin/skins/Trolltech-Touchscreen.skin/defaultbuttons.conf index 6665125..6665125 100644 --- a/tools/qvfb/S60-nHD-Touchscreen.skin/defaultbuttons.conf +++ b/tools/shared/deviceskin/skins/Trolltech-Touchscreen.skin/defaultbuttons.conf |