From 3798c8718c277d856562829d8326bb7cced0d84a Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 3 Mar 2011 18:56:26 -0300 Subject: [PATCH 001/489] More code snippets ported to Python. --- .../src/snippets/code/doc_src_phonon-api.qdoc | 192 ++++++++++++++++++ .../code/src_gui_effects_qgraphicseffect.cpp | 37 ++++ .../code/src_gui_widgets_qmainwindow.cpp | 15 ++ .../src_network_access_qnetworkdiskcache.cpp | 24 +++ ...c_network_bearer_qnetworkconfigmanager.cpp | 8 + .../code/src_opengl_qglshaderprogram.cpp | 53 +++++ .../imageprovider/imageprovider-example.qml | 9 + .../graphicsview/simpleanchorlayout/main.cpp | 23 +++ .../examples/mainwindows/sdi/mainwindow.cpp | 11 + .../examples/widgets/groupbox/window.cpp | 138 +++++++++++++ .../snippets/customstyle/main.cpp | 12 ++ doc/codesnippets/snippets/phonon.cpp | 39 ++++ .../snippets/phonon/samplebackend/main.cpp | 66 ++++++ .../qtwebkit_qwebinspector_snippet.cpp | 11 + .../qtwebkit_qwebview_snippet.cpp | 31 +++ .../webkitsnippets/webpage/main.cpp | 33 +++ doc/extras/PySide.QtTest.rst | 7 + doc/extras/PySide.QtUiTools.rst | 9 + 18 files changed, 718 insertions(+) create mode 100644 doc/codesnippets/doc/src/snippets/code/doc_src_phonon-api.qdoc create mode 100644 doc/codesnippets/doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp create mode 100644 doc/codesnippets/doc/src/snippets/code/src_gui_widgets_qmainwindow.cpp create mode 100644 doc/codesnippets/doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp create mode 100644 doc/codesnippets/doc/src/snippets/code/src_network_bearer_qnetworkconfigmanager.cpp create mode 100644 doc/codesnippets/doc/src/snippets/code/src_opengl_qglshaderprogram.cpp create mode 100644 doc/codesnippets/examples/declarative/cppextensions/imageprovider/imageprovider-example.qml create mode 100644 doc/codesnippets/examples/graphicsview/simpleanchorlayout/main.cpp create mode 100644 doc/codesnippets/examples/mainwindows/sdi/mainwindow.cpp create mode 100644 doc/codesnippets/examples/widgets/groupbox/window.cpp create mode 100644 doc/codesnippets/snippets/customstyle/main.cpp create mode 100644 doc/codesnippets/snippets/phonon.cpp create mode 100644 doc/codesnippets/snippets/phonon/samplebackend/main.cpp create mode 100644 doc/codesnippets/webkitsnippets/qtwebkit_qwebinspector_snippet.cpp create mode 100644 doc/codesnippets/webkitsnippets/qtwebkit_qwebview_snippet.cpp create mode 100644 doc/codesnippets/webkitsnippets/webpage/main.cpp create mode 100644 doc/extras/PySide.QtTest.rst create mode 100644 doc/extras/PySide.QtUiTools.rst diff --git a/doc/codesnippets/doc/src/snippets/code/doc_src_phonon-api.qdoc b/doc/codesnippets/doc/src/snippets/code/doc_src_phonon-api.qdoc new file mode 100644 index 0000000..3f0771e --- /dev/null +++ b/doc/codesnippets/doc/src/snippets/code/doc_src_phonon-api.qdoc @@ -0,0 +1,192 @@ +//! [0] +class PushStream (AbstractMediaStream): + def __init__(self, parent = None): + AbstractMediaStream.__init(self, parent) + self.timer = QTimer(self) + self.setStreamSize(self.getMediaStreamSize()) + + self.timer.timeout.connect(self.moreData) + self.timer.setInterval(0) + + @Slot() + def moreData(self): + data = self.getMediaData() + if data.isEmpty(): + self.endOfData() + else: + self.writeData(data) + + def needData(self): + self.timer.start() + self.moreData() + + def enoughData(self): + self.timer.stop() +//! [0] + + +//! [1] +class PushStream (AbstractMediaStream): + def __init__(self, parent = None): + AbstractMediaStream.__init(self, parent) + self.setStreamSize(self.getMediaStreamSize()) + + @Slot() + def needData(self): + data = self.getMediaData() + if data.isEmpty(): + self.endOfData() + else: + self.writeData(data) +//! [1] + + +//! [2] +self.seekStream(0) +//! [2] + + +//! [3] +m = MediaObject() +fileName = "/home/foo/bar.ogg" +url = QUrl("http://www.example.com/stream.mp3") +someBuffer = QBuffer() +m.setCurrentSource(fileName) +m.setCurrentSource(url) +m.setCurrentSource(someBuffer) +m.setCurrentSource(Phonon.Cd) +//! [3] + + +//! [4] +player = VideoPlayer(Phonon.VideoCategory, parentWidget) +player.finished.connect(player.deleteLater) +player.play(url) +//! [4] + + +//! [5] +audioPlayer.load(url) +audioPlayer.play() +//! [5] + + +//! [6] +media = MediaObject(self) +media.finished.connect(self.slotFinished) +media.setCurrentSource("/home/username/music/filename.ogg") + +# ... + +media.play() +//! [6] + + +//! [7] +media.setCurrentSource(":/sounds/startsound.ogg") +media.enqueue("/home/username/music/song.mp3") +media.enqueue(":/sounds/endsound.ogg") +//! [7] + + +//! [8] + media.setCurrentSource(":/sounds/startsound.ogg") + media.aboutToFinish.connect(lambda : media.enqueue("/home/username/music/song.mp3")) +//! [8] + + +//! [9] +x = 200 +media.setTickInterval(x) +assert(x == producer.tickInterval()) +//! [9] + + +//! [10] +x = 200 +media.setTickInterval(x) +assert(x >= producer.tickInterval() and x <= * producer.tickInterval()) +//! [10] + + +//! [11] +//! [12] + self.media.hasVideoChanged[bool].connect(hasVideoChanged) + self.media.setCurrentSource("somevideo.avi") + self.media.hasVideo() # returns false + + @Slot(bool) + def hasVideoChanged(self, b): + # b == true + media.hasVideo() # returns true +//! [12] +//! [11] + +//! [13] +self.setMetaArtist(media.metaData("ARTIST")) +self.setMetaAlbum(media.metaData("ALBUM")) +self.setMetaTitle(media.metaData("TITLE")) +self.setMetaDate(media.metaData("DATE")) +self.setMetaGenre(media.metaData("GENRE")) +self.setMetaTrack(media.metaData("TRACKNUMBER")) +self.setMetaComment(media.metaData("DESCRIPTION")) +//! [13] + + +//! [14] +url = QUrl("http://www.example.com/music.ogg") +media.setCurrentSource(url) +//! [14] + + +//! [15] +progressBar.setRange(0, 100) # this is the default +self.media.bufferStatus[int].connect(progressBar.setValue) +//! [15] + + +//! [16] +BackendCapabilities.notifier.capabilitiesChanged.connect(...) +//! [16] + + +//! [17] +cb = QComboBox(parentWidget) +model = ObjectDescriptionModel(cb) +model.setModelData(BackendCapabilities.availableAudioOutputDevices()) +cb.setModel(model) +cb.setCurrentIndex(0) # select first entry +//! [17] + + +//! [18] +cbIndex = cb.currentIndex() +selectedDevice = model.modelData(cbIndex) +//! [18] + + +//! [19] +path = Phonon.createPath(...) +effect = Effect(this) +path.insertEffect(effect) +//! [19] + + +//! [20] +media = MediaObject() +output = AudioOutput(Phonon.MusicCategory) +path = Phonon.createPath(media, output) +assert(path.isValid()) # for this simple case the path should always be + # valid - there are unit tests to ensure it +# insert an effect +effectList = BackendCapabilities.availableAudioEffects() +if effectList: + effect = path.insertEffect(effectList[0]) +//! [20] + + +//! [21] +media = MediaObject(parent) +vwidget = VideoWidget(parent) +Phonon.createPath(media, vwidget) +//! [21] diff --git a/doc/codesnippets/doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp b/doc/codesnippets/doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp new file mode 100644 index 0000000..c5d4809 --- /dev/null +++ b/doc/codesnippets/doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp @@ -0,0 +1,37 @@ +//! [0] +def draw(self, painter): + # Fully opaque draw directly without going through a pixmap. + if qFuzzyCompare(self.opacity, 1): + drawSource(painter) + return + # ... +//! [0] + +//! [1] +def draw(self, painter): + # ... + offset = QPoint() + if self.sourceIsPixmap(): + # No point in drawing in device coordinates (pixmap will be scaled anyways). + pixmap = sourcePixmap(Qt.LogicalCoordinates, offset) + ... + painter.drawPixmap(offset, pixmap) + else: + # Draw pixmap in device coordinates to avoid pixmap scaling + pixmap = sourcePixmap(Qt.DeviceCoordinates, offset) + painter.setWorldTransform(QTransform()) + # ... + painter.drawPixmap(offset, pixmap) + # ... +//! [1] + +//! [2] +# ... +alphaGradient = QLinearGradient(rect.topLeft(), rect.bottomLeft()) +alphaGradient.setColorAt(0.0, Qt.transparent) +alphaGradient.setColorAt(0.5, Qt.black) +alphaGradient.setColorAt(1.0, Qt.transparent) +effect = QGraphicsOpacityEffect() +effect.setOpacityMask(alphaGradient) +# ... +//! [2] diff --git a/doc/codesnippets/doc/src/snippets/code/src_gui_widgets_qmainwindow.cpp b/doc/codesnippets/doc/src/snippets/code/src_gui_widgets_qmainwindow.cpp new file mode 100644 index 0000000..465fff1 --- /dev/null +++ b/doc/codesnippets/doc/src/snippets/code/src_gui_widgets_qmainwindow.cpp @@ -0,0 +1,15 @@ +//! [0] +def closeEvent(self, event): + settings = QSettings("MyCompany", "MyApp") + settings.setValue("geometry", self.saveGeometry()) + settings.setValue("windowState", self.saveState()) + QMainWindow.closeEvent(self, event) +//! [0] + + +//! [1] +def readSettings(self): + settings = QSettings("MyCompany", "MyApp") + restoreGeometry(settings.value("myWidget/geometry")) + restoreState(settings.value("myWidget/windowState")) +//! [1] diff --git a/doc/codesnippets/doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp b/doc/codesnippets/doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp new file mode 100644 index 0000000..8d18510 --- /dev/null +++ b/doc/codesnippets/doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp @@ -0,0 +1,24 @@ +//! [0] +manager = QNetworkAccessManager(self) +diskCache = QNetworkDiskCache(self) +diskCache.setCacheDirectory("cacheDir") +manager.setCache(diskCache) +//! [0] + +//! [1] +# do a normal request (preferred from network, as this is the default) +request = QNetworkRequest(QUrl("http://qt.nokia.com")) +manager.get(request) + +# do a request preferred from cache +request2 = QNetworkRequest(QUrl("http://qt.nokia.com")) +request2.setAttribute(QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.PreferCache) +manager.get(request2) +//! [1] + +//! [2] +@Slot(QNetworkReply) +def replyFinished(reply): + fromCache = reply.attribute(QNetworkRequest.SourceIsFromCacheAttribute) + print("page from cache? %d" % fromCache) +//! [2] diff --git a/doc/codesnippets/doc/src/snippets/code/src_network_bearer_qnetworkconfigmanager.cpp b/doc/codesnippets/doc/src/snippets/code/src_network_bearer_qnetworkconfigmanager.cpp new file mode 100644 index 0000000..837ea03 --- /dev/null +++ b/doc/codesnippets/doc/src/snippets/code/src_network_bearer_qnetworkconfigmanager.cpp @@ -0,0 +1,8 @@ +//! [0] +mgr = QNetworkConfigurationManager() +activeConfigs = mgr.allConfigurations(QNetworkConfiguration.Active) +if activeConfigs: + assert(mgr.isOnline()) +else: + assert(not mgr.isOnline()) +//! [0] diff --git a/doc/codesnippets/doc/src/snippets/code/src_opengl_qglshaderprogram.cpp b/doc/codesnippets/doc/src/snippets/code/src_opengl_qglshaderprogram.cpp new file mode 100644 index 0000000..9c8f35a --- /dev/null +++ b/doc/codesnippets/doc/src/snippets/code/src_opengl_qglshaderprogram.cpp @@ -0,0 +1,53 @@ +//! [0] +shader = QGLShader(QGLShader.Vertex) +shader.compileSourceCode(code) + +program = QGLShaderProgram(context) +program.addShader(shader) +program.link() + +program.bind() +//! [0] + +//! [1] +program.addShaderFromSourceCode(QGLShader.Vertex, + "attribute highp vec4 vertex\n" \ + "attribute mediump mat4 matrix\n" \ + "void main(void)\n" \ + "{\n" \ + " gl_Position = matrix * vertex\n" \ + "}") +program.addShaderFromSourceCode(QGLShader.Fragment, + "uniform mediump vec4 color\n" \ + "void main(void)\n" \ + "{\n" \ + " gl_FragColor = color\n" \ + "}") +program.link() +program.bind() + +vertexLocation = program.attributeLocation("vertex") +matrixLocation = program.attributeLocation("matrix") +colorLocation = program.uniformLocation("color") +//! [1] + +//! [2] +triangleVertices = ( + 60.0f, 10.0f, 0.0f, + 110.0f, 110.0f, 0.0f, + 10.0f, 110.0f, 0.0f) + +color = QColor(0, 255, 0, 255) + +pmvMatrix = QMatrix4x4() +pmvMatrix.ortho(self.rect()) + +program.enableAttributeArray(vertexLocation) +program.setAttributeArray(vertexLocation, triangleVertices, 3) +program.setUniformValue(matrixLocation, pmvMatrix) +program.setUniformValue(colorLocation, color) + +glDrawArrays(GL_TRIANGLES, 0, 3) + +program.disableAttributeArray(vertexLocation) +//! [2] diff --git a/doc/codesnippets/examples/declarative/cppextensions/imageprovider/imageprovider-example.qml b/doc/codesnippets/examples/declarative/cppextensions/imageprovider/imageprovider-example.qml new file mode 100644 index 0000000..5f4c99b --- /dev/null +++ b/doc/codesnippets/examples/declarative/cppextensions/imageprovider/imageprovider-example.qml @@ -0,0 +1,9 @@ +import QtQuick 1.0 +import "ImageProviderCore" // import the plugin that registers the color image provider + +//![0] +Column { + Image { source: "image://colors/yellow" } + Image { source: "image://colors/red" } +} +//![0] diff --git a/doc/codesnippets/examples/graphicsview/simpleanchorlayout/main.cpp b/doc/codesnippets/examples/graphicsview/simpleanchorlayout/main.cpp new file mode 100644 index 0000000..b35f279 --- /dev/null +++ b/doc/codesnippets/examples/graphicsview/simpleanchorlayout/main.cpp @@ -0,0 +1,23 @@ + +//! [adding a corner anchor in two steps] +layout.addAnchor(a, Qt.AnchorTop, layout, Qt.AnchorTop) +layout.addAnchor(a, Qt.AnchorLeft, layout, Qt.AnchorLeft) +//! [adding a corner anchor in two steps] + +//! [adding a corner anchor] +layout.addCornerAnchors(a, Qt.TopLeftCorner, layout, Qt.TopLeftCorner) +//! [adding a corner anchor] + +//! [adding anchors] +layout.addAnchor(b, Qt.AnchorLeft, a, Qt.AnchorRight) +layout.addAnchor(b, Qt.AnchorTop, a, Qt.AnchorBottom) +//! [adding anchors] + +//! [adding anchors to match sizes in two steps] +layout.addAnchor(b, Qt.AnchorLeft, c, Qt.AnchorLeft) +layout.addAnchor(b, Qt.AnchorRight, c, Qt.AnchorRight) +//! [adding anchors to match sizes in two steps] + +//! [adding anchors to match sizes] +layout.addAnchors(b, c, Qt.Horizontal) +//! [adding anchors to match sizes] diff --git a/doc/codesnippets/examples/mainwindows/sdi/mainwindow.cpp b/doc/codesnippets/examples/mainwindows/sdi/mainwindow.cpp new file mode 100644 index 0000000..6e1236e --- /dev/null +++ b/doc/codesnippets/examples/mainwindows/sdi/mainwindow.cpp @@ -0,0 +1,11 @@ + +//! [implicit tr context] +def createMenus(self): + fileMenu = menuBar().addMenu("&File") +//! [implicit tr context] + +//! [0] + fileToolBar = addToolBar("File") + fileToolBar.addAction(newAct) + fileToolBar.addAction(openAct) +//! [0] diff --git a/doc/codesnippets/examples/widgets/groupbox/window.cpp b/doc/codesnippets/examples/widgets/groupbox/window.cpp new file mode 100644 index 0000000..688f02a --- /dev/null +++ b/doc/codesnippets/examples/widgets/groupbox/window.cpp @@ -0,0 +1,138 @@ + +//! [0] +def __init__(self, parent = None): + QWidget.__init__(self, parent) + + grid = QGridLayout() + grid.addWidget(createFirstExclusiveGroup(), 0, 0) + grid.addWidget(createSecondExclusiveGroup(), 1, 0) + grid.addWidget(createNonExclusiveGroup(), 0, 1) + grid.addWidget(createPushButtonGroup(), 1, 1) + setLayout(grid) + + setWindowTitle("Group Boxes") + resize(480, 320) + +//! [0] + +//! [1] +def createFirstExclusiveGroup(self): +//! [2] + groupBox = QGroupBox("Exclusive Radio Buttons") + + radio1 = QRadioButton("&Radio button 1") + radio2 = QRadioButton("R&adio button 2") + radio3 = QRadioButton("Ra&dio button 3") + + radio1.setChecked(True) +//! [1] //! [3] + + vbox = QVBoxLayout() + vbox.addWidget(radio1) + vbox.addWidget(radio2) + vbox.addWidget(radio3) + vbox.addStretch(1) + groupBox.setLayout(vbox) +//! [2] + return groupBox +//! [3] + +//! [4] +def createSecondExclusiveGroup(self): + groupBox = QGroupBox("E&xclusive Radio Buttons") + groupBox.setCheckable(True) + groupBox.setChecked(False) +//! [4] + +//! [5] + radio1 = QRadioButton("Rad&io button 1") + radio2 = QRadioButton("Radi&o button 2") + radio3 = QRadioButton("Radio &button 3") + radio1.setChecked(True) + checkBox = QCheckBox("Ind&ependent checkbox") + checkBox.setChecked(True) +//! [5] + +//! [6] + vbox = QVBoxLayout() + vbox.addWidget(radio1) + vbox.addWidget(radio2) + vbox.addWidget(radio3) + vbox.addWidget(checkBox) + vbox.addStretch(1) + groupBox.setLayout(vbox) + + return groupBox +//! [6] + +//! [7] +def createNonExclusiveGroup(self): + groupBox = QGroupBox("Non-Exclusive Checkboxes") + groupBox.setFlat(True) +//! [7] + +//! [8] + checkBox1 = QCheckBox("&Checkbox 1") + checkBox2 = QCheckBox("C&heckbox 2") + checkBox2.setChecked(True) + tristateBox = QCheckBox("Tri-&state button") + tristateBox.setTristate(True) +//! [8] + tristateBox.setCheckState(Qt.PartiallyChecked) + +//! [9] + vbox = QVBoxLayout() + vbox.addWidget(checkBox1) + vbox.addWidget(checkBox2) + vbox.addWidget(tristateBox) + vbox.addStretch(1) + groupBox.setLayout(vbox) + + return groupBox +//! [9] + +//! [10] +def createPushButtonGroup(self): + groupBox = QGroupBox("&Push Buttons") + groupBox.setCheckable(True) + groupBox.setChecked(True) +//! [10] + +//! [11] + pushButton = QPushButton("&Normal Button") + toggleButton = QPushButton("&Toggle Button") + toggleButton.setCheckable(True) + toggleButton.setChecked(True) + flatButton = QPushButton("&Flat Button") + flatButton.setFlat(True) +//! [11] + +//! [12] + popupButton = QPushButton("Pop&up Button") + menu = QMenu(self) + menu.addAction("&First Item") + menu.addAction("&Second Item") + menu.addAction("&Third Item") + menu.addAction("F&ourth Item") + popupButton.setMenu(menu) +//! [12] + + newAction = menu.addAction("Submenu") + QMenu *subMenu = QMenu("Popup Submenu") + subMenu.addAction("Item 1") + subMenu.addAction("Item 2") + subMenu.addAction("Item 3") + newAction.setMenu(subMenu) + +//! [13] + vbox = QVBoxLayout() + vbox.addWidget(pushButton) + vbox.addWidget(toggleButton) + vbox.addWidget(flatButton) + vbox.addWidget(popupButton) + vbox.addStretch(1) + groupBox.setLayout(vbox) + + return groupBox +} +//! [13] diff --git a/doc/codesnippets/snippets/customstyle/main.cpp b/doc/codesnippets/snippets/customstyle/main.cpp new file mode 100644 index 0000000..a1ac4ac --- /dev/null +++ b/doc/codesnippets/snippets/customstyle/main.cpp @@ -0,0 +1,12 @@ + +//! [using a custom style] +import sys +from PySide.QtGui import * + +QApplication.setStyle(CustomStyle()) +app = QApplication(sys.argv) +spinBox = QSpinBox() +spinBox.show() +sys.exit(app.exec_()) + +//! [using a custom style] diff --git a/doc/codesnippets/snippets/phonon.cpp b/doc/codesnippets/snippets/phonon.cpp new file mode 100644 index 0000000..950fe24 --- /dev/null +++ b/doc/codesnippets/snippets/phonon.cpp @@ -0,0 +1,39 @@ + +//![0] +music = Phonon.createPlayer(Phonon.MusicCategory, Phonon.MediaSource("/path/mysong.wav")) +music.play() +//![0] + +parentWidget = QWidget() +url = QUrl("Myfancymusic") + +//![1] +player = Phonon.VideoPlayer(Phonon.VideoCategory, parentWidget) +player.play(url) +//![1] + +//![2] +mediaObject = Phonon.MediaObject(self) +mediaObject.setCurrentSource(Phonon.MediaSource("/mymusic/barbiegirl.wav")) +audioOutput = Phonon.AudioOutput(Phonon.MusicCategory, self) +path = Phonon.createPath(mediaObject, audioOutput) +//![2] + +//![3] +effect = Phonon.Effect(Phonon.BackendCapabilities.availableAudioEffects()[0], self) +path.insertEffect(effect) +//![3] + +//![4] +mediaObject = Phonon.MediaObject(self) + +videoWidget = Phonon.VideoWidget(self) +Phonon.createPath(mediaObject, videoWidget) + +audioOutput = Phonon.AudioOutput(Phonon.VideoCategory, self) +Phonon.createPath(mediaObject, audioOutput) +//![4] + +//![5] +mediaObject.play() +//![5] diff --git a/doc/codesnippets/snippets/phonon/samplebackend/main.cpp b/doc/codesnippets/snippets/phonon/samplebackend/main.cpp new file mode 100644 index 0000000..555f93b --- /dev/null +++ b/doc/codesnippets/snippets/phonon/samplebackend/main.cpp @@ -0,0 +1,66 @@ + +//! [snippet] +def createObject(self, c, parent, args): + if c == BackendInterface.MediaObjectClass: + return MediaObject(parent) + elif c == BackendInterface.VolumeFaderEffectClass: + return VolumeFaderEffect(parent) + elif c == BackendInterface.AudioOutputClass: + return AudioOutput(parent) + elif c == BackendInterface.AudioDataOutputClass: + return AudioDataOutput(parent) + elif c == BackendInterface.VisualizationClass: + return Visualization(parent) + elif c == BackendInterface.VideoDataOutputClass: + return VideoDataOutput(parent) + elif c == BackendInterface.EffectClass: + return Effect(args[0].toInt(), parent) + elif c == BackendInterface.VideoWidgetClass: + return VideoWidget(parent) + return None + +def objectDescriptionIndexes(self, type_): + retval = set() + + if type_ == Phonon.AudioOutputDeviceType: + # use AudioDeviceEnumerator to list ALSA and OSS devices + retval.add(10000) + retval.add(10001) + elif type_ == Phonon.AudioCaptureDeviceType: + retval.add(20000) + retval.add(20001) + elif type_ == Phonon.VideoCaptureDeviceType: + retval.add(30000) + retval.add(30001) + elif type_ == Phonon.EffectType: + retval.add(0x7F000001) + return retval + +def objectDescriptionProperties(self, type_, index): + ret = {} + if type_ == Phonon.AudioOutputDeviceType: + if index == 10000: + ret["name"] = "internal Soundcard" + elif index == 10001: + ret["name"] = "USB Headset" + ret["available"] = False + elif type_ == Phonon.AudioCaptureDeviceType: + if index == 20000: + ret["name"] = "Soundcard" + ret["description"] = "first description" + elif index == 20001: + ret["name"] = "DV" + ret["description"] = "second description" + elif type_ == Phonon.VideoCaptureDeviceType: + elif index == 30000: + ret["name"] = "USB Webcam" + ret["description"] = "first description" + elif index == 30001: + ret["name"] = "DV")) + ret["description"] = "second description" + elif type_ == Phonon.EffectType: + if index == 0x7F000001: + ret["name"] = "Delay" + ret["description"] = "Simple delay effect with time, feedback and level controls." + return ret +//! [snippet] diff --git a/doc/codesnippets/webkitsnippets/qtwebkit_qwebinspector_snippet.cpp b/doc/codesnippets/webkitsnippets/qtwebkit_qwebinspector_snippet.cpp new file mode 100644 index 0000000..c8245b6 --- /dev/null +++ b/doc/codesnippets/webkitsnippets/qtwebkit_qwebinspector_snippet.cpp @@ -0,0 +1,11 @@ + +def wrapInFunction(): +//! [0] + # ... + page = QWebPage() + # ... + + inspector = QWebInspector() + inspector.setPage(page) +//! [0] + diff --git a/doc/codesnippets/webkitsnippets/qtwebkit_qwebview_snippet.cpp b/doc/codesnippets/webkitsnippets/qtwebkit_qwebview_snippet.cpp new file mode 100644 index 0000000..19a6835 --- /dev/null +++ b/doc/codesnippets/webkitsnippets/qtwebkit_qwebview_snippet.cpp @@ -0,0 +1,31 @@ + +def wrapInFunction(): +//! [0] + view.page().history() +//! [0] + + +//! [1] + view.page().settings() +//! [1] + + +//! [2] + view.triggerAction(QWebPage.Copy) +//! [2] + + +//! [3] + view.page().triggerPageAction(QWebPage.Stop) +//! [3] + + +//! [4] + view.page().triggerPageAction(QWebPage.GoBack) +//! [4] + + +//! [5] + view.page().triggerPageAction(QWebPage.GoForward) +//! [5] + diff --git a/doc/codesnippets/webkitsnippets/webpage/main.cpp b/doc/codesnippets/webkitsnippets/webpage/main.cpp new file mode 100644 index 0000000..4fa1949 --- /dev/null +++ b/doc/codesnippets/webkitsnippets/webpage/main.cpp @@ -0,0 +1,33 @@ +//! [0] +class Thumbnailer (QObject): + def __init__(self, url): +//! [1] + QObject.__init__(self) + self.page = QWebPage() + self.page.mainFrame().load(url) + page.loadFinished[bool].connect(self.render) +//! [1] + + finished = Signal() + +//! [2] + def render(self): + self.page.setViewportSize(self.page.mainFrame().contentsSize()) + image = QImage(self.page.viewportSize(), QImage.Format_ARGB32) + painter = QPainter(image) + + self.page.mainFrame().render(painter) + painter.end() + + thumbnail = image.scaled(400, 400) + thumbnail.save("thumbnail.png") + + self.finished.emit() +//! [2] +//! [0] + +app = QApplication(sys.argv) + +thumbnail = Thumbnailer(QUrl("http://qt.nokia.com")) +thumbnail.finished.connect(app.quit) +sys.exit(app.exec_()) diff --git a/doc/extras/PySide.QtTest.rst b/doc/extras/PySide.QtTest.rst new file mode 100644 index 0000000..d5963cb --- /dev/null +++ b/doc/extras/PySide.QtTest.rst @@ -0,0 +1,7 @@ +To include the definitions of the module's classes, use the following directive: + +:: + + import PySide.QtTest + +.. note:: All macros in the C++ version of QtTest were not binded in PySide, this module is useful only for GUI testing and benchmarking, for ordinary unit testing you should use the ``unittest`` Python module. diff --git a/doc/extras/PySide.QtUiTools.rst b/doc/extras/PySide.QtUiTools.rst new file mode 100644 index 0000000..c8558f2 --- /dev/null +++ b/doc/extras/PySide.QtUiTools.rst @@ -0,0 +1,9 @@ +These forms are processed at run-time to produce dynamically-generated user interfaces. In order to generate a form at run-time, a resource file containing a UI file is needed. + +A form loader object, provided by the QUiLoader class, is used to construct the user interface. This user interface can be retrieved from any QIODevice; for example, a QFile object can be used to obtain a form stored in a project's resources. The :meth:`PySide.QtUiTools.QUiLoader.load` function takes the user interface description contained in the file and constructs the form widget. + +To include the definitions of the module's classes, use the following directive: + +:: + + import PySide..QtUiTools From 632105b470da139380275c55d47076e4440f14ff Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 4 Mar 2011 11:36:55 -0300 Subject: [PATCH 002/489] Version bump to 1.0.1 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f56b8b..b38bccb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,7 +63,7 @@ endif() set(BINDING_NAME PySide) set(BINDING_API_MAJOR_VERSION "1") set(BINDING_API_MINOR_VERSION "0") -set(BINDING_API_MICRO_VERSION "0") +set(BINDING_API_MICRO_VERSION "1") set(BINDING_API_RELEASE_LEVEL "final") # alpha, beta, rc, or final set(BINDING_API_SERIAL 1) # leave as 0 when release level is final set(BINDING_API_VERSION "${BINDING_API_MAJOR_VERSION}.${BINDING_API_MINOR_VERSION}.${BINDING_API_MICRO_VERSION}" CACHE STRING "PySide version" FORCE) From 36fdd023e0d470bc3feb7472985f59eedc0a0857 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 4 Mar 2011 11:35:54 -0300 Subject: [PATCH 003/489] Removed Signal/Slot documentation content. --- doc/extras/PySide.QtCore.Signal.rst | 106 +--------------------------- doc/extras/PySide.QtCore.Slot.rst | 85 ---------------------- 2 files changed, 1 insertion(+), 190 deletions(-) diff --git a/doc/extras/PySide.QtCore.Signal.rst b/doc/extras/PySide.QtCore.Signal.rst index a0318d4..b4c4e36 100644 --- a/doc/extras/PySide.QtCore.Signal.rst +++ b/doc/extras/PySide.QtCore.Signal.rst @@ -25,110 +25,6 @@ Detailed Description PySide adopt PyQt's new signal and slot syntax as-is. The PySide implementation is functionally compatible with the PyQt 4.5 one, with the exceptions listed bellow. - .. note:: Parts of the documentation bellow are from the `PyQt4 documentation `_ public available on the internet Copyright (c) 2010 Riverbank Computing Limited just modified to fit the PySide implementation. - - -Defining New Signals with QtCore.Signal() ------------------------------------------ - - PySide automatically defines signals for all Qt's built-in signals. New signals can be defined as class attributes using the QtCore.Signal() factory. - - QtCore.Signal() takes a number of type arguments that corresponds to the signature of the signal. Each type may be a Python type object or a string that is the name of a C++ type. Alternatively each argument could be a sequence of type arguments. In this case each sequence defines the signature of a different signal overload. The first overload will be the default. - - QtCore.Signal() takes an optional name keyword argument that is the name of the signal. If it is omitted then the name of the class attribute is used. - - The following example shows the definition of a number of new signals: - - :: - - from PySide import QtCore - - class Foo(QtCore.QObject): - - # This defines a signal called 'closed' that takes no arguments. - closed = QtCore.Signal() - - # This defines a signal called 'rangeChanged' that takes two - # integer arguments. - range_changed = QtCore.Signal(int, int, name='rangeChanged') - - # This defines a signal called 'valueChanged' that has two overloads, - # one that takes an integer argument and one that takes a QString - # argument. - valueChanged = QtCore.Signal((int, ), (unicode, )) - - # The following will create exactly the same overloaded signal as - # above and demonstrates the use of C++ type names instead of Python - # type objects, and lists instead of tuples. - valueChanged = QtCore.Signal(['int'], ['unicode']) - - New signals should only be defined in sub-classes of QObject. - - New signals defined in this way will be automatically added to the class's QMetaObject. This means that they will appear in Qt Designer and can be introspected using the QMetaObject API. - -Connecting, Disconnecting and Emitting Signals ----------------------------------------------- - - Signals are connected and disconnected to slots using the :meth:`Signal.connect` and :meth:`Signal.disconnect` methods of a bound signal and emitted using the :meth:`Signal.emit` method. - - The following code demonstrates the definition, connection and emit of a signal without arguments: - - :: - - from PySide import QtCore - - class Foo(QtCore.QObject): - # Define a new signal called 'trigger' that has no arguments. - trigger = QtCore.Signal() - - def connect_and_emit_trigger(self): - # Connect the trigger signal to a slot. - self.trigger.connect(self.handle_trigger) - - # Emit the signal. - self.trigger.emit() - - def handle_trigger(self): - # Show that the slot has been called. - print "trigger signal received" - - The following code demonstrates the connection of overloaded signals: - - :: - - from PySide import QtGui - - class Bar(QtGui.QComboBox): - - def connect_activated(self): - # Avoid using default overloads, they are not safe and can change in the future. - self.activated.connect(self.handle_int) - - # For non-default overloads we have to specify which we want to - # connect. In this case the one with the single string argument. - # (Note that we could also explicitly specify the default if we - # wanted to.) - self.activated[str].connect(self.handle_string) - - def handle_int(self, index): - print "activated signal passed integer", index - - def handle_string(self, text): - print "activated signal passed string", text - -Connecting Signals Using Keyword Arguments ------------------------------------------- - - It is also possible to connect signals by passing a slot as a keyword argument corresponding to the name of the signal when creating an object. For example the following three fragments are equivalent: - - :: - - act = QtGui.QAction("Action", self) - act.triggered.connect(self.on_triggered) - - act = QtGui.QAction("Action", self, triggered=self.on_triggered) - - .. method:: Signal.connect(receiver[, type=Qt.AutoConnection]) Create a connection between this signal and a `receiver`, the `receiver` can be a Python callable, a :class:`Slot` or a :class:`Signal`. @@ -139,5 +35,5 @@ Connecting Signals Using Keyword Arguments .. method:: Signal.emit(*args) - `args` is the optional sequence of arguments to pass to any connected slots. + `args` is the arguments to pass to any connected slots, if any. diff --git a/doc/extras/PySide.QtCore.Slot.rst b/doc/extras/PySide.QtCore.Slot.rst index 27791d0..38654f9 100644 --- a/doc/extras/PySide.QtCore.Slot.rst +++ b/doc/extras/PySide.QtCore.Slot.rst @@ -8,88 +8,3 @@ Detailed Description -------------------- PySide adopt PyQt's new signal and slot syntax as-is. The PySide implementation is functionally compatible with the PyQt 4.5 one, with the exceptions listed bellow. - - .. note:: Parts of the documentation bellow are from the `PyQt4 documentation `_ public available on the internet Copyright (c) 2010 Riverbank Computing Limited just modified to fit the PySide implementation. - - Although PySide allows any Python callable to be used as a slot when connecting signals, it is sometimes necessary to explicitly mark a Python method as being a Qt slot and to provide a C++ signature for it. PySide provides the QtCore.Slot() function decorator to do this. - - All of the non-keyword arguments to the decorator are interpreted as the types of the corresponding C++ arguments. A type is either a Python type object or a string that specifies a C++ type. The decorator also takes two optional keywords arguments: name and result. name is the name of the slot that will be seen by C++. If ommitted the name of the Python method being decorated will be used. result is the type of the result and may also be a Python type object or a string that specifies a C++ type. - - For example: - - :: - - @QtCore.Slot() - def foo(self): - """ C++: void foo() """ - - @QtCore.Slot(int, unicode) - def foo(self, arg1, arg2): - """ C++: void foo(int, QString) """ - - @QtCore.Slot(int, name='bar') - def foo(self, arg1): - """ C++: void bar(int) """ - - @QtCore.Slot(int, result=int) - def foo(self, arg1): - """ C++: int foo(int) """ - - @QtCore.Slot(int, QtGui.QWidget) - def foo(self, arg1): - """ C++: int foo(int, QWidget*) """ - - It is also possible to chain the decorators in order to define a Python method several times with different signatures. - - For example: - - :: - - @QtCore.Slot(int) - @QtCore.Slot('QString') - def valueChanged(self, value): - """ Two slots will be defined in the QMetaObject. """ - -Connecting Slots By Name ------------------------- - - PySide supports the QtCore.QMetaObject.connectSlotsByName() function that is most commonly used by pyside-uic generated Python code to automatically connect signals to slots that conform to a simple naming convention besides the QtCore.Slot decoration. - - For example the :class:`PySide.QtGui.QSpinBox` class has the following signals: - - :: - - void valueChanged(int i); - void valueChanged(const QString& text); - - For example, if you were interested in the integer variant of the signal then your slot definition would look like the following: - - :: - - @QtCore.Slot(int) - def on_spinbox_valueChanged(self, i): - # i will be an integer. - pass - - If you wanted to handle both variants of the signal, but with different Python methods, then your slot definitions might look like the following: - - :: - - @QtCore.Slot(int, name='on_spinbox_valueChanged') - def spinbox_int_value(self, i): - # i will be an integer. - pass - - @QtCore.Slot(unicode, name='on_spinbox_valueChanged') - def spinbox_qstring_value(self, s): - # s will be a Python unicode object. - pass - - The following shows an example using a button when you are not interested in the optional argument: - - :: - - @QtCore.Slot() - def on_button_clicked(self): - pass - From 8b261892b87b6261810b0085b75374467a4ae243 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 4 Mar 2011 13:10:38 -0300 Subject: [PATCH 004/489] Last code snippets.... --- .../src/snippets/qxmlschemavalidator/main.cpp | 63 +++++++++++++++++++ .../imageprovider/imageprovider.cpp | 33 ++++++++++ .../cppextensions/plugins/plugin.cpp | 19 ++++++ 3 files changed, 115 insertions(+) create mode 100644 doc/codesnippets/doc/src/snippets/qxmlschemavalidator/main.cpp create mode 100644 doc/codesnippets/examples/declarative/cppextensions/imageprovider/imageprovider.cpp create mode 100644 doc/codesnippets/examples/declarative/cppextensions/plugins/plugin.cpp diff --git a/doc/codesnippets/doc/src/snippets/qxmlschemavalidator/main.cpp b/doc/codesnippets/doc/src/snippets/qxmlschemavalidator/main.cpp new file mode 100644 index 0000000..5c15482 --- /dev/null +++ b/doc/codesnippets/doc/src/snippets/qxmlschemavalidator/main.cpp @@ -0,0 +1,63 @@ + +def validateFromUrl(): +//! [0] + schema = getSchema() + + url = QUrl("http://www.schema-example.org/test.xml") + + validator = QXmlSchemaValidator(schema) + if validator.validate(url): + print "instance document is valid" + else: + print "instance document is invalid" +//! [0] + +def validateFromFile(): +//! [1] + schema = getSchema() + + file = QFile("test.xml") + file.open(QIODevice.ReadOnly) + + validator = QXmlSchemaValidator(schema) + if validator.validate(file, QUrl.fromLocalFile(file.fileName())): + print "instance document is valid" + else: + print "instance document is invalid" +//! [1] +} + +def validateFromData(): +//! [2] + schema = getSchema() + + data = QByteArray("") + + buffer = QBuffer(data) + buffer.open(QIODevice.ReadOnly) + + QXmlSchemaValidator validator(schema) + if validator.validate(buffer): + print "instance document is valid" + else: + print "instance document is invalid" +//! [2] + +def validateComplete(): +//! [3] + schemaUrl = QUrl("file:///home/user/schema.xsd") + + schema = QXmlSchema() + schema.load(schemaUrl) + + if schema.isValid(): + file = QFile("test.xml") + file.open(QIODevice.ReadOnly) + + validator = QXmlSchemaValidator(schema) + if validator.validate(file, QUrl.fromLocalFile(file.fileName())): + print "instance document is valid" + else: + print "instance document is invalid" + } +//! [3] diff --git a/doc/codesnippets/examples/declarative/cppextensions/imageprovider/imageprovider.cpp b/doc/codesnippets/examples/declarative/cppextensions/imageprovider/imageprovider.cpp new file mode 100644 index 0000000..7be620b --- /dev/null +++ b/doc/codesnippets/examples/declarative/cppextensions/imageprovider/imageprovider.cpp @@ -0,0 +1,33 @@ +//![0] +class ColorImageProvider (QDeclarativeImageProvider): + def __init__(self): + QDeclarativeImageProvider.__init__(self, QDeclarativeImageProvider.Pixmap) + + def requestPixmap(id, size, requestedSize): + width = 100 + height = 50 + + if size: + size.setWidth(width) + size.setHeight(height) + + if requestedSize.width() > 0: + width = requestedSize.width() + if requestedSize.height() > 0: + height = requestedSize.height() + + pixmap = QPixmap(width, height) + pixmap.fill(QColor(id).rgba()) +//![0] + # write the color name + painter = QPainter(pixmap) + f = painter.font() + f.setPixelSize(20) + painter.setFont(f) + painter.setPen(Qt.black) + if requestedSize.isValid(): + painter.scale(requestedSize.width() / width, requestedSize.height() / height) + painter.drawText(QRectF(0, 0, width, height), Qt.AlignCenter, id) +//![1] + return pixmap +//![1] diff --git a/doc/codesnippets/examples/declarative/cppextensions/plugins/plugin.cpp b/doc/codesnippets/examples/declarative/cppextensions/plugins/plugin.cpp new file mode 100644 index 0000000..eef2ad7 --- /dev/null +++ b/doc/codesnippets/examples/declarative/cppextensions/plugins/plugin.cpp @@ -0,0 +1,19 @@ + +//![0] +class TimeModel (QObject): + hour = Property(int, getHour, notify = timeChanged) + minute = Property(int, getMinute, notify = timeChanged) +//![0] + +//![plugin] +class QExampleQmlPlugin (QDeclarativeExtensionPlugin): + + def registerTypes(self, uri): + assert(uri == "com.nokia.TimeExample") + qmlRegisterType(TimeModel, uri, 1, 0, "Time") +//![plugin] + +//![export] +# This isn't supported by PySide yet. +# Q_EXPORT_PLUGIN2(qmlqtimeexampleplugin, QExampleQmlPlugin); +//![export] From c453a7ca2bc1ca5f752c1defec43ac1d65f7b997 Mon Sep 17 00:00:00 2001 From: Lauro Neto Date: Fri, 4 Mar 2011 16:00:56 -0300 Subject: [PATCH 005/489] Remove duplicated const functions from QRegExp Reviewer: Luciano Wolf Reviewer: Marcelo Lira --- PySide/QtCore/typesystem_core.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/PySide/QtCore/typesystem_core.xml b/PySide/QtCore/typesystem_core.xml index 85df6f3..6a0d882 100644 --- a/PySide/QtCore/typesystem_core.xml +++ b/PySide/QtCore/typesystem_core.xml @@ -1450,6 +1450,13 @@ + + + + + + From e8a8e3c63e85524bc2edfec1fccf2104cda87f38 Mon Sep 17 00:00:00 2001 From: Renato Filho Date: Wed, 9 Mar 2011 17:17:43 -0300 Subject: [PATCH 006/489] Removed parent policy from QLabel.setPixmap. This is not a parent transfer because the function receives a "const &" and stores a copy of the pixmap. Fixes bug #714. Reviewer: Luciano Wolf Marcelo Lira --- PySide/QtGui/typesystem_gui_common.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/PySide/QtGui/typesystem_gui_common.xml b/PySide/QtGui/typesystem_gui_common.xml index e1a6f40..8c2c0ed 100644 --- a/PySide/QtGui/typesystem_gui_common.xml +++ b/PySide/QtGui/typesystem_gui_common.xml @@ -3979,12 +3979,6 @@ - - - - - - From 40bbb494874e4f39ca814e23af3f27b9804e7429 Mon Sep 17 00:00:00 2001 From: Renato Filho Date: Wed, 9 Mar 2011 17:18:11 -0300 Subject: [PATCH 007/489] Created unit test for bug #714. Reviewer: Luciano Wolf Marcelo Lira --- tests/QtGui/CMakeLists.txt | 1 + tests/QtGui/bug_714.py | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 tests/QtGui/bug_714.py diff --git a/tests/QtGui/CMakeLists.txt b/tests/QtGui/CMakeLists.txt index 3897532..5a6931d 100644 --- a/tests/QtGui/CMakeLists.txt +++ b/tests/QtGui/CMakeLists.txt @@ -41,6 +41,7 @@ PYSIDE_TEST(bug_667.py) PYSIDE_TEST(bug_668.py) PYSIDE_TEST(bug_674.py) PYSIDE_TEST(bug_675.py) +PYSIDE_TEST(bug_714.py) PYSIDE_TEST(customproxywidget_test.py) PYSIDE_TEST(deepcopy_test.py) PYSIDE_TEST(float_to_int_implicit_conversion_test.py) diff --git a/tests/QtGui/bug_714.py b/tests/QtGui/bug_714.py new file mode 100644 index 0000000..937ff82 --- /dev/null +++ b/tests/QtGui/bug_714.py @@ -0,0 +1,21 @@ +import unittest +import sys +from PySide.QtGui import QLabel, QApplication, QPixmap + +class TestLabelPixmap(unittest.TestCase): + def testReference(self): + l = QLabel() + p = QPixmap() + l.setPixmap(p) # doesn't increment pixmap ref because this makes a copy + self.assertEqual(sys.getrefcount(p), 2) + + p = l.pixmap() # this increment the reference because this is an internal pointer + self.assertEqual(sys.getrefcount(p), 3) + + p2 = l.pixmap() + self.assertEqual(p, p2) + +if __name__ == '__main__': + app = QApplication([]) + unittest.main() + From e2121ae09afcc73fffb1af408dca4ce33988dcda Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 11 Mar 2011 17:30:00 -0300 Subject: [PATCH 008/489] Add comments to some function removals. --- PySide/QtCore/typesystem_core.xml | 81 ++++++++++++++++++------------- 1 file changed, 46 insertions(+), 35 deletions(-) diff --git a/PySide/QtCore/typesystem_core.xml b/PySide/QtCore/typesystem_core.xml index 6a0d882..92659d2 100644 --- a/PySide/QtCore/typesystem_core.xml +++ b/PySide/QtCore/typesystem_core.xml @@ -919,7 +919,7 @@ Py_XINCREF(%PYARG_0); - + @@ -941,8 +941,6 @@ - - @@ -1565,13 +1563,14 @@ #endif - + %PYARG_0 = PyString_FromStringAndSize(%CPPSELF.%FUNCTION_NAME(), %CPPSELF.size()); + @@ -1579,10 +1578,11 @@ + + + - - @@ -1893,12 +1893,10 @@ + - - - - + @@ -1920,9 +1918,13 @@ + + + + @@ -2057,11 +2059,13 @@ + - + + @@ -2100,10 +2104,8 @@ - - - + @@ -2181,7 +2183,7 @@ - + @@ -2193,8 +2195,13 @@ + + + + + @@ -2202,7 +2209,7 @@ - + @@ -2210,8 +2217,6 @@ - - @@ -2225,6 +2230,10 @@ %PYARG_0 = Shiboken::makeTuple(retval, pid); + + + + @@ -2260,10 +2269,10 @@ - - + - + + @@ -2336,6 +2345,7 @@ + @@ -2348,7 +2358,9 @@ + + @@ -2361,6 +2373,7 @@ + *(%CPPSELF) << %1; @@ -2426,8 +2439,6 @@ } - - @@ -2437,11 +2448,8 @@ %PYARG_0 = %CONVERTTOPYTHON[int](r); - - - @@ -2564,7 +2572,9 @@ - + + + @@ -2632,10 +2642,6 @@ - - - - @@ -2647,8 +2653,6 @@ - - @@ -2692,15 +2696,19 @@ + + + + @@ -2798,7 +2806,10 @@ + http://bugs.pyside.org/show_bug.cgi?id=201 + Se also bug: + http://bugs.pyside.org/show_bug.cgi?id=725 + --> @@ -2943,7 +2954,7 @@ - + From 945f9bffd9e1b2dd797110c0a1738a3f273bc21f Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 11 Mar 2011 17:42:21 -0300 Subject: [PATCH 009/489] Fix bug 718 - "PySide/PyQt4 QByteArray incompatibilities: setNum method" Fix bug 719 - "PySide/PyQt4 QByteArray incompatibilities: appendByte method" --- PySide/QtCore/typesystem_core.xml | 148 ++++-------------------------- tests/QtCore/qbytearray_test.py | 19 ++++ 2 files changed, 35 insertions(+), 132 deletions(-) diff --git a/PySide/QtCore/typesystem_core.xml b/PySide/QtCore/typesystem_core.xml index 92659d2..b261a2a 100644 --- a/PySide/QtCore/typesystem_core.xml +++ b/PySide/QtCore/typesystem_core.xml @@ -1592,26 +1592,27 @@ + + + + + + + + + + + + + - - - - - - - - - char c = PyString_AS_STRING(%PYARG_1)[0]; - if (c) { - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%CPPSELF.%FUNCTION_NAME(c)); - } - - + + @@ -1678,81 +1679,8 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1762,50 +1690,6 @@ %PYARG_0 = %CONVERTTOPYTHON[QByteArray](QByteArray(%1)); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/QtCore/qbytearray_test.py b/tests/QtCore/qbytearray_test.py index fa838c1..4a600ba 100644 --- a/tests/QtCore/qbytearray_test.py +++ b/tests/QtCore/qbytearray_test.py @@ -28,6 +28,25 @@ class QByteArrayTestToNumber(unittest.TestCase): self.assertEqual((ctypes.c_double(37.109).value, True), obj.toDouble()) + def testSetNum(self): + b = QByteArray() + b.setNum(-124124L) + self.assertEqual(b, "-124124") + b = QByteArray() + b.setNum(-124124) + self.assertEqual(b, "-124124") + b = QByteArray() + b.setNum(-0.5) + self.assertEqual(b, "-0.5") + + def testAppend(self): + b = QByteArray() + b.append("A") + self.assertEqual(b.size(), 1) + b.append("AB") + self.assertEqual(b.size(), 3) + + class QByteArraySplit(unittest.TestCase): '''Test case for QByteArray.split''' From a8be4c2326f01aa6ad209e3f9787553088e16b11 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 15 Mar 2011 16:54:55 -0300 Subject: [PATCH 010/489] Add unit test for bug 706 - "dataChanged signal raise an incorrect TypeError" Reviewer: Marcelo Lira Luciano Wolf --- tests/QtCore/CMakeLists.txt | 1 + tests/QtCore/bug_706.py | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 tests/QtCore/bug_706.py diff --git a/tests/QtCore/CMakeLists.txt b/tests/QtCore/CMakeLists.txt index c6f9ffd..434c8fe 100644 --- a/tests/QtCore/CMakeLists.txt +++ b/tests/QtCore/CMakeLists.txt @@ -6,6 +6,7 @@ PYSIDE_TEST(bug_462.py) PYSIDE_TEST(bug_505.py) PYSIDE_TEST(bug_515.py) PYSIDE_TEST(bug_656.py) +PYSIDE_TEST(bug_706.py) PYSIDE_TEST(blocking_signals_test.py) PYSIDE_TEST(child_event_test.py) PYSIDE_TEST(deepcopy_test.py) diff --git a/tests/QtCore/bug_706.py b/tests/QtCore/bug_706.py new file mode 100644 index 0000000..1825029 --- /dev/null +++ b/tests/QtCore/bug_706.py @@ -0,0 +1,27 @@ +import unittest + +from PySide.QtCore import * + +class MyModel (QAbstractListModel): + def rowCount(self, parent = None): + return 3 + +class TestBug706(unittest.TestCase): + + def mySlot(self, idx, start, end): + self.start = start + self.end = end + + def testIt(self): + self.start = None + self.end = None + + app = QCoreApplication([]) + model = MyModel() + model.columnsAboutToBeInserted.connect(self.mySlot) + model.columnsAboutToBeInserted.emit(QModelIndex(), 0, 1) + self.assertEqual(self.start, 0) + self.assertEqual(self.end, 1) + +if __name__ == '__main__': + unittest.main() From 32fb36f97ac76ef23271049dbb6642bf7bfed557 Mon Sep 17 00:00:00 2001 From: Renato Filho Date: Fri, 11 Mar 2011 15:56:25 -0300 Subject: [PATCH 011/489] Fix QToolbar.clear parent policy. Fixes bug #711. Reviewer: Luciano Wolf Lauro Moura --- PySide/QtGui/typesystem_gui_common.xml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/PySide/QtGui/typesystem_gui_common.xml b/PySide/QtGui/typesystem_gui_common.xml index 8c2c0ed..970447a 100644 --- a/PySide/QtGui/typesystem_gui_common.xml +++ b/PySide/QtGui/typesystem_gui_common.xml @@ -4601,6 +4601,26 @@ + + + QList<PyObject* > lst; + Shiboken::BindingManager& bm = Shiboken::BindingManager::instance(); + foreach(QToolButton* child, %CPPSELF.findChildren<QToolButton*>()) { + if (bm.hasWrapper(child)) { + PyObject* pyChild = %CONVERTTOPYTHON[QToolButton*](child); + Shiboken::Object::setParent(0, pyChild); + lst << pyChild; + } + } + + %CPPSELF.clear(); + + foreach(PyObject* obj, lst) { + Shiboken::Object::invalidate(reinterpret_cast<SbkObject* >(obj)); + Py_XDECREF(obj); + } + + From d3fb0b38b76eb9a08a60c1a5667388afe9521fea Mon Sep 17 00:00:00 2001 From: Renato Filho Date: Fri, 11 Mar 2011 15:57:27 -0300 Subject: [PATCH 012/489] Created unit test for bug #711. Reviewer: Luciano Wolf Lauro Moura --- tests/QtGui/bug_711.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/QtGui/bug_711.py diff --git a/tests/QtGui/bug_711.py b/tests/QtGui/bug_711.py new file mode 100644 index 0000000..f3d0b59 --- /dev/null +++ b/tests/QtGui/bug_711.py @@ -0,0 +1,21 @@ +import unittest +import sys +from PySide.QtGui import QToolBar, QApplication, QAction, QToolButton + +class TestLabelPixmap(unittest.TestCase): + def testReference(self): + toolbar = QToolBar() + + for i in xrange(20): + toolbar.addAction(QAction("Action %d" % i, None)) + + buttons = toolbar.findChildren(QToolButton, "") + toolbar.clear() + + for b in buttons: + self.assertRaises(RuntimeError, b.objectName) + +if __name__ == '__main__': + app = QApplication([]) + unittest.main() + From 855ad2d587161e8ae3ea7b0c64d30f73130e3cd8 Mon Sep 17 00:00:00 2001 From: Renato Filho Date: Tue, 15 Mar 2011 15:33:30 -0300 Subject: [PATCH 013/489] Check if class is valid before call meta object function on class getattro function. Fix bug #696. Reviewer: Hugo Parente Lima Marcelo Lira --- libpyside/pyside.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libpyside/pyside.cpp b/libpyside/pyside.cpp index ae3ce3f..7fe39ea 100644 --- a/libpyside/pyside.cpp +++ b/libpyside/pyside.cpp @@ -228,6 +228,9 @@ void initQObjectSubType(SbkObjectType* type, PyObject* args, PyObject* kwds) PyObject* getMetaDataFromQObject(QObject* cppSelf, PyObject* self, PyObject* name) { + if (!Shiboken::Object::isValid(self)) + return 0; + PyObject* attr = PyObject_GenericGetAttr(self, name); if (attr && Property::isPropertyType(attr)) { PyObject *value = Property::getValue(reinterpret_cast(attr), self); From 734e08632729128135844b5c98817b4881a00a68 Mon Sep 17 00:00:00 2001 From: Renato Filho Date: Tue, 15 Mar 2011 15:34:33 -0300 Subject: [PATCH 014/489] Created unit test for bug #696. Reviewer: Hugo Parente Lima Marcelo Lira --- tests/QtGui/CMakeLists.txt | 1 + tests/QtGui/bug_696.py | 43 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 tests/QtGui/bug_696.py diff --git a/tests/QtGui/CMakeLists.txt b/tests/QtGui/CMakeLists.txt index 5a6931d..68be0de 100644 --- a/tests/QtGui/CMakeLists.txt +++ b/tests/QtGui/CMakeLists.txt @@ -41,6 +41,7 @@ PYSIDE_TEST(bug_667.py) PYSIDE_TEST(bug_668.py) PYSIDE_TEST(bug_674.py) PYSIDE_TEST(bug_675.py) +PYSIDE_TEST(bug_696.py) PYSIDE_TEST(bug_714.py) PYSIDE_TEST(customproxywidget_test.py) PYSIDE_TEST(deepcopy_test.py) diff --git a/tests/QtGui/bug_696.py b/tests/QtGui/bug_696.py new file mode 100644 index 0000000..b165d04 --- /dev/null +++ b/tests/QtGui/bug_696.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. 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. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +import sys +import unittest + +from helper import UsesQApplication +from PySide.QtGui import QMainWindow, QMenu, QApplication + +class MainWindow(QMainWindow): + def __init__(self, *args): + self._menu = QMenu(self.dontexist) # attribute called with invalid C++ object + +class Bug696(UsesQApplication): + def testContructorInitialization(self): + self.assertRaises(RuntimeError, MainWindow) + +if __name__ == '__main__': + unittest.main() + From 9fd4705cf6093b7962ac6b82668362cb00db0341 Mon Sep 17 00:00:00 2001 From: Renato Filho Date: Wed, 16 Mar 2011 11:40:50 -0300 Subject: [PATCH 015/489] Fixed test for bug #674 to works with new getattr check. Reviewer: Hugo Parente Lima Marcelo Lira --- tests/QtGui/bug_674.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/QtGui/bug_674.py b/tests/QtGui/bug_674.py index 4d015b5..4b9ac19 100644 --- a/tests/QtGui/bug_674.py +++ b/tests/QtGui/bug_674.py @@ -16,7 +16,7 @@ class TestBug679(unittest.TestCase): scene.clear() self.assertEqual(sys.getrefcount(hello), 2) self.assertEqual(len(scene.items()), 0) - self.assertRaises(RuntimeError, hello.isVisible) # the C++ object was deleted + self.assertRaises(RuntimeError, lambda: hello.isVisible) # the C++ object was deleted if __name__ == '__main__': unittest.main() From 120ace2cf9af79157035c266d7fbe27d9a09f76c Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 18 Mar 2011 17:37:00 -0300 Subject: [PATCH 016/489] Add unit test for bug 693 - "Heap corruption or double free reported on program exit" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Renato Araújo Luciano Wolf --- tests/QtGui/CMakeLists.txt | 1 + tests/QtGui/bug_693.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 tests/QtGui/bug_693.py diff --git a/tests/QtGui/CMakeLists.txt b/tests/QtGui/CMakeLists.txt index 68be0de..615e131 100644 --- a/tests/QtGui/CMakeLists.txt +++ b/tests/QtGui/CMakeLists.txt @@ -42,6 +42,7 @@ PYSIDE_TEST(bug_668.py) PYSIDE_TEST(bug_674.py) PYSIDE_TEST(bug_675.py) PYSIDE_TEST(bug_696.py) +PYSIDE_TEST(bug_693.py) PYSIDE_TEST(bug_714.py) PYSIDE_TEST(customproxywidget_test.py) PYSIDE_TEST(deepcopy_test.py) diff --git a/tests/QtGui/bug_693.py b/tests/QtGui/bug_693.py new file mode 100644 index 0000000..4bfbe7c --- /dev/null +++ b/tests/QtGui/bug_693.py @@ -0,0 +1,31 @@ + +from PySide.QtCore import * +from PySide.QtGui import * +import unittest + +class MyModel (QAbstractListModel): + + stupidLine = QLine(0, 0, 10, 10) + + def rowCount(self, parent): + return 1 + + def data(self, index, role): + return self.stupidLine + +class TestBug693(unittest.TestCase): + def testIt(self): + app = QApplication([]) + model = MyModel() + view = QListView() + view.setModel(model) + view.show() + + # This must NOT throw the exception: + # RuntimeError: Internal C++ object (PySide.QtCore.QLine) already deleted. + MyModel.stupidLine.isNull() + + + +if __name__ == "__main__": + unittest.main() From 258995d03cd0cf81288917e073056d64844c003d Mon Sep 17 00:00:00 2001 From: Renato Filho Date: Mon, 21 Mar 2011 10:08:04 -0300 Subject: [PATCH 017/489] Does not use normalizeSignature in functions with return type. Fix bug #726. Reviewer: Luciano Wolf Lauro Moura --- libpyside/pysideslot.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libpyside/pysideslot.cpp b/libpyside/pysideslot.cpp index 28c6ed6..18c044b 100644 --- a/libpyside/pysideslot.cpp +++ b/libpyside/pysideslot.cpp @@ -153,13 +153,15 @@ PyObject* slotCall(PyObject* self, PyObject* args, PyObject* kw) data->slotName = strdup(PyString_AS_STRING(funcName)); } - QString signature; - signature.sprintf("%s %s(%s)", data->resultType, data->slotName, data->args); + QByteArray returnType = QMetaObject::normalizedType(data->resultType); + QByteArray signature = QString().sprintf("%s(%s)", data->slotName, data->args).toAscii(); + signature = returnType + " " + signature; + if (!pySlotName) pySlotName = PyString_FromString(PYSIDE_SLOT_LIST_ATTR); - PyObject *pySignature = PyString_FromString(QMetaObject::normalizedSignature(signature.toAscii())); + PyObject *pySignature = PyString_FromString(signature); PyObject *signatureList = 0; if (PyObject_HasAttr(callback, pySlotName)) { signatureList = PyObject_GetAttr(callback, pySlotName); From 69abc806ec895239154287779dca9c4cac8adcea Mon Sep 17 00:00:00 2001 From: Renato Filho Date: Mon, 21 Mar 2011 10:09:51 -0300 Subject: [PATCH 018/489] Created unit test for bug #726. Reviewer: Luciano Wolf Lauro Moura --- tests/QtDeclarative/CMakeLists.txt | 1 + tests/QtDeclarative/bug_726.py | 41 +++++++++++++++++ tests/QtDeclarative/bug_726.qml | 71 ++++++++++++++++++++++++++++++ tests/signals/decorators_test.py | 10 +++++ 4 files changed, 123 insertions(+) create mode 100644 tests/QtDeclarative/bug_726.py create mode 100644 tests/QtDeclarative/bug_726.qml diff --git a/tests/QtDeclarative/CMakeLists.txt b/tests/QtDeclarative/CMakeLists.txt index 84bc495..01a4172 100644 --- a/tests/QtDeclarative/CMakeLists.txt +++ b/tests/QtDeclarative/CMakeLists.txt @@ -1,6 +1,7 @@ PYSIDE_TEST(bug_451.py) PYSIDE_TEST(bug_456.py) PYSIDE_TEST(bug_557.py) +PYSIDE_TEST(bug_726.py) PYSIDE_TEST(qdeclarativenetwork_test.py) PYSIDE_TEST(qdeclarativeview_test.py) PYSIDE_TEST(connect_python_qml.py) diff --git a/tests/QtDeclarative/bug_726.py b/tests/QtDeclarative/bug_726.py new file mode 100644 index 0000000..fa18aac --- /dev/null +++ b/tests/QtDeclarative/bug_726.py @@ -0,0 +1,41 @@ +from PySide import QtCore, QtGui, QtDeclarative +from helper import adjust_filename, TimedQApplication +import unittest + +class ProxyObject(QtCore.QObject): + def __init__(self): + super(ProxyObject,self).__init__() + self._o = None + self._receivedName = "" + + @QtCore.Slot(result='QObject*') + def getObject(self): + if self._o: + return self._o + + self._o = QtCore.QObject() + self._o.setObjectName("PySideObject") + return self._o + + @QtCore.Slot(str) + def receivedObject(self, name): + self._receivedName = name + + +class TestConnectionWithInvalidSignature(TimedQApplication): + + def testSlotRetur(self): + view = QtDeclarative.QDeclarativeView() + proxy = ProxyObject() + + context = view.rootContext() + context.setContextProperty("proxy", proxy) + view.setSource(QtCore.QUrl.fromLocalFile(adjust_filename('bug_726.qml', __file__))) + root = view.rootObject() + button = root.findChild(QtCore.QObject, "buttonMouseArea") + view.show() + button.entered.emit() + self.assertEqual(proxy._receivedName, "PySideObject") + +if __name__ == '__main__': + unittest.main() diff --git a/tests/QtDeclarative/bug_726.qml b/tests/QtDeclarative/bug_726.qml new file mode 100644 index 0000000..27cf59f --- /dev/null +++ b/tests/QtDeclarative/bug_726.qml @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: PySide Team (pyside@openbossa.org) +** +** This file is part of the examples of PySide: Python for Qt. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt 4.7 + +Rectangle { + id: page + + width: 500; height: 200 + color: "lightgray" + + Rectangle { + id: button + width: 150; height: 40 + color: "darkgray" + anchors.horizontalCenter: page.horizontalCenter + y: 120 + MouseArea { + id: buttonMouseArea + objectName: "buttonMouseArea" + anchors.fill: parent + onEntered: { + proxy.receivedObject(proxy.getObject().objectName) + } + } + Text { + id: buttonText + text: "Press me!" + anchors.horizontalCenter: button.horizontalCenter + anchors.verticalCenter: button.verticalCenter + font.pointSize: 16; + } + } +} diff --git a/tests/signals/decorators_test.py b/tests/signals/decorators_test.py index b25e129..da9c1ca 100644 --- a/tests/signals/decorators_test.py +++ b/tests/signals/decorators_test.py @@ -32,6 +32,10 @@ class MyObject(QObject): def mySlot5(self): self._slotCalledCount = self._slotCalledCount + 1 + @Slot(result=QObject) + def mySlot6(self): + self._slotCalledCount = self._slotCalledCount + 1 + class StaticMetaObjectTest(unittest.TestCase): def testSignalPropagation(self): @@ -56,6 +60,12 @@ class StaticMetaObjectTest(unittest.TestCase): m = mo.method(i) self.assertEqual(m.typeName(), "int") + def testResultObject(self): + o = MyObject() + mo = o.metaObject() + i = mo.indexOfSlot('mySlot6()') + m = mo.method(i) + self.assertEqual(m.typeName(), "QObject*") class SlotWithoutArgs(unittest.TestCase): From 44f5f6261876d508d52826534f7f77270c2b31ce Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Mon, 21 Mar 2011 15:11:03 -0300 Subject: [PATCH 019/489] Fix bug 728 - "QFileDialog.getOpenFileNames never returns (hangs)" Reviewer: Lauro Moura Luciano Wolf --- PySide/typesystem_templates.xml | 38 +++++++++++++++++++++++++++++++++ tests/QtGui/CMakeLists.txt | 1 + tests/QtGui/bug_728.py | 8 +++++++ 3 files changed, 47 insertions(+) create mode 100644 tests/QtGui/bug_728.py diff --git a/PySide/typesystem_templates.xml b/PySide/typesystem_templates.xml index e13b78d..9ef317d 100644 --- a/PySide/typesystem_templates.xml +++ b/PySide/typesystem_templates.xml @@ -31,47 +31,65 @@