Permalink
Browse files

waterfall diagram almost done

  • Loading branch information...
1 parent 9bd6f5d commit 392a413590b25ae631639ebe9e15f8aa2588f650 @moscartong moscartong committed Feb 21, 2012
Showing with 182 additions and 36 deletions.
  1. +4 −2 Rythem.pro
  2. +24 −10 RythemTimes/.idea/workspace.xml
  3. +1 −0 RythemTimes/css/times.css
  4. +23 −5 RythemTimes/js/times.js
  5. +1 −0 httpfiles.qrc
  6. +12 −5 mainwindow.cpp
  7. +4 −0 rypipedata.cpp
  8. +2 −0 rypipedata.h
  9. +46 −8 waterfallwindow.cpp
  10. +15 −6 waterfallwindow.h
  11. +50 −0 waterfallwindow.ui
View
@@ -86,7 +86,8 @@ mac:SOURCES -= rywinhttp.cpp
FORMS += mainwindow.ui \
rule_config.ui \
- composer.ui
+ composer.ui \
+ waterfallwindow.ui
mac:CONFIG += app_bundle
@@ -116,7 +117,8 @@ OTHER_FILES += \
RythemTimes/lib/backbone.js \
RythemTimes/js/times.js \
RythemTimes/css/times.css \
- static/icloud_64.png
+ static/icloud_64.png \
+ RythemTimes/lib/parseuri.js
CONFIG(release){
#DEFINES += DEBUGTOFILE
#message("debug")
@@ -34,7 +34,7 @@
<file leaf-file-name="times.js" pinned="false" current="true" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/js/times.js">
<provider selected="true" editor-type-id="text-editor">
- <state line="38" column="0" selection-start="990" selection-end="990" vertical-scroll-proportion="0.88785046">
+ <state line="41" column="39" selection-start="1088" selection-end="1088" vertical-scroll-proportion="0.30373833">
<folding />
</state>
</provider>
@@ -55,10 +55,10 @@
<component name="IdeDocumentHistory">
<option name="changedFiles">
<list>
- <option value="$PROJECT_DIR$/css/times.css" />
<option value="$PROJECT_DIR$/index.html" />
- <option value="$PROJECT_DIR$/js/times.js" />
<option value="$PROJECT_DIR$/lib/parseuri.js" />
+ <option value="$PROJECT_DIR$/css/times.css" />
+ <option value="$PROJECT_DIR$/js/times.js" />
</list>
</option>
</component>
@@ -133,6 +133,20 @@
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
+ <PATH>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="RythemTimes" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="RythemTimes" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="css" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+ </PATH_ELEMENT>
+ </PATH>
</subPane>
</pane>
<pane id="Scope" />
@@ -236,30 +250,30 @@
<breakpoint-manager />
</component>
<component name="editorHistoryManager">
- <entry file="file://$PROJECT_DIR$/css/times.css">
+ <entry file="file://$PROJECT_DIR$/lib/parseuri.js">
<provider selected="true" editor-type-id="text-editor">
- <state line="19" column="13" selection-start="288" selection-end="288" vertical-scroll-proportion="0.04292528">
+ <state line="32" column="2" selection-start="1027" selection-end="1027" vertical-scroll-proportion="0.76311606">
<folding />
</state>
</provider>
</entry>
- <entry file="file://$PROJECT_DIR$/index.html">
+ <entry file="file://$PROJECT_DIR$/css/times.css">
<provider selected="true" editor-type-id="text-editor">
- <state line="21" column="34" selection-start="526" selection-end="526" vertical-scroll-proportion="-13.125">
+ <state line="4" column="23" selection-start="66" selection-end="66" vertical-scroll-proportion="0.093457945">
<folding />
</state>
</provider>
</entry>
- <entry file="file://$PROJECT_DIR$/lib/parseuri.js">
+ <entry file="file://$PROJECT_DIR$/index.html">
<provider selected="true" editor-type-id="text-editor">
- <state line="32" column="2" selection-start="1027" selection-end="1027" vertical-scroll-proportion="0.76311606">
+ <state line="21" column="34" selection-start="526" selection-end="526" vertical-scroll-proportion="-13.125">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/times.js">
<provider selected="true" editor-type-id="text-editor">
- <state line="38" column="0" selection-start="990" selection-end="990" vertical-scroll-proportion="0.88785046">
+ <state line="41" column="39" selection-start="1088" selection-end="1088" vertical-scroll-proportion="0.30373833">
<folding />
</state>
</provider>
@@ -2,6 +2,7 @@
padding: 0;
margin: 0;
font-size: 10px;
+ font-family: Arial;
}
.hgroup{
display: -webkit-box;
View
@@ -22,7 +22,6 @@
header = header.split('\r\n\r\n')[0];
var lines = header.split('\r\n');
var firstLine = lines[0].split(' ');
-
//parse the first line("GET /xxx HTTP/1.1" for request or "HTTP/1.1 200 OK" for response)
var method, url, host, path, requestName, httpVersion, status, description;
if(parseInt(firstLine[1])){
@@ -42,14 +41,12 @@
path = uri.path;
requestName = uri.file;
}
-
//parse the header fields
var i, len = lines.length, fields = {};
for(i=1; i<len; i++){
var kv = lines[i].split(': ');
fields[kv[0]] = kv[1];
}
-
return {
isRequest: true,
method: method,
@@ -248,18 +245,39 @@
}
}
+ /**
+ * update all connections, this method is invoke by the client
+ * conns = [conn1, conn2, ...]
+ * conn = {id, socketID, requestHeader, responseHeader, startTime, responseStartTime, responseFinishTime}
+ * @param conns
+ */
+ function updateAllConnections(conns){
+ var i, len=conns.length;
+ for(i=0; i<len; i++){
+ var conn = conns[i];
+ var c = Connection.get(conn.id, conn.socketID);
+ c.setRequestHeader(conn.requestHeader);
+ c.setResponseHeader(conn.responseHeader);
+ c.setStartTime(conn.startTime);
+ c.setResponseStartTime(conn.responseStartTime);
+ c.setResponseFinishTime(conn.responseFinishTime);
+ updateConnUI(c);
+ }
+ }
+
function main(){
- var c1 = Connection.get(1, 'socket a');
+ /*var c1 = Connection.get(1, 'socket a');
var c2 = Connection.get(2, 'socket a');
var c3 = Connection.get(3, 'socket b');
var c4 = Connection.get(4, 'socket a');
updateConnUI(c1);
updateConnUI(c2);
updateConnUI(c3);
- updateConnUI(c4);
+ updateConnUI(c4);*/
}
window.Connection = Connection;
+ window.updateAllConnections = updateAllConnections;
document.addEventListener('DOMContentLoaded', main);
})();
View
@@ -35,6 +35,7 @@
<file>RythemTimes/lib/backbone.js</file>
<file>RythemTimes/js/times.js</file>
<file>RythemTimes/css/times.css</file>
+ <file>RythemTimes/lib/parseuri.js</file>
</qresource>
<qresource prefix="/static">
<file>static/icloud_64.png</file>
View
@@ -8,11 +8,10 @@
#include <QSettings>
#include <QVariant>
#include <QUrl>
-
-
#include <QNetworkConfigurationManager>
#include <QMAp>
#include <QList>
+#include <QMessageBox>
#ifdef Q_WS_WIN32
#include "wininet.h"
@@ -246,9 +245,17 @@ void MainWindow::onWaterfallActionTriggered(){
pipes.append(data);
}
- WaterfallWindow *win = new WaterfallWindow();
- win->setPipeData(pipes);
- win->show();
+ if(pipes.length()){
+ //deleteLater would be call when win close, don't worry about the memory
+ WaterfallWindow *win = new WaterfallWindow();
+ win->setPipeData(pipes);
+ win->show();
+ }
+ else{
+ QMessageBox box;
+ box.setText("Please select some network request first");
+ box.exec();
+ }
}
View
@@ -12,6 +12,10 @@ RyPipeData::RyPipeData(int _socketHandle,quint64 connectionId,QObject *parent):
_isResponseChunked = false;
}
+bool RyPipeData::operator <(RyPipeData &pipeData){
+ return this->performances.requestBegin < pipeData.performances.requestBegin;
+}
+
int RyPipeData::parseRequest(QByteArray* request,bool* isRequestOk){
// get header body devider
View
@@ -11,6 +11,8 @@ class RyPipeData : public QObject
public:
explicit RyPipeData(int socketHandle,quint64 socketConnectionId,QObject *parent = 0);
+ bool operator <(RyPipeData &pipeData);
+
// return byte remain (if the request/response has content-length but
// not complete yet
int parseRequest(QByteArray* request,bool* isRequestOk=0);
View
@@ -1,22 +1,60 @@
-#include <QCloseEvent>
+#include <QWebFrame>
#include "waterfallwindow.h"
+#include "ui_waterfallwindow.h"
WaterfallWindow::WaterfallWindow(QWidget *parent) :
- QMainWindow(parent)
+ QMainWindow(parent),
+ ui(new Ui::WaterfallWindow)
{
- this->setWindowTitle("Network Request Waterfall Diagram");
- this->resize(800, 480);
+ ui->setupUi(this);
+ connect(ui->webView, SIGNAL(loadFinished(bool)), this, SLOT(onWebContentLoaded()));
}
-WaterfallWindow::~WaterfallWindow(){
+WaterfallWindow::~WaterfallWindow()
+{
+ delete ui;
qDebug() << "[WaterfallWindow] i am dead";
}
void WaterfallWindow::setPipeData(QList<RyPipeData_ptr> list){
- qDebug() << "hey you selected" << list.length() << "pipes";
+ //save the list first
+ pipes = list;
+ if(loaded){
+ //constructor the js object
+ qSort(pipes);
+ QStringList results;
+ QListIterator<RyPipeData_ptr> it(list);
+ while(it.hasNext()){
+ RyPipeData_ptr p = it.next();
+ QString result;
+ QTextStream stream(&result);
+ stream << "{id:" << p->id
+ << ", socketID:" << p->socketConnectionId
+ << ", requestHeader:\"" << QString(p->requestHeaderRawData()).replace("\r\n", "\\r\\n") << "\""
+ << ", responseHeader:\"" << QString(p->responseHeaderRawData()).replace("\r\n", "\\r\\n") << "\""
+ << ", startTime:" << p->performances.requestBegin
+ << ", responseStartTime:" << p->performances.responseBegin
+ << ", responseFinishTime:" << p->performances.responseDone
+ << "}";
+ results << result;
+ }
+
+ //invoke js update method
+ QWebFrame *frame = ui->webView->page()->mainFrame();
+ QString args = "[" + results.join(",") + "]";
+ qDebug() << args;
+ frame->evaluateJavaScript("window.updateAllConnections(" + args + ")");
+ }
+}
+
+void WaterfallWindow::onWebContentLoaded(){
+ loaded = true;
+ if(pipes.length()){
+ setPipeData(pipes);
+ }
}
-void WaterfallWindow::closeEvent(QCloseEvent *e){
- e->accept();
+void WaterfallWindow::closeEvent(QCloseEvent *event){
+ event->accept();
deleteLater();
}
View
@@ -3,23 +3,32 @@
#include <QMainWindow>
#include <QtCore>
-#include "rypipedata.h"
+#include <QCloseEvent>
+#include <rypipedata.h>
+
+namespace Ui {
+class WaterfallWindow;
+}
class WaterfallWindow : public QMainWindow
{
Q_OBJECT
+
public:
explicit WaterfallWindow(QWidget *parent = 0);
~WaterfallWindow();
void setPipeData(QList<RyPipeData_ptr> list);
-
-signals:
-
+
public slots:
+ void onWebContentLoaded();
+
+private:
+ Ui::WaterfallWindow *ui;
+ bool loaded;
+ QList<RyPipeData_ptr> pipes;
protected:
- void closeEvent(QCloseEvent *);
-
+ void closeEvent(QCloseEvent *event);
};
#endif // WATERFALLWINDOW_H
View
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>WaterfallWindow</class>
+ <widget class="QMainWindow" name="WaterfallWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>600</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Network Waterfall Diagram</string>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QWebView" name="webView">
+ <property name="url">
+ <url>
+ <string>qrc:/web/waterfall/RythemTimes/index.html</string>
+ </url>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menubar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>22</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QStatusBar" name="statusbar"/>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QWebView</class>
+ <extends>QWidget</extends>
+ <header>QtWebKit/QWebView</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>

0 comments on commit 392a413

Please sign in to comment.