SF.net SVN: fclient:[872] trunk/fclient/fclient/impl
Status: Pre-Alpha
Brought to you by:
jurner
From: <jU...@us...> - 2008-08-07 10:33:31
|
Revision: 872 http://fclient.svn.sourceforge.net/fclient/?rev=872&view=rev Author: jUrner Date: 2008-08-07 10:33:37 +0000 (Thu, 07 Aug 2008) Log Message: ----------- add a sideBar to browser to display detailed load info Modified Paths: -------------- trunk/fclient/fclient/impl/ViewBrowser.py trunk/fclient/fclient/impl/config.py trunk/fclient/fclient/impl/res/stylesheets/default.css trunk/fclient/fclient/impl/tpls/Ui_ViewBrowserWidgetTpl.py trunk/fclient/fclient/impl/tpls/ViewBrowserWidgetTpl.ui Added Paths: ----------- trunk/fclient/fclient/impl/SideBarLoadDetails.py trunk/fclient/fclient/impl/tpls/SideBarLoadDetailsTpl.ui trunk/fclient/fclient/impl/tpls/Ui_SideBarLoadDetailsTpl.py Added: trunk/fclient/fclient/impl/SideBarLoadDetails.py =================================================================== --- trunk/fclient/fclient/impl/SideBarLoadDetails.py (rev 0) +++ trunk/fclient/fclient/impl/SideBarLoadDetails.py 2008-08-07 10:33:37 UTC (rev 872) @@ -0,0 +1,163 @@ +"""sideBar for the browser to show detailed information on page load""" +#******************************************************************************** +#TODO: +# +# x. how to adjust item colors via stylesheet? +# x. assumed we get a networkReplyError() signal when for example an image culd not be loaded. does not happen. check +# x. limit number of requests we keep track off? +# x. context menu actions for items like ...load in browser ..download key (...) +# x. save column widths +# +#******************************************************************************** + + +from __future__ import absolute_import +if __name__ == '__main__': # see --> http://bugs.python.org/issue1510172 . works only current dir and below + import os; __path__ = [os.path.dirname(__file__)] + +import posixpath +from PyQt4 import QtCore, QtGui + +from . import config +from .tpls.Ui_SideBarLoadDetailsTpl import Ui_SideBarLoadDetails +#********************************************************************************** +# +#********************************************************************************** +class SideBarLoadDetailsSettings(config.SettingsBase): + _key_ = config.IdSideBarLoadDetails + _settings_ = ( + ('ColorFgItem', 'QColor', QtGui.QColor('black')), + ('ColorBgItem', 'QColor', QtGui.QColor('white')), + ('ColorFgItemError', 'QColor', QtGui.QColor('black')), + ('ColorBgItemError', 'QColor', QtGui.QColor('red')), + + ) + +class SideBarLoadDetails(QtGui.QWidget, Ui_SideBarLoadDetails): + + IdTree = 'tree' + IdBtClose = 'btClose' + + + def __init__(self, parent=None, closeAction=None): + QtGui.QWidget.__init__(self, parent) + self.setupUi(self) + config.ObjectRegistry.register(self) + self.fcSettings = SideBarLoadDetailsSettings(self).restore() + + # setup tree + tree = self.controlById(self.IdTree) + tree.setUniformRowHeights(True) + tree.setRootIsDecorated(False) + + # setup close button + if closeAction is not None: + bt = self.controlById(self.IdBtClose) + bt.setDefaultAction(closeAction) + + ############################## + ## methods + ############################## + def addNetworkReply(self, indexReply, networkReplyData): + #TODO: better extraction of filename part + tree = self.controlById(self.IdTree) + n = tree.topLevelItemCount() + if indexReply < n: + return + + key = unicode(networkReplyData.url.toString()) + fname = posixpath.basename(posixpath.basename(key)) + if not fname: + fname = '/' + + item= QtGui.QTreeWidgetItem(tree) + item.setData( + 0, + QtCore.Qt.DisplayRole, + QtCore.QVariant('0%') + ) + item.setData( + 1, + QtCore.Qt.DisplayRole, + QtCore.QVariant(fname), + ) + if networkReplyData.bytesTotal < 1: + progress = '0%' + else: + progress = str(int((float(networkReplyData.bytesReceived) / networkReplyData.bytesTotal * 100))) + '%' + if item is not None: + item.setData( + 0, + QtCore.Qt.DisplayRole, + QtCore.QVariant(progress), + ) + item.setForeground(0, self.fcSettings.value('ColorFgItem')) + item.setBackground(0, self.fcSettings.value('ColorBgItem')) + + + def controlById(self, idControl): + return getattr(self, idControl) + + def setBrowser(self, browser): + tree = self.controlById(self.IdTree) + tree.clear() + # setup browser + if browser is not None: + self.connect(browser, QtCore.SIGNAL('networkRequestCreated(int, QObject*)'), self.addNetworkReply) + self.connect(browser, QtCore.SIGNAL('networkReplyProgress(int, QObject*)'), self.onBrowserNetworkReplyProgress) + self.connect(browser, QtCore.SIGNAL('networkReplyError(int, QObject*)'), self.onBrowserNetworkReplyError) + self.connect(browser, QtCore.SIGNAL('networkReplyFinished(int, QObject*)'), self.onBrowserNetworkReplyFinished) + self.connect(browser, QtCore.SIGNAL('loadStarted()'), self.onBrowserLoadStarted) + for indexReply, networkReplyData in enumerate(browser.networkGetReplies()): + self.addNetworkReply(indexReply, networkReplyData) + + def onSetCurrent(self, browserWidget, flag): + if flag: + self.setBrowser(browserWidget.currentBrowser()) + else: + self._items = {} + + ########################### + ## + ########################### + def retranslateUi(self, this): + Ui_SideBarLoadDetails.retranslateUi(self, this) + tree = self.controlById(self.IdTree) + tree.setHeaderLabels(( + self.trUtf8('Progress'), + self.trUtf8('Name'), + )) + + ############################## + ## event handlers + ############################## + def onBrowserLoadStarted(self): + tree = self.controlById(self.IdTree) + tree.clear() + + def onBrowserNetworkReplyProgress(self, indexReply, networkReplyData): + tree = self.controlById(self.IdTree) + item = tree.invisibleRootItem().child(indexReply) + if networkReplyData.bytesTotal < 1: + progress = '0%' + else: + progress = str(int((float(networkReplyData.bytesReceived) / networkReplyData.bytesTotal * 100))) + '%' + if item is not None: + item.setData( + 0, + QtCore.Qt.DisplayRole, + QtCore.QVariant(progress), + ) + + def onBrowserNetworkReplyError(self, indexReply, networkReplyData): + tree = self.controlById(self.IdTree) + item = tree.invisibleRootItem().child(indexReply) + item.setForeground(0, self.fcSettings.value('ColorFgItemError')) + item.setBackground(0, self.fcSettings.value('ColorBgItemError')) + + def onBrowserNetworkReplyFinished(self, indexReply, networkReplyData): + tree = self.controlById(self.IdTree) + item = tree.invisibleRootItem().child(indexReply) + + + Modified: trunk/fclient/fclient/impl/ViewBrowser.py =================================================================== --- trunk/fclient/fclient/impl/ViewBrowser.py 2008-08-03 19:18:54 UTC (rev 871) +++ trunk/fclient/fclient/impl/ViewBrowser.py 2008-08-07 10:33:37 UTC (rev 872) @@ -37,8 +37,19 @@ # x. dropping. accept keys +1. what else to accept? # x. option to upload content from browser? "upload current page" / image ..whatevs # x. print contents -# x. save page + # x. a note on "save link". if it points to a html page, no media is saved, just the html +# +# x. save page ++ load progress details +# idea: we get pretty detailed information about page load via NetworkAccessManager. +# 1. collect all replies +# 2. request replies one by one via urllib if user wants to dl a page. <dl page to folder...> +# 3. provide detailed feedback for the user on page load. a global widget for all browsers +# should get too heavy. a toolDialog for each page is better maybe. not too hard to +# implement. downside is dialogs flapping around ++ feedback to what browser a +# dialog belongs. upside is: multiple pages can be easily monitored while loading. +# maybe a later version can provide a manager for the dialogs to bundle them +# x. close icon for ActionCloseSideBar #****************************************************************************************** """ @@ -59,37 +70,53 @@ from . import DlgPropsBrowserObject from . import DlgDownloadKeyToDisk +from . import SideBarLoadDetails + from .tpls.Ui_ViewBrowserWidgetTpl import Ui_ViewBrowserWidget #***************************************************************************************** # #***************************************************************************************** # to browse via fcp... -#from PyQt4 import QtNetwork -#class NetworkAccessManager(QtNetwork.QNetworkAccessManager): -# -# def __init__(self, parent): -# QtNetwork.QNetworkAccessManager.__init__(self, parent) -# -# def createRequest(self, operation, request, outgoingData): -# print 'createRequest', request.url() -# reply = QtNetwork.QNetworkAccessManager.createRequest(self, operation, request, outgoingData) -# #TODO: implement QNetworkReply() -# return reply +from PyQt4 import QtNetwork +class NetworkAccessManager(QtNetwork.QNetworkAccessManager): + + def __init__(self, parent): + QtNetwork.QNetworkAccessManager.__init__(self, parent) + + def createRequest(self, operation, request, outgoingData): + reply = QtNetwork.QNetworkAccessManager.createRequest(self, operation, request, outgoingData) + self.emit(QtCore.SIGNAL('networkRequestCreated(QNetworkReply*)'), reply) + + + #print 'createRequest', reply.url() + #self.connect(reply, QtCore.SIGNAL('downloadProgress(qint64, qint64)'), self.foo) + return reply + + def foo(self, *args): + print args - class Page(QtWebKit.QWebPage): def __init__(self, parent): QtWebKit.QWebPage.__init__(self, parent) - #self.setNetworkAccessManager(NetworkAccessManager(self)) - + self.setNetworkAccessManager(NetworkAccessManager(self)) #def acceptNavigationRequest(self, frame, request, typeRequest): # return True #***************************************************************************************** # #***************************************************************************************** +class NetworkReplyData(QtCore.QObject): + def __init__(self, parent, url): + QtCore.QObject.__init__(self, parent) + self.url = url + self.bytesReceived = 0 + self.bytesTotal = 0 + self.finished = False + self.errorCode = None + + class Browser(QtWebKit.QWebView): """ browser customized for freenet """ @@ -105,16 +132,44 @@ #NOTE: we store last progress made to set busy cursor accordingly self._lastProgress = 0 self._userData = userData - + self._networkGetReplies = [[], []] # (QNetworkReplies, urls) + self._networkReplySignals = ( + ('downloadProgress(qint64, qint64)', self.onNetworkReplyDownloadProgress), + ('error(int)', self.onNetworkReplyError), + ('finished()', self.onNetworkReplyFinished), + ) + # connect actions self.connect(self, QtCore.SIGNAL('loadStarted()'), self.onLoadStarted) self.connect(self, QtCore.SIGNAL('loadProgress(int)'), self.onLoadProgress) self.connect(self, QtCore.SIGNAL('loadFinished(bool)'), self.onLoadFinished) self.connect(self.pageAction(QtWebKit.QWebPage.Stop), QtCore.SIGNAL('triggered()'), self.onActionStopTriggered) - + ################################ ## methods ################################ + #TODO: impl in BrowserWidget + def lastProgress(self): + """returns the last progress made by the browser + @return: (int) last progress + """ + return self._lastProgress + + def networkGetReplies(self): + return self._networkGetReplies[1] + + def networkGetReply(self, indexReply): + return self._networkGetReplies[1][indexReply] + + def setUserData(self, userData): + self._userData = userData + + def userData(self): + return self._userData + + ################################ + ## overwritten methods + ################################ #def createWindow(self, typeWindow): # pass @@ -136,22 +191,22 @@ return QtWebKit.QWebView.setHtm(self, *args) def setPage(self, page): - """sets the contents of the browser without changing its url""" + """""" self._lastProgress = 0 + self.connect( + page.networkAccessManager(), + QtCore.SIGNAL('networkRequestCreated(QNetworkReply*)'), + self.onNetworkRequestCreated + ) + + self.emit(QtCore.SIGNAL('pageSet(QWebPage*)'), page) return QtWebKit.QWebView.setPage(self, page) - def setUserData(self, userData): - self._userData = userData - def mouseMoveEvent(self, event): + QtWebKit.QWebView.mouseMoveEvent(self, event) if self._lastProgress < self.MaxProgress: self.setCursor(QtCore.Qt.BusyCursor) - else: - QtWebKit.QWebView.mouseMoveEvent(self, event) - - def userData(self): - return self._userData - + ############################### ## event handlers ############################### @@ -168,16 +223,55 @@ def onLoadStarted(self): self._lastProgress = 0 - + self._networkGetReplies = [[], []] + def onLoadProgress(self, n): self._lastProgress = n - def onLoadFinished(self): - self._lastProgress = self.MaxProgress + def onLoadFinished(self, ok): + if ok: + self._lastProgress = self.MaxProgress self.onActionStopTriggered() def onPageDownloadRequested(self, networkRequest): self.emit(QtCore.SIGNAL('downloadRequested(const QNetworkRequest &)'), networkRequest) + + def onNetworkRequestCreated(self, reply): + if reply.operation() == NetworkAccessManager.GetOperation: + self._networkGetReplies[0].append(reply) + url = QtCore.QUrl(reply.url()) # copy url, qt nules it on return + networkReplyData = NetworkReplyData(self, url) + self._networkGetReplies[1].append(networkReplyData) + for signal, handler in self._networkReplySignals: + self.connect(reply, QtCore.SIGNAL(signal), handler) + self.emit(QtCore.SIGNAL('networkRequestCreated(int, QObject*)'), self._networkGetReplies[0].index(reply), networkReplyData) + + def onNetworkReplyDownloadProgress(self, bytesReceived, bytesTotal): + reply = self.sender() + i = self._networkGetReplies[0].index(reply) + networkReplyData = self._networkGetReplies[1][i] + networkReplyData.bytesReceived = bytesReceived + networkReplyData.bytesTotal = bytesTotal + self.emit(QtCore.SIGNAL('networkReplyProgress(int, QObject*)'), i, networkReplyData) + + def onNetworkReplyError(self, errorCode): + reply = self.sender() + i = self._networkGetReplies[0].index(reply) + networkReplyData = self._networkGetReplies[1][i] + networkReplyData.finished = True + networkReplyData.errorCode = errorCode + self.emit(QtCore.SIGNAL('networkReplyError(int, QObject*)'), i, networkReplyData) + #for signal, handler in self._networkReplySignals: + # self.disconnect(reply, QtCore.SIGNAL(signal), handler) + + def onNetworkReplyFinished(self): + reply = self.sender() + i = self._networkGetReplies[0].index(reply) + networkReplyData = self._networkGetReplies[1][i] + networkReplyData.finished = True + for signal, handler in self._networkReplySignals: + self.disconnect(reply, QtCore.SIGNAL(signal), handler) + self.emit(QtCore.SIGNAL('networkReplyFinished(int, QObject*)'), i, networkReplyData) #********************************************************************************** # @@ -246,6 +340,10 @@ ('TabProgressBarColor', 'QColor', QtGui.QColor('blue')), ('TabProgressBarAlpha', 'UInt', 55), + + ('SplitterPos', 'ByteArray', QtCore.QByteArray()), + ('LastSideBarAction', 'String', QtCore.QString('')), + ) def setValues(self, **kws): @@ -301,12 +399,19 @@ ) #TODO: shortcut self.action( - name='ActionOpenNewTab', - text=self.trUtf8('Open &new tab'), - trigger=parent.onOpenNewTab, + name='ActionCreateNewTab', + text=self.trUtf8('Create &new tab'), + trigger=parent.onCreateNewTab, ) #TODO: shortcut self.action( + name='ActionDuplicateTab', + text=self.trUtf8('&Duplicate tab'), + trigger=parent.onDuplicateTab, + ) + + #TODO: shortcut + self.action( name='ActionGoToFProxy', text=self.trUtf8('Go to f&Proxy homepage'), trigger=parent.onGoToFProxy, @@ -406,6 +511,35 @@ shortcut=QtGui.QKeySequence(QtGui.QKeySequence.FindPrevious), trigger=parent.onFindPrevious, ) + self.action( + name='ActionSavePage', + text=self.trUtf8('Save page..'), + isEnabled=True, + ##shortcut=QtGui.QKeySequence(QtGui.QKeySequence.FindPrevious), + trigger=parent.onSavePage, + ) + + # sideBars + group = self.group( + name='GroupSideBars', + isExclusive=True, + trigger=parent.onShowSidebar, + ) + self.action( + name='ActionShowSideBarLoadDetails', + group=group, + text=self.trUtf8('Load details'), + isEnabled=True, + isCheckable=True, + ) + + self.action( + name='ActionCloseCurrentSideBar', + text=self.trUtf8('Close sidebar'), + isEnabled=True, + trigger=parent.onCloseCurrentSideBar, + ) + def intertwineBrowserActions(self, browser=None): """intertwines Browser actions with BrowserWidget actions @@ -464,7 +598,7 @@ # to give feedback to the user on the navbar. downside is we have # to reimplement contextMenuEvent() :-( self.url = QtCore.QUrl() if url is None else url - + class BrowserTabBar(QtGui.QTabBar): """customized tabBar to show progress indicstor on tabs""" @@ -533,6 +667,9 @@ IdFrameAddressBar = 'frameAddressBar' IdEdAddressBar = 'edAddressBar' + IdTabSideBar = 'tabSideBar' + IdSplitter = 'splitter' + IdBtBack = 'btBack' IdBtForward = 'btForward' IdBtReload = 'btReload' @@ -549,6 +686,8 @@ def __init__(self, parent, idGlobalFeedback=config.IdMainWindow): QtGui.QWidget.__init__(self, parent) + self.menuSideBars = QtGui.QMenu(self.trUtf8('Side bars')) #TODO: retranslate + self.setupUi(self) config.ObjectRegistry.register(self) @@ -572,10 +711,27 @@ self.connect(tabWidget, QtCore.SIGNAL('currentChanged(int)'), self.onTabCurrentChanged) self.connect(tabWidget, QtCore.SIGNAL('customContextMenuRequested(const QPoint &)'), self.onTabContextMenuEvent) - # setup addressbar + # setup sideBar + tabWidget = self.controlById(self.IdTabSideBar) + tabWidget.clear() # clear, setTabBar() seems to take over alreeady present tabs (qt-designer!) + tabWidget.setVisible(False) + tabWidget.tabBar().setVisible(False) + + # add sideBars + for action in self.fcActions['GroupSideBars'].actions(): + self.menuSideBars.addAction(action) + self.sideBarLoadDetails = SideBarLoadDetails.SideBarLoadDetails(tabWidget, closeAction=self.fcActions['ActionCloseCurrentSideBar']) + tabWidget.addTab(self.sideBarLoadDetails, self.trUtf8('Load details')) + + # setup splitter + splitter = self.controlById(self.IdSplitter) + splitter.restoreState(self.fcSettings.value('SplitterPos')) + self.connect(splitter, QtCore.SIGNAL('splitterMoved(int, int)'), self.onSplitterMoved) + + # setup addressBar addressbar = self.controlById(self.IdEdAddressBar) self.connect(addressbar, QtCore.SIGNAL('returnPressed()'), self.onNavBarReturnPressed) - + # setup tool buttons self.controlById(self.IdBtBack).setDefaultAction(self.fcActions['ActionBack']) self.controlById(self.IdBtForward).setDefaultAction(self.fcActions['ActionForward']) @@ -595,9 +751,21 @@ frameFind = self.controlById(self.IdFrameFind) frameFind.setVisible(False) + # finally + #TODO: hopefuly the user will not play around with this setting + actionName = self.fcSettings.value('LastSideBarAction') + action = self.fcActions.get(actionName, None) + if action is not None: + action.trigger() + ######################################### ## private methods ######################################### + def _adjustCurrentBrowserDependendStuff(self): + self.fcActions.intertwineBrowserActions(self.currentBrowser()) + if self.sideBarLoadDetails.isVisible(): + self.sideBarLoadDetails.setBrowser(self.currentBrowser()) + #NOTE: to reduce flicker set min size to max size def _adjustTabText(self, qString): maxTabText = self.fcSettings.value('MaxTabText') @@ -755,7 +923,7 @@ settings.setAttribute(settings.JavascriptCanAccessClipboard, False) settings.setAttribute(settings.PluginsEnabled, False) settings.setAttribute(settings.AutoLoadImages, self.fcSettings.value('AutoLoadImages')) - + # connect browser signals self.connect(browser, QtCore.SIGNAL('loadStarted()'), self.onBrowserLoadStarted) self.connect(browser, QtCore.SIGNAL('loadProgress(int)'), self.onBrowserLoadProgress) @@ -782,6 +950,7 @@ self.connect(page, QtCore.SIGNAL('linkHovered(const QString &, const QString &, const QString &)'), self.onPageLinkHovered) tabWidget.addTab(browser, self._adjustTabText(title)) + self._adjustCurrentBrowserDependendStuff() return browser #TODO: rework. we need more then one menu @@ -794,12 +963,14 @@ menu.addAction(self.fcActions['ActionGoToHomePage']) menu.addAction(self.fcActions['ActionCloseCurrentTab']) menu.addAction(self.fcActions['ActionCloseAllTabs']) - menu.addAction(self.fcActions['ActionOpenNewTab']) + menu.addAction(self.fcActions['ActionCreateNewTab']) menu.addAction(self.fcActions['ActionZoomIn']) menu.addAction(self.fcActions['ActionZoomOut']) menu.addAction(self.fcActions['ActionFind']) menu.addAction(self.fcActions['ActionFindNext']) menu.addAction(self.fcActions['ActionFindPrevious']) + + menu.addMenu(self.menuSideBars) return menu ######################################### @@ -989,20 +1160,74 @@ # have to do it by hand to reset [BackIsClose] tabWidget = self.controlById(self.IdTabBrowsers) tabWidget.clear() - self.fcActions.intertwineBrowserActions(self.currentBrowser()) + self._adjustCurrentBrowserDependendStuff() def onCloseCurrentTab(self, action): tabWidget = self.controlById(self.IdTabBrowsers) i = tabWidget.currentIndex() if i > -1: tabWidget.removeTab(i) - self.fcActions.intertwineBrowserActions(self.currentBrowser()) + self._adjustCurrentBrowserDependendStuff() + + def onCloseCurrentSideBar(self, action): + tabWidget = self.controlById(self.IdTabSideBar) + sideBar = tabWidget.currentWidget() + sideBar.onSetCurrent(self, False) + tabWidget.setVisible(False) + checkedAction = self.fcActions['GroupSideBars'].checkedAction() + if checkedAction is not None: + checkedAction.setChecked(False) + self.fcSettings.setValues(LastSideBarAction=QtCore.QString('')) + + def onDuplicateTab(self, action): + tabWidget = self.controlById(self.IdTabBrowsers) + browser = self.currentBrowser() + print browser + lastBrowserState = browser.userData() + self.fcActions['ActionCreateNewTab'].trigger() + browser = tabWidget.widget(tabWidget.count() -1) + self.load(lastBrowserState.url, browser=browser) def onEdFindTextChanged(self, text): self.fcActions['ActionFindNext'].setEnabled(bool(text)) self.fcActions['ActionFindPrevious'].setEnabled(bool(text)) + def onFind(self, action): + frameFind = self.controlById(self.IdFrameFind) + ed = self.controlById(self.IdEdFind) + #ed.setText('fooBar') + + frameFind.setVisible(not frameFind.isVisible()) + #self.fcActions['ActionFindNext'].setEnabled() + #self.fcActions['ActionFindPrevious'].setEnabled() + if frameFind.isVisible(): + ed.setFocus(QtCore.Qt.OtherFocusReason) + ed.selectAll() + + #TODO: give feedback when no matching text was found + def onFindNext(self): + browser = self.currentBrowser() + if browser is not None: + page = browser.page() + ed = self.controlById(self.IdEdFind) + ck = self.controlById(self.IdCkFindCaseSensitive) + flags = page.FindWrapsAroundDocument + if ck.checkState() == QtCore.Qt.Checked: + flags |= page.FindCaseSensitively + if not browser.findText(ed.text(), flags): + pass + def onFindPrevious(self): + browser = self.currentBrowser() + if browser is not None: + page = browser.page() + ed = self.controlById(self.IdEdFind) + ck = self.controlById(self.IdCkFindCaseSensitive) + flags = page.FindWrapsAroundDocument | page.FindBackward + if ck.checkState() == QtCore.Qt.Checked: + flags |= page.FindCaseSensitively + browser.findText(ed.text(), flags) + #TODO: open in new tab option? def onGoToFProxy(self, action): url = QtCore.QUrl() @@ -1025,12 +1250,17 @@ self.load(qUrl, browser=browser) #TODO: we get no load progress feedback here? - #TODO: more choices for page to load - def onOpenNewTab(self, action): + #TODO: more choices for page to load + #TODO: we load fproxy in new page. this is because we enforce fproxy host/port on urls + # ...no way to distinguish in onDuplicateTab() between an empty page and fproxy page + # ...cos it relies on lastBrowserState.url + def onCreateNewTab(self, action): browser = self.newBrowser(title=self.trUtf8('Empty')) if self.fcSettings.value('OpenHomePageOnNewTabCreated'): homePage = self.fcSettings.value('HomePage') self.load(QtCore.QUrl(homePage), browser=browser) + else: + self.load(QtCore.QUrl(), browser=browser) def onPageLinkHovered(self, link, title, textContent): self.fcGlobalFeedback.setFeedback(QtCore.QString(link)) @@ -1041,62 +1271,50 @@ if browser is not None and act is browser.pageAction(browser.page().Back): self._adjustBackIsClose() - def onFind(self, action): - frameFind = self.controlById(self.IdFrameFind) - ed = self.controlById(self.IdEdFind) - #ed.setText('fooBar') - - frameFind.setVisible(not frameFind.isVisible()) - #self.fcActions['ActionFindNext'].setEnabled() - #self.fcActions['ActionFindPrevious'].setEnabled() - if frameFind.isVisible(): - ed.setFocus(QtCore.Qt.OtherFocusReason) - ed.selectAll() - - #TODO: give feedback when no matching text was found - def onFindNext(self): + def onSavePage(self, action): + # we have to cheat a bit here and reload the page to make shure the page has + # all QNetWorkReplies present browser = self.currentBrowser() - if browser is not None: - page = browser.page() - ed = self.controlById(self.IdEdFind) - ck = self.controlById(self.IdCkFindCaseSensitive) - flags = page.FindWrapsAroundDocument - if ck.checkState() == QtCore.Qt.Checked: - flags |= page.FindCaseSensitively - if not browser.findText(ed.text(), flags): - pass - def onFindPrevious(self): - browser = self.currentBrowser() - if browser is not None: - page = browser.page() - ed = self.controlById(self.IdEdFind) - ck = self.controlById(self.IdCkFindCaseSensitive) - flags = page.FindWrapsAroundDocument | page.FindBackward - if ck.checkState() == QtCore.Qt.Checked: - flags |= page.FindCaseSensitively - browser.findText(ed.text(), flags) + def onShowSidebar(self, action): + tabWidget = self.controlById(self.IdTabSideBar) + if action == self.fcActions['ActionShowSideBarLoadDetails']: + index = tabWidget.indexOf(self.sideBarLoadDetails) + self.sideBarLoadDetails.onSetCurrent(self, True) + else: + raise ValueError('No such sideBar') + self.fcSettings.setValues(LastSideBarAction=action.objectName()) + tabWidget.setCurrentIndex(index) + tabWidget.setVisible(True) + + def onSplitterMoved(self, pos, index): + splitter = self.controlById(self.IdSplitter) + self.fcSettings.setValues(SplitterPos=splitter.saveState()) def onTabContextMenuEvent(self, pt): menu = QtGui.QMenu() + browser = self.currentBrowser() tabWidget = self.controlById(self.IdTabBrowsers) pt = tabWidget.mapToGlobal(pt) pt2 = tabWidget.tabBar().mapFromGlobal(pt) i = tabWidget.tabBar().tabAt(pt2) + # setup menu actCloseBrowserUnderMouse = self.fcActions['ActionCloseBrowserUnderMouse'] actCloseBrowserUnderMouse.setEnabled(i >-1) menu.addAction(actCloseBrowserUnderMouse) + menu.addAction(self.fcActions['ActionCreateNewTab']) + menu.addAction(self.fcActions['ActionDuplicateTab']) menu.addAction(self.fcActions['ActionCloseAllTabs']) act = menu.exec_(pt) if act == actCloseBrowserUnderMouse: tabWidget.removeTab(i) - self.fcActions.intertwineBrowserActions(self.currentBrowser()) - + self._adjustCurrentBrowserDependendStuff() + def onTabCurrentChanged(self, i): tabWidget = self.controlById(self.IdTabBrowsers) browser = tabWidget.widget(i) - self.fcActions.intertwineBrowserActions(browser) + self._adjustCurrentBrowserDependendStuff() if browser is not None: lastBrowserState = browser.userData() addressBar = self.controlById(self.IdEdAddressBar) @@ -1132,6 +1350,10 @@ from .ViewConnection import ViewConnectionWidget from .ViewDownloads import ViewDownloadsWidget + + from .ViewBrowserDetails import ViewBrowserDetailsWidget + + app = QtGui.QApplication(sys.argv) mainWindow = MainWindow() @@ -1144,7 +1366,10 @@ browserWidget, ViewDownloadsWidget(mainWindow), ) - viewWidget.addBottomViews(ViewLoggerWidget(mainWindow)) + viewWidget.addBottomViews( + ViewLoggerWidget(mainWindow), + ViewBrowserDetailsWidget(mainWindow), + ) mainWindow.show() res = app.exec_() Modified: trunk/fclient/fclient/impl/config.py =================================================================== --- trunk/fclient/fclient/impl/config.py 2008-08-03 19:18:54 UTC (rev 871) +++ trunk/fclient/fclient/impl/config.py 2008-08-07 10:33:37 UTC (rev 872) @@ -46,6 +46,7 @@ IdViewLoggerWidget = 'ViewLoggerWidget' IdDlgPrefs = 'DlgPrefs' +IdSideBarLoadDetails = 'SideBarLoadDetails' class ObjectRegistry(weakref.WeakValueDictionary): """global object registry Modified: trunk/fclient/fclient/impl/res/stylesheets/default.css =================================================================== --- trunk/fclient/fclient/impl/res/stylesheets/default.css 2008-08-03 19:18:54 UTC (rev 871) +++ trunk/fclient/fclient/impl/res/stylesheets/default.css 2008-08-07 10:33:37 UTC (rev 872) @@ -13,6 +13,21 @@ **********************************************************************************************/ /* label style. sample: + MyHeader*/ +QLabel#labelHeader, +QLabel#labelHeader_2, +QLabel#labelHeader_3, +QLabel#labelHeader_4, +QLabel#labelHeader_5, +QLabel#labelHeader_6, +QLabel#labelHeader_7, +QLabel#labelHeader_8, +QLabel#labelHeader_9{ + font: bold; + } + + +/* label style. sample: Host: | 9999| */ QLabel#fieldHeader, Added: trunk/fclient/fclient/impl/tpls/SideBarLoadDetailsTpl.ui =================================================================== --- trunk/fclient/fclient/impl/tpls/SideBarLoadDetailsTpl.ui (rev 0) +++ trunk/fclient/fclient/impl/tpls/SideBarLoadDetailsTpl.ui 2008-08-07 10:33:37 UTC (rev 872) @@ -0,0 +1,47 @@ +<ui version="4.0" > + <class>SideBarLoadDetails</class> + <widget class="QWidget" name="SideBarLoadDetails" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>497</width> + <height>488</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout" > + <item row="0" column="0" > + <layout class="QHBoxLayout" name="horizontalLayout" > + <item> + <widget class="QLabel" name="labelHeader" > + <property name="text" > + <string>Load details</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="btClose" > + <property name="text" > + <string>...</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="0" > + <widget class="QTreeWidget" name="tree" > + <column> + <property name="text" > + <string>1</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> Added: trunk/fclient/fclient/impl/tpls/Ui_SideBarLoadDetailsTpl.py =================================================================== --- trunk/fclient/fclient/impl/tpls/Ui_SideBarLoadDetailsTpl.py (rev 0) +++ trunk/fclient/fclient/impl/tpls/Ui_SideBarLoadDetailsTpl.py 2008-08-07 10:33:37 UTC (rev 872) @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/me/src/fclient/trunk/fclient/fclient/impl/tpls/SideBarLoadDetailsTpl.ui' +# +# Created: Thu Aug 7 11:44:00 2008 +# by: PyQt4 UI code generator 4.4.3-snapshot-20080705 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +class Ui_SideBarLoadDetails(object): + def setupUi(self, SideBarLoadDetails): + SideBarLoadDetails.setObjectName("SideBarLoadDetails") + SideBarLoadDetails.resize(497, 488) + self.gridLayout = QtGui.QGridLayout(SideBarLoadDetails) + self.gridLayout.setObjectName("gridLayout") + self.horizontalLayout = QtGui.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.labelHeader = QtGui.QLabel(SideBarLoadDetails) + self.labelHeader.setObjectName("labelHeader") + self.horizontalLayout.addWidget(self.labelHeader) + self.btClose = QtGui.QToolButton(SideBarLoadDetails) + self.btClose.setObjectName("btClose") + self.horizontalLayout.addWidget(self.btClose) + self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1) + self.tree = QtGui.QTreeWidget(SideBarLoadDetails) + self.tree.setObjectName("tree") + self.gridLayout.addWidget(self.tree, 1, 0, 1, 1) + + self.retranslateUi(SideBarLoadDetails) + QtCore.QMetaObject.connectSlotsByName(SideBarLoadDetails) + + def retranslateUi(self, SideBarLoadDetails): + SideBarLoadDetails.setWindowTitle(QtGui.QApplication.translate("SideBarLoadDetails", "Form", None, QtGui.QApplication.UnicodeUTF8)) + self.labelHeader.setText(QtGui.QApplication.translate("SideBarLoadDetails", "Load details", None, QtGui.QApplication.UnicodeUTF8)) + self.btClose.setText(QtGui.QApplication.translate("SideBarLoadDetails", "...", None, QtGui.QApplication.UnicodeUTF8)) + self.tree.headerItem().setText(0, QtGui.QApplication.translate("SideBarLoadDetails", "1", None, QtGui.QApplication.UnicodeUTF8)) + + +if __name__ == "__main__": + import sys + app = QtGui.QApplication(sys.argv) + SideBarLoadDetails = QtGui.QWidget() + ui = Ui_SideBarLoadDetails() + ui.setupUi(SideBarLoadDetails) + SideBarLoadDetails.show() + sys.exit(app.exec_()) + Modified: trunk/fclient/fclient/impl/tpls/Ui_ViewBrowserWidgetTpl.py =================================================================== --- trunk/fclient/fclient/impl/tpls/Ui_ViewBrowserWidgetTpl.py 2008-08-03 19:18:54 UTC (rev 871) +++ trunk/fclient/fclient/impl/tpls/Ui_ViewBrowserWidgetTpl.py 2008-08-07 10:33:37 UTC (rev 872) @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -# Form implementation generated from reading ui file '/home/me/src/proj/fclient/trunk/fclient/src/fclient/impl/tpls/ViewBrowserWidgetTpl.ui' +# Form implementation generated from reading ui file '/home/me/src/fclient/trunk/fclient/fclient/impl/tpls/ViewBrowserWidgetTpl.ui' # -# Created: Tue Jul 29 12:29:18 2008 +# Created: Thu Aug 7 09:08:51 2008 # by: PyQt4 UI code generator 4.4.3-snapshot-20080705 # # WARNING! All changes made in this file will be lost! @@ -14,6 +14,8 @@ ViewBrowserWidget.setObjectName("ViewBrowserWidget") ViewBrowserWidget.resize(710, 794) self.gridLayout_4 = QtGui.QGridLayout(ViewBrowserWidget) + self.gridLayout_4.setMargin(0) + self.gridLayout_4.setSpacing(0) self.gridLayout_4.setObjectName("gridLayout_4") self.horizontalLayout = QtGui.QHBoxLayout() self.horizontalLayout.setSpacing(0) @@ -58,14 +60,38 @@ self.gridLayout.addWidget(self.edAddressBar, 0, 0, 1, 1) self.horizontalLayout.addWidget(self.frameAddressBar) self.gridLayout_4.addLayout(self.horizontalLayout, 0, 0, 1, 1) - self.tabBrowsers = QtGui.QTabWidget(ViewBrowserWidget) + self.splitter = QtGui.QSplitter(ViewBrowserWidget) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.splitter.sizePolicy().hasHeightForWidth()) + self.splitter.setSizePolicy(sizePolicy) + self.splitter.setOrientation(QtCore.Qt.Horizontal) + self.splitter.setObjectName("splitter") + self.tabSideBar = QtGui.QTabWidget(self.splitter) + self.tabSideBar.setObjectName("tabSideBar") + self.tab_2 = QtGui.QWidget() + self.tab_2.setGeometry(QtCore.QRect(0, 0, 154, 736)) + self.tab_2.setObjectName("tab_2") + self.tabSideBar.addTab(self.tab_2, "") + self.tab_3 = QtGui.QWidget() + self.tab_3.setGeometry(QtCore.QRect(0, 0, 150, 712)) + self.tab_3.setObjectName("tab_3") + self.tabSideBar.addTab(self.tab_3, "") + self.widget = QtGui.QWidget(self.splitter) + self.widget.setObjectName("widget") + self.verticalLayout = QtGui.QVBoxLayout(self.widget) + self.verticalLayout.setSpacing(99) + self.verticalLayout.setMargin(0) + self.verticalLayout.setObjectName("verticalLayout") + self.tabBrowsers = QtGui.QTabWidget(self.widget) self.tabBrowsers.setObjectName("tabBrowsers") self.tab = QtGui.QWidget() - self.tab.setGeometry(QtCore.QRect(0, 0, 688, 672)) + self.tab.setGeometry(QtCore.QRect(0, 0, 540, 601)) self.tab.setObjectName("tab") self.tabBrowsers.addTab(self.tab, "") - self.gridLayout_4.addWidget(self.tabBrowsers, 1, 0, 1, 1) - self.frameFind = QtGui.QFrame(ViewBrowserWidget) + self.verticalLayout.addWidget(self.tabBrowsers) + self.frameFind = QtGui.QFrame(self.widget) self.frameFind.setFrameShape(QtGui.QFrame.StyledPanel) self.frameFind.setFrameShadow(QtGui.QFrame.Raised) self.frameFind.setObjectName("frameFind") @@ -97,7 +123,8 @@ spacerItem = QtGui.QSpacerItem(48, 25, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem) self.gridLayout_3.addLayout(self.horizontalLayout_2, 0, 0, 1, 1) - self.gridLayout_4.addWidget(self.frameFind, 2, 0, 1, 1) + self.verticalLayout.addWidget(self.frameFind) + self.gridLayout_4.addWidget(self.splitter, 1, 0, 1, 1) self.retranslateUi(ViewBrowserWidget) self.tabBrowsers.setCurrentIndex(0) @@ -109,6 +136,8 @@ self.btForward.setText(QtGui.QApplication.translate("ViewBrowserWidget", "Forward", None, QtGui.QApplication.UnicodeUTF8)) self.btReload.setText(QtGui.QApplication.translate("ViewBrowserWidget", "Reload", None, QtGui.QApplication.UnicodeUTF8)) self.btStop.setText(QtGui.QApplication.translate("ViewBrowserWidget", "Stop", None, QtGui.QApplication.UnicodeUTF8)) + self.tabSideBar.setTabText(self.tabSideBar.indexOf(self.tab_2), QtGui.QApplication.translate("ViewBrowserWidget", "Tab 1", None, QtGui.QApplication.UnicodeUTF8)) + self.tabSideBar.setTabText(self.tabSideBar.indexOf(self.tab_3), QtGui.QApplication.translate("ViewBrowserWidget", "Tab 2", None, QtGui.QApplication.UnicodeUTF8)) self.tabBrowsers.setTabText(self.tabBrowsers.indexOf(self.tab), QtGui.QApplication.translate("ViewBrowserWidget", "Tab 1", None, QtGui.QApplication.UnicodeUTF8)) self.label.setText(QtGui.QApplication.translate("ViewBrowserWidget", "Find:", None, QtGui.QApplication.UnicodeUTF8)) self.btFindNext.setText(QtGui.QApplication.translate("ViewBrowserWidget", "Next", None, QtGui.QApplication.UnicodeUTF8)) Modified: trunk/fclient/fclient/impl/tpls/ViewBrowserWidgetTpl.ui =================================================================== --- trunk/fclient/fclient/impl/tpls/ViewBrowserWidgetTpl.ui 2008-08-03 19:18:54 UTC (rev 871) +++ trunk/fclient/fclient/impl/tpls/ViewBrowserWidgetTpl.ui 2008-08-07 10:33:37 UTC (rev 872) @@ -13,6 +13,12 @@ <string>Form</string> </property> <layout class="QGridLayout" name="gridLayout_4" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>0</number> + </property> <item row="0" column="0" > <layout class="QHBoxLayout" name="horizontalLayout" > <property name="spacing" > @@ -105,102 +111,153 @@ </layout> </item> <item row="1" column="0" > - <widget class="QTabWidget" name="tabBrowsers" > - <property name="currentIndex" > - <number>0</number> + <widget class="QSplitter" name="splitter" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Expanding" hsizetype="Expanding" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> - <widget class="QWidget" name="tab" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>688</width> - <height>672</height> - </rect> - </property> - <attribute name="title" > - <string>Tab 1</string> - </attribute> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <widget class="QTabWidget" name="tabSideBar" > + <widget class="QWidget" name="tab_2" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>154</width> + <height>736</height> + </rect> + </property> + <attribute name="title" > + <string>Tab 1</string> + </attribute> + </widget> + <widget class="QWidget" name="tab_3" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>150</width> + <height>712</height> + </rect> + </property> + <attribute name="title" > + <string>Tab 2</string> + </attribute> + </widget> </widget> - </widget> - </item> - <item row="2" column="0" > - <widget class="QFrame" name="frameFind" > - <property name="frameShape" > - <enum>QFrame::StyledPanel</enum> - </property> - <property name="frameShadow" > - <enum>QFrame::Raised</enum> - </property> - <layout class="QGridLayout" name="gridLayout_3" > - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>0</number> - </property> - <item row="0" column="0" > - <layout class="QHBoxLayout" name="horizontalLayout_2" > - <property name="spacing" > - <number>6</number> - </property> - <item> - <widget class="QLabel" name="label" > - <property name="text" > - <string>Find:</string> + <widget class="QWidget" name="" > + <layout class="QVBoxLayout" name="verticalLayout" > + <property name="spacing" > + <number>99</number> + </property> + <property name="margin" > + <number>0</number> + </property> + <item> + <widget class="QTabWidget" name="tabBrowsers" > + <property name="currentIndex" > + <number>0</number> + </property> + <widget class="QWidget" name="tab" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>540</width> + <height>601</height> + </rect> </property> + <attribute name="title" > + <string>Tab 1</string> + </attribute> </widget> - </item> - <item> - <widget class="QLineEdit" name="edFind" > - <property name="dragEnabled" > - <bool>true</bool> + </widget> + </item> + <item> + <widget class="QFrame" name="frameFind" > + <property name="frameShape" > + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow" > + <enum>QFrame::Raised</enum> + </property> + <layout class="QGridLayout" name="gridLayout_3" > + <property name="margin" > + <number>0</number> </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="btFindNext" > - <property name="text" > - <string>Next</string> + <property name="spacing" > + <number>0</number> </property> - <property name="flat" > - <bool>false</bool> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="btFindPrevious" > - <property name="text" > - <string>Previous</string> - </property> - <property name="flat" > - <bool>false</bool> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="ckFindCaseSensitive" > - <property name="text" > - <string>Case sensitive</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer" > - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0" > - <size> - <width>48</width> - <height>25</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - </layout> + <item row="0" column="0" > + <layout class="QHBoxLayout" name="horizontalLayout_2" > + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QLabel" name="label" > + <property name="text" > + <string>Find:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="edFind" > + <property name="dragEnabled" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btFindNext" > + <property name="text" > + <string>Next</string> + </property> + <property name="flat" > + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btFindPrevious" > + <property name="text" > + <string>Previous</string> + </property> + <property name="flat" > + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="ckFindCaseSensitive" > + <property name="text" > + <string>Case sensitive</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>48</width> + <height>25</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </item> + </layout> + </widget> </widget> </item> </layout> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |