From 9bb04f26032def256541d8b0fde2443a39e5aaaf Mon Sep 17 00:00:00 2001 From: Jens Persson Date: Tue, 14 Jun 2011 18:06:11 +0200 Subject: [PATCH] added about dialog to qml --- data/ui/qml/AboutDialog.qml | 81 +++++++++++++++++++++++++++++ data/ui/qml/ContextMenu.qml | 45 ++++++++++++++++ data/ui/qml/SelectableItem.qml | 36 +++++++++++++ data/ui/qml/ShadowText.qml | 24 +++++++++ data/ui/qml/config.js | 24 +++++++++ data/ui/qml/main.qml | 114 +++++++++++++++++++++++++++++++++++++++-- icons/gtk-close.png | Bin 0 -> 1675 bytes setup.py | 2 +- src/panucci/qmlui/qmlmain.py | 32 +++++++++++- 9 files changed, 352 insertions(+), 6 deletions(-) create mode 100644 data/ui/qml/AboutDialog.qml create mode 100644 data/ui/qml/ContextMenu.qml create mode 100644 data/ui/qml/SelectableItem.qml create mode 100644 data/ui/qml/ShadowText.qml create mode 100644 data/ui/qml/config.js create mode 100644 icons/gtk-close.png diff --git a/data/ui/qml/AboutDialog.qml b/data/ui/qml/AboutDialog.qml new file mode 100644 index 0000000..d93a4dc --- /dev/null +++ b/data/ui/qml/AboutDialog.qml @@ -0,0 +1,81 @@ + +import Qt 4.7 + +Item { + id: aboutDialogArea + signal close + property variant items: ["","","",""] + + MouseArea { + anchors.fill: parent + onClicked: aboutDialogArea.close() + } + Rectangle { + color: "#" + config.background + anchors.fill: parent + opacity: .9 + } + Image { + x: 10 + y: 10 + smooth: true + source: "panucci_64x64.png" + } + Text { + id: about_name + x: 90 + y: 10 + font.pixelSize: config.font_size + 3 + font.weight: Font.Bold + color: "#" + config.foreground + text: items[0] + } + Text { + id: about_text + x: 90 + y: about_name.y + config.font_size + 13 + font.pixelSize: config.font_size + 1 + color: "#" + config.foreground + text: items[1] + } + Text { + id: about_copyright + x: 90 + y: about_text.y + config.font_size + 11 + font.pixelSize: config.font_size + 1 + color: "#" + config.foreground + text: items[2] + } + Text { + id: about_website + x: 90 + y: about_copyright.y + config.font_size + 11 + font.pixelSize: config.font_size + 1 + color: "#" + config.foreground + text: "" + items[3] + "" + onLinkActivated: main.open_external_url(link) + } + /* + Rectangle { + x: 90 + y: about_website.y + config.font_size + 15 + color: "#" + config.button_color + width: config.button_width + height: config.button_height + border.color: "#" + config.button_border_color + border.width: config.button_border_width + radius: 10 + smooth: true + + Image { + anchors.centerIn: parent + smooth: true + source: "gtk-close.png" + } + MouseArea { + anchors.fill: parent + onClicked: {aboutDialogArea.close()} + } + } + */ +} diff --git a/data/ui/qml/ContextMenu.qml b/data/ui/qml/ContextMenu.qml new file mode 100644 index 0000000..abdb6ab --- /dev/null +++ b/data/ui/qml/ContextMenu.qml @@ -0,0 +1,45 @@ + +import Qt 4.7 + +import 'config.js' as Config + +Item { + id: contextMenuArea + property variant items: [] + signal close + signal response(int index) + + MouseArea { + anchors.fill: parent + } + Rectangle { + color: "black" + anchors.fill: parent + opacity: .9 + } + ListView { + model: contextMenuArea.items + anchors.fill: parent + header: Item { height: Config.headerHeight * 2 } + footer: Item { height: Config.headerHeight } + + delegate: SelectableItem { + ShadowText { + anchors.leftMargin: Config.switcherWidth + anchors { + left: parent.left + right: parent.right + verticalCenter: parent.verticalCenter + } + color: "white" + font.pixelSize: parent.height * .3 + text: items[index].text + } + onSelected: { + contextMenuArea.response(index) + contextMenuArea.close() + items[index].trigger() + } + } + } +} diff --git a/data/ui/qml/SelectableItem.qml b/data/ui/qml/SelectableItem.qml new file mode 100644 index 0000000..4e50f6a --- /dev/null +++ b/data/ui/qml/SelectableItem.qml @@ -0,0 +1,36 @@ + +import Qt 4.7 + +import 'config.js' as Config + +Item { + id: selectableItem + signal selected(variant item) + signal contextMenu(variant item) + + height: Config.listItemHeight + width: parent.width + + Rectangle { + id: highlight + opacity: mouseArea.pressed?.2:0 + color: "white" + anchors.fill: parent + + Behavior on opacity { NumberAnimation { duration: Config.slowTransition } } + } + + MouseArea { + id: mouseArea + acceptedButtons: Qt.LeftButton | Qt.RightButton + anchors.fill: parent + onClicked: { + if (mouse.button == Qt.LeftButton) { + selectableItem.selected(modelData) + } else if (mouse.button == Qt.RightButton) { + selectableItem.contextMenu(modelData) + } + } + onPressAndHold: selectableItem.contextMenu(modelData) + } +} diff --git a/data/ui/qml/ShadowText.qml b/data/ui/qml/ShadowText.qml new file mode 100644 index 0000000..90642b7 --- /dev/null +++ b/data/ui/qml/ShadowText.qml @@ -0,0 +1,24 @@ + +import Qt 4.7 + +Text { + property color shadowColor: "black" + property int offsetX: -1 + property int offsetY: -2 + property alias color: innerText.color + color: shadowColor + elide: Text.ElideNone + + Text { + id: innerText + text: parent.text + anchors.fill: parent + font: parent.font + anchors.leftMargin: parent.offsetX + anchors.topMargin: parent.offsetY + elide: parent.elide + clip: parent.clip + } + +} + diff --git a/data/ui/qml/config.js b/data/ui/qml/config.js new file mode 100644 index 0000000..d068a37 --- /dev/null +++ b/data/ui/qml/config.js @@ -0,0 +1,24 @@ + +var scale = 1 + +var smallSpacing = 7 * scale +var largeSpacing = smallSpacing * 2 + +var switcherWidth = 90 * scale +var headerHeight = 56 * scale + +var listItemHeight = 78 * scale +var iconSize = 36 * scale + +var fadeHeight = 26 * scale + +var quickTransition = 50 +var slowTransition = 150 +var fadeTransition = 300 + +var baseColor = '#3b485b' +var offlineColor = '#4b4b4b' + +var hasCloseButton = false +var hasTaskSwitcher = false + diff --git a/data/ui/qml/main.qml b/data/ui/qml/main.qml index b878a23..1ac4d8d 100644 --- a/data/ui/qml/main.qml +++ b/data/ui/qml/main.qml @@ -1,11 +1,24 @@ import Qt 4.7 +import 'config.js' as Config + Rectangle { + id: root color: "#" + config.background width: config.main_width height: config.main_height + function openContextMenu(items) { + contextMenu.state = 'opened' + contextMenu.items = [action_add_file, action_add_folder, + action_play_one, action_save_playlist, action_clear_playlist, action_delete_bookmarks, + action_about, action_quit] + } + function openAboutDialog(items) { + aboutDialog.state = 'opened' + aboutDialog.items = items + } function set_text_x() { if (cover.source == "") { artist.x = (config.main_width - artist.width) / 2 @@ -13,7 +26,6 @@ Rectangle { title_rect.x = 5 title_rect.width = config.main_width - 10 title.x = (config.main_width - title.width) / 2 - } else { artist.x = config.cover_height + 5 @@ -87,7 +99,7 @@ Rectangle { MouseArea { anchors.fill: parent - onClicked: action_player_play.trigger() + onClicked: {action_player_play.trigger()} } } Text { @@ -157,7 +169,6 @@ Rectangle { font.pixelSize: config.font_size text: main.time_string verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignRight } Rectangle { x: 0 @@ -299,5 +310,102 @@ Rectangle { smooth: true source: "bookmark-new.png" } + MouseArea { + anchors.fill: parent + onClicked: action_bookmark.trigger() + } + } + ContextMenu { + id: contextMenu + width: parent.width + opacity: 0 + + anchors { + top: parent.top + bottom: parent.bottom + } + + onClose: contextMenu.state = 'closed' + //onResponse: controller.contextMenuResponse(index) + + state: 'closed' + + Behavior on opacity { NumberAnimation { duration: Config.fadeTransition } } + + states: [ + State { + name: 'opened' + PropertyChanges { + target: contextMenu + opacity: 1 + } + AnchorChanges { + target: contextMenu + anchors.right: root.right + } + }, + State { + name: 'closed' + PropertyChanges { + target: contextMenu + opacity: 0 + } + AnchorChanges { + target: contextMenu + anchors.right: root.left + } + StateChangeScript { + //script: controller.contextMenuClosed() + } + } + ] + + transitions: Transition { + AnchorAnimation { duration: Config.slowTransition } + } + } + AboutDialog { + id: aboutDialog + width: parent.width + opacity: 0 + + anchors { + top: parent.top + bottom: parent.bottom + } + onClose: aboutDialog.state = 'closed' + state: 'closed' + Behavior on opacity { NumberAnimation { duration: Config.fadeTransition } } + + states: [ + State { + name: 'opened' + PropertyChanges { + target: aboutDialog + opacity: 1 + } + AnchorChanges { + target: aboutDialog + anchors.right: root.right + } + }, + State { + name: 'closed' + PropertyChanges { + target: aboutDialog + opacity: 0 + } + AnchorChanges { + target: aboutDialog + anchors.right: root.left + } + StateChangeScript { + //script: controller.contextMenuClosed() + } + } + ] + transitions: Transition { + AnchorAnimation { duration: Config.slowTransition } + } } } diff --git a/icons/gtk-close.png b/icons/gtk-close.png new file mode 100644 index 0000000000000000000000000000000000000000..ab3edcc3a4613caf2feb797a7fdf5b37ece83ec8 GIT binary patch literal 1675 zcwPaE26Xv}P)q&n2<-(S!2ux9|w<9ubVXH%s%N|X5M?>&+pCq{eA;{ zYX9#>J3Z__*Z+MNqYIq#eT>+w;MVJxFOS^*UkaZ+d-^LRNx$bde~B@cv26aU;mgAp zYvWwcB))d$yMC|#57FLe_~_B2Qgd_j{-tz!pzFnsxsN`anW;xSIgm_9k~Dt&*zuO` zSG%Qytp^)2nanrZI}Shk=-$V7t7BPhGJ*ZNr>93NnI+8K{}%#*2E|7W4T0KDs|Y2VK{3tf$Az$aSGM{uuzy`M!og1M>Mb2qBPKOku0Eg}%N% zZ7+z5_{msIBO)v+1#h{eE!HoA(4@%=KX=oxx{6(*hy_V+`5s3QV(v_^G(2 zDmz0|#QWlX8e@cXdKru{5D{8i+mKmK!^Nb(?+IXW`$yBaZ|j_M960a-0Dy>)UCqL> zEF?}PG9pbG!88TD={2!MSt&-;os88z;Y2 zZe?aAv)zqIBmzZNFgiM>7fZ%@Ay`q7q`}0u6B>cAoL&Ow96|_0BFz8@@4WrCVO!R@ z!NDt|bpbqukl*Nw#WWCMWhJxS(nzEkvLs>n>Q!*gar*RWFvhUFyaXWxIOhn5BOnmQ z$H#XSe=a~ZM7%Gq5qk>37(+N5fvUQ}xeadHNN3XEoP%?YNH_uk!uYjohGm+&iUT{G z1J!o#-puTaN4h?qe=wiu=;)CBJ|A>l2N9uIECLX)OcQI)j;XYrK)6zv1}w`2 z=K@3oP1E4oA;K`E>6bfrFiUx=XBpASetx^d>lt)T1 zq1Icst_~yzl1WvTE=GHMWy`X$vAF>T1_FT?z=&X5HdIwXXICdu|4GG=z0k_+O_BtVU1*nKeqft!=UKS?; zfe;EcLQxc4zkVHa_vg_5xpsKH-t8@F7zR|g8;1`cl2Z$d&xP0#pdxVF9&)kMCnSS^3mtJ<-o&x{~A<*D&03*WW zMy!wng|Ai+lNzbtz6^Fue_qURQB6iy$S$1 z-B7s@M?#H3Dy$c_gZ%ym5D`9@nld&v^w&qOjEn(rSNrhrn}2?i-}vFwjT?q#S_lS$ z+xfZNDngBouubbFl+PZQqY37?3xEcofdn4r*YeObFNg?!zaK=vUvJ(lu4Gq#`qrCo zy;oT|0M&5?fNym4+Kp^xEQhiZw;T zj}2Wv*%WS+gTWA1#V+(ixaaYe~vcH(0e=zIhm;glOI+h#&4*>Ux-kxtZNA~}W81@M+QV&y)FHBEQ z{|!J1z?S2@=2KR8MDFhHezm3Tg_3nh5T>ceP?0_KoNl9)cVB#faDaBYrd0k zR%-&VoJ6~Jn5rNYC)b6iGiE!vrsJhb(oR1lgr{=>2Y~M)x|>x1DhuFM{;7S!{tLhI V-|9O%6W9O%002ovPDHLkV1lwg4`=`Y literal 0 HcwPel00001 diff --git a/setup.py b/setup.py index 0ab88cc..810204b 100644 --- a/setup.py +++ b/setup.py @@ -39,7 +39,7 @@ if not os.path.exists('data/panucci.service') and 'clean' not in sys.argv: DATA_FILES = [ ('share/panucci', glob.glob('icons/*.png')), - ('share/panucci', glob.glob('data/ui/qml/*.qml')), + ('share/panucci', glob.glob('data/ui/qml/*')), ('share/panucci', ['data/panucci.conf', 'data/panucci-all.conf']), ('share/applications', ['data/panucci.desktop']), ('share/icons/hicolor/scalable/apps', ['data/panucci.svg']), diff --git a/src/panucci/qmlui/qmlmain.py b/src/panucci/qmlui/qmlmain.py index e061a82..a42c305 100644 --- a/src/panucci/qmlui/qmlmain.py +++ b/src/panucci/qmlui/qmlmain.py @@ -17,6 +17,7 @@ # along with Panucci. If not, see . import sys +import os import logging from PySide import QtCore @@ -27,6 +28,7 @@ import panucci from panucci import util from panucci import platform from panucci import playlist +from panucci import about from panucci.dbusinterface import interface from panucci.services import ObservableService @@ -104,26 +106,35 @@ class PanucciGUI(QtCore.QObject, ObservableService): # File menu self.action_add_file = QtGui.QAction(QtGui.QIcon(':/actions/add.png'), _("Add File").decode("utf-8"), self.main_window, shortcut="Ctrl+A", statusTip="Add file to playlist", triggered=self.add_file_callback) + self.context.setContextProperty('action_add_file', self.action_add_file) self.action_add_folder = QtGui.QAction(QtGui.QIcon(':/images/open.png'), _("Add Folder").decode("utf-8"), self.main_window, shortcut="Ctrl+D", statusTip="Add folder to playlist", triggered=self.add_folder_callback) + self.context.setContextProperty('action_add_folder', self.action_add_folder) self.action_play_one = QtGui.QAction(QtGui.QIcon(''), _("Play One").decode("utf-8"), self.main_window, shortcut="Ctrl+O", statusTip="Play one file", triggered=self.play_one_callback) + self.context.setContextProperty('action_play_one', self.action_play_one) self.action_save_playlist = QtGui.QAction(QtGui.QIcon(':/images/save.png'), _("Save Playlist").decode("utf-8"), self.main_window, shortcut="Ctrl+W", statusTip="Save current playlist as m3u", triggered=self.save_playlist_callback) + self.context.setContextProperty('action_save_playlist', self.action_save_playlist) self.action_clear_playlist = QtGui.QAction(QtGui.QIcon(':/images/trashcan.png'), _("Clear Playlist").decode("utf-8"), self.main_window, shortcut="Ctrl+H", statusTip="Clear current playlist", triggered=self.clear_playlist_callback) + self.context.setContextProperty('action_clear_playlist', self.action_clear_playlist) self.action_delete_bookmarks = QtGui.QAction(QtGui.QIcon(':/images/trashcan.png'), _("Delete All Bookmarks").decode("utf-8"), self.main_window, shortcut="Ctrl+K", statusTip="Delete all bookmarks", triggered=self.delete_bookmarks_callback) + self.context.setContextProperty('action_delete_bookmarks', self.action_delete_bookmarks) self.action_quit = QtGui.QAction(QtGui.QIcon('/usr/share/icons/gnome/16x16/actions/exit.png'), "Quit", self.main_window, shortcut="Ctrl+Q", statusTip="Exit the application", triggered=self.quit_panucci) self.context.setContextProperty('action_quit', self.action_quit) # Tools menu self.action_playlist = QtGui.QAction(_("Playlist"), self.main_window, shortcut="Ctrl+P", statusTip=_("Open playlist"), triggered=self.playlist_callback) + self.context.setContextProperty('action_playlist', self.action_playlist) self.action_settings = QtGui.QAction(_("Settings"), self.main_window, shortcut="Ctrl+C", statusTip=_("Open settings dialog"), triggered=self.settings_callback) + self.context.setContextProperty('action_setings', self.action_settings) self.action_timer = QtGui.QAction(_("Sleep Timer"), self.main_window, shortcut="Ctrl+T", statusTip=_("Start a timed shutdown"), triggered=self.create_timer_dialog) + self.context.setContextProperty('action_timer', self.action_timer) # Settings menu self.action_lock_progress = QtGui.QAction(_("Lock Progress Bar").decode("utf-8"), self.main_window, shortcut="Ctrl+L", statusTip="Lock progress bar", triggered=self.lock_progress_callback) @@ -178,6 +189,7 @@ class PanucciGUI(QtCore.QObject, ObservableService): # help menu self.action_about = QtGui.QAction(QtGui.QIcon('about.png'), _("About").decode("utf-8"), self.main_window, statusTip="Show about dialog", triggered=self.about_callback) + self.context.setContextProperty('action_about', self.action_about) # Player self.action_player_rrewind = QtGui.QAction(QtGui.QIcon(''), _("").decode("utf-8"), self.main_window, triggered=self.player_rrewind_callback) @@ -201,6 +213,9 @@ class PanucciGUI(QtCore.QObject, ObservableService): self.action_player_skip_forward = QtGui.QAction(QtGui.QIcon(''), _("").decode("utf-8"), self.main_window, triggered=self.player_skip_forward_callback) self.context.setContextProperty('action_player_skip_forward', self.action_player_skip_forward) + self.action_bookmark = QtGui.QAction(QtGui.QIcon(''), _("").decode("utf-8"), self.main_window, + triggered=self.bookmark_callback) + self.context.setContextProperty('action_bookmark', self.action_bookmark) def create_menus(self): # Player menu @@ -236,6 +251,10 @@ class PanucciGUI(QtCore.QObject, ObservableService): def show_main_window(self): self.main_window.activateWindow() + def show_context_menu(self, actions): + self.context_menu_actions = actions + self.root.open_context_menu(self.context_menu_actions) + def add_file_callback(self): filenames = qtutil.get_file_from_filechooser(self) if filenames: @@ -327,8 +346,10 @@ class PanucciGUI(QtCore.QObject, ObservableService): self.set_config_option("play_mode", "repeat") def about_callback(self): - from panucci.qtui import qtaboutdialog - qtaboutdialog.AboutDialog(self.main_window, panucci.__version__) + #from panucci.qtui import qtaboutdialog + #qtaboutdialog.AboutDialog(self.main_window, panucci.__version__) + self.view.rootObject().openAboutDialog([about.about_name+" "+panucci.__version__, about.about_text, + about.about_copyright, about.about_website]) def set_config_option(self, option, value): self.config.set("options", option, value) @@ -360,6 +381,9 @@ class PanucciGUI(QtCore.QObject, ObservableService): def player_play_callback(self): self.playlist.play_pause_toggle() + def bookmark_callback(self): + self.view.rootObject().openContextMenu([self.action_about, self.action_about, self.action_about, self.action_about]) + def do_seek(self, seek_amount): resp = self.playlist.do_seek(from_current=seek_amount*10**9) if resp: @@ -499,6 +523,10 @@ class PanucciGUI(QtCore.QObject, ObservableService): self.reset_progress() self.main_window.setWindowTitle("Panucci") + @QtCore.Slot(str) + def open_external_url(self, url): + os.system("xdg-open " + url) + class ImageProvider(QtDeclarative.QDeclarativeImageProvider): def __init__(self, main): QtDeclarative.QDeclarativeImageProvider.__init__(self, QtDeclarative.QDeclarativeImageProvider.Pixmap) -- 2.11.4.GIT