From 0157ab132283533387d6130cf5939c0a463f902b Mon Sep 17 00:00:00 2001 From: anthony Date: Wed, 13 Jan 2021 20:09:47 +0000 Subject: [PATCH] Work on cutting and pasting bookmarks --- frontends/gnustep/AppDelegate.h | 3 + frontends/gnustep/BookmarkFolder.m | 2 + frontends/gnustep/BookmarksWindowController.h | 6 ++ frontends/gnustep/BookmarksWindowController.m | 96 ++++++++++++++++++ frontends/gnustep/Website.h | 4 +- frontends/gnustep/Website.m | 11 ++ frontends/gnustep/res/Menu.gorm/objects.gorm | Bin 15315 -> 15261 bytes 7 files changed, 121 insertions(+), 1 deletion(-) diff --git a/frontends/gnustep/AppDelegate.h b/frontends/gnustep/AppDelegate.h index 13d01784a..669211297 100644 --- a/frontends/gnustep/AppDelegate.h +++ b/frontends/gnustep/AppDelegate.h @@ -22,6 +22,9 @@ along with this program. If not, see . #define TAG_MENU_REMOVE 206 #define TAG_MENU_CANCEL 204 #define TAG_MENU_OPEN 104 +#define TAG_MENU_COPY 202 +#define TAG_MENU_CUT 201 +#define TAG_MENU_PASTE 203 #define TAG_SUBMENU_HISTORY 500 @interface AppDelegate: NSResponder { diff --git a/frontends/gnustep/BookmarkFolder.m b/frontends/gnustep/BookmarkFolder.m index df637b240..13d4ea600 100644 --- a/frontends/gnustep/BookmarkFolder.m +++ b/frontends/gnustep/BookmarkFolder.m @@ -90,6 +90,7 @@ lazy-loaded when requested. NSString *destPath = [path stringByAppendingPathComponent: filename]; ok = [[child asDictionary] writeToFile: destPath atomically: YES]; [child setFilename: filename]; + [child setParentFolder: self]; } else if ([child isKindOfClass: [BookmarkFolder class]]) { ok = [[NSFileManager defaultManager] createDirectoryAtPath: path attributes: nil]; @@ -227,6 +228,7 @@ lazy-loaded when requested. chDict = [NSDictionary dictionaryWithContentsOfFile: chPath]; child = [[Website alloc] initWithDictionary: chDict fromFileNamed: fileName]; + [child setParentFolder: self]; [newChildren addObject: [child autorelease]]; } } diff --git a/frontends/gnustep/BookmarksWindowController.h b/frontends/gnustep/BookmarksWindowController.h index b987c5df9..dfad199d3 100644 --- a/frontends/gnustep/BookmarksWindowController.h +++ b/frontends/gnustep/BookmarksWindowController.h @@ -5,8 +5,14 @@ id outlineView; id searchBar; NSArray *topLevelFolders; + BOOL isCutting; + NSArray *copiedItems; } -(void)search: (id)sender; -(void)clearSearch: (id)sender; -(void)newFolder: (id)sender; +-(void)cut: (id)sender; +-(void)copy: (id)sender; +-(void)paste: (id)sender; +-(void)remove: (id)sender; @end diff --git a/frontends/gnustep/BookmarksWindowController.m b/frontends/gnustep/BookmarksWindowController.m index 79529f8f8..3233a9ebe 100644 --- a/frontends/gnustep/BookmarksWindowController.m +++ b/frontends/gnustep/BookmarksWindowController.m @@ -2,6 +2,11 @@ #import "BookmarksWindowController.h" #import "BookmarkFolder.h" #import "Website.h" +#import "AppDelegate.h" + +@interface BookmarksWindowController (Private) +-(void)copySelectedItems; +@end @implementation BookmarksWindowController @@ -12,6 +17,12 @@ return self; } +-(void)dealloc { + [copiedItems release]; + [topLevelFolders release]; + [super dealloc]; +} + -(BOOL)windowShouldClose: (id)sender { [topLevelFolders release]; topLevelFolders = nil; @@ -32,6 +43,55 @@ [self onWindowAppeared]; } +-(void)cut: (id)sender { + isCutting = YES; + [self copySelectedItems]; +} + +-(void)copy: (id)sender { + isCutting = NO; + [self copySelectedItems]; +} + +-(void)paste: (id)sender { + NSEnumerator *selected = [outlineView selectedRowEnumerator]; + NSNumber *row = [selected nextObject]; + if (row == nil) { + return; + } + id item = [outlineView itemAtRow: [row integerValue]]; + if (row == nil) { + return; + } + BookmarkFolder *destinationFolder = nil; + if ([item isKindOfClass: [Website class]]) { + destinationFolder = [item parentFolder]; + } else if ([item isKindOfClass: [BookmarkFolder class]]) { + destinationFolder = item; + } + if (destinationFolder == nil) { + NSLog(@"Couldn't find destination for paste"); + return; + } + for (NSUInteger i = 0; i < [copiedItems count]; i++) { + item = [copiedItems objectAtIndex: i]; + if (isCutting) { + [[item parentFolder] removeChild: item]; + } + [destinationFolder addChild: item]; + } + + if (isCutting) { + isCutting = NO; + [copiedItems release]; + copiedItems = nil; + } +} + +-(void)remove: (id)sender { + +} + -(void)newFolder: (id)sender { NSLog(@"create new folder"); } @@ -50,6 +110,17 @@ NSLog(@"Clear bookmarks search"); } +-(BOOL)validateMenuItem: (NSMenuItem*)aMenuItem { + NSInteger tag = [aMenuItem tag]; + if (tag == TAG_MENU_REMOVE || tag == TAG_MENU_OPEN || tag == TAG_MENU_COPY || + tag == TAG_MENU_CUT) { + return [outlineView numberOfSelectedRows] > 0; + } else if (tag == TAG_MENU_PASTE) { + return copiedItems != nil; + } + return YES; +} + -(id)outlineView: (NSOutlineView*)outlineView child: (NSInteger)index ofItem: (id)item { if (item == nil) { @@ -101,4 +172,29 @@ } } +-(void)copySelectedItems { + NSEnumerator *selected = [outlineView selectedRowEnumerator]; + NSMutableArray *copiedFolders = [NSMutableArray array]; + NSMutableArray *toCopy = [NSMutableArray array]; + BOOL addedToPB = NO; + id row, item; + while ((row = [selected nextObject]) != NULL) { + item = [outlineView itemAtRow: [row integerValue]]; + if (!addedToPB && [item isKindOfClass: [Website class]]) { + [[NSPasteboard generalPasteboard] setString: [item url] + forType: NSStringPboardType]; + addedToPB = YES; + } + if ([item isKindOfClass: [BookmarkFolder class]]) { + [copiedFolders addObject: item]; + } + if ([copiedFolders containsObject: [item parentFolder]]) { + break; + } + [toCopy addObject: item]; + } + [copiedItems release]; + copiedItems = [toCopy retain]; +} + @end diff --git a/frontends/gnustep/Website.h b/frontends/gnustep/Website.h index 5ec56be8b..62d118b1b 100644 --- a/frontends/gnustep/Website.h +++ b/frontends/gnustep/Website.h @@ -14,6 +14,7 @@ struct website_data { @class BookmarkFolder; @interface Website: NSObject { + BookmarkFolder *parentFolder; NSString *filename; long fileOffset; struct website_data *data; @@ -28,7 +29,8 @@ struct website_data { -(long)fileOffset; -(NSString*)filename; -(void)setFilename: (NSString*)aFilename; - +-(BookmarkFolder*)parentFolder; +-(void)setParentFolder: (BookmarkFolder*)aBookmarkFolder; -(NSDictionary*)asDictionary; -(void)open; diff --git a/frontends/gnustep/Website.m b/frontends/gnustep/Website.m index c71806d7c..eb4865205 100644 --- a/frontends/gnustep/Website.m +++ b/frontends/gnustep/Website.m @@ -41,6 +41,7 @@ -(void)dealloc { free(data); + [parentFolder release]; [filename release]; [super dealloc]; } @@ -74,6 +75,16 @@ filename = [aFilename retain]; } +// Set when init from bookmarks or added to folder +-(BookmarkFolder*)parentFolder { + return parentFolder; +} + +-(void)setParentFolder: (BookmarkFolder*)aBookmarkFolder { + [parentFolder release]; + parentFolder = [aBookmarkFolder retain]; +} + -(NSDictionary*)asDictionary { NSMutableDictionary *dict = [NSMutableDictionary dictionary]; [dict setObject: [self name] forKey: @"name"]; diff --git a/frontends/gnustep/res/Menu.gorm/objects.gorm b/frontends/gnustep/res/Menu.gorm/objects.gorm index f4f92c013e679dacf73cd4b8e8c2fc385d07cac2..ade626ac84c74823ce2eae6f7f7a5d49585f12e6 100644 GIT binary patch literal 15261 zcmb7L33yyp6@K?+Ytkj%DNE^ep(FzBo$RS7cA;&gO)s4mN?VXg@|p}yX2N9Bw8cW% zidDdXqJX%IVo{tZiVLeKYk?x-f{KXy1}cl9V*SrMZ(eSCXYMF`U%&HS{_~&Z-h1xy z?yPFxIFRxBBk^=+Phy8BrQFs~*C3Zbz<<#w3w3pk!5fJ`iKuWUt%|iLI+mxBnRp`U zr5(p{qpmZqJ+`jn0j1gAQ5D9nfByD%x_pX9FcLyRFMof)rdSWX-n5A{hS6OK$A1J@>YdR?w_ zy>EP2R*zIX=NDXEpK{(keGmh-|;q1hKS_}^l zyN>G&%V}Vn&TQjCwsCIEOYcZ@dIQCX++jHbK2Dc2*+=9iTg}Wzfq51)PY9VOxT_Og zUd~NLU!K6t=nv*Hxe$yeGGkT9ScNe&6gfMQ>`D#E8q@Kl-ElAHxU2>H zTUdYWh#ZP+h+5Z(;+S*gQj>Uxo%r#Pco~S7vwnG)hjMp$ zJlW~>$`vN_ay#?Ekoj~luVj6F9P+F})kv-~+2eNhCqnksU~e=1Uhnm#u=seV$(*(` zKbd15?R00r#2O~jJKahYks_T=oIEVoqSLLB?cC`~X%;M%>%gd(Q6DhG7*X-0*GmKD zOw;#mR^P=bIp5`a7>KdHz9#Vvw0k=0L&@G$yvtuaSn3HDA@baj z3V9w==yO19u%nOGeedEn7u4oLo)3F*22TzL*kmjdlT;={v$DesZiPK@*O|d}!dRE- z+3LhVCY9b*tk=FeEIov_%_PW$);%V)9#~5-SYJH`p#?_e1!iEY?SZ{!2DTlhdYMRX zwPmT)_P%&}d$Cq4xnfxMA+%)S&{7XXC=I$BI_)7)3Dr$Vm2gqaf*T^ z{cbQ`#Ekk9F-B|64XIRbM?5XxZMu%-kYz3Fo)e~L5BM+6!=Fj@N7i7ZVlyW%G5Hs9 z`t{9_wk&cthx~iNe<|zhOY!v{l>tBb@-mY?m_`cGZwcuy2mKYSuh;r@=|p!T8Sjn6 z61zQlrD;Ig{ofiI*arhwvA$k~Hm6d3k+!6Kk4b%!o%-C6dOxV&%ldjD_Nmulh4em? z`xHC(c{%RU9(gs4Tx0srYxH6R+P!;NUW-n7jeI|M$`Ts4C2|;~*DV^34%khsU{YDtNiHY3XoIj}Wu`nCbdy*8Wm5*Ki#N5Fcm5j{HPU_+)gVGc7#PSdr+=BvQ$En$KA# z(UH;Ecm7Got@2ask3KHx#D>mXYNB;@wb>r|X&Xc~)@FCe&oD$Ee8f@{t;R-hnj?%oO7ubS@q zTeGj3yusG2IPYEH{W|NLTeEMN#KG3AIPo_@{4Lhkw`O!wnJIcWGTKacgXSKlDX+1{1(VfvFCV8+kDn#yvBjHhyKgRlcP4UT9ZfEqk zX<(IoNQ@pE9)y7>Sbt_X3(a&l4$wghozkN0MYg5V5i%*CG%a~{OBK0LFjL&d2Xjxs zI^E!Kq%oWtMPorrM$?tK~2CM34!1;aV)He*VOgx>5fH}S$i@M_6xntmG zLH7fu)6*WK72^NR7DkSV=7&tGPsOA2gRITg${(3#M-g>Rwb?V|k8KdyTARH^KF1Ja z2Ep`luKbD33CvN8eAS!|TQWQ4v9^(Wan#J52H%BJ5^o82ORZ9z05i+9N1Fhbu0j5cL$ zc8dJ1g`yr!wMYJr5vG&Kz*_lxi+&^Wd{F+u;sPk9$v;{s>d}~&%RgBV&B)b3`DaF$ zP9lVBF<$@17=OVLR`&mW$iKqsc^eCH93x+~ z_)w2Nw_m=-2s01JW1oE8qTlQ{_TMdt#+F+74@CI}WAvFOx2-SwbqclfpQxR0$bSW^ zTzt;slKgLG%^N(NpCjM2xYml!-Y@^d2s3!3rdb}g>7%C}rG#UFG*eGhLNFw+n=rFb z3D-sf$kj@eFhsBGqoXp44mnPVQVUHhsz<95WmX!b zv^z0poipSl9nVQCG0wDvue|;Jy@}2^P0vbHng}fLnA#7qmM3DMLkaa18c;O0&x z@_bzmdqE2_ieQhn89_96C~=Gh(tvJqqY}qjAaxjIPbqO+Ay*OX%}UI+Ff_E(DslWs zl@fDI)Y7i5NJnrqt3-qW`W`d*Bv5E&9d2Hfm}|0+rVD)ofzGo)nvnD@O3Y`7*#VIU zPl*NmXMIFzS3+vgDkVysU@_Bz4zx~*g%(H?a(cHCC)yzJ1}rrU$zS>;oLR3#t%arq z?cb@yTWk;%fYnNzWVM9sp0C8ojM4W1d_yH$ro<^W0xBVAD6znZ?u>d;vG|j+~-Yz12bxMM|+8IMwP0 z`ZE&pHVaKXa=$}~w==}>1KC2>PqPq2IqC0Uh%vzH5NDqfODzobNctQlmRTTCBox_N zZhGPJaR`fV@>n#>f;R@_*wb=n= zzY^zKAgx>$&SOaasgz17a`G-44G;YDtuzP;(_Gv}gWLhqVWXjnjH2CX!%(s7QKHL= zfyKqv%-_hS?&sNTYRuL z6Upt0BTM}=Ojz8mpBNqz$1BlGtIR&;m=bbKas4mNxn<@6zLcAlSLCm}u23Rriwpx4 z^*&{RG@$cfo7&G1GkD}?tr8bn80eJnAtlllNCUbS_GtqaNE6y}u@ad=ejt*kl^C=z zG@w(VrFK{#O^D`pC59}JI@%BHq?X#nDE(^yeG*b)H~&H32L#`Q3VgsE{dl9qMXYQl z8d<~=;oTP38ZaVmQDTn;(u6c&t$VQr(t-v@TU=7e57Z6J(W}Iz7EBYu zL8Z9N0%<{~Ksc9MAWd)v^ZFGQNDEpWJAf-~5abPKANv@RzlKU=1(WVoHX2kC6s`AI zX%G`I`)wGiS}51=<@(S|-!_rV_eHDel0E-~Ac-#_Df$V4;~c^rJZz<}9;rSgHq(O= z*O0szkC3k=xebqy-%oNg%flp3#v|TeN3!Dg*N;?ZUt#eB^m;$bA0&Ax%Quj`iA{Zo z(Iof)~TXVR%&{C-1Az7hwxC5;2Kl}^G*I|EJz;VN-Eqx5}udN4`%p4P;7;gQE+y_`tiIk%`?sg41p&Q3fI3P%z)-!2_|}8lPyl~B z01qnhAcOUY5IwHf1NNN&hLys1P0oHVjjy16{=FH1A0lv@5)W&H1&(hYVaV*T)68~L z=`JtrUl+m$%4AnO-R1vW#lNTv@<)jrWB*|#9%E(w^LoZh_u-ybhVt+@jhqEQViX;W zPI0FDBL|tshy1Yv2N)ogc!CM_#_9@wprpi;WEcenxThGWUv=tAbZv2{L>^~gh#mYJ(6eP5%M#{3Hg8$-)GM1FcZ~ooUc!{CH-uG@>x>7m{os3s*s`j zLsr#CUeF@ieJQB_h}5UE`j1H+GSr`Ab-j}u(V#yea0;O)@lyutwPS!U;PO%uW`0I! zD*j45UmX2&LR0-dB%W8|1$v??>_7d2o~Ua2PcNeUzK93p?UxkE+1VE%{))tIJVE|7 z;UOca->_wUIn?Qox!)3=w1NK};UNS6d&cXfs1v^)KsbLOg(NHdkrW_9A^7sAAJFyF z&jO(FXVRF#8ZVIsWN5t1CiLz);NK!ZO@h{6Mkf2=De>3hS^FEAn8(R@1$lW6PYCE$ zdc7z69K_eiFd>w9y*S_B3BAYf-2Y(o^spmNcd6coSEj=b{stMllzsRo$(P^}mj6Za ziFkzkZ<1HB{3gl!SpE-uewoF?WSVG{>lAg=6@&))0_D1S&~TLQVg$v)Eg>|_A5d=a z)k>enwgE}k^Oq>MjDYYBz;dS5hXVm~7fJxGKuf`SV8=05FBp_7zd_wfiuVe?8@N>@ zU&-=#vIQCX!RI2qT?m(`)x)Cyf xgg|F5>*zO2{Ur_G*AF%3k*C|(z4@dK8L0?9Tj(7mw;kpg*gaunqW{a){{s7%mJI*^ literal 15315 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