Browse Source

- Added right-click menu to transfer list

adaptive-webui-19844
Christophe Dumez 15 years ago
parent
commit
d42ab6120e
  1. BIN
      src/Icons/skin/delete22.png
  2. BIN
      src/Icons/skin/delete_perm22.png
  3. BIN
      src/Icons/skin/pause22.png
  4. BIN
      src/Icons/skin/play22.png
  5. 4
      src/icons.qrc
  6. 2
      src/torrentpersistentdata.h
  7. 3
      src/webui.qrc
  8. 92
      src/webui/css/mootabs1.2.css
  9. 16
      src/webui/css/style.css
  10. 8
      src/webui/index.html
  11. 155
      src/webui/scripts/contextmenu.js
  12. 22
      src/webui/scripts/dynamicTable.js
  13. 53
      src/webui/scripts/mocha-init.js
  14. 223
      src/webui/scripts/mootabs1.2.js
  15. 33
      src/webui/transferlist.html

BIN
src/Icons/skin/delete22.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src/Icons/skin/delete_perm22.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
src/Icons/skin/pause22.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/Icons/skin/play22.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

4
src/icons.qrc

@ -24,6 +24,7 @@ @@ -24,6 +24,7 @@
<file>Icons/skin/handle-icon.gif</file>
<file>Icons/skin/url.png</file>
<file>Icons/skin/stalledUP.png</file>
<file>Icons/skin/delete_perm22.png</file>
<file>Icons/skin/filteractive.png</file>
<file>Icons/skin/connected.png</file>
<file>Icons/skin/pausedDL.png</file>
@ -37,10 +38,13 @@ @@ -37,10 +38,13 @@
<file>Icons/skin/qb_question.png</file>
<file>Icons/skin/download.png</file>
<file>Icons/skin/open.png</file>
<file>Icons/skin/play22.png</file>
<file>Icons/skin/qbittorrent16.png</file>
<file>Icons/skin/downloading.png</file>
<file>Icons/skin/filterinactive.png</file>
<file>Icons/skin/pause22.png</file>
<file>Icons/skin/pause_all.png</file>
<file>Icons/skin/delete22.png</file>
<file>Icons/skin/play_all.png</file>
<file>Icons/skin/pause.png</file>
<file>Icons/skin/firewalled.png</file>

2
src/torrentpersistentdata.h

@ -222,7 +222,7 @@ public: @@ -222,7 +222,7 @@ public:
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
QHash<QString, QVariant> all_data = settings.value("torrents", QHash<QString, QVariant>()).toHash();
QHash<QString, QVariant> data = all_data[hash].toHash();
qDebug("TorrentPersistentData: getSavePath %s", data["save_path"].toString().toLocal8Bit().data());
//qDebug("TorrentPersistentData: getSavePath %s", data["save_path"].toString().toLocal8Bit().data());
return data["save_path"].toString();
}

3
src/webui.qrc

@ -14,7 +14,6 @@ @@ -14,7 +14,6 @@
<file>webui/css/mocha.css</file>
<file>webui/css/dynamicTable.css</file>
<file>webui/css/style.css</file>
<file>webui/css/mootabs1.2.css</file>
<file>webui/scripts/excanvas-compressed.js</file>
<file>webui/scripts/mocha.js</file>
<file>webui/scripts/mocha-init.js</file>
@ -23,7 +22,7 @@ @@ -23,7 +22,7 @@
<file>webui/scripts/dynamicTable.js</file>
<file>webui/scripts/client.js</file>
<file>webui/scripts/download.js</file>
<file>webui/scripts/mootabs1.2.js</file>
<file>webui/scripts/progressbar.js</file>
<file>webui/scripts/contextmenu.js</file>
</qresource>
</RCC>

92
src/webui/css/mootabs1.2.css

@ -1,92 +0,0 @@ @@ -1,92 +0,0 @@
/*
* MIT License
* Copyright (c) 2008 Christophe Dumez <chris@qbittorrent.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* Original code from http://www.silverscripting.com/mootabs/
* Edited by Christophe Dumez
*/
.toolbarTabs {
padding: 0 5px 2px 2px;
background: url(../images/skin/tabs.gif) repeat-x;
background-position: left -70px;
overflow: visible;
}
.mootabs_title {
padding-top: 1px;
list-style: none;
margin: 0;
padding: 0;
line-height: 16px;
font-size: 11px;
}
.mootabs_title li {
display: block;
float: left;
margin: 0 0 5px 0;
cursor: pointer;
background: url(../images/skin/tabs.gif) repeat-x;
background-position: left -35px;
}
.mootabs_title li.active {
background: url(../images/skin/tabs.gif) repeat-x;
background-position: left 0;
}
.mootabs_title li a {
display: block;
margin-left: 8px;
padding: 6px 16px 5px 10px;
text-align: center;
font-weight: normal;
color: #141414;
background: url(../images/skin/tabs.gif) repeat-x;
background-position: right -35px;
}
.mootabs_title li.active a {
color: #141414;
font-weight: bold;
background: url(../images/skin/tabs.gif) repeat-x;
background-position: right 0;
}
.mootabs_panel {
display: none;
background-color: #ddd;
position: relative;
width: 100%;
top: -1px;
clear: both;
overflow: auto;
}
.mootabs_panel.active {
background-color: #e6e6e6;
display: block;
}

16
src/webui/css/style.css

@ -154,3 +154,19 @@ a.propButton { @@ -154,3 +154,19 @@ a.propButton {
a.propButton img {
margin-bottom: -4px;
}
/* context menu specific */
#contextmenu { border:1px solid #999; padding:0; background:#eee; width:200px; list-style-type:none; display:none; }
#contextmenu .separator { border-top:1px solid #999; }
#contextmenu li { margin:0; padding:0; }
#contextmenu li a { display:block; padding:5px 10px 5px 35px; width:155px; font-size:12px; text-decoration:none; font-family:tahoma,arial,sans-serif; color:#000; background-position:8px 2px; background-repeat:no-repeat; }
#contextmenu li a:hover { background-color:#ddd; }
#contextmenu li a.disabled { color:#ccc; font-style:italic; }
#contextmenu li a.disabled:hover { background-color:#eee; }
/* context menu items */
#contextmenu li a.pause { background-image:url(../images/skin/pause22.png); }
#contextmenu li a.start { background-image:url(../images/skin/play22.png); }
#contextmenu li a.recheck { background-image:url(../images/oxygen/gear.png); }
#contextmenu li a.delete { background-image:url(../images/skin/delete22.png); }
#contextmenu li a.deleteHD { background-image:url(../images/skin/delete_perm22.png); }

8
src/webui/index.html

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
<script type="text/javascript" src="scripts/progressbar.js"></script>
<script type="text/javascript" src="scripts/dynamicTable.js" charset="utf-8"></script>
<script type="text/javascript" src="scripts/client.js" charset="utf-8"></script>
<script type="text/javascript" src="scripts/contextmenu.js" charset="utf-8"></script>
</head>
<body>
<div id="desktop">
@ -75,5 +76,12 @@ @@ -75,5 +76,12 @@
</div>
</div>
<ul id="contextmenu">
<li><a href="#Start" class="start">_(Start)</a></li>
<li><a href="#Pause" class="pause">_(Pause)</a></li>
<li class="separator"><a href="#ForceRecheck" class="recheck">_(Force recheck)</a></li>
<li class="separator"><a href="#Delete" class="delete">_(Delete)</a></li>
<li><a href="#DeleteHD" class="deleteHD">_(Delete from HD)</a></li>
</ul>
</body>
</html>

155
src/webui/scripts/contextmenu.js

@ -0,0 +1,155 @@ @@ -0,0 +1,155 @@
var ContextMenu = new Class({
//implements
Implements: [Options,Events],
//options
options: {
actions: {},
menu: 'contextmenu',
stopEvent: true,
targets: 'body',
trigger: 'contextmenu',
offsets: { x:0, y:0 },
onShow: $empty,
onHide: $empty,
onClick: $empty,
fadeSpeed: 200
},
//initialization
initialize: function(options) {
//set options
this.setOptions(options)
//option diffs menu
this.menu = $(this.options.menu);
this.targets = $$(this.options.targets);
//fx
this.fx = new Fx.Tween(this.menu, { property: 'opacity', duration:this.options.fadeSpeed });
//hide and begin the listener
this.hide().startListener();
//hide the menu
this.menu.setStyles({ 'position':'absolute','top':'-900000px', 'display':'block' });
},
addTarget: function(t) {
this.targets[this.targets.length] = t;
t.addEvent(this.options.trigger,function(e) {
//enabled?
if(!this.options.disabled) {
//prevent default, if told to
if(this.options.stopEvent) { e.stop(); }
//record this as the trigger
this.options.element = $(t);
//position the menu
this.menu.setStyles({
top: (e.page.y + this.options.offsets.y),
left: (e.page.x + this.options.offsets.x),
position: 'absolute',
'z-index': '2000'
});
//show the menu
this.show();
}
}.bind(this));
},
//get things started
startListener: function() {
/* all elements */
this.targets.each(function(el) {
/* show the menu */
el.addEvent(this.options.trigger,function(e) {
//enabled?
if(!this.options.disabled) {
//prevent default, if told to
if(this.options.stopEvent) { e.stop(); }
//record this as the trigger
this.options.element = $(el);
//position the menu
this.menu.setStyles({
top: (e.page.y + this.options.offsets.y),
left: (e.page.x + this.options.offsets.x),
position: 'absolute',
'z-index': '2000'
});
//show the menu
this.show();
}
}.bind(this));
},this);
/* menu items */
this.menu.getElements('a').each(function(item) {
item.addEvent('click',function(e) {
if(!item.hasClass('disabled')) {
this.execute(item.get('href').split('#')[1],$(this.options.element));
this.fireEvent('click',[item,e]);
}
}.bind(this));
},this);
//hide on body click
$(document.body).addEvent('click', function() {
this.hide();
}.bind(this));
},
//show menu
show: function(trigger) {
//this.menu.fade('in');
this.fx.start(1);
this.fireEvent('show');
this.shown = true;
return this;
},
//hide the menu
hide: function(trigger) {
if(this.shown)
{
this.fx.start(0);
//this.menu.fade('out');
this.fireEvent('hide');
this.shown = false;
}
return this;
},
//disable an item
disableItem: function(item) {
this.menu.getElements('a[href$=' + item + ']').addClass('disabled');
return this;
},
//enable an item
enableItem: function(item) {
this.menu.getElements('a[href$=' + item + ']').removeClass('disabled');
return this;
},
//diable the entire menu
disable: function() {
this.options.disabled = true;
return this;
},
//enable the entire menu
enable: function() {
this.options.disabled = false;
return this;
},
//execute an action
execute: function(action,element) {
if(this.options.actions[action]) {
this.options.actions[action](element,this);
}
return this;
}
});

22
src/webui/scripts/dynamicTable.js

@ -36,13 +36,14 @@ var dynamicTable = new Class ({ @@ -36,13 +36,14 @@ var dynamicTable = new Class ({
initialize: function(){
},
setup: function(table, progressIndex){
setup: function(table, progressIndex, context_menu){
this.table = $(table);
this.rows = new Hash();
this.cur = new Array();
this.priority_hidden = false;
this.progressIndex = progressIndex;
this.filter = 'all';
this.context_menu = context_menu;
},
getCurrentTorrentHash: function() {
@ -130,6 +131,7 @@ var dynamicTable = new Class ({ @@ -130,6 +131,7 @@ var dynamicTable = new Class ({
return;
}
var tr = new Element('tr');
tr.addClass("menu-target");
this.rows.set(id, tr);
for(var i=0; i<row.length; i++)
{
@ -148,6 +150,22 @@ var dynamicTable = new Class ({ @@ -148,6 +150,22 @@ var dynamicTable = new Class ({
tr.addEvent('mouseout', function(e){
tr.removeClass('over');
}.bind(this));
tr.addEvent('contextmenu', function(e) {
if(!this.cur.contains(id)) {
// Remove selected style from previous ones
for(i=0; i<this.cur.length; i++) {
if(this.rows.has(this.cur[i])) {
var temptr = this.rows.get(this.cur[i]);
temptr.removeClass('selected');
}
}
this.cur.empty();
this.cur[this.cur.length] = id;
temptr = this.rows.get(id);
temptr.addClass("selected");
}
return true;
}.bind(this));
tr.addEvent('click', function(e){
e.stop();
if(e.control) {
@ -215,6 +233,8 @@ var dynamicTable = new Class ({ @@ -215,6 +233,8 @@ var dynamicTable = new Class ({
// Insert
tr.injectInside(this.table);
this.altRow();
// Update context menu
this.context_menu.addTarget(tr);
},
selectAll: function() {

53
src/webui/scripts/mocha-init.js

@ -56,33 +56,62 @@ initializeWindows = function(){ @@ -56,33 +56,62 @@ initializeWindows = function(){
addClickEvent('delete', function(e){
new Event(e).stop();
deleteFN = function() {
var h = myTable.selectedIds();
if(h.length && confirm('_(Are you sure you want to delete the selected torrents from the transfer list?)')) {
h.each(function(item, index){
new Request({url: '/command/delete', method: 'post', data: {hash: item}}).send();
});
}
});
};
addClickEvent('delete', function(e){
new Event(e).stop();
deleteFN();
});
addClickEvent('deletePerm', function(e){
new Event(e).stop();
var h = myTable.selectedIds();
deleteHDFN = function() {
var h = myTable.selectedIds();
if(h.length && confirm('_(Are you sure you want to delete the selected torrents from the transfer list and hard disk?)')) {
h.each(function(item, index){
new Request({url: '/command/deletePerm', method: 'post', data: {hash: item}}).send();
});
}
};
addClickEvent('deletePerm', function(e){
new Event(e).stop();
deleteHDFN();
});
pauseFN = function() {
var h = myTable.selectedIds();
if(h.length){
h.each(function(hash, index){
new Request({url: '/command/pause', method: 'post', data: {hash: hash}}).send();
});
}
};
startFN = function() {
var h = myTable.selectedIds();
if(h.length){
h.each(function(hash, index){
new Request({url: '/command/resume', method: 'post', data: {hash: hash}}).send();
});
}
};
recheckFN = function() {
var h = myTable.selectedIds();
if(h.length){
h.each(function(hash, index){
new Request({url: '/command/recheck', method: 'post', data: {hash: hash}}).send();
});
}
};
['pause','resume','decreasePrio','increasePrio','recheck'].each(function(item) {
addClickEvent(item, function(e){
new Event(e).stop();

223
src/webui/scripts/mootabs1.2.js

@ -1,223 +0,0 @@ @@ -1,223 +0,0 @@
/*
* MIT License
* Copyright (c) 2008 Christophe Dumez <chris@qbittorrent.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* Original code from http://www.silverscripting.com/mootabs/
* Ported to Mootools 1.2 by Christophe Dumez
*/
var mootabs = new Class({
Implements: [Options],
options: {
width: '300px',
height: '200px',
changeTransition: Fx.Transitions.Bounce.easeOut,
duration: 1000,
mouseOverClass: 'over',
activateOnLoad: 'first',
useAjax: false,
ajaxUrl: '',
ajaxOptions: {method:'get', evalScripts: true},
ajaxLoadingText: 'Loading...'
},
initialize: function(element, options) {
if(options) this.setOptions(options);
this.el = $(element);
this.elid = element;
this.el.setStyles({
height: this.options.height,
width: this.options.width
});
this.titles = $$('#' + this.elid + ' ul li');
this.panelHeight = this.el.getSize().y - (this.titles[0].getSize().y + 4);
this.panels = $$('#' + this.elid + ' .mootabs_panel');
this.panels.setStyle('height', this.panelHeight);
this.titles.each(function(item) {
item.addEvent('click', function(){
if(item != this.activeTitle)
{
item.removeClass(this.options.mouseOverClass);
this.activate(item);
}
}.bind(this));
item.addEvent('mouseover', function() {
if(item != this.activeTitle)
{
item.addClass(this.options.mouseOverClass);
}
}.bind(this));
item.addEvent('mouseout', function() {
if(item != this.activeTitle)
{
item.removeClass(this.options.mouseOverClass);
}
}.bind(this));
}.bind(this));
if(this.options.activateOnLoad != 'none')
{
if(this.options.activateOnLoad == 'first')
{
this.activate(this.titles[0], true);
}
else
{
this.activate(this.options.activateOnLoad, true);
}
}
},
activate: function(tab, skipAnim){
if(! $defined(skipAnim))
{
skipAnim = false;
}
if($type(tab) == 'string')
{
myTab = $$('#' + this.elid + ' ul li').filter('[title=' + tab + ']')[0];
tab = myTab;
}
if($type(tab) == 'element')
{
var newTab = tab.getProperty('title');
this.panels.removeClass('active');
this.activePanel = this.panels.filter('#' + newTab)[0];
this.activePanel.addClass('active');
if(this.options.changeTransition != 'none' && skipAnim==false)
{
this.panels.filter('#' + newTab).setStyle('height', 0);
var changeEffect = new Fx.Elements(this.panels.filter('#' + newTab), {duration: this.options.duration, transition: this.options.changeTransition});
changeEffect.start({
'0': {
'height': [0, this.panelHeight]
}
});
}
this.titles.removeClass('active');
tab.addClass('active');
this.activeTitle = tab;
if(this.options.useAjax)
{
this._getContent();
}
}
},
_getContent: function(){
this.activePanel.setHTML(this.options.ajaxLoadingText);
var newOptions = {
url: this.options.ajaxUrl + '?tab=' + this.activeTitle.getProperty('title'),
update: this.activePanel.getProperty('id')
};
this.options.ajaxOptions = $merge(this.options.ajaxOptions, newOptions);
var tabRequest = new Request.HTML(this.options.ajaxOptions);
tabRequest.send();
},
addTab: function(title, label, content){
//the new title
var newTitle = new Element('li', {
'title': title
});
newTitle.appendText(label);
this.titles.include(newTitle);
$$('#' + this.elid + ' ul').adopt(newTitle);
newTitle.addEvent('click', function() {
this.activate(newTitle);
}.bind(this));
newTitle.addEvent('mouseover', function() {
if(newTitle != this.activeTitle)
{
newTitle.addClass(this.options.mouseOverClass);
}
}.bind(this));
newTitle.addEvent('mouseout', function() {
if(newTitle != this.activeTitle)
{
newTitle.removeClass(this.options.mouseOverClass);
}
}.bind(this));
//the new panel
var newPanel = new Element('div', {
'style': {'height': this.options.panelHeight},
'id': title,
'class': 'mootabs_panel'
});
if(!this.options.useAjax)
{
newPanel.setHTML(content);
}
this.panels.include(newPanel);
this.el.adopt(newPanel);
},
removeTab: function(title){
if(this.activeTitle.title == title)
{
this.activate(this.titles[0]);
}
$$('#' + this.elid + ' ul li').filter('[title=' + title + ']')[0].remove();
$$('#' + this.elid + ' .mootabs_panel').filter('#' + title)[0].remove();
},
next: function(){
var nextTab = this.activeTitle.getNext();
if(!nextTab) {
nextTab = this.titles[0];
}
this.activate(nextTab);
},
previous: function(){
var previousTab = this.activeTitle.getPrevious();
if(!previousTab) {
previousTab = this.titles[this.titles.length - 1];
}
this.activate(previousTab);
}
});

33
src/webui/transferlist.html

@ -17,6 +17,33 @@ @@ -17,6 +17,33 @@
</thead>
<tbody id="myTable"></tbody>
</table>
<script>
myTable.setup('myTable', 4);
</script>
<script type="text/javascript">
//create a context menu
var context_menu = new ContextMenu({
targets: '.menu-target',
menu: 'contextmenu',
actions: {
Delete: function(element,ref) {
deleteFN();
},
DeleteHD: function(element,ref) {
deleteHDFN();
},
Start: function(element, ref) {
startFN();
},
Pause: function(element, ref) {
pauseFN();
},
ForceRecheck: function(element, ref) {
recheckFN();
}
},
offsets: { x:-15, y:2 }
});
myTable.setup('myTable', 4, context_menu);
</script>
Loading…
Cancel
Save