It is currently April 19th, 2024, 11:33 am

qBT - qBitttorrent skin

Media controls, music players, video and animated visualizers
User avatar
jsmorley
Developer
Posts: 22629
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

qBT - qBitttorrent skin

Post by jsmorley »

I did some re-work on my existing uTorrent skin, and converted it to support qBittorrent.

While qBittorrent might be missing an unessential feature or two that uTorrent has, there is no doubt it is a lot lighter, snappier, and I can live without all the advertising. I like it...
qBT3.png
Skin:

Code: Select all

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1

[Metadata]
Name=qBT
Author=JSMorley
Information=Skin to display torrent information from the WebUI interface for qBittorrent
License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0
Version=Apr 23, 2016

[Variables]
; qBittorrent info you MUST set
WebUIPort=8088
PathToqBittorrent="C:\Program Files (x86)\qBittorrent\qbittorrent.exe"
;End of qBittorrent info

;Colors you can change
ListFontColor=237,242,247,255
HeaderColor=201,218,242,255
qBittorrentColor=239,219,137
;PanelColor=2,14,31,180
PanelColor=10,10,10,200
ProgressBarColor=138,168,209,255
SeparatorLineColor=150,150,150,255
GreyColor=180,180,180,255
;End of colors

;Don't change these
ProcessName=qbittorrent
WebUIURL=http://localhost:#WebUIPort#/query/torrents
BackgroundHeight=230
Bar1Calc=0
Bar2Calc=0
Bar3Calc=0
Bar4Calc=0
Bar5Calc=0
;End of [Variables]

;[Create interface]==================================================

[ListStyle]
FontColor=#ListFontColor#
FontFace=Arial
FontSize=10
StringStyle=Normal
StringAlign=LEFT
AntiAlias=1

[MeterTopBackground]
Meter=Image
SolidColor=#PanelColor#
W=545
H=25
X=0
Y=0

[MeterLabelBackground]
Group=Body
Meter=Image
SolidColor=#PanelColor#
W=545
H=30
X=0
Y=25
Hidden=1

[MeterBodyBackground]
Group=Body
Meter=Image
SolidColor=#PanelColor#
W=545
H=#BackgroundHeight#
X=0
Y=55
Hidden=1
DynamicVariables=1

[MeterTopLabel]
Meter=String
MeterStyle=ListStyle
X=5
Y=5
FontColor=#HeaderColor#
SolidColor=0,0,0,1
InlineSetting=GradientColor | 180 | #ListFontColor# ; 0.1 | #HeaderColor# ; 0.5 | #ProgressBarColor# ; 1.0
InlinePattern=.*
Text=qBT - qBittorrent

[MeterRefresh]
Meter=Image
ImageName=#@#Images\refresh.png
W=18
H=18
PreserveAspectRatio=1
X=495
Y=4
Greyscale=1
ImageTint=#HeaderColor#
ToolTipText="Refresh Skin"
LeftMouseUpAction=!Refresh

[MeterPowerButton]
Meter=Image
ImageName=#@#Images\Power.png
W=18
H=18
PreserveAspectRatio=1
X=520
Y=4
Greyscale=1
ImageTint=#HeaderColor#

[MeterHeaders]
Group=Body
Meter=String
MeterStyle=ListStyle
FontColor=#HeaderColor#
W=545
H=19
X=0
Y=25
Text=" Name                                            | Size          | DL Speed       | Seeds       | Status"
Hidden=1

;[Check qbittorrent process]===========================================

[MeasureProcess]
Measure=Plugin
Plugin=Process.dll
ProcessName=#ProcessName#.exe
UpdateDivider=2
IfAboveValue=0
IfAboveAction=[!EnableMeasure MeasureWebUI][!SetOption MeterPowerButton ImageTint 93,242,85,255][!SetOption MeterPowerButton ToolTipText "Close uTorrent application"][!SetOption MeterPowerButton LeftMouseUpAction """["#@#Addons\KillqBittorrent.exe"]"""]
IfBelowValue=0
IfBelowAction=[!DisableMeasure MeasureWebUI][!SetOption MeterPowerButton ImageTint #HeaderColor#][!SetOption MeterPowerButton ToolTipText "Run uTorrent application"][!SetOption MeterPowerButton LeftMouseUpAction """["#PathToqBittorrent#"]"""]

;[Get torrent info from WebUI]=====================================

[MeasureWebUI]
Group=AllMeasures
Measure=Plugin
Plugin=WebParser.dll
URL=#WebUIURL#
RegExp="(?siU)^(.*)$"
ForceReload=1
UpdateRate=2
Disabled=1
FinishAction=[!EnableMeasure MeasureLua]

;[Lua Measure]===============================================================

[MeasureLua]
Measure=Script
ScriptFile=qBittorrent.lua
maxTorrents=5
UpdateDivider=2
Disabled=1

;[Torrent Meters]=============================================================

[Meter1Name]
Group=Torrent1
Meter=String
MeterStyle=ListStyle
W=185
H=15
ClipString=1
ToolTipType=1
ToolTipIcon=#@#Images\qbittorrent.ico
X=5
Y=55

[Meter1Size]
Group=Torrent1
Meter=String
MeterStyle=ListStyle
X=201
Y=55

[Meter1DLSpeed]
Group=Torrent1
Meter=String
MeterStyle=ListStyle
X=274
Y=55

[Meter1Seeds]
Group=Torrent1
Meter=String
MeterStyle=ListStyle
X=365
Y=55

[Meter1Status]
Group=Torrent1
Meter=String
MeterStyle=ListStyle
X=436
Y=55

[Meter1Line]
Group=Torrent1
Meter=Image
SolidColor=#SeparatorLineColor#
W=507
H=1
X=5
Y=74
Hidden=1

[Measure1BarCalc]
Group=Torrent1
Measure=Calc
Formula=#Bar1Calc#
MinValue=0
MaxValue=100
DynamicVariables=1

[Meter1Bar]
Group=Torrent1
Meter=Bar
MeasureName=Measure1BarCalc
BarColor=#ProgressBarColor#
BarOrientation=Horizontal
W=507
H=3
X=5
Y=73

[Meter1Percent]
Group=Torrent1
Meter=String
MeterStyle=ListStyle
FontSize=7
StringAlign=RIGHT
X=541
Y=-4r

;=============================================

[Meter2Name]
Group=Torrent2
Meter=String
MeterStyle=ListStyle
W=185
H=15
ClipString=1
ToolTipType=1
ToolTipIcon=#@#Images\qbittorrent.ico
X=5
Y=15r

[Meter2Size]
Group=Torrent2
Meter=String
MeterStyle=ListStyle
X=201
Y=0r

[Meter2DLSpeed]
Group=Torrent2
Meter=String
MeterStyle=ListStyle
X=274
Y=0r

[Meter2Seeds]
Group=Torrent2
Meter=String
MeterStyle=ListStyle
X=365
Y=0r

[Meter2Status]
Group=Torrent2
Meter=String
MeterStyle=ListStyle
X=436
Y=0r

[Meter2Line]
Group=Torrent2
Meter=Image
SolidColor=#SeparatorLineColor#
W=507
H=1
X=5
Y=20r
Hidden=1

[Measure2BarCalc]
Group=Torrent2
Measure=Calc
Formula=#Bar2Calc#
MinValue=0
MaxValue=100
DynamicVariables=1

[Meter2Bar]
Group=Torrent2
Meter=Bar
MeasureName=Measure2BarCalc
BarColor=#ProgressBarColor#
BarOrientation=Horizontal
W=507
H=3
X=5
Y=-1r

[Meter2Percent]
Group=Torrent2
Meter=String
MeterStyle=ListStyle
FontSize=7
StringAlign=RIGHT
X=541
Y=-4r

;=============================================

[Meter3Name]
Group=Torrent3
Meter=String
MeterStyle=ListStyle
W=185
H=15
ClipString=1
ToolTipType=1
ToolTipIcon=#@#Images\qbittorrent.ico
X=5
Y=15r

[Meter3Size]
Group=Torrent3
Meter=String
MeterStyle=ListStyle
X=201
Y=0r

[Meter3DLSpeed]
Group=Torrent3
Meter=String
MeterStyle=ListStyle
X=274
Y=0r

[Meter3Seeds]
Group=Torrent3
Meter=String
MeterStyle=ListStyle
X=365
Y=0r

[Meter3Status]
Group=Torrent3
Meter=String
MeterStyle=ListStyle
X=436
Y=0r

[Meter3Line]
Group=Torrent3
Meter=Image
SolidColor=#SeparatorLineColor#
W=507
H=1
X=5
Y=20r
Hidden=1

[Measure3BarCalc]
Group=Torrent3
Measure=Calc
Formula=#Bar3Calc#
MinValue=0
MaxValue=100
DynamicVariables=1

[Meter3Bar]
Group=Torrent3
Meter=Bar
MeasureName=Measure3BarCalc
BarColor=#ProgressBarColor#
BarOrientation=Horizontal
W=507
H=3
X=5
Y=-1r

[Meter3Percent]
Group=Torrent3
Meter=String
MeterStyle=ListStyle
FontSize=7
StringAlign=RIGHT
X=541
Y=-4r

;=============================================

[Meter4Name]
Group=Torrent4
Meter=String
MeterStyle=ListStyle
W=185
H=15
ClipString=1
ToolTipType=1
ToolTipIcon=#@#Images\qbittorrent.ico
X=5
Y=15r

[Meter4Size]
Group=Torrent4
Meter=String
MeterStyle=ListStyle
X=201
Y=0r

[Meter4DLSpeed]
Group=Torrent4
Meter=String
MeterStyle=ListStyle
X=274
Y=0r

[Meter4Seeds]
Group=Torrent4
Meter=String
MeterStyle=ListStyle
X=365
Y=0r

[Meter4Status]
Group=Torrent4
Meter=String
MeterStyle=ListStyle
X=436
Y=0r

[Meter4Line]
Group=Torrent4
Meter=Image
SolidColor=#SeparatorLineColor#
W=507
H=1
X=5
Y=20r
Hidden=1

[Measure4BarCalc]
Group=Torrent4
Measure=Calc
Formula=#Bar4Calc#
MinValue=0
MaxValue=100
DynamicVariables=1

[Meter4Bar]
Group=Torrent4
Meter=Bar
MeasureName=Measure4BarCalc
BarColor=#ProgressBarColor#
BarOrientation=Horizontal
W=507
H=3
X=5
Y=-1r

[Meter4Percent]
Group=Torrent4
Meter=String
MeterStyle=ListStyle
FontSize=7
StringAlign=RIGHT
X=541
Y=-4r

;=============================================

[Meter5Name]
Group=Torrent5
Meter=String
MeterStyle=ListStyle
W=185
H=15
ClipString=1
ToolTipType=1
ToolTipIcon=#@#Images\qbittorrent.ico
X=5
Y=15r

[Meter5Size]
Group=Torrent5
Meter=String
MeterStyle=ListStyle
X=201
Y=0r

[Meter5DLSpeed]
Group=Torrent5
Meter=String
MeterStyle=ListStyle
X=274
Y=0r

[Meter5Seeds]
Group=Torrent5
Meter=String
MeterStyle=ListStyle
X=365
Y=0r

[Meter5Status]
Group=Torrent5
Meter=String
MeterStyle=ListStyle
X=436
Y=0r

[Meter5Line]
Group=Torrent5
Meter=Image
SolidColor=#SeparatorLineColor#
W=507
H=1
X=5
Y=20r
Hidden=1

[Measure5BarCalc]
Group=Torrent5
Measure=Calc
Formula=#Bar5Calc#
MinValue=0
MaxValue=100
DynamicVariables=1

[Meter5Bar]
Group=Torrent5
Meter=Bar
MeasureName=Measure5BarCalc
BarColor=#ProgressBarColor#
BarOrientation=Horizontal
W=507
H=3
X=5
Y=-1r

[Meter5Percent]
Group=Torrent5
Meter=String
MeterStyle=ListStyle
FontSize=7
StringAlign=RIGHT
X=541
Y=-4r
Lua:

Code: Select all

function Initialize()
	
	normalColor = SKIN:GetVariable('ListFontColor')
	greyColor = SKIN:GetVariable('GreyColor')
	maxTorrents = SELF:GetNumberOption('MaxTorrents')	
	runningState = SKIN:GetMeasure('MeasureProcess')
	measureWebUI = SKIN:GetMeasure('MeasureWebUI')
	
	torrentPattern = '{"added_on".-upspeed":.-}'
	namePattern = '"name":"(.-)",'
	sizePattern = '"size":(.-),'
	speedPattern = '"dlspeed":(.-),'
	progressPattern = '"progress":(.-),'
	etaPattern = '"eta":(.-),'
	seedsPattern = '"num_seeds":(.-),'
	peersPattern = '"num_leechs":(.-),'
	statePattern = '"state":"(.-)",'
	
end

function Update()

	isRunning = runningState:GetValue()
	
	if isRunning == 1 then
	
		entireHTML = measureWebUI:GetStringValue()
		
		dummyString, fullCount = string.gsub(entireHTML, torrentPattern, '')
		torrentCount = (fullCount <= maxTorrents) and fullCount or maxTorrents
		
		startPos = 0
		
		for i = 1, torrentCount do
			
			torrentStart, torrentEnd = string.find(entireHTML, torrentPattern, startPos)
			oneTorrent = string.sub(entireHTML, torrentStart, torrentEnd)
			
			torrentName = string.match(oneTorrent, namePattern)
			torrentSize = tonumber(string.match(oneTorrent, sizePattern))
			torrentSpeed = tonumber(string.match(oneTorrent, speedPattern))
			torrentProgress = tonumber(string.match(oneTorrent, progressPattern))
			torrentETA = tonumber(string.match(oneTorrent, etaPattern))
			torrentSeeds = tonumber(string.match(oneTorrent, seedsPattern))
			torrentPeers = tonumber(string.match(oneTorrent, peersPattern))
			torrentState = string.match(oneTorrent, statePattern)

			startPos = torrentEnd + 1
	
			SKIN:Bang('!ShowMeterGroup', 'Torrent'..i)
			SKIN:Bang('!SetOption', 'Meter'..i..'Name', 'Text', torrentName)
			sizeScaled, sizeScale = AutoScale(torrentSize, 1)
			SKIN:Bang('!SetOption', 'Meter'..i..'Size', 'Text', sizeScaled..' '..sizeScale)
			speedScaled, speedScale = AutoScale(torrentSpeed, 1)
			SKIN:Bang('!SetOption', 'Meter'..i..'DLSpeed', 'Text', speedScaled..' '..speedScale..'/s')
			if torrentSpeed == 0 then
				SKIN:Bang('!SetOption', 'Meter'..i..'DLSpeed', 'FontColor', greyColor)
			else
				SKIN:Bang('!SetOption', 'Meter'..i..'DLSpeed', 'FontColor', normalColor)
			end	
			downloadedScaled, downloadedScale = AutoScale((torrentSize * torrentProgress), 1)
			progressPercent = Round((torrentProgress * 100), 0)
			SKIN:Bang('!SetOption', 'Meter'..i..'Percent', 'Text', progressPercent..'%')
			SKIN:Bang('!SetVariable', 'Bar'..i..'Calc', progressPercent)			
			SKIN:Bang('!SetOption', 'Meter'..i..'Seeds', 'Text', torrentSeeds)
			if torrentSeeds == 0 then
				SKIN:Bang('!SetOption', 'Meter'..i..'Seeds', 'FontColor', greyColor)
			else
				SKIN:Bang('!SetOption', 'Meter'..i..'Seeds', 'FontColor', normalColor)
			end				
			
			torrentState = string.gsub(torrentState, 'downloading', 'Download')
			torrentState = string.gsub(torrentState, 'queued.+', 'Queued')
			torrentState = string.gsub(torrentState, 'meta.+', 'Metadata')
			torrentState = string.gsub(torrentState, 'stalled.+', 'Stalled')
			torrentState = string.gsub(torrentState, 'paused.+', 'Paused')
			torrentState = string.gsub(torrentState, 'uploading', 'Seeding')
			
			if torrentProgress == 1 then torrentState = 'Completed' end
			
			SKIN:Bang('!SetOption', 'Meter'..i..'Status', 'Text', torrentState)
			
			etaFormated = FormatSeconds(torrentETA)..' remaining'
			if torrentETA == 8640000 then
				if torrentState == 'Completed' then
					etaFormated = 'Completed'
				else
					etaFormated = 'Unknown'
				end
			end
			
			SKIN:Bang('!SetOption', 'Meter'..i..'Name', 'ToolTipTitle', torrentName)
			SKIN:Bang('!SetOption', 'Meter'..i..'Name', 'ToolTipText', 'Torrent: '..i..' of '..fullCount..'#CRLF#'..'Seeds: '..torrentSeeds..' Peers: '..torrentPeers..'#CRLF#'..'Status: '..torrentState..'#CRLF#'..'Downloaded: '..downloadedScaled..' '..downloadedScale..' of '..sizeScaled..' '..sizeScale..'#CRLF#'..'Speed '..speedScaled..' '..speedScale..'/s'..'#CRLF#'..'Estimate: '..etaFormated) 

		end
		
		SKIN:Bang('!EnableMeasureGroup', 'AllMeasures')
		if torrentCount == 0 then
		 SKIN:Bang('!HideMeterGroup', 'Body')
		else	
		 SKIN:Bang('!ShowMeterGroup', 'Body')
		end
		
		SKIN:Bang('!SetVariable', 'BackgroundHeight', tostring(torrentCount * 31))
		
		if torrentCount < maxTorrents then
		 for i = torrentCount + 1, maxTorrents do
			SKIN:Bang('!HideMeterGroup', 'Torrent'..i)
		 end	
		end
	
	else
		
		SKIN:Bang("!DisableMeasureGroup AllMeasures")
		SKIN:Bang("!HideMeterGroup Body")
		for i = 1, maxTorrents do
			SKIN:Bang("!HideMeterGroup Torrent"..i)
		end	
		
	end

	return fullCount
	
end

function FormatSeconds(inputSeconds)
		
		local tableWeeks = inputSeconds / 604800
		local weeksRemainder = inputSeconds % 604800
		local tableDays = weeksRemainder / 86400
		local daysRemainder = weeksRemainder % 86400
		local tableHours = daysRemainder / 3600
		local hoursRemainder = daysRemainder % 3600
		local tableMinutes = hoursRemainder / 60
		local minutesRemainder = hoursRemainder % 60
		local tableSeconds = minutesRemainder % 60		

		local formatTable = {}
		formatTable['weeks'] = math.floor(tableWeeks)
		formatTable['days'] = math.floor(tableDays)
		formatTable['hours'] = math.floor(tableHours)
		formatTable['mins'] = math.floor(tableMinutes)
		formatTable['secs'] = math.floor(tableSeconds)
													
		if formatTable['weeks'] == 1 then weekText = 'week' else weekText = 'weeks' end
		if formatTable['days'] == 1 then dayText = 'day' else dayText = 'days' end
		if formatTable['hours'] == 1 then	hourText = 'hour' else hourText = 'hours' end
		if formatTable['mins'] == 1 then minText = 'minute' else minText = 'minutes' end
		if formatTable['secs'] == 1 then secText = 'second' else secText = 'seconds' end

		if inputSeconds >= 604800 then
			outputString = formatTable['weeks']..' '..weekText..' '..formatTable['days']..' '..dayText..' '..formatTable['hours']..' '..hourText..' '..formatTable['mins']..' '..minText..' '..formatTable['secs']..' '..secText
		elseif inputSeconds >= 86400 then
			outputString = formatTable['days']..' '..dayText..' '..formatTable['hours']..' '..hourText..' '..formatTable['mins']..' '..minText..' '..formatTable['secs']..' '..secText
		elseif inputSeconds >= 3600 then
			outputString = formatTable['hours']..' '..hourText..' '..formatTable['mins']..' '..minText..' '..formatTable['secs']..' '..secText
		elseif inputSeconds >= 60 then
			outputString = formatTable['mins']..' '..minText..' '..formatTable['secs']..' '..secText
		else	
			outputString = formatTable['secs']..' '..secText
		end					
	
	return outputString
	
end

function AutoScale(num, idp)
	assert(tonumber(num), 'AutoScale expects a number.')
	local scales = {'B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'}
	local places = idp or 0
	local scale = ""
	local scaled = 0

	for i, v in ipairs(scales) do
		if (num < (1024 ^ i)) or (i == #scales) then
			scale = v
			scaled = Round(num / 1024 ^ (i - 1), places)
			break
		end
	end

	return scaled, scale
end

function Round(num, idp)
	assert(tonumber(num), 'Round expects a number.')
	local mult = 10 ^ (idp or 0)
	if num >= 0 then
		return math.floor(num * mult + 0.5) / mult
	else
		return math.ceil(num * mult - 0.5) / mult
	end
end
You must ensure your qBittorrent client has these settings. Use any Port number you like, but I don't really recommend 8080, as that can often conflict with other stuff that wants to use localhost.
qBT2.png
You do not have the required permissions to view the files attached to this post.
User avatar
jsmorley
Developer
Posts: 22629
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: qBT - qBitttorrent skin

Post by jsmorley »

Version 1.1 - Apr 23, 2016: Tweaked a small potential bug in the Lua. Added more data and some cosmetics to the ToolTip.
1.png
Bishop149, FYI - The problem in the Lua was with this pattern in Initialize():

torrentPattern = '{"added_on".-}'

If the name of the torrent had an embedded "}" character in it, and there is no reason why it can't, this would cause the pattern to fail. Corrected with:

torrentPattern = '{"added_on".-upspeed":.-}'
You do not have the required permissions to view the files attached to this post.
zeus163
Posts: 2
Joined: August 14th, 2016, 12:09 am

Re: qBT - qBitttorrent skin

Post by zeus163 »

I've just started working with Rainmeter and was excited to see a qbittorrent meter. However, I can't seem to get your version or Bishop149's to work. I have the correct settings in qbittorent and have no problems using the web interface. When I query the interface, I see text, but it appears that is just showing my torrent info.

When I load the script, I get a qbittorrent small box with no active torrents shown. With Bishop149's, I get essentially the same. I copied your skin code into a text file, but didn't do anything with the .lua file. Does the .lua code also need to be copied into the same text file?

Just looking for some advice. Thanks.
User avatar
jsmorley
Developer
Posts: 22629
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: qBT - qBitttorrent skin

Post by jsmorley »

zeus163 wrote:I've just started working with Rainmeter and was excited to see a qbittorrent meter. However, I can't seem to get your version or Bishop149's to work. I have the correct settings in qbittorent and have no problems using the web interface. When I query the interface, I see text, but it appears that is just showing my torrent info.

When I load the script, I get a qbittorrent small box with no active torrents shown. With Bishop149's, I get essentially the same. I copied your skin code into a text file, but didn't do anything with the .lua file. Does the .lua code also need to be copied into the same text file?

Just looking for some advice. Thanks.
Just go here:

https://www.deviantart.com/deviation/604532816

Download the .rmskin and double-click it to install it.

Then just make sure you have the settings in qBTorrent as in the image in the first post. Use any port you like, but be sure the port in qBTorrent and the skin .ini file are the same.

That should be all you need to do.
zeus163
Posts: 2
Joined: August 14th, 2016, 12:09 am

Re: qBT - qBitttorrent skin

Post by zeus163 »

Thanks. That seems to have done the trick!! I appreciate it.
chevalm4n
Posts: 2
Joined: August 22nd, 2016, 9:29 pm

Re: qBT - qBitttorrent skin

Post by chevalm4n »

I like it, It tweaked it a bit but it works great.

What I don't like tho, is the pop up with the data showing up again... we already have all those infos.

What would be better IMO, is that a right click on a torrent could remove it. Is there anyway to do such a thing?

Anyways, great skin, it's a keeper.
Rendal
Posts: 1
Joined: November 5th, 2016, 7:14 pm

Re: qBT - qBitttorrent skin

Post by Rendal »

Hi, I'm using it since the last week and it works really good.

But I'm trying to add some information, could you give me some tips please ?

I'm trying to add the Upload Speed and the ratio.