]> granicus.if.org Git - handbrake/commitdiff
MacGui: show statistics for completed jobs.
authorDamiano Galassi <damiog@gmail.com>
Sat, 27 Jul 2019 14:39:06 +0000 (16:39 +0200)
committerDamiano Galassi <damiog@gmail.com>
Sat, 27 Jul 2019 14:39:06 +0000 (16:39 +0200)
macosx/Base.lproj/HBQueueInfoViewController.xib
macosx/HBJob+UIAdditions.h
macosx/HBJob+UIAdditions.m
macosx/HBQueueInfoViewController.m
macosx/HBQueueItem.h
macosx/HBQueueItem.m

index 59cdb20c141ea018e14aaf5c92073b1a35d02bb4..d1683793a8a98b980e76e5191f049b2bf078fa17 100644 (file)
@@ -9,6 +9,7 @@
         <customObject id="-2" userLabel="File's Owner" customClass="HBQueueInfoViewController">
             <connections>
                 <outlet property="scrollView" destination="MXt-Cb-20x" id="dGY-tf-zF7"/>
+                <outlet property="statisticsHeader" destination="m2h-yw-mRX" id="do6-gL-eBp"/>
                 <outlet property="statisticsLabel" destination="Mm9-nD-res" id="I4f-MN-amu"/>
                 <outlet property="summaryLabel" destination="3EV-1F-TH6" id="Mtc-l6-0eA"/>
                 <outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
                         <action selector="resetItem:" target="-2" id="42R-t4-FxO"/>
                     </connections>
                 </button>
-                <scrollView borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MXt-Cb-20x">
+                <scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MXt-Cb-20x">
                     <rect key="frame" x="0.0" y="49" width="480" height="286"/>
                     <clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="kkx-XF-sYr" customClass="HBFlippedClipView">
                         <rect key="frame" x="0.0" y="0.0" width="480" height="286"/>
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                         <subviews>
                             <view translatesAutoresizingMaskIntoConstraints="NO" id="Akt-r1-6fP">
-                                <rect key="frame" x="0.0" y="228" width="480" height="58"/>
+                                <rect key="frame" x="0.0" y="188" width="480" height="98"/>
                                 <subviews>
-                                    <stackView distribution="fill" orientation="vertical" alignment="leading" horizontalStackHuggingPriority="250" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VVC-g8-nGU">
-                                        <rect key="frame" x="8" y="8" width="464" height="42"/>
+                                    <stackView distribution="fill" orientation="vertical" alignment="leading" spacing="4" horizontalStackHuggingPriority="250" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VVC-g8-nGU">
+                                        <rect key="frame" x="8" y="8" width="464" height="82"/>
                                         <subviews>
+                                            <customView translatesAutoresizingMaskIntoConstraints="NO" id="m2h-yw-mRX" userLabel="Header">
+                                                <rect key="frame" x="0.0" y="64" width="464" height="18"/>
+                                                <subviews>
+                                                    <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="OOz-qb-LU4">
+                                                        <rect key="frame" x="-2" y="4" width="58" height="14"/>
+                                                        <textFieldCell key="cell" lineBreakMode="clipping" title="Statistics" id="aCP-yp-iZy">
+                                                            <font key="font" metaFont="systemBold" size="11"/>
+                                                            <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                        </textFieldCell>
+                                                    </textField>
+                                                    <box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="2Jd-SZ-7V9">
+                                                        <rect key="frame" x="0.0" y="0.0" width="464" height="5"/>
+                                                    </box>
+                                                </subviews>
+                                                <constraints>
+                                                    <constraint firstAttribute="trailing" secondItem="2Jd-SZ-7V9" secondAttribute="trailing" id="8Fh-E4-uz1"/>
+                                                    <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="OOz-qb-LU4" secondAttribute="trailing" constant="20" symbolic="YES" id="FG1-Uj-5of"/>
+                                                    <constraint firstItem="OOz-qb-LU4" firstAttribute="leading" secondItem="m2h-yw-mRX" secondAttribute="leading" id="Kcc-7y-khF"/>
+                                                    <constraint firstItem="2Jd-SZ-7V9" firstAttribute="top" secondItem="OOz-qb-LU4" secondAttribute="bottom" constant="1" id="OrG-7d-qqY"/>
+                                                    <constraint firstItem="OOz-qb-LU4" firstAttribute="top" secondItem="m2h-yw-mRX" secondAttribute="top" id="Vsr-Dn-EY9"/>
+                                                    <constraint firstItem="2Jd-SZ-7V9" firstAttribute="leading" secondItem="m2h-yw-mRX" secondAttribute="leading" id="g1B-3l-mG2"/>
+                                                    <constraint firstAttribute="bottom" secondItem="2Jd-SZ-7V9" secondAttribute="bottom" constant="2" id="ySb-ad-7ww"/>
+                                                </constraints>
+                                            </customView>
                                             <textField horizontalHuggingPriority="249" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" textCompletion="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Mm9-nD-res" userLabel="Statistics">
-                                                <rect key="frame" x="-2" y="25" width="468" height="17"/>
+                                                <rect key="frame" x="-2" y="43" width="468" height="17"/>
                                                 <textFieldCell key="cell" selectable="YES" allowsUndo="NO" title="Statistics" allowsEditingTextAttributes="YES" id="S15-bh-qKU">
                                                     <font key="font" usesAppearanceFont="YES"/>
                                                     <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
                                                     <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                                                 </textFieldCell>
                                             </textField>
+                                            <customView translatesAutoresizingMaskIntoConstraints="NO" id="iyF-c4-9B8" userLabel="Header">
+                                                <rect key="frame" x="0.0" y="21" width="464" height="18"/>
+                                                <subviews>
+                                                    <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8hj-1a-dlb">
+                                                        <rect key="frame" x="-2" y="4" width="58" height="14"/>
+                                                        <textFieldCell key="cell" lineBreakMode="clipping" title="Summary" id="cx1-rC-AMC">
+                                                            <font key="font" metaFont="systemBold" size="11"/>
+                                                            <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                        </textFieldCell>
+                                                    </textField>
+                                                    <box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="biJ-yg-tVf">
+                                                        <rect key="frame" x="0.0" y="0.0" width="464" height="5"/>
+                                                    </box>
+                                                </subviews>
+                                                <constraints>
+                                                    <constraint firstAttribute="trailing" secondItem="biJ-yg-tVf" secondAttribute="trailing" id="1cm-3u-CQh"/>
+                                                    <constraint firstItem="biJ-yg-tVf" firstAttribute="top" secondItem="8hj-1a-dlb" secondAttribute="bottom" constant="1" id="CdR-UL-BFz"/>
+                                                    <constraint firstItem="8hj-1a-dlb" firstAttribute="leading" secondItem="iyF-c4-9B8" secondAttribute="leading" id="KgR-bb-hlc"/>
+                                                    <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="8hj-1a-dlb" secondAttribute="trailing" constant="20" symbolic="YES" id="ODa-vq-183"/>
+                                                    <constraint firstItem="biJ-yg-tVf" firstAttribute="leading" secondItem="iyF-c4-9B8" secondAttribute="leading" id="gQq-fz-MFq"/>
+                                                    <constraint firstItem="8hj-1a-dlb" firstAttribute="top" secondItem="iyF-c4-9B8" secondAttribute="top" id="y30-0p-PP7"/>
+                                                    <constraint firstAttribute="bottom" secondItem="biJ-yg-tVf" secondAttribute="bottom" constant="2" id="zOF-GU-omz"/>
+                                                </constraints>
+                                            </customView>
                                             <textField horizontalHuggingPriority="249" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" textCompletion="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3EV-1F-TH6" userLabel="Summary">
                                                 <rect key="frame" x="-2" y="0.0" width="468" height="17"/>
                                                 <textFieldCell key="cell" selectable="YES" allowsUndo="NO" title="Summary" allowsEditingTextAttributes="YES" id="GaR-qk-UW7">
                                         <visibilityPriorities>
                                             <integer value="1000"/>
                                             <integer value="1000"/>
+                                            <integer value="1000"/>
+                                            <integer value="1000"/>
                                         </visibilityPriorities>
                                         <customSpacing>
                                             <real value="3.4028234663852886e+38"/>
                                             <real value="3.4028234663852886e+38"/>
+                                            <real value="3.4028234663852886e+38"/>
+                                            <real value="3.4028234663852886e+38"/>
                                         </customSpacing>
                                     </stackView>
                                 </subviews>
                         <rect key="frame" x="-100" y="-100" width="478" height="16"/>
                         <autoresizingMask key="autoresizingMask"/>
                     </scroller>
-                    <scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="ied-bM-m6x">
-                        <rect key="frame" x="464" y="0.0" width="16" height="286"/>
+                    <scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="ied-bM-m6x">
+                        <rect key="frame" x="465" y="0.0" width="15" height="286"/>
                         <autoresizingMask key="autoresizingMask"/>
                     </scroller>
                 </scrollView>
                 <constraint firstAttribute="trailing" secondItem="Z14-gh-hWn" secondAttribute="trailing" constant="20" id="tSm-Qq-U0q"/>
                 <constraint firstItem="oq4-g0-srt" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="20" symbolic="YES" id="y0g-z9-6Sn"/>
             </constraints>
-            <point key="canvasLocation" x="-125" y="239"/>
+            <point key="canvasLocation" x="-125" y="238.5"/>
         </customView>
     </objects>
 </document>
index 99dcc10c8fcfc6d2d5fcfaf08ff602be0d83a307..7eef32785047c670312a915a1270c55d7c748ba7 100644 (file)
@@ -15,7 +15,6 @@
 @property (nonatomic, readonly) NSArray<NSString *> *angles;
 @property (nonatomic, readonly) NSArray<NSString *> *containers;
 
-@property (nonatomic, readonly) NSAttributedString *attributedTitleDescription;
 @property (nonatomic, readonly) NSAttributedString *attributedDescription;
 
 @property (nonatomic, readonly) NSString *shortDescription;
index a1367049987a15c6e507d049984ac46ec3cb7849..7bc90090b81bce4f285221d96f1019029f0e3e32 100644 (file)
@@ -25,7 +25,6 @@
 // Text Styles
 static NSDictionary            *detailAttr;
 static NSDictionary            *detailBoldAttr;
-static NSDictionary            *titleAttr;
 static NSDictionary            *shortHeightAttr;
 
 @implementation HBJob (UIAdditions)
@@ -98,24 +97,19 @@ static NSDictionary            *shortHeightAttr;
     if (!detailAttr)
     {
         // Attributes
-        NSMutableParagraphStyle *ps = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
+        NSMutableParagraphStyle *ps = [NSParagraphStyle.defaultParagraphStyle mutableCopy];
         ps.headIndent = 88.0;
         ps.paragraphSpacing = 1.0;
-        ps.tabStops = @[[[NSTextTab alloc] initWithType:
-                          NSRightTabStopType location: 88],
-                         [[NSTextTab alloc] initWithType:
-                          NSLeftTabStopType location: 90]];
+        ps.tabStops = @[[[NSTextTab alloc] initWithType:NSRightTabStopType location:88],
+                        [[NSTextTab alloc] initWithType:NSLeftTabStopType location:90]];
 
-        detailAttr = @{NSFontAttributeName: [NSFont systemFontOfSize:[NSFont smallSystemFontSize]],
-                        NSParagraphStyleAttributeName: ps};
-
-        detailBoldAttr = @{NSFontAttributeName: [NSFont boldSystemFontOfSize:[NSFont smallSystemFontSize]],
-                            NSParagraphStyleAttributeName: ps};
-
-        titleAttr = @{NSFontAttributeName: [NSFont systemFontOfSize:[NSFont systemFontSize]],
+        detailAttr = @{NSFontAttributeName: [NSFont systemFontOfSize:NSFont.smallSystemFontSize],
                        NSParagraphStyleAttributeName: ps};
 
-        shortHeightAttr = @{NSFontAttributeName: [NSFont systemFontOfSize:2.0]};
+        detailBoldAttr = @{NSFontAttributeName: [NSFont systemFontOfSize:NSFont.smallSystemFontSize],
+                           NSParagraphStyleAttributeName: ps};
+
+        shortHeightAttr = @{NSFontAttributeName: [NSFont systemFontOfSize:8.0]};
     }
 }
 
@@ -180,18 +174,6 @@ static NSDictionary            *shortHeightAttr;
 
     return attrString;
 }
-- (NSAttributedString *)titleAttributedDescription
-{
-    NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] init];
-
-    // Job name
-    [attrString appendString:self.description withAttributes:titleAttr];
-
-    [attrString appendString:[NSString stringWithFormat:@" (%@) ▸ %@\n", [self rangeDescription], self.outputFileName]
-                  withAttributes:detailAttr];
-
-    return attrString;
-}
 
 - (NSAttributedString *)presetAttributedDescription
 {
@@ -645,12 +627,6 @@ static NSDictionary            *shortHeightAttr;
     return attrString;
 }
 
-- (NSAttributedString *)attributedTitleDescription
-{
-    [self initStyles];
-    return [self titleAttributedDescription];
-}
-
 - (NSAttributedString *)attributedDescription
 {
     NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] init];
@@ -659,37 +635,37 @@ static NSDictionary            *shortHeightAttr;
     @autoreleasepool
     {
         [attrString appendAttributedString:[self presetAttributedDescription]];
-        [attrString appendString:@"\n" withAttributes: detailAttr];
+        [attrString appendString:@"\n" withAttributes: shortHeightAttr];
 
         [attrString appendAttributedString:[self sourceAttributedDescription]];
-        [attrString appendString:@"\n" withAttributes: detailAttr];
+        [attrString appendString:@"\n" withAttributes: shortHeightAttr];
 
         [attrString appendAttributedString:[self destinationAttributedDescription]];
-        [attrString appendString:@"\n" withAttributes: detailAttr];
+        [attrString appendString:@"\n" withAttributes: shortHeightAttr];
 
         [attrString appendAttributedString:[self formatAttributedDescription]];
-        [attrString appendString:@"\n" withAttributes: detailAttr];
+        [attrString appendString:@"\n" withAttributes: shortHeightAttr];
 
         [attrString appendAttributedString:[self rangeAttributedDescription]];
-        [attrString appendString:@"\n" withAttributes: detailAttr];
+        [attrString appendString:@"\n" withAttributes: shortHeightAttr];
 
         [attrString appendAttributedString:[self dimensionsAttributedDescription]];
-        [attrString appendString:@"\n" withAttributes: detailAttr];
+        [attrString appendString:@"\n" withAttributes: shortHeightAttr];
 
         NSAttributedString *filters = [self filtersAttributedDescription];
         if (filters.length)
         {
             [attrString appendAttributedString:[self filtersAttributedDescription]];
-            [attrString appendString:@"\n" withAttributes: detailAttr];
+            [attrString appendString:@"\n" withAttributes: shortHeightAttr];
         }
 
         [attrString appendAttributedString:[self videoAttributedDescription]];
-        [attrString appendString:@"\n" withAttributes: detailAttr];
+        [attrString appendString:@"\n" withAttributes: shortHeightAttr];
 
         if (self.audio.countOfTracks > 1)
         {
             [attrString appendAttributedString:[self audioAttributedDescription]];
-            [attrString appendString:@"\n" withAttributes: detailAttr];
+            [attrString appendString:@"\n" withAttributes: shortHeightAttr];
         }
         if (self.subtitles.countOfTracks > 1)
         {
index 1ae88bfc8ad1b67ba87176e0d6e3da3d46a20312..e5c68a0a2b5ed1924d2d1d4eb2fa997cee456b8f 100644 (file)
@@ -5,11 +5,13 @@
  It may be used under the terms of the GNU General Public License. */
 
 #import "HBQueueInfoViewController.h"
+#import "HBQueue.h"
 
 @interface HBQueueInfoViewController ()
 
-@property (weak) IBOutlet NSTextField *summaryLabel;
+@property (weak) IBOutlet NSView *statisticsHeader;
 @property (weak) IBOutlet NSTextField *statisticsLabel;
+@property (weak) IBOutlet NSTextField *summaryLabel;
 @property (weak) IBOutlet NSScrollView *scrollView;
 
 @property (weak) id<HBQueueDetailsViewControllerDelegate> delegate;
 - (void)viewDidLoad {
     [super viewDidLoad];
     [self updateLabels];
+    [self setUpObservers];
+}
+
+- (void)setUpObservers
+{
+    NSNotificationCenter * __weak center = NSNotificationCenter.defaultCenter;
+
+    [center addObserverForName:HBQueueDidCompleteItemNotification
+                                              object:nil
+                                               queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification * _Nonnull note)
+                           {
+                               HBQueueItem *completedItem = note.userInfo[HBQueueItemNotificationItemKey];
+
+                               if (completedItem == self.item)
+                               {
+                                   [self updateLabels];
+                               }
+                           }];
+
+    [center addObserverForName:HBQueueDidCompleteItemNotification
+                        object:nil
+                         queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification * _Nonnull note)
+     {
+         HBQueueItem *completedItem = note.userInfo[HBQueueItemNotificationItemKey];
+
+         if (completedItem == self.item)
+         {
+             [self updateLabels];
+         }
+     }];
+
 }
 
 - (void)updateLabels
@@ -38,6 +71,7 @@
     if (self.item)
     {
         self.statisticsLabel.hidden = self.item.endedDate == nil;
+        self.statisticsHeader.hidden = self.item.endedDate == nil;
         self.summaryLabel.hidden = NO;
 
         self.statisticsLabel.attributedStringValue = self.item.attributedStatistics;
@@ -47,6 +81,7 @@
     }
     else
     {
+        self.statisticsHeader.hidden = YES;
         self.statisticsLabel.hidden = YES;
         self.summaryLabel.hidden = YES;
     }
index 535d20a1771078b547fd321b87b9ddbcf849a760..54a4f82a97834cac1de40266fc555ce7d1762c2b 100644 (file)
@@ -53,10 +53,9 @@ typedef NS_ENUM(NSUInteger, HBQueueItemState) {
 - (void)pausedAtDate:(NSDate *)date;
 - (void)resumedAtDate:(NSDate *)date;
 
-@property (nonatomic, readonly) NSAttributedString *attributedTitleDescription;
 @property (nonatomic, readonly) NSAttributedString *attributedDescription;
 
-@property (nonatomic, readonly) NSAttributedString *attributedStatistics;
+@property (nonatomic, readonly, nullable) NSAttributedString *attributedStatistics;
 
 
 @end
index f3279790e3f63e0f3176d2f1a6ea2a12b998e85f..ff18938661f9fdb544811a3814b858ff19c9cdd4 100644 (file)
@@ -7,21 +7,52 @@
 #import "HBQueueItem.h"
 
 #import "HBCodingUtilities.h"
+#import "HBAttributedStringAdditions.h"
+
+static NSDateFormatter *_dateFormatter = nil;
+
+static NSDictionary     *detailAttr;
+static NSDictionary     *detailBoldAttr;
+static NSDictionary     *shortHeightAttr;
 
 @interface HBQueueItem ()
 
 @property (nonatomic, nullable) NSDate *pausedDate;
 @property (nonatomic, nullable) NSDate *resumedDate;
 
+@property (nonatomic, readwrite, nullable) NSAttributedString *attributedStatistics;
+
 @end
 
 @implementation HBQueueItem
 
++ (void)initialize
+{
+    if (self == [HBQueueItem class]) {
+        _dateFormatter = [[NSDateFormatter alloc] init];
+        [_dateFormatter setDateStyle:NSDateFormatterLongStyle];
+        [_dateFormatter setTimeStyle:NSDateFormatterLongStyle];
+
+        // Attributes
+        NSMutableParagraphStyle *ps = [NSParagraphStyle.defaultParagraphStyle mutableCopy];
+        ps.headIndent = 88.0;
+        ps.paragraphSpacing = 1.0;
+        ps.tabStops = @[[[NSTextTab alloc] initWithType:NSRightTabStopType location:88],
+                        [[NSTextTab alloc] initWithType:NSLeftTabStopType location:90]];
+
+        detailAttr = @{NSFontAttributeName: [NSFont systemFontOfSize:NSFont.smallSystemFontSize],
+                       NSParagraphStyleAttributeName: ps};
+
+        detailBoldAttr = @{NSFontAttributeName: [NSFont systemFontOfSize:NSFont.smallSystemFontSize],
+                           NSParagraphStyleAttributeName: ps};
+
+        shortHeightAttr = @{NSFontAttributeName: [NSFont systemFontOfSize:2.0]};
+    }
+}
+
 @synthesize job = _job;
-@synthesize attributedTitleDescription = _attributedTitleDescription;
 @synthesize attributedDescription = _attributedDescription;
 
-
 @synthesize uuid = _uuid;
 
 - (instancetype)initWithJob:(HBJob *)job
     return _job.completeOutputURL;
 }
 
-- (NSAttributedString *)attributedTitleDescription
-{
-    if (_attributedTitleDescription == nil) {
-        _attributedTitleDescription = _job.attributedTitleDescription;
-    }
-    return _attributedTitleDescription;
-}
-
 - (NSAttributedString *)attributedDescription
 {
     if (_attributedDescription == nil) {
     return _attributedDescription;
 }
 
+- (NSAttributedString *)attributedStatistics
+{
+    if (self.endedDate == nil)
+    {
+        return nil;
+    }
+
+    if (_attributedStatistics == nil)
+    {
+        NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] init];
+
+        [attrString appendString:@"\t" withAttributes:detailAttr];
+        [attrString appendString:NSLocalizedString(@"Started at:", @"Job statistics") withAttributes:detailBoldAttr];
+        [attrString appendString:@" \t" withAttributes:detailAttr];
+        [attrString appendString:[_dateFormatter stringFromDate:self.startedDate] withAttributes:detailAttr];
+        [attrString appendString:@"\n\t" withAttributes:detailAttr];
+        [attrString appendString:NSLocalizedString(@"Ended at:", @"Job statistics") withAttributes:detailBoldAttr];
+        [attrString appendString:@" \t" withAttributes:detailAttr];
+        [attrString appendString:[_dateFormatter stringFromDate:self.endedDate] withAttributes:detailAttr];
+        [attrString appendString:@"\n\n" withAttributes:shortHeightAttr];
+        [attrString appendString:@"\t" withAttributes:detailAttr];
+
+        [attrString appendString:NSLocalizedString(@"Run time:", @"Job statistics") withAttributes:detailBoldAttr];
+        [attrString appendString:@" \t" withAttributes:detailAttr];
+        uint64_t encodeDuration = (uint64_t)self.encodeDuration;
+        [attrString appendString:[NSString stringWithFormat:@"%02lld:%02lld:%02lld", encodeDuration / 3600, (encodeDuration/ 60) % 60, encodeDuration % 60]  withAttributes:detailAttr];
+        [attrString appendString:@"\n\t"  withAttributes:detailAttr];
+        [attrString appendString:NSLocalizedString(@"Paused time:", @"Job statistics") withAttributes:detailBoldAttr];
+        [attrString appendString:@" \t" withAttributes:detailAttr];
+        uint64_t pauseDuration = (uint64_t)self.pauseDuration;
+        [attrString appendString:[NSString stringWithFormat:@"%02lld:%02lld:%02lld", pauseDuration / 3600, (pauseDuration/ 60) % 60, pauseDuration % 60]  withAttributes:detailAttr];
+        [attrString appendString:@"\n" withAttributes:detailAttr];
+
+        _attributedStatistics = attrString;
+    }
+
+    return _attributedStatistics;
+}
+
 #pragma mark - Statistics
 
 - (void)resetStatistics
     self.endedDate = nil;
     self.encodeDuration = 0;
     self.pauseDuration = 0;
+    self.attributedStatistics = nil;
 }
 
 - (void)pausedAtDate:(NSDate *)date
 {
     self.resumedDate = date;
     self.pauseDuration += [self.resumedDate timeIntervalSinceDate:self.pausedDate];
+    self.pausedDate = nil;
 }
 
 - (void)setEndedDate:(NSDate *)endedDate
 {
     _endedDate = endedDate;
-    self.encodeDuration = [self.startedDate timeIntervalSinceDate:self.endedDate];
+    if (endedDate && self.pausedDate)
+    {
+        [self resumedAtDate:endedDate];
+    }
+    self.encodeDuration = [self.endedDate timeIntervalSinceDate:self.startedDate];
     self.encodeDuration -= self.pauseDuration;
 }